summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwlemb <wlemb>2000-02-06 09:34:01 +0000
committerwlemb <wlemb>2000-02-06 09:34:01 +0000
commit653c6faab591f3c5f290a18a7f58c29cb1a3b0a7 (patch)
tree633fec7ba17c3da901e7725d1907a103a17e4532
downloadgroff-653c6faab591f3c5f290a18a7f58c29cb1a3b0a7.tar.gz
Initial revision
-rw-r--r--BUG-REPORT55
-rw-r--r--COPYING339
-rw-r--r--ChangeLog6497
-rw-r--r--INSTALL35
-rw-r--r--INSTALL.gen183
-rw-r--r--MORE.STUFF23
-rw-r--r--Makefile.ccpg33
-rw-r--r--Makefile.comm259
-rw-r--r--Makefile.cpg27
-rw-r--r--Makefile.dev4
-rw-r--r--Makefile.in489
-rw-r--r--Makefile.init25
-rw-r--r--Makefile.lib20
-rw-r--r--Makefile.man5
-rw-r--r--Makefile.sub7
-rw-r--r--NEWS893
-rw-r--r--PROBLEMS575
-rw-r--r--PROJECTS16
-rw-r--r--README84
-rw-r--r--REVISION1
-rw-r--r--TODO24
-rw-r--r--VERSION1
-rw-r--r--aclocal.m4464
-rwxr-xr-xconfigure2965
-rwxr-xr-xconfigure.in55
-rw-r--r--contrib/mm/ChangeLog484
-rw-r--r--contrib/mm/Makefile.sim66
-rw-r--r--contrib/mm/Makefile.sub49
-rw-r--r--contrib/mm/NOTES103
-rw-r--r--contrib/mm/README28
-rw-r--r--contrib/mm/examples/APP352
-rw-r--r--contrib/mm/examples/B1B291
-rw-r--r--contrib/mm/examples/COVER235
-rw-r--r--contrib/mm/examples/IND4191
-rw-r--r--contrib/mm/examples/LT1058
-rw-r--r--contrib/mm/examples/LT.se1062
-rw-r--r--contrib/mm/examples/ML169
-rw-r--r--contrib/mm/examples/MOVE175
-rw-r--r--contrib/mm/examples/MUL535
-rw-r--r--contrib/mm/examples/NCOL196
-rw-r--r--contrib/mm/examples/ND17
-rw-r--r--contrib/mm/examples/README32
-rw-r--r--contrib/mm/examples/References975
-rw-r--r--contrib/mm/examples/SETR109
-rw-r--r--contrib/mm/groff_mm.man1894
-rw-r--r--contrib/mm/groff_mmse.man82
-rw-r--r--contrib/mm/mm/0.MT146
-rw-r--r--contrib/mm/mm/4.MT81
-rw-r--r--contrib/mm/mm/5.MT34
-rw-r--r--contrib/mm/mm/ms.cov84
-rw-r--r--contrib/mm/mm/se_ms.cov3
-rw-r--r--contrib/mm/mmroff.man48
-rw-r--r--contrib/mm/mmroff.pl134
-rwxr-xr-xcontrib/mm/tmac.m3471
-rwxr-xr-xcontrib/mm/tmac.mse184
-rwxr-xr-xdoc/Makefile83
-rw-r--r--doc/groff.texinfo5794
-rwxr-xr-xdoc/homepage.ms162
-rw-r--r--doc/meintro.me2246
-rw-r--r--doc/meref.me2198
-rw-r--r--doc/pic.ms2434
-rw-r--r--font/devX100-12/CB306
-rw-r--r--font/devX100-12/CBI306
-rw-r--r--font/devX100-12/CI306
-rw-r--r--font/devX100-12/CR306
-rw-r--r--font/devX100-12/DESC9
-rw-r--r--font/devX100-12/HB306
-rw-r--r--font/devX100-12/HBI306
-rw-r--r--font/devX100-12/HI306
-rw-r--r--font/devX100-12/HR306
-rw-r--r--font/devX100-12/Makefile.sub2
-rw-r--r--font/devX100-12/NB306
-rw-r--r--font/devX100-12/NBI306
-rw-r--r--font/devX100-12/NI306
-rw-r--r--font/devX100-12/NR306
-rw-r--r--font/devX100-12/S226
-rw-r--r--font/devX100-12/TB306
-rw-r--r--font/devX100-12/TBI306
-rw-r--r--font/devX100-12/TI306
-rw-r--r--font/devX100-12/TR306
-rw-r--r--font/devX100/CB306
-rw-r--r--font/devX100/CBI306
-rw-r--r--font/devX100/CI306
-rw-r--r--font/devX100/CR306
-rw-r--r--font/devX100/DESC9
-rw-r--r--font/devX100/HB306
-rw-r--r--font/devX100/HBI306
-rw-r--r--font/devX100/HI306
-rw-r--r--font/devX100/HR306
-rw-r--r--font/devX100/Makefile.sub2
-rw-r--r--font/devX100/NB306
-rw-r--r--font/devX100/NBI306
-rw-r--r--font/devX100/NI306
-rw-r--r--font/devX100/NR306
-rw-r--r--font/devX100/S226
-rw-r--r--font/devX100/TB306
-rw-r--r--font/devX100/TBI306
-rw-r--r--font/devX100/TI306
-rw-r--r--font/devX100/TR306
-rw-r--r--font/devX75-12/CB306
-rw-r--r--font/devX75-12/CBI306
-rw-r--r--font/devX75-12/CI306
-rw-r--r--font/devX75-12/CR306
-rw-r--r--font/devX75-12/DESC9
-rw-r--r--font/devX75-12/HB306
-rw-r--r--font/devX75-12/HBI306
-rw-r--r--font/devX75-12/HI306
-rw-r--r--font/devX75-12/HR306
-rw-r--r--font/devX75-12/Makefile.sub2
-rw-r--r--font/devX75-12/NB306
-rw-r--r--font/devX75-12/NBI306
-rw-r--r--font/devX75-12/NI306
-rw-r--r--font/devX75-12/NR306
-rw-r--r--font/devX75-12/S226
-rw-r--r--font/devX75-12/TB306
-rw-r--r--font/devX75-12/TBI306
-rw-r--r--font/devX75-12/TI306
-rw-r--r--font/devX75-12/TR306
-rw-r--r--font/devX75/CB306
-rw-r--r--font/devX75/CBI306
-rw-r--r--font/devX75/CI306
-rw-r--r--font/devX75/CR306
-rw-r--r--font/devX75/DESC9
-rw-r--r--font/devX75/HB306
-rw-r--r--font/devX75/HBI306
-rw-r--r--font/devX75/HI306
-rw-r--r--font/devX75/HR306
-rw-r--r--font/devX75/Makefile.sub2
-rw-r--r--font/devX75/NB306
-rw-r--r--font/devX75/NBI306
-rw-r--r--font/devX75/NI306
-rw-r--r--font/devX75/NR306
-rw-r--r--font/devX75/S226
-rw-r--r--font/devX75/TB306
-rw-r--r--font/devX75/TBI306
-rw-r--r--font/devX75/TI306
-rw-r--r--font/devX75/TR306
-rw-r--r--font/devascii/DESC.proto8
-rw-r--r--font/devascii/Makefile.sub31
-rw-r--r--font/devascii/R.proto165
-rwxr-xr-xfont/devdvi/B347
-rwxr-xr-xfont/devdvi/BI352
-rw-r--r--font/devdvi/CW158
-rw-r--r--font/devdvi/DESC.in10
-rw-r--r--font/devdvi/EX144
-rwxr-xr-xfont/devdvi/H302
-rw-r--r--font/devdvi/HB302
-rw-r--r--font/devdvi/HI303
-rwxr-xr-xfont/devdvi/I353
-rw-r--r--font/devdvi/MI136
-rw-r--r--font/devdvi/Makefile.sub11
-rwxr-xr-xfont/devdvi/R430
-rw-r--r--font/devdvi/S152
-rw-r--r--font/devdvi/SA143
-rw-r--r--font/devdvi/SB132
-rwxr-xr-xfont/devdvi/generate/CompileFonts15
-rw-r--r--font/devdvi/generate/Makefile93
-rwxr-xr-xfont/devdvi/generate/cork.map206
-rw-r--r--font/devdvi/generate/msam.map127
-rw-r--r--font/devdvi/generate/msbm.map121
-rw-r--r--font/devdvi/generate/texb.map127
-rw-r--r--font/devdvi/generate/texex.map100
-rw-r--r--font/devdvi/generate/texi.map127
-rw-r--r--font/devdvi/generate/texmi.map32
-rw-r--r--font/devdvi/generate/texr.map127
-rw-r--r--font/devdvi/generate/texsy.map100
-rw-r--r--font/devdvi/generate/textt.map126
-rwxr-xr-xfont/devhtml/CB306
-rwxr-xr-xfont/devhtml/CBI306
-rwxr-xr-xfont/devhtml/CI306
-rwxr-xr-xfont/devhtml/CR306
-rwxr-xr-xfont/devhtml/DESC12
-rwxr-xr-xfont/devhtml/HB306
-rwxr-xr-xfont/devhtml/HBI306
-rwxr-xr-xfont/devhtml/HI306
-rwxr-xr-xfont/devhtml/HR306
-rw-r--r--font/devhtml/Makefile.sub2
-rwxr-xr-xfont/devhtml/NB306
-rwxr-xr-xfont/devhtml/NBI306
-rwxr-xr-xfont/devhtml/NI306
-rwxr-xr-xfont/devhtml/NR306
-rwxr-xr-xfont/devhtml/S226
-rwxr-xr-xfont/devhtml/TB306
-rwxr-xr-xfont/devhtml/TBI306
-rwxr-xr-xfont/devhtml/TI306
-rwxr-xr-xfont/devhtml/TR306
-rw-r--r--font/devlatin1/DESC.proto8
-rw-r--r--font/devlatin1/Makefile.sub32
-rw-r--r--font/devlatin1/R.proto353
-rw-r--r--font/devlj4/ALBB773
-rw-r--r--font/devlj4/ALBR788
-rw-r--r--font/devlj4/AOB744
-rw-r--r--font/devlj4/AOI797
-rw-r--r--font/devlj4/AOR720
-rw-r--r--font/devlj4/CB347
-rw-r--r--font/devlj4/CBI348
-rw-r--r--font/devlj4/CI348
-rw-r--r--font/devlj4/CLARENDON348
-rw-r--r--font/devlj4/CORONET348
-rw-r--r--font/devlj4/CR347
-rw-r--r--font/devlj4/DESC.in9
-rw-r--r--font/devlj4/GB732
-rw-r--r--font/devlj4/GBI736
-rw-r--r--font/devlj4/GI669
-rw-r--r--font/devlj4/GR853
-rw-r--r--font/devlj4/LGB347
-rw-r--r--font/devlj4/LGI348
-rw-r--r--font/devlj4/LGR347
-rw-r--r--font/devlj4/MARIGOLD348
-rw-r--r--font/devlj4/Makefile.sub33
-rw-r--r--font/devlj4/OB797
-rw-r--r--font/devlj4/OBI793
-rw-r--r--font/devlj4/OI905
-rw-r--r--font/devlj4/OR876
-rw-r--r--font/devlj4/S195
-rw-r--r--font/devlj4/TB971
-rw-r--r--font/devlj4/TBI1023
-rw-r--r--font/devlj4/TI1106
-rw-r--r--font/devlj4/TR860
-rw-r--r--font/devlj4/UB809
-rw-r--r--font/devlj4/UBI759
-rw-r--r--font/devlj4/UCB774
-rw-r--r--font/devlj4/UCBI683
-rw-r--r--font/devlj4/UCI822
-rw-r--r--font/devlj4/UCR742
-rw-r--r--font/devlj4/UI917
-rw-r--r--font/devlj4/UR858
-rw-r--r--font/devlj4/generate/Makefile163
-rw-r--r--font/devlj4/generate/special.map178
-rw-r--r--font/devlj4/generate/text.map341
-rw-r--r--font/devps/AB559
-rw-r--r--font/devps/ABI560
-rw-r--r--font/devps/AI559
-rw-r--r--font/devps/AR558
-rw-r--r--font/devps/BMB438
-rw-r--r--font/devps/BMBI441
-rw-r--r--font/devps/BMI434
-rw-r--r--font/devps/BMR430
-rw-r--r--font/devps/CB336
-rw-r--r--font/devps/CBI337
-rw-r--r--font/devps/CI337
-rw-r--r--font/devps/CR336
-rw-r--r--font/devps/DESC.in11
-rw-r--r--font/devps/HB546
-rw-r--r--font/devps/HBI547
-rw-r--r--font/devps/HI617
-rw-r--r--font/devps/HNB546
-rw-r--r--font/devps/HNBI547
-rw-r--r--font/devps/HNI617
-rw-r--r--font/devps/HNR616
-rw-r--r--font/devps/HR616
-rw-r--r--font/devps/Makefile.sub35
-rw-r--r--font/devps/NB446
-rw-r--r--font/devps/NBI447
-rw-r--r--font/devps/NI447
-rw-r--r--font/devps/NR447
-rw-r--r--font/devps/PB449
-rw-r--r--font/devps/PBI451
-rw-r--r--font/devps/PI453
-rw-r--r--font/devps/PR456
-rw-r--r--font/devps/S227
-rw-r--r--font/devps/SS194
-rw-r--r--font/devps/TB533
-rw-r--r--font/devps/TBI515
-rw-r--r--font/devps/TI528
-rw-r--r--font/devps/TR519
-rw-r--r--font/devps/ZCMI477
-rw-r--r--font/devps/ZD193
-rw-r--r--font/devps/ZDR193
-rw-r--r--font/devps/download5
-rw-r--r--font/devps/generate/Makefile224
-rwxr-xr-xfont/devps/generate/afmname44
-rwxr-xr-xfont/devps/generate/dingbatsmap2
-rwxr-xr-xfont/devps/generate/dingbatsrmap1
-rw-r--r--font/devps/generate/lgreekmap28
-rw-r--r--font/devps/generate/symbol.sed33
-rw-r--r--font/devps/generate/symbolchars60
-rw-r--r--font/devps/generate/symbolsl.afm203
-rw-r--r--font/devps/generate/textmap450
-rw-r--r--font/devps/prologue.ps228
-rw-r--r--font/devps/psstrip.sed7
-rw-r--r--font/devps/symbol.afm215
-rw-r--r--font/devps/symbolmap510
-rw-r--r--font/devps/symbolsl.ps41
-rw-r--r--font/devps/text.enc231
-rw-r--r--font/devps/zapfdr.afm222
-rw-r--r--font/devps/zapfdr.ps225
-rw-r--r--font/devutf8/DESC.proto8
-rw-r--r--font/devutf8/Makefile.sub32
-rw-r--r--font/devutf8/NOTES91
-rw-r--r--font/devutf8/R.proto468
-rw-r--r--gendef.sh24
-rwxr-xr-xinstall-sh238
-rw-r--r--man/Makefile.sub5
-rw-r--r--man/groff_char.man563
-rw-r--r--man/groff_font.man389
-rw-r--r--man/groff_out.man232
-rw-r--r--mdate.sh41
-rwxr-xr-xmkinstalldirs40
-rw-r--r--src/devices/grodvi/Makefile.sub6
-rw-r--r--src/devices/grodvi/dvi.cc896
-rw-r--r--src/devices/grodvi/grodvi.man171
-rwxr-xr-xsrc/devices/grohtml/ChangeLog172
-rw-r--r--src/devices/grohtml/Makefile.sub10
-rwxr-xr-xsrc/devices/grohtml/TODO294
-rwxr-xr-xsrc/devices/grohtml/design.ms129
-rw-r--r--src/devices/grohtml/grohtml.man179
-rwxr-xr-xsrc/devices/grohtml/html.cc6505
-rw-r--r--src/devices/grohtml/html.h57
-rwxr-xr-xsrc/devices/grohtml/html_chars.h27
-rwxr-xr-xsrc/devices/grohtml/ordered_list.h193
-rw-r--r--src/devices/grohtml/output.cc257
-rw-r--r--src/devices/grolj4/Makefile.sub6
-rw-r--r--src/devices/grolj4/grolj4.man119
-rw-r--r--src/devices/grolj4/lj4.cc695
-rw-r--r--src/devices/grops/Makefile.sub12
-rw-r--r--src/devices/grops/TODO29
-rw-r--r--src/devices/grops/grops.man835
-rw-r--r--src/devices/grops/ps.cc1532
-rw-r--r--src/devices/grops/ps.h122
-rw-r--r--src/devices/grops/psfig.diff106
-rw-r--r--src/devices/grops/psrm.cc1103
-rw-r--r--src/devices/grotty/Makefile.sub6
-rw-r--r--src/devices/grotty/TODO3
-rw-r--r--src/devices/grotty/grotty.man234
-rw-r--r--src/devices/grotty/tty.cc474
-rw-r--r--src/include/Makefile.sub22
-rw-r--r--src/include/assert.h39
-rw-r--r--src/include/cmap.h56
-rw-r--r--src/include/cset.h75
-rw-r--r--src/include/device.h21
-rw-r--r--src/include/driver.h36
-rw-r--r--src/include/errarg.h46
-rw-r--r--src/include/error.h58
-rw-r--r--src/include/font.h116
-rw-r--r--src/include/index.h42
-rw-r--r--src/include/lib.h129
-rw-r--r--src/include/macropath.h21
-rw-r--r--src/include/posix.h49
-rw-r--r--src/include/printer.h76
-rw-r--r--src/include/ptable.h168
-rw-r--r--src/include/refid.h35
-rw-r--r--src/include/search.h96
-rw-r--r--src/include/searchpath.h29
-rw-r--r--src/include/stringclass.h195
-rwxr-xr-xsrc/include/unix.h0
-rw-r--r--src/libs/libbib/Makefile.sub14
-rw-r--r--src/libs/libbib/common.cc38
-rw-r--r--src/libs/libbib/index.cc624
-rw-r--r--src/libs/libbib/linear.cc489
-rw-r--r--src/libs/libbib/map.c75
-rw-r--r--src/libs/libbib/search.cc131
-rw-r--r--src/libs/libdriver/Makefile.sub7
-rw-r--r--src/libs/libdriver/input.cc501
-rw-r--r--src/libs/libdriver/printer.cc263
-rw-r--r--src/libs/libgroff/Makefile.sub78
-rw-r--r--src/libs/libgroff/assert.cc34
-rw-r--r--src/libs/libgroff/change_lf.cc37
-rw-r--r--src/libs/libgroff/cmap.cc56
-rw-r--r--src/libs/libgroff/cset.cc102
-rw-r--r--src/libs/libgroff/device.cc36
-rw-r--r--src/libs/libgroff/errarg.cc118
-rw-r--r--src/libs/libgroff/error.cc137
-rw-r--r--src/libs/libgroff/fatal.cc27
-rw-r--r--src/libs/libgroff/filename.cc1
-rw-r--r--src/libs/libgroff/fmod.c28
-rw-r--r--src/libs/libgroff/font.cc938
-rw-r--r--src/libs/libgroff/fontfile.cc66
-rw-r--r--src/libs/libgroff/getcwd.c38
-rw-r--r--src/libs/libgroff/iftoa.c65
-rwxr-xr-xsrc/libs/libgroff/illegal.cc22
-rw-r--r--src/libs/libgroff/itoa.c43
-rw-r--r--src/libs/libgroff/lf.cc62
-rw-r--r--src/libs/libgroff/lineno.cc1
-rw-r--r--src/libs/libgroff/macropath.cc28
-rw-r--r--src/libs/libgroff/matherr.c45
-rw-r--r--src/libs/libgroff/nametoindex.cc118
-rw-r--r--src/libs/libgroff/new.cc67
-rw-r--r--src/libs/libgroff/prime.cc26
-rw-r--r--src/libs/libgroff/progname.cc1
-rw-r--r--src/libs/libgroff/ptable.cc52
-rw-r--r--src/libs/libgroff/putenv.c95
-rw-r--r--src/libs/libgroff/searchpath.cc117
-rw-r--r--src/libs/libgroff/strerror.c41
-rw-r--r--src/libs/libgroff/string.cc311
-rw-r--r--src/libs/libgroff/strsave.cc31
-rw-r--r--src/libs/libgroff/strtol.c131
-rw-r--r--src/libs/libgroff/tmpfile.cc99
-rw-r--r--src/preproc/eqn/Makefile.sub57
-rw-r--r--src/preproc/eqn/TODO49
-rw-r--r--src/preproc/eqn/box.cc611
-rw-r--r--src/preproc/eqn/box.h277
-rw-r--r--src/preproc/eqn/delim.cc381
-rwxr-xr-xsrc/preproc/eqn/eqn.cc1277
-rw-r--r--src/preproc/eqn/eqn.h51
-rw-r--r--src/preproc/eqn/eqn.man880
-rwxr-xr-xsrc/preproc/eqn/eqn.tab.h67
-rw-r--r--src/preproc/eqn/eqn.y331
-rw-r--r--src/preproc/eqn/lex.cc1165
-rw-r--r--src/preproc/eqn/limit.cc195
-rw-r--r--src/preproc/eqn/list.cc237
-rw-r--r--src/preproc/eqn/main.cc356
-rw-r--r--src/preproc/eqn/mark.cc121
-rw-r--r--src/preproc/eqn/neqn.sh5
-rw-r--r--src/preproc/eqn/other.cc601
-rw-r--r--src/preproc/eqn/over.cc196
-rw-r--r--src/preproc/eqn/pbox.h141
-rw-r--r--src/preproc/eqn/pile.cc293
-rw-r--r--src/preproc/eqn/script.cc221
-rw-r--r--src/preproc/eqn/special.cc115
-rw-r--r--src/preproc/eqn/sqrt.cc179
-rw-r--r--src/preproc/eqn/text.cc528
-rw-r--r--src/preproc/pic/Makefile.sub31
-rw-r--r--src/preproc/pic/TODO37
-rw-r--r--src/preproc/pic/common.cc497
-rw-r--r--src/preproc/pic/common.h70
-rwxr-xr-xsrc/preproc/pic/depend21
-rw-r--r--src/preproc/pic/lex.cc1939
-rw-r--r--src/preproc/pic/main.cc624
-rw-r--r--src/preproc/pic/object.cc1833
-rw-r--r--src/preproc/pic/object.h217
-rw-r--r--src/preproc/pic/output.h79
-rwxr-xr-xsrc/preproc/pic/pic.cc5220
-rw-r--r--src/preproc/pic/pic.h104
-rw-r--r--src/preproc/pic/pic.man762
-rwxr-xr-xsrc/preproc/pic/pic.tab.h130
-rw-r--r--src/preproc/pic/pic.y1803
-rw-r--r--src/preproc/pic/position.h47
-rw-r--r--src/preproc/pic/tex.cc412
-rw-r--r--src/preproc/pic/text.h28
-rw-r--r--src/preproc/pic/troff.cc502
-rw-r--r--src/preproc/refer/Makefile.sub23
-rw-r--r--src/preproc/refer/TODO124
-rw-r--r--src/preproc/refer/command.cc807
-rw-r--r--src/preproc/refer/command.h36
-rwxr-xr-xsrc/preproc/refer/label.cc1602
-rw-r--r--src/preproc/refer/label.y1177
-rw-r--r--src/preproc/refer/ref.cc1160
-rw-r--r--src/preproc/refer/ref.h120
-rw-r--r--src/preproc/refer/refer.cc1228
-rw-r--r--src/preproc/refer/refer.h78
-rw-r--r--src/preproc/refer/refer.man1299
-rw-r--r--src/preproc/refer/token.cc378
-rw-r--r--src/preproc/refer/token.h88
-rw-r--r--src/preproc/soelim/Makefile.sub6
-rw-r--r--src/preproc/soelim/TODO1
-rw-r--r--src/preproc/soelim/soelim.cc337
-rw-r--r--src/preproc/soelim/soelim.man72
-rw-r--r--src/preproc/tbl/Makefile.sub12
-rw-r--r--src/preproc/tbl/main.cc1513
-rw-r--r--src/preproc/tbl/table.cc2778
-rw-r--r--src/preproc/tbl/table.h152
-rw-r--r--src/preproc/tbl/tbl.man178
-rw-r--r--src/roff/groff/Makefile.sub8
-rw-r--r--src/roff/groff/groff.cc619
-rw-r--r--src/roff/groff/groff.man432
-rw-r--r--src/roff/groff/pipeline.c239
-rw-r--r--src/roff/groff/pipeline.h30
-rw-r--r--src/roff/grog/Makefile.sub22
-rw-r--r--src/roff/grog/grog.man72
-rw-r--r--src/roff/grog/grog.pl149
-rw-r--r--src/roff/grog/grog.sh78
-rw-r--r--src/roff/nroff/Makefile.sub18
-rw-r--r--src/roff/nroff/nroff.man95
-rw-r--r--src/roff/nroff/nroff.sh83
-rw-r--r--src/roff/troff/Makefile.sub57
-rw-r--r--src/roff/troff/TODO139
-rw-r--r--src/roff/troff/charinfo.h171
-rw-r--r--src/roff/troff/column.cc732
-rw-r--r--src/roff/troff/dictionary.cc212
-rw-r--r--src/roff/troff/dictionary.h92
-rw-r--r--src/roff/troff/div.cc1129
-rw-r--r--src/roff/troff/div.h150
-rw-r--r--src/roff/troff/env.cc3114
-rw-r--r--src/roff/troff/env.h333
-rw-r--r--src/roff/troff/hvunits.h340
-rwxr-xr-xsrc/roff/troff/hyphen.us4449
-rw-r--r--src/roff/troff/input.cc6323
-rw-r--r--src/roff/troff/node.cc4896
-rw-r--r--src/roff/troff/node.h495
-rw-r--r--src/roff/troff/number.cc669
-rw-r--r--src/roff/troff/reg.cc458
-rw-r--r--src/roff/troff/reg.h73
-rw-r--r--src/roff/troff/request.h81
-rw-r--r--src/roff/troff/symbol.cc150
-rw-r--r--src/roff/troff/symbol.h73
-rw-r--r--src/roff/troff/token.h201
-rw-r--r--src/roff/troff/troff.h83
-rw-r--r--src/roff/troff/troff.man2102
-rw-r--r--src/utils/addftinfo/Makefile.sub11
-rw-r--r--src/utils/addftinfo/addftinfo.cc196
-rw-r--r--src/utils/addftinfo/addftinfo.man102
-rw-r--r--src/utils/addftinfo/guess.cc490
-rw-r--r--src/utils/addftinfo/guess.h44
-rw-r--r--src/utils/afmtodit/Makefile.sub21
-rw-r--r--src/utils/afmtodit/afmtodit.man221
-rw-r--r--src/utils/afmtodit/afmtodit.pl326
-rw-r--r--src/utils/hpftodit/Makefile.sub6
-rw-r--r--src/utils/hpftodit/hpftodit.cc779
-rw-r--r--src/utils/hpftodit/hpftodit.man151
-rw-r--r--src/utils/indxbib/Makefile.sub30
-rwxr-xr-xsrc/utils/indxbib/dirnamemax.c49
-rw-r--r--src/utils/indxbib/eign133
-rw-r--r--src/utils/indxbib/indxbib.cc744
-rw-r--r--src/utils/indxbib/indxbib.man204
-rw-r--r--src/utils/indxbib/signal.c63
-rw-r--r--src/utils/lkbib/Makefile.sub6
-rw-r--r--src/utils/lkbib/lkbib.cc124
-rw-r--r--src/utils/lkbib/lkbib.man107
-rw-r--r--src/utils/lookbib/Makefile.sub7
-rw-r--r--src/utils/lookbib/lookbib.cc128
-rw-r--r--src/utils/lookbib/lookbib.man75
-rw-r--r--src/utils/pfbtops/Makefile.sub6
-rw-r--r--src/utils/pfbtops/pfbtops.c112
-rw-r--r--src/utils/pfbtops/pfbtops.man44
-rw-r--r--src/utils/tfmtodit/Makefile.sub6
-rw-r--r--src/utils/tfmtodit/tfmtodit.cc851
-rw-r--r--src/utils/tfmtodit/tfmtodit.man167
-rw-r--r--src/xditview/ChangeLog353
-rw-r--r--src/xditview/DESC9
-rw-r--r--src/xditview/Dvi.c579
-rw-r--r--src/xditview/Dvi.h46
-rw-r--r--src/xditview/DviChar.c664
-rw-r--r--src/xditview/DviChar.h37
-rw-r--r--src/xditview/DviP.h233
-rw-r--r--src/xditview/FontMap17
-rw-r--r--src/xditview/GXditview-ad.h52
-rw-r--r--src/xditview/GXditview.ad57
-rw-r--r--src/xditview/INSTALL20
-rwxr-xr-xsrc/xditview/Imakefile60
-rw-r--r--src/xditview/Menu.h46
-rw-r--r--src/xditview/README14
-rw-r--r--src/xditview/TODO17
-rw-r--r--src/xditview/XFontName.c256
-rw-r--r--src/xditview/XFontName.h45
-rw-r--r--src/xditview/ad2c62
-rw-r--r--src/xditview/device.c594
-rw-r--r--src/xditview/device.h21
-rw-r--r--src/xditview/draw.c721
-rw-r--r--src/xditview/font.c471
-rw-r--r--src/xditview/gray1.bm4
-rw-r--r--src/xditview/gray2.bm4
-rw-r--r--src/xditview/gray3.bm4
-rw-r--r--src/xditview/gray4.bm4
-rw-r--r--src/xditview/gray5.bm4
-rw-r--r--src/xditview/gray6.bm4
-rw-r--r--src/xditview/gray7.bm4
-rw-r--r--src/xditview/gray8.bm4
-rw-r--r--src/xditview/gxditview.man246
-rw-r--r--src/xditview/lex.c103
-rw-r--r--src/xditview/page.c88
-rw-r--r--src/xditview/parse.c334
-rw-r--r--src/xditview/xdit.bm14
-rw-r--r--src/xditview/xdit_mask.bm14
-rw-r--r--src/xditview/xditview.c594
-rw-r--r--src/xditview/xtotroff.c303
-rw-r--r--test-groff39
-rw-r--r--tmac/Makefile.sub87
-rw-r--r--tmac/TODO38
-rw-r--r--tmac/doc-common450
-rw-r--r--tmac/doc-ditroff281
-rw-r--r--tmac/doc-nroff225
-rw-r--r--tmac/doc-syms236
-rw-r--r--tmac/eqnrc63
-rw-r--r--tmac/fixmacros.sed6
-rw-r--r--tmac/groff_man.man171
-rwxr-xr-xtmac/groff_markup.man319
-rw-r--r--tmac/groff_mdoc.man422
-rwxr-xr-xtmac/groff_mdoc.samples.man2925
-rw-r--r--tmac/groff_me.man274
-rw-r--r--tmac/groff_ms.man235
-rwxr-xr-xtmac/groff_msafer.man59
-rw-r--r--tmac/man.local2
-rw-r--r--tmac/man.ultrix103
-rwxr-xr-xtmac/mm.diff70
-rw-r--r--tmac/strip.sed2
-rwxr-xr-xtmac/tmac.X46
-rwxr-xr-xtmac/tmac.Xps44
-rwxr-xr-xtmac/tmac.a43
-rwxr-xr-xtmac/tmac.an350
-rwxr-xr-xtmac/tmac.andoc12
-rwxr-xr-xtmac/tmac.arkup161
-rwxr-xr-xtmac/tmac.doc3427
-rwxr-xr-xtmac/tmac.dvi135
-rwxr-xr-xtmac/tmac.e1661
-rwxr-xr-xtmac/tmac.html60
-rwxr-xr-xtmac/tmac.latin1101
-rwxr-xr-xtmac/tmac.lj418
-rwxr-xr-xtmac/tmac.pic10
-rwxr-xr-xtmac/tmac.ps53
-rwxr-xr-xtmac/tmac.psatk61
-rwxr-xr-xtmac/tmac.psfig87
-rwxr-xr-xtmac/tmac.psnew26
-rwxr-xr-xtmac/tmac.psold60
-rwxr-xr-xtmac/tmac.pspic50
-rwxr-xr-xtmac/tmac.s1869
-rwxr-xr-xtmac/tmac.safer10
-rwxr-xr-xtmac/tmac.trace10
-rwxr-xr-xtmac/tmac.tty47
-rwxr-xr-xtmac/tmac.tty-char198
-rw-r--r--tmac/troffrc27
-rw-r--r--tmac/troffrc-end6
602 files changed, 230429 insertions, 0 deletions
diff --git a/BUG-REPORT b/BUG-REPORT
new file mode 100644
index 00000000..b3f325c8
--- /dev/null
+++ b/BUG-REPORT
@@ -0,0 +1,55 @@
+ Groff Bug Report
+
+Please read the PROBLEMS file before sending in a bug report.
+
+Please fill in all fields, even if you think they are not relevant.
+
+Please delete the text in brackets before sending it in.
+
+Please report separate bugs separately.
+
+Send the completed form to bug-groff@gnu.org
+
+GROFF VERSION:
+[The version of groff you are using. For example, `1.05']
+
+MACHINE:
+[The machine you are using. For example, `Sun SPARCstation 2']
+
+OS:
+[The operating system you are using. For example, `SunOS 4.1.1']
+
+COMPILER:
+[The compiler you are used to compile groff. For example, `g++ 1.40.3']
+
+INPUT FILES:
+[Include all the files necessary to reproduce the problem that are not
+part of the standard groff distribution. This includes font
+description files, DESC files and macro files (with the exception of
+the -ms and -mm macros: we have them). Send them as a shell archive
+or as a uuencoded, compressed tar file.
+
+It's easier for us if you can provide an example that doesn't depend
+on any macro package, but obviously if you're reporting a problem with
+a macro package that won't be possible. Also a short example is more
+convenient than a long one, but don't worry if you can't find a short
+example. Don't say something like ``any file that X'': Always send a
+definite example.]
+
+COMMAND LINE:
+[The command line that we should run in order to observe the bug. For
+example, `gtroff -Tps bug.tr'. If the command line uses -ms or -mm,
+say whether these refer to the groff versions or the Unix versions of
+the macros.]
+
+DESCRIPTION OF INCORRECT BEHAVIOUR:
+[What goes wrong when that command line is run? For example, `gtroff
+gets a segmentation fault', or `The output looks bad because the bar
+over the x is too long and is too far over to the left.' If you get
+an error message, include it here without modification: Don't edit it
+to make it more readable.]
+
+SUGGESTED FIX [optional]:
+[If you can suggest a fix for the problem, include a context diff
+here. But don't delay sending in a bug report in the hope of finding
+a fix. Guesses about the cause of the bug are not usually helpful.]
diff --git a/COPYING b/COPYING
new file mode 100644
index 00000000..e8a612e5
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, 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 software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, 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 redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+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 give any other recipients of the Program a copy of this License
+along with the Program.
+
+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 Program or any portion
+of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+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 Program, 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 Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) 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; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, 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 executable. 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.
+
+If distribution of executable or 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 counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program 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.
+
+ 5. 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 Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program 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.
+
+ 7. 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 Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program 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 Program.
+
+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.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program 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.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the 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 Program
+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 Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, 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
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), 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 Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. 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 program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 00000000..2889ce10
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,6497 @@
+2000-02-06 Werner LEMBERG <wl@gnu.org>
+
+ I've considerably modified the directory structure of the
+ distribution to get a more vertical layout. For example, the number
+ of top level directories has been reduced from 42 to 6.
+
+ As a consequence, many changes, especially to the makefiles, were
+ necessary:
+
+ * The makefile variables `top_builddir' and `top_srcdir' have been
+ introduced. Virtually all relative paths have been replaced with
+ absolute ones using these two variables.
+
+ * Dependencies (in the files `Makefile.dep') are no longer part of
+ the distribution. Instead, they are created during a `make install'
+ in the build directory.
+
+ * aclocal.m4 (GROFF_SRCDIR, GROFF_BUILDDIR): Two new functions to
+ make `top_srcdir' and `top_builddir' absolute.
+
+ Some other changes:
+
+ * Man pages no depend on the files `VERSION' and `REVISION'.
+
+ * The added shell script `mkinstalldirs' will replace `mkdir' in
+ almost all cases.
+
+ * VERSION: Version number increased to 1.16.
+
+2000-02-04 Werner LEMBERG <wl@gnu.org>
+
+ * grops/psrm.cc (read_one_of): Fixed pointer incrementation.
+
+ * Makefile.in: Removed $(tmac_m) since it is no longer needed
+ (after an update of the mm stuff).
+
+ * troff/Makefile.sub (majorminor.cc): Fix dependencies.
+
+2000-02-03 Werner LEMBERG <wl@gnu.org>
+
+ The .psbb request will now also accept Mac PS images (i.e. using LF
+ as the EOL character).
+
+ * troff/input.cc (ps_get_line): New function, taken from psrm.cc
+ (with slight modifications).
+ * troff/input.cc (do_ps_file): Use it.
+
+ * test-groff: Add grohtml and grolj4 output devices to PATH.
+
+2000-01-30 Werner LEMBERG <wl@gnu.org>
+
+ * NEWS, MORE.STUFF: Updated.
+
+2000-01-30 Cary D. Renzema <caryr@dollar.mxim.com>
+
+ Add the `srand' command to pic.
+
+ * pic/lex.cc, pic/pic.y: Implement it.
+ * pic/pic.man: Document it.
+ * pic/pic.cc, pic/pic.tab.h: Regenerated (with yacc).
+
+2000-01-30 Werner LEMBERG <wl@gnu.org>
+
+ Add a new request `.psbb'. This does exactly what the external
+ program psbb did. It scans a PostScript image file for a
+ %%BoundingBox comment and extracts the bounding box values (in
+ PostScript units) which are then stored in the four new (read-only)
+ number registers `llx', `lly', `urx', and `ury'.
+
+ This will allow the usage of the .PSPIC macro without worrying
+ about unsafe behaviour of groff, i.e., it will work without the
+ `-U' switch of groff.
+
+ * troff/input.cc: Implement it.
+ * tmac/tmac.pspic: Use it.
+ * troff/troff.man, grops/grops.man, NEWS: Document it.
+ * psbb/*, Makefile.in: Remove it since it is no longer needed.
+
+ This is bloody C code simply adapted from psbb.c! Any improvements
+ welcome.
+
+2000-01-29 Werner LEMBERG <wl@gnu.org>
+
+ * man/groff_font.man: Minor clarifications.
+
+ * NEWS: Updated.
+
+2000-01-28 Werner LEMBERG <wl@gnu.org>
+
+ * afmtodit/afmtodit.pl: Use new `--' comment delimiter.
+
+2000-01-28 Gaius Mulley <gaius@glam.ac.uk>
+
+ * man/groff_font.man: Brought up to date regarding tcommand
+ extensions.
+ * libgroff/font.cc: Handle everything after `--' as a comment
+ in the font files.
+ * devps/*: Added comment delimiter inside devps font files.
+
+2000-01-28 Werner LEMBERG <wl@gnu.org>
+
+ * tmac/tmac.arkup, tmac/groff_markup.man: Replace \fC...\fR with
+ \fC...\fP (which now works as expected).
+
+ * troff/troff.man: Fix typo.
+
+2000-01-27 Gaius Mulley <gaius@glam.ac.uk>
+
+ Completed the pass_filenames implementation in troff.
+
+ * libdriver/input.cc: Will read the new `F' tcommand.
+ * troff/node.cc, troff/node.h: Will issue the new `F' tcommand.
+ * troff/input.cc: Use it.
+
+2000-01-26 Werner LEMBERG <wl@gnu.org>
+
+ * troff/env.cc (set_font): Fix the behaviour of \fP. The previous
+ font will now be updated even if an invalid font is selected.
+
+2000-01-24 Werner LEMBERG <wl@gnu.org>
+
+ * doc/homepage.ms: Updated for new tmac.arkup.
+
+ * tmac/tmac.html: Disable line breaks after hyphen-like characters.
+
+ * tmac/tmac.arkup: Cleanup.
+
+ Added `\&' to .HTML macro to `leave vertical mode', so to say.
+
+ Removed obsolete .LINK macro completely.
+
+ The macros .URL, .FTP, and .MAILTO now accept a third argument which
+ will be immediately appended to the second argument (to be used with
+ punctuation, for example).
+
+ Disabled .CDFTP macro temporarily for security reasons.
+
+ * tmac/groff_markup.man: Complete revision for latest changes in
+ tmac.arkup -- note that it does not yet format correctly with
+ grohtml :-(
+
+2000-01-23 Bruno Haible <haible@clisp.cons.org>
+
+ * nroff/nroff.sh: Accept -Tutf8 option and pass it through.
+ * devutf8/R.proto: Add mappings for wp, lh, rh.
+ * devutf8/NOTES: Updated.
+
+2000-01-23 Werner LEMBERG <wl@gnu.org>
+
+ * doc/groff.texinfo: Updated version/copyright info.
+
+2000-01-21 Gaius Mulley <gaius@glam.ac.uk>
+
+ Added support for two new directives in device descriptions:
+ `pass_filenames' (to pass the input file name to the output device)
+ and `use_charnames_in_special' (to support e.g. accented characters
+ in the `X' request).
+
+ * include/font.h, troff/charinfo.h: Declare it.
+
+ * libgroff/font.cc, libgroff/fontfile.cc: Set it.
+
+ * devhtml/DESC: Use it.
+
+ * troff/input.cc: New function encoded_char.
+
+ * troff/token.h: Add test for `specialness'.
+
+2000-01-21 Werner LEMBERG <wl@gnu.org>
+
+ * tmac/Makefile.sub: tmac.a4 and tmac.trace have been removed by
+ mistake from the list of files to be installed.
+
+2000-01-18 Werner LEMBERG <wl@gnu.org>
+
+ * README: Added info how to apply patches.
+
+2000-01-15 Jan Echternach <echter@informatik.uni-rostock.de>
+
+ * troff/node.cc (ligature_note::operator delete): Fix g++ warning.
+
+2000-01-15 Gaius Mulley <gaius@glam.ac.uk>
+
+ * troff/input.cc: Add support for troffrc-end.
+
+ * tbl/main.cc: Altered to issue table-start and table-end special
+ characters if using the html device.
+
+ * devhtml/*: Modified font files to incorporate html encoding of
+ characters.
+
+ * tmac/groff_markup.man: New file documenting tmac.arkup.
+
+ * tmac/troffrc-end: New file. This is invoked after all user
+ specified macros. Currently used by the html device to include
+ tmac.html. Thus no need for users to specify -mhtml anymore.
+
+ * tmac/Makefile.sub (NORMALFILES): Add troffrc-end.
+ (MAN7): Add groff_markup.man.
+
+ * tmac/tmac.an, tmac/tmac.html: Small html updates.
+
+ * tmac/troffrc: tmac.arkup will now be called for the html device.
+
+ * libgroff/font.cc, libgroff/font.h: Altered to include reading of
+ extra device specific information about fonts.
+
+ * doc/homepage.ms: New file. It is an example how an HTML home page
+ could look like with grohtml.
+
+ * doc/Makefile: Add homepage.ms. Remove rule for pic.html.
+
+2000-01-12 Bruno Haible <haible@clisp.cons.org>
+
+ * devutf8/R.proto: Add mappings for ti, Fn, st, an. Change mappings
+ of Im, Re.
+
+ * devutf8/NOTES: Updated.
+
+2000-01-08 Bruno Haible <haible@clisp.cons.org>
+
+ * eqn/box.cc, eqn/lex.cc, eqn/other.cc, eqn/over.cc, eqn/special.cc,
+ eqn/text.cc, grodvi/dvi.cc, grops/ps.cc, grops/psrm.cc,
+ libbib/index.cc, libbib/linear.cc, libbib/search.cc,
+ libdriver/printer.cc, libgroff/font.cc, libgroff/string.cc,
+ pic/lex.cc, pic/object.cc, refer/label.y, refer/ref.cc, tbl/main.cc,
+ tbl/table.cc, tfmtodit/tfmtodit.cc, troff/dictionary.cc,
+ troff/div.cc, troff/env.cc, troff/input.cc, troff/node.cc,
+ troff/node.h, troff/reg.cc: Avoid most "g++ -Wall -Wno-sign-compare"
+ warnings.
+
+ * troff/node.cc (bracket_node::copy): Initialize last to NULL.
+
+2000-01-12 Fabrizio Polacco <fab@prosa.it>
+
+ grolj4: Paper size will be searched case-insensitively.
+
+ * grolj4/lib.h: Add check for strcasecmp().
+ * grolj4/li4.cc (lookup_paper_size): Use strcasecmp().
+ * configure.in: Check for strcasecmp().
+
+2000-01-11 Werner LEMBERG <wl@gnu.org>
+
+ * troff/Makefile.sub (majorminor.cc): Fix incorrect path to
+ `REVISION'.
+
+2000-01-10 Werner LEMBERG <wl@gnu.org>
+
+ * Makefile.comm, Makefile.in, doc/Makefile: More fixes for the
+ revision scheme.
+
+ Add a new read-only register, `.Y', which contains the groff
+ revision.
+
+ * troff/input.cc (init_input_requests): Define it.
+ * troff/Makefile.sub (majorminor.cc): Define `revision' string.
+ * doc/groff.texinfo, troff/troff.man: Document it.
+
+ * libgroff/Makefile.sub (version.cc): Add definition of
+ `Version_string[]', consisting of `<major>.<minor>.<revision>'
+ * eqn/main.cc, grodvi/dvi.cc, grolj4/lj4.cc, grops/ps.cc,
+ grotty/tty.cc, hpftodit/hpftodit.cc, indxbib/indxbib.cc, pic/main.cc,
+ refer/refer.cc, soelim/soelim.cc, tbl/main.cc, tfmtodit/tfmtodit.cc,
+ troff/input.cc, pfbtops/pfbtops.c: Use it.
+
+2000-01-10 Fabrizio Polacco <fab@prosa.it>
+
+ Add a revision scheme to the groff package.
+
+ * REVISION: New file.
+ * libgroff/Makefile.sub (version.cc): Use it to define
+ `revision_string[]'.
+ * grops/psrm.cc: Use revision_string (converted to an unsigned
+ integer) in constructor of resource_manager.
+
+2000-01-10 Bruno Haible <haible@clisp.cons.org>
+
+ * devutf8/Makefile.sub, devutf8/DESC.proto, devutf8/R.proto: New
+ files.
+ * Makefile.in (DEVDIRS): Add devutf8.
+ * grotty/tty.cc: Include device.h.
+ (glyph): Change type of `code' to `unsigned int'.
+ (tty_printer): New field is_utf8. Constructor takes device argument.
+ (tty_printer::tty_printer): If device if `utf8', set is_utf8.
+ (tty_printer::add_char): Change type of first arg to `unsigned int'.
+ (tty_printer::put_char): New function.
+ (tty_printer::end_page): Use put_char() instead of ::putchar().
+ (make_printer): Pass device to tty_printer constructor.
+ * nroff.sh: Determine default device by calling 'locale'. As a
+ fallback, look at all of $LC_ALL, $LC_CTYPE, $LANG, $LESSCHARSET.
+ Recognize UTF-8 locales.
+ * tmac/eqnrc: Recognize utf8 like latin1.
+ * tmac/troffrc: Device utf8 needs tmac.tty.
+
+2000-01-07 Werner LEMBERG <wl@gnu.org>
+
+ * tmac/Makefile.sub: tmac.a4 and tmac.trace will now be installed.
+
+2000-01-07 Paul Eggert <eggert@twinsun.com>
+
+ Add a new predefined writeable number register, `year',
+ which contains the current year.
+
+ * doc/groff.texinfo, PROBLEMS, troff/troff.man: Document it.
+ * tmac/tmac.s: Use it.
+ * troff/input.cc (init_registers): Initialize it.
+
+2000-01-06 Werner LEMBERG <wl@gnu.org>
+
+ * PROBLEMS: Fixed typo.
+
+2000-01-04 Paul Eggert <eggert@twinsun.com>
+
+ * PROBLEMS: Add Y2k advice for the yr number register.
+
+2000-01-03 Paul Eggert <eggert@twinsun.com>
+
+ * doc/groff.texinfo: Fix Y2k bug in documentation of \n(yr.
+
+2000-01-02 Werner LEMBERG <wl@gnu.org>
+
+ * tmac/tmac.arkup: Slight modification of macros to provide better
+ appearance for non-HTML formats.
+
+2000-01-01 Charles Levert <charles@comm.polymtl.ca>
+
+ * soelim/soelim.cc (include_path_append): realloc(NULL, n)
+ does not automatically translate to malloc(n) on all OSes
+ (e.g., SunOS) so do it explicitly. Also, check the returned
+ value.
+
+2000-01-01 Werner LEMBERG <wl@gnu.org>
+
+ * tmac/tmac.arkup: Added .LINE macro. Some formatting.
+
+ * Makefile.in: Added $(tmac_m) again since the Makefile in `mm'
+ expects this variable
+
+2000-01-01 Gaius Mulley <gaius@glam.ac.uk>
+
+ * doc/Makefile: Added instructions to create HTML and text
+ versions of some files.
+
+1999-12-31 Werner LEMBERG <wl@gnu.org>
+
+ * Updated INSTALL.gen.
+
+ * tmac/tmac.arkup: Added fixes so that .FTP and .MAILTO works
+ better resp. correctly with non-HTML devices.
+
+Version 1.15 released
+=====================
+
+1999-12-28 Werner LEMBERG <wl@gnu.org>
+
+ * NEWS, VERSION: Changed to 1.15
+
+1999-12-27 Paul Eggert <eggert@twinsun.com>
+
+ * nroff/nroff.man: -S is safer, not safe.
+
+ * groff/groff.cc (main): Use `safer', not `safe', in variable
+ names. This does not change the behavior.
+
+ * troff/input.cc (main): Likewise.
+
+ * nroff/nroff.sh: Likewise.
+
+ * troff/input.cc (prepend_string): New function.
+ (main): Prepend -msafer, so that we check macro libraries for
+ safety.
+
+ * PROBLEMS: Report problem with Sun C++ 5.0 and 5.1.
+
+Version 1.14 released
+=====================
+
+1999-12-26 Werner LEMBERG <wl@gnu.org>
+
+ * NEWS, VERSION: Changed to 1.14.
+
+1999-12-24 Werner LEMBERG <wl@gnu.org>
+
+ * refer/refer.cc: Fixing the last fix.
+
+Version 1.13 released
+=====================
+
+1999-12-23 Werner LEMBERG <wl@gnu.org>
+
+ * tmac/tmac.an: A typo (`.if' instead of `.ie') made the page
+ number disappear.
+
+ * NEWS: Updated.
+
+ * tmac/tmac.safer: Forgot to remove `so' from the `rm' request.
+
+ * VERSION: Changed to 1.13 -- to be compliant with the Adobe 3.0
+ document conventions, the version number must be a real.
+
+Version 1.12.1 released
+=======================
+
+1999-12-22 Werner LEMBERG <wl@gnu.org>
+
+ * VERSION: Changed to 1.12.1.
+
+1999-12-22 Alan Rooks <arooks@istar.ca>
+
+ * refer/refer.cc (do_file): Slight modification to satisfy the
+ `Standard system CC - C++ Compilation System 3.1 03/03/99' on SCO
+ UnixWare 7.1.
+
+1999-12-20 Werner LEMBERG <wl@gnu.org>
+
+ * changed prep.ai.mit.edu -> ftp.gnu.org; updated copyright
+ notices.
+
+ * tmac/tmac.safer, tmac/groff_msafer.man: Remove `so' (again) from
+ list of unsafe requests.
+
+ * pic/pic.man: Fixed a typo.
+
+ * man/groff_out.man: Fixed a typo.
+
+1999-12-18 Werner LEMBERG <wl@gnu.org>
+
+ * Makefile.in: Doc fixes.
+
+1999-12-17 Fabrizio Polacco <fab@prosa.it>
+
+ * groff/groff.cc: Missing `U' option added to getopt().
+
+ * troff/troff.man: Missing `U' option added to synopsis.
+
+Version 1.12 released
+=====================
+
+1999-12-14 Werner LEMBERG <wl@gnu.org>
+
+ * troff/input.cc (usage), groff/groff.cc (synopsis): Added -U flag
+ to the synopsis.
+
+ * nroff/nroff.sh, nroff/nroff.man: Replaced `secure', `unsecure'
+ with the more appropriate terms `safer' and `unsafe'.
+
+ * libgroff/strerror.c, aclocal.m4, configure.in: Added checks for
+ sys_nerr and sys_errlist[].
+
+ * pic/pic.h, aclocal.m4, configure.in: Added check for hypot().
+
+ * pic/pic.y, pic/pic.cc: Added check for fmod().
+
+1999-12-13 Werner LEMBERG <wl@gnu.org>
+
+ * VERSION: Changed to 1.12.
+
+ Here some patches from various sources; most of them taken from
+ the Debian distribution.
+
+ * tmac/groff_mdoc.man, tmac/groff_mdoc.samples.man,
+ tmac/Makefile.sub: New files copied directly from the NetBSD
+ distribution. Probably, some additional adaptation later on is
+ necessary...
+
+ * tmac/tmac.safer, tmac/groff_msafer.man: Added `so' to the list
+ of unsafe requests.
+
+ * groff/groff.cc, groff/groff.man, nroff/nroff.sh,
+ nroff/nroff.man, pic/main.cc, pic/pic.man, troff/input.cc,
+ troff/troff.man: Added option `-U' for unsafe mode. Safe mode
+ (`-S') is now the default.
+
+ * README, NEWS: Updated.
+
+1999-12-09 Werner LEMBERG <wl@gnu.org>
+
+ * doc/groff.texinfo: Regenerated nodes and menus with emacs.
+
+ * doc/Makefile (clean): Added cleaning commands for groff.texinfo.
+
+1999-12-06 Werner LEMBERG <wl@gnu.org>
+
+ * configure.in: Removed AC_PREFIX_PROGRAM since it causes more
+ grief than relief today. Additionally, it is against the GNU
+ coding standards.
+
+ * configure: Recreated.
+
+1999-12-05 Werner LEMBERG <wl@gnu.org>
+
+ * configure.in: Added GROFF_LIBM.
+
+ * configure: Recreated.
+
+ * aclocal.m4 (GROFF_LIBM): New function which tests whether -lm is
+ necessary.
+
+ * Makefile.in: Added definition of $(LIBM).
+
+ * Makefile.comm (LIBM): Removed.
+
+ * pfbtops/Makefile.sub: On AIX, -lm is needed also.
+
+1999-12-03 Gaius Mulley <gaius@glam.ac.uk>
+
+ * doc/Makefile: Added rule for generation pic.html.
+
+ (clean): Files produced by grohtml will be removed also.
+
+ * doc/pic.ms: Small fix.
+
+ * tmac/tmac.html: Fixed suppression of headers.
+
+1999-11-16 Gaius Mulley <gaius@glam.ac.uk>
+
+ * tmac/tmac.html: Fixing horizontal arrows.
+
+ Turning off hyphenation.
+
+ * tmac/tmac.an: Improved support for grohtml; better indentation,
+ no footers/headers.
+
+1999-10-31 Gaius Mulley <gaius@glam.ac.uk>
+
+ * tmac/tmac.arkup: Added CDFTP macro
+
+ * tmac/tmac.html: All headers are turned off for ms, me, and mm
+ macros.
+
+ * tmac/troffrc: Some additions for HTML stuff.
+
+1999-10-06 Gaius Mulley <gaius@glam.ac.uk>
+
+ * tmac/tmac.html: Small changes.
+
+1999-09-26 Werner LEMBERG <wl@gnu.org>
+
+ * doc/groff.texinfo: Minor fixes.
+
+1999-09-26 Gaius Mulley <gaius@glam.ac.uk>
+
+ * devhtml/TR: Changed spacewidth to 3.
+
+ * tmac/Makefile.sub (NORMALFILES): Added tmac.arkup.
+
+ * tmac/tmac.html: Moved markup macros to tmap.arkup.
+
+ * tmac/tmac.arkup: New file.
+
+ * grohtml/ChangeLog: New file.
+
+1999-09-16 Werner LEMBERG <wl@gnu.org>
+
+ * doc/groff.texinfo (Common Features): Added Copying chapter.
+ Changed format to @smallbook.
+
+1999-09-15 Werner LEMBERG <wl@gnu.org>
+
+ * NEWS: Added info about groff.texinfo.
+
+ * doc/groff.texinfo: Will now compile (using texi2dvi) without
+ warning messages.
+
+1999-09-14 Werner LEMBERG <wl@gnu.org>
+
+ * groff/groff.man: More updates.
+
+1999-09-13 Werner LEMBERG <wl@gnu.org>
+
+ * doc/groff.texinfo: New file. This manual is still very
+ rudimentary. It has been originally contributed by Trent
+ A. Fisher <trent@gnurd.portland.or.us> with first corrections and
+ additions by me.
+
+ * INSTALL: Added information about the `doc' subdir
+
+ * troff/troff.man: Minor fixes.
+
+ * groff/groff.man: Added missing `-L arg' to SYNOPSIS section;
+ reordered options.
+
+ * troff/input.cc (usage): Added missing `-ffam' to usage message.
+
+ * Makefile.in (dist): groff-$(version).tar.gz must be removed
+ also, otherwise it is included itself in another call of `make
+ dist'.
+
+ * groff/groff.cc (synopsis): Removed superfluous space.
+
+ * PROJECTS, PROBLEMS, NEWS: Updated.
+
+ * xditview/Makefile: Removed.
+
+ * VERSION: Updated to 1.12beta.
+
+ * BUG-REPORT: Some cosmetic fixes. Corrected email address.
+
+ * README: Updated: Included documentation about CVS repository,
+ mailing lists, and daily snapshots.
+
+ * tmac/Makefile.sub: Fixed $(tmap_wrap) finally.
+
+1999-09-12 Bjarni Ingi Gislason <bjarniig@rhi.hi.is>
+
+ * tmac/tmac.an: If the tag didn't fit into the space that the
+ macro `TP' specifies, the rest of the tag went into the space for
+ the next line.
+
+1999-09-12 Jeffrey Copeland <jeff@opennt.com>
+
+ * grolj4/lj4.cc: Added duplex printing (option `-d').
+
+ * grolj4/grolj4.man: Document duplex printing.
+
+1999-09-12 Werner LEMBERG <wl@gnu.org>
+
+ * doc/Makefile (pic.ps): Fixed rule which caused problems with
+ non-GNUish sed programs.
+
+ * tmac/doc-syms: Removed extra space from -iso8802-3 macro
+ definition.
+
+ * configure.in (LIBS): Added `-lc'
+
+ * Makefile.comm (.man.n): Added substitution for @TMAC_AN_PREFIX@.
+
+ * pic/tex.cc (solid_arc): Casting M_PI to double.
+
+ * libgroff/putenv.c (putenv): Changed function header to ANSI C.
+
+ * groff/groff.man, tmac/Makefile.sub (MAN7), tmac/groff_msafer.man
+ (new file), tmac/msafer.man (deleted), tmac/groff_me.man (new
+ file), tmac/me.man (deleted): {me,msafer} -> groff_{me,msafer}.
+
+ * groff/groff_man.man: New file. This manual page was originally
+ written for the Debian GNU/Linux system by Susan G. Kleinmann
+ <sgk@debian.org>.
+
+ * eqn/list.cc (list_box::compute_metrics,
+ list_box::compute_sublist_width): Removed variable declaration to
+ avoid shadowing warnings.
+
+ * grops/psrm.cc (resource_manager::process_file): Ditto.
+
+ * tfmtodit/tfmtodit.cc (main): Ditto.
+
+ * libgroff/font.cc (font::load_desc): Renamed auxiliary variable
+ to avoid shadowing warnings.
+
+ * tbl/table.cc (block_entry::do_divert, table::do_row): Renamed
+ shadowing loop variable.
+
+ * groff/groff.man, troff/troff.man: Added doc about grohtml.
+
+1999-09-12 Gaius Mulley <gaius@glam.ac.uk>
+
+ New grohtml frontend to convert groff input to html.
+
+ * Makefile.in (CCPROGDIRS, DEVDIRS): Added html device.
+
+ * tmac/Makefile.sub (NORMALFILES): Added tmac.html.
+
+ * tmac/eqnrc: Added html device.
+
+ * tmac/tmac.html: New file.
+
+ * eqn/main.cc (do_file, inline_equation), pic/troff.cc
+ (troff_output::start_picture, troff_output::finish_picture),
+ tbl/main.cc (process_input_file):
+ Surrounded output with `graphics_start' and `graphics_end' so that
+ the html driver can identify non-text portions.
+
+ * grodvi/dvi.cc (dvi_printer::set_char), grolj4/lj4.cc
+ (lj4_printer::set_char), grops/ps.cc (ps_printer::set_char),
+ grotty/tty.ps (tty_printer::set_char): Additional parameter
+ `name'.
+
+ * include/printer.h: Class printer: New function
+ set_char_and_width; new variables (is_char_named, is_named_set,
+ named_command, named_char_s, named_char_n) to hold information
+ about named characters -- needed by the html driver.
+
+ * libdriver/printer.cc (printer::set_ascii_char,
+ printer::set_special_char): Use set_char_and_width.
+
+ * devhtml/*: New device files for html driver.
+
+ * grohtml/*: New driver grohtml.
+
+1999-09-11 Wilfredo Sanchez <wsanchez@apple.com>
+
+ * tmac/doc-common, tmac/tmac.an: Removed the word `UNIX' in
+ default strings.
+
+1999-09-11 Luke Mewburn <lukem@netbsd.org>
+
+ * libgroff/string.cc (search): Small fix to test against NULL
+ pointer.
+
+1999-09-11 Jeff Conrad <jeff_conrad@msn.com>
+
+ * troff/node.cc (copy): The characters in a bracket escape (e.g.,
+ \b'abc') were stacked in reverse order when processed in a
+ diversion.
+
+ * troff/node.h: Added `*last' to struct `node' to make the above
+ fix work.
+
+ * troff/input.cc (read_draw_node), libdriver/input.cc (do_file):
+ The default scale for the 'f' and 't' graphics functions were 'm'
+ rather than 'u' (i.e., no scaling).
+
+1999-09-11 Peter Miller <peterm@jna.com.au>
+
+ * groff/groff.cc (main), groff.man, soelim/soelim.cc (main,
+ do_file), soelim/soelim.man: Added `-I file' option to soelim,
+ defining include paths.
+
+ * soelim/soelim.cc (include_path_append): New function.
+
+1999-09-11 Larry Jones <larry.jones@sdrc.com>
+
+ * tbl/main.cc (process_options): Unix (at least Documenter's
+ Workbench) tbl allows arbitrary non-alpha characters between
+ options.
+
+1999-09-11 Paul Eggert <eggert@twinsun.com>
+
+ Y2k fixes. Don't assume that the current year precedes 2000.
+
+ * doc/meref.me: Add \n(y2, \n(y4.
+
+ * tmac/doc-common (Yr): New number register.
+ (Dd): Don't assume current year precedes 2000.
+
+ * tmac/tmac.e (td): Likewise.
+ (y2, y4): New number registers.
+
+ * pic/pic.man: Update reference for pic paper to May, 1991
+ version.
+
+1999-09-11 Werner LEMBERG <wl@gnu.org>
+
+ * tmac/Makefile.sub (install_data, stamp-wrap, uninstall_sub):
+ Removed quotation marks which prevented correct expansion of
+ $(tmac_wrap).
+
+ * devlj4/Makefile.sub (LJ4RES): Fixed value (600 instead of 300).
+
+1999-09-10 Werner LEMBERG <wl@gnu.org>
+
+ * Makefile.sub (DISTCLEANFILES): Added `config.log' and
+ `config.cache'.
+
+ * Removed configure.old.
+
+1999-08-31 Werner LEMBERG <wl@gnu.org>
+
+ * VERSION: Updated to 1.11.1
+
+1999-05-27 Werner LEMBERG <wl@gnu.org>
+
+ * doc/Makefile: changed `.PS' postfix to `.ps' for consistency.
+
+ * tmac/Makefile.sub (install_data, stamp-wrap, uninstall_sub):
+ added quotations around $(tmac_wrap) to avoid syntax error if
+ variable is empty.
+
+ * configure: Newly generated using autoconf 2.13.
+
+ * Makefile.in (LDFLAGS): Set variable to @LDFLAGS@.
+
+Fri Aug 15 08:51:47 1997 Eric S. Raymond <esr@snark.thyrsus.com>
+
+ * README, PROJECTS, NEWS, INSTALL, VERSION,
+ doc/Makefile. doc/pic.ms, groff/groff.man:
+ Prepare for 1.11 release. No code changes.
+ Documentation for pic added (doc/pic.ms).
+
+Sun Nov 26 11:45:13 1995 James Clark <jjc@jclark.com>
+
+ * Version 1.10 released.
+
+Fri Nov 24 09:56:16 1995 James Clark <jjc@jclark.com>
+
+ * afmtodit/afmtodit.pl: Avoid comment on first line.
+
+Mon Nov 20 11:13:49 1995 James Clark <jjc@jclark.com>
+
+ * aclocal.m4 (GROFF_INSTALL_SH): New macro.
+ * configure.in: Call it.
+
+ * Makefile.sub (configure): Depends on aclocal.m4 not acgroff.m4.
+ (distfiles): Doesn't depend on config.log or config.cache.
+
+Sun Oct 1 08:45:36 1995 James Clark <jjc@jclark.com>
+
+ * grog/grog.sh: Use print "" rather than print in END rule.
+
+Wed Aug 23 13:30:52 1995 James Clark <jjc@jclark.com>
+
+ * tbl/main.cc (process_data): Don't give error for excess data
+ entries that are comments.
+
+Fri Jul 28 11:00:27 1995 James Clark <jjc@jclark.com>
+
+ * tbl/main.cc (process_data): Fix case where new for-scope rules
+ silently change meaning of code.
+
+Tue Jul 4 23:39:51 1995 James Clark <jjc@jclark.com>
+
+ * troff/env.cc (hyphenate): Loop over all consecutive sequences
+ of non-zero hyphenation codes.
+
+Sat Jul 1 00:42:15 1995 James Clark <jjc@jclark.com>
+
+ * aclocal.m4 (GROFF_POSIX): Use conflicting declaration technique.
+
+Thu Jun 29 13:58:36 1995 James Clark <jjc@jclark.com>
+
+ * tmac/tmac.e (ip): Divert the tag so as to freeze the spaces.
+
+Tue Jun 27 12:30:16 1995 James Clark <jjc@jclark.com>
+
+ * tmac/tmac.andoc: Make it work in compatibility mode.
+
+ * refer/token.h (token_info::is_range_sep): New function.
+ * refer/token.cc (init_special_chars): Make \(en a RANGE_SEP.
+ * refer/ref.cc (reference::output): More sophisticated check for
+ multiple pages.
+
+ * devps/prologue.ps (MANUAL): New procedure.
+ * grops/ps.cc (main): New -m option.
+ (usage): Include -m.
+ (ps_printer::~ps_printer): Implement -m.
+
+ * aclocal.m4 (GROFF_G): New macro.
+ * configure.in: Call it.
+ * Makefile.in (g): Provided by configure.
+
+ * hpftodit/hpftodit.cc (basename): Rename to xbasename.
+
+ * tmac/tmac.tty: Disable warning about bad fonts. Remove font
+ translations.
+
+ * Makefile.in (tmacpath): Don't include /usr/lib/tmac.
+ (tmac_m, tmac_s): Deleted.
+ (sys_tmac_prefix, tmac_wrap, tmac_prefix, tmac_an_prefix,
+ tmac_s_prefix): New variables.
+ (MDEFINES): Change accordingly.
+ * Makefile.comm (.man.n): Use new TMAC_* variables.
+ * configure.in (GROFF_TMAC): Call.
+ * aclocal.m4 (GROFF_TMAC): Define.
+ * tmac/Makefile.sub (stamp_wrap): New target.
+ (install_data, uninstall_sub): Handle macro wrapping.
+
+Mon Jun 26 14:54:39 1995 James Clark <jjc@jclark.com>
+
+ * tbl/main.cc (main): Ignore -T option.
+
+Thu Jun 22 09:08:06 1995 James Clark <jjc@jclark.com>
+
+ * devlj4/generate/special.map: Add definition of \(nb.
+
+ * tmac/tmac.dvi: Add definition of \(nb.
+
+ * troff/dictionary.c (dictionary::dictionary): association::v gets
+ initialized by association::association.
+
+ * tmac/Makefile.sub: Avoid using temporary files when installing.
+
+ * troff/env.cc (environment::set_font): Make bad font number a
+ warning.
+
+ * Makefile.in (fontpath): Remove $(prefix)/lib/font from fontpath.
+
+ * Makefile.in (datadir): Use share rather than lib.
+
+ * groff/groff.cc (basename): Rename to xbasename.
+
+Wed Jun 21 16:59:46 1995 James Clark <jjc@jclark.com>
+
+ * Makefile (CCLIBS): Don't use.
+ * Makefile.ccpg: Likewise.
+
+ * acgroff.m4: Rename to...
+ * aclocal.m4: Modify extensively for autoconf 2.
+ * configure.in: Likewise.
+ * Makefile.in: Likewise.
+
+ * groff/pipeline.c (const): Declare as empty if __STDC__ not
+ defined.
+ (xstrsignal): Check for definition of NSIG. Conditionalize
+ on SYS_SIGLIST_DECLARED. Make return type const.
+
+Sat Jun 10 12:28:16 1995 James Clark <jjc@jclark.com>
+
+ * troff/input.cc (interpolate_macro): Rephrase missing space
+ warning.
+
+Thu May 11 01:07:16 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * addftinfo/addftinfo.cc, eqn/delim.cc, eqn/lex.cc, eqn/list.cc,
+ grodvi/dvi.cc, groff/groff.cc, grops/ps.cc, grops/psrm.cc,
+ grotty/tty.cc, include/ptable.h indxbib/indxbib.cc,
+ libbib/index.cc, libbib/linear.cc, libbib/search.cc,
+ libdriver/input.cc, libdriver/printer.cc, libgroff/font.cc,
+ libgroff/lf.cc, libgroff/nametoindex.cc, libgroff/ptable.cc,
+ libgroff/string.cc, lkbib/lkbib.cc, lookbib/lookbib.cc,
+ pic/lex.cc, pic/object.cc, pic/pic.y refer/label.y refer/ref.cc,
+ refer/refer.cc, refer/token.cc, tbl/main.cc, tbl/table.cc,
+ tfmtodit/tfmtodit.cc, troff/dictionary.cc, troff/div.cc,
+ troff/env.cc, troff/input.cc, troff/node.cc, troff/symbol.cc:
+ Fix 'for' scoping.
+
+Wed Apr 19 21:15:11 1995 James Clark <jjc@jclark.com>
+
+ * troff/input.cc (spring_trap): Push a macro_iterator rather than a
+ string_iterator.
+ (spring_trap, postpone_traps, unpostpone_traps): Move to later in
+ file.
+ (macro_iterator::macro_iterator): Add additional argument.
+
+Mon Apr 10 12:06:02 1995 James Clark <jjc@jclark.com>
+
+ * troff/div.cc (vertical_size::vertical_size): In place of integer
+ specifying line spacing use cunits specifying post vertical
+ space.
+ (macro_diversion::output, top_level_diversion::output): Likewise.
+ * troff/div.h: Change declarations accordingly.
+ * troff/env.cc (pending_output_line): Replace ls field by post_vs
+ field.
+ (pending_output_line::pending_output_line,
+ pending_output_line::output, environment::output,
+ environment::output_line, environment::output_title,
+ environment::hyphenate_line): In place of
+ integer specifying line spacing use cunits specifying post vertical
+ space.
+ (environment::environment): Add post_vertical_spacing and
+ prev_post_vertical_spacing arguments.
+ (environment::get_post_vertical_spacing): New function.
+ (environment::total_post_vertical_spacing): New function.
+ (environment::post_vertical_spacing): New function.
+ (init_env_requests): Initialize pvs request and .pvs register.
+ * troff/env.h: Change declarations.
+
+Tue Mar 28 09:52:07 1995 James Clark <jjc@jclark.com>
+
+ * tmac/tmac.pspic: Immediately remove the temporary file.
+
+Sat Mar 25 10:43:11 1995 James Clark <jjc@jclark.com>
+
+ * tmac/tmac.pspic (PSPIC): Scale graphic uniformly even when
+ height is specified.
+
+Thu Jan 26 16:20:13 1995 James Clark <jjc@jclark.com>
+
+ * tbl/table.c (struct vertical rule, class table_entry): Use int
+ not short for start_row and end_row.
+
+Fri Jan 13 13:53:05 1995 James Clark <jjc@jclark.com>
+
+ * troff/input.cc (trapping_blank_line, blank_line_macro): New
+ functions.
+ (diverted_space_node::reread, process_input_stack): Call
+ trapping_blank_line() rather than blank_line().
+ (init_input_requests): Bind "blm" to blank_line_macro().
+
+ * tmac/tmac.s (XA): Use .br and par@reset rather than XA.
+
+Tue Jan 10 11:40:35 1995 James Clark <jjc@jclark.com>
+
+ * troff/env.cc (environment::possibly_break_line): Require that
+ width total excluding width of final space node be greater than
+ the target text length.
+
+Tue Jan 3 09:13:37 1995 James Clark <jjc@jclark.com>
+
+ * troff/node.cc (kern_pair_node::vertical_extent): New function.
+
+Sun Dec 4 13:19:07 1994 James Clark <jjc@jclark.com>
+
+ * troff/node.cc (charinfo_node): New class.
+ (glyph_node, composite_node): Derive from charinfo_node. Change
+ member functions accordingly.
+
+Wed Nov 30 10:29:29 1994 James Clark <jjc@jclark.com>
+
+ * nroff/nroff.sh: Use -Tlatin1 not -TLatin1.
+
+Mon Aug 8 10:17:59 1994 James Clark (jjc@jclark.com)
+
+ * tmac/tmac.tty-char: Add definitions for \(ab and \[arrowvertex].
+
+ * devps/generate/textmap (notsubset): Add.
+
+ * tmac/tmac.a4: New file.
+
+Sun Jul 24 20:08:42 1994 James Clark (jjc@jclark.com)
+
+ * pic/main.cc (had_parse_error): New variable.
+ (do_picture, do_whole_file): Set had_parse_error if yyparse()
+ returns non-zero.
+ (main): Return 1 if had_parse_error is true.
+
+Tue Jul 19 13:40:31 1994 James Clark (jjc@jclark.com)
+
+ * grolj4/lj4.cc (main): Avoid use of strtoul.
+
+Mon Jul 18 15:03:02 1994 James Clark (jjc@jclark.com)
+
+ * nroff/nroff.sh: Default device is -Tlatin1 if $LC_CTYPE is
+ iso_8859_1 or $LESSCHARSET is latin1.
+
+Sun Jul 10 13:38:35 1994 James Clark (jjc@jclark.com)
+
+ * hpftodit: New directory.
+ * Makefile.in (CCPROGDIRS): Add hpftodit.
+ * devlj4/generate: New directory.
+
+Thu Jul 7 23:49:48 1994 James Clark (jjc@jclark.com)
+
+ * configure.in: Don't use AC_VFORK.
+ * groff/pipeline.c (run_pipeline): Use fork() always.
+
+Wed Jul 6 11:13:17 1994 James Clark (jjc@jclark.com)
+
+ * grops/ps.cc (main): Use %1 not %s in error message for -w.
+
+ * Makefile.in (CCPROGDIRS): Add grolj4.
+ (DEVDIRS): Add devlj4.
+ * grolj4, devlj4: New directories.
+ * tmac/troffrc: Handle lj4.
+ * tmac/tmac.lj4: New file.
+
+Fri Jun 17 18:02:53 1994 James Clark (jjc@jclark.com)
+
+ * tmac/tmac.e (@n): Set indent to 0 before calling |h.
+
+Wed Jun 1 07:33:47 1994 James Clark (jjc@jclark.com)
+
+ * troff/input.cc (do_if_request): At end of second string, switch
+ environments before getting next token.
+
+Fri May 20 07:39:18 1994 James Clark (jjc@jclark.com)
+
+ * devps/psstrip.sed: Split rule that strips whitespace on either
+ side of delimiters.
+
+Wed May 18 08:13:47 1994 James Clark (jjc@jclark.com)
+
+ * troff/node.h (font_family::make_definition): Add return value to
+ declaration. * troff/symbol.h (symbol::operator==,
+ symbol::operator!=): Likewise.
+
+Tue May 17 20:46:06 1994 James Clark (jjc@jclark.com)
+
+ * groff/groff.cc (main, help, synopsis): Handle -S.
+ (possible_command::insert_arg): New function.
+
+ * tmac/tmac.safer: New file.
+ * tmac/msafer.man: New file.
+ * tmac/Makefile.sub (FILES): Add tmac.safer and msafer.man.
+
+Thu Mar 10 01:58:30 1994 Paul Eggert (eggert@twinsun.com)
+
+ * pic/pic.h, pic/main.cc (safer_flag): New variable.
+ * pic/pic.y (placeless_element): Avoid unsafe operations if
+ `safer_flag' is set.
+ * pic/main.cc (main): Add -S option, which sets `safer_flag'.
+
+Tue May 10 13:02:31 1994 James Clark (jjc@jclark.com)
+
+ * eqn/lex.cc (get_token): Put call to add_context() in block to
+ work around Sun C++ 4.0 bug.
+
+ * include/stringclass.h (operator +): Use ?: instead of `if' to
+ work around Sun C++ 4.0 bug.
+
+Thu May 5 11:18:03 1994 James Clark (jjc@jclark.com)
+
+ * tbl/main.cc (process_format): Accept - as a synonym for the _
+ key letter.
+
+ * libbib/index.cc (minus_one): Don't declare as const.
+
+Fri Apr 29 09:32:48 1994 James Clark (jjc@jclark.com)
+
+ * troff/input.cc (get_char_for_escape_name): Push back a newline.
+
+Wed Apr 27 21:14:18 1994 James Clark (jjc@jclark.com)
+
+ * troff/input.cc (write_macro_request): New function.
+ (init_input_requests): Bind write_macro_request to writem.
+
+Sun Apr 17 11:15:38 1994 James Clark (jjc@jclark.com)
+
+ * tmac/tmac.s (@EN): Turn filling back on even if there was no
+ equation.
+
+ * eqn/lex.cc (do_space): Supply missing argument to lex_error.
+
+ * tmac/tmac.s (@TS): Renamed from TS.
+ (TS): Call LP then TS again.
+ (cov*ab-init): Alias @TS to TS.
+
+ * tmac/tmac.s: Allow QP or RS to initialize.
+
+ * tmac/tmac.s (par@load-init): New macro. Call at end of file.
+ Move initializations of PS and LL here.
+ (par@init): Don't initialize HY. Avoid changing environment 0.
+ (par*env-init): Don't all par@reset.
+
+Thu Apr 14 19:15:45 1994 James Clark (jjc@jclark.com)
+
+ * include/posix.h: Include <fcntl.h> only if not using <osfcn.h>.
+
+Sun Apr 10 09:54:44 1994 James Clark (jjc@jclark.com)
+
+ * Makefile.in (MDEFINES): Add LDFLAGS.
+ (LDFLAGS): Add definition line.
+
+Thu Apr 7 22:22:22 1994 James Clark (jjc@jclark.com)
+
+ * troff/input.cc (get_optional_char): Split off error check into...
+ (check_missing_character): New function.
+ * troff/token.h: Declare it.
+ * troff/env.cc (margin_character): Don't call get_optional_char.
+ Only call tok.next() after making the node.
+
+ * include/lib.h (getopt): Make 2nd argument char *const *.
+
+Fri Mar 11 07:28:03 1994 James Clark (jjc@jclark.com)
+
+ * nroff/conftest.sh: Deleted.
+
+Fri Mar 4 10:51:36 1994 James Clark (jjc@jclark.com)
+
+ * pic/make-dos-dist: Deleted.
+
+Wed Mar 2 20:59:16 1994 James Clark (jjc@jclark.com)
+
+ * devps/psstrip.sed: Strip comments before stripping trailing
+ white space.
+
+Sat Feb 19 13:07:16 1994 James Clark (jjc@jclark.com)
+
+ * Version 1.09 released.
+
+Wed Feb 16 16:53:49 1994 James Clark (jjc@jclark.com)
+
+ * tmac/doc-ditroff (hK): Don't reset page number if \nC is > 0.
+
+Mon Feb 14 08:26:40 1994 James Clark (jjc@jclark.com)
+
+ * libgroff/font.cc (font::load_desc): Fix typo in error message.
+
+Sun Feb 13 09:37:38 1994 James Clark (jjc@jclark.com)
+
+ * libgroff/new.cc (operator new): Rewrite so as to avoid warning
+ about returning without a value.
+
+ * troff/charinfo.h (charinfo::get_special_translation): Cast
+ TRANSLATE_NONE to int.
+
+ * refer/token.cc (lookup_token, store_token): Remove bogus loop
+ test. Fix test so that it works with n unsigned.
+
+ * pic/pic.y (defaults_table): Fully bracket initializer.
+ * pic/lex.cc (lookup_keyword): Likewise.
+ * eqn/lex.cc (token_table, def_table): Likewise.
+ * eqn/box.cc (param_table): Likewise.
+ * troff/input.cc (warning_table): Likewise.
+ * libgroff/font.cc (table): Likewise.
+ * grops/ps.cc (ps_printer::special): Likewise.
+ * grops/psrm.cc (resource_manager::process_file): Likewise.
+ * tfmtodit/tfmtodit.cc (lig_chars, lig_table): Likewise.
+ * refer/command.cc (command_table): Likewise.
+ * addftinfo/addftinfo.cc (param_table): Likewise.
+
+ * troff/symbol.cc (symbol::symbol): Prevent compiler warnings
+ about temp's being unused.
+ (unused): New function.
+
+ * groff/pipeline.cc: Declare c_fatal.
+
+ * libbib/linear.cc (bmpattern::search): Cast patterrn[--j] to
+ uchar.
+
+ * libbib/index.cc (index_search_item::load): Prevent compiler
+ warnings about fd_closer's being unused.
+ (unused): New function.
+
+Sat Feb 12 10:31:59 1994 James Clark (jjc@jclark.com)
+
+ * troff/input.cc (copy_mode_error): Make `prefix' static.
+ Fix typo.
+
+ * include/posix.h: Include <osfcn.h> is HAVE_CC_OSFCN_H is
+ defined.
+ * acgroff.m4, configure.in, Makefile: Rename HAVE_CC_UNISTD_H to
+ HAVE_CC_OSFCN_H and modify accordingly.
+
+ * troff/input.cc (init_charset_table): radicalex overlaps
+ horizontally.
+
+ * groff/acgroff.m4 (GROFF_ISC_SYSV3): New macro (from
+ udodo!hans@relay.NL.net).
+ * groff/configure.in: Call it.
+
+ * groff/acgroff.m4 (GROFF_PCLOSE): New macro.
+ * groff/configure.in: Call it.
+ * include/lib.h: Conditionalize declaration of pclose.
+
+ * troff/div.cc (last_page_number): New global variable.
+ (top_level_diversion::begin_page): Exit if we just printed the
+ last page.
+ * troff/div.h (last_page_number): Declare it.
+ * troff/input.cc (parse_output_page_list): Set last_page_number.
+
+ * eqn/sqrt.cc: Rename \(rn to \[radicalex].
+ * devps/S, devps/textmap, tmac/tmac.ps, tmac/tmac.dvi,
+ tmac/tmac.X: Likewise.
+ * tmac/tmac.ps, tmac/tmac.X, tmac.dvi: Add definitions of \(rn.
+ * tmac.dvi: Make \(ru and \(ul extend beyond their width by .04m.
+
+Fri Feb 11 11:45:40 1994 James Clark (jjc@jclark.com)
+
+ * tmac/doc-ditroff (hK): Remove groff specific code which
+ prevented page-breaks between separate manual entries. If this is
+ the first page, don't set the page number to 1.
+
+ * acgroff.m4 (GROFF_POSIX): New macro.
+ * configure.in: Use it.
+
+ * troff/node.cc (class real_output_file,
+ real_output_file::real_output_file,
+ real_output_file::~real_output_file): Conditionalize use of
+ popen/pclose on POPEN_MISSING.
+ * troff/node.h: Conditionalize pipe_command on POPEN_MISSING.
+ * troff/input.cc (pipe_command): Give an error if POPEN_MISSING.
+ (pipe_source): Similarily.
+
+ * acgroff.m4 (GROFF_PROG_CCC): Update message about libg++.
+
+ * acgroff.m4 (GROFF_GETOPT, GROFF_PUTENV, GROFF_POPEN): Detect
+ presence of declarations by trying to compile example with
+ conflicting declarations. (gcc only gives a warning for missing
+ declarations.)
+
+Wed Feb 9 09:12:23 1994 James Clark (jjc@jclark.com)
+
+ * tmac/tmac.pspic (PSPIC): Allow options to specify alignment
+ (from Ulrich Lauther).
+
+Tue Feb 8 03:56:40 1994 James Clark (jjc@jclark.com)
+
+ * libbib/linear.cc (file_buffer::load): Use S_ISREG macro.
+
+Thu Feb 3 09:34:35 1994 James Clark (jjc@jclark.com)
+
+ * indxbib/indxbib.cc (write_hash_table): Add code for case where
+ pointers and ints have different sizes.
+
+Sun Jan 9 16:17:51 1994 James Clark (jjc@jclark.com)
+
+ * tmac/tmac.s (par*env-init): Call par@reset.
+
+Fri Jan 7 10:24:27 1994 James Clark (jjc@jclark.com)
+
+ * tmac/tmac.s (@IP): Switch to a new environment when diverting
+ tag.
+ (par*push-tag-env, par*pop-tag-env): New macros.
+
+Wed Jan 5 21:18:34 1994 James Clark (jjc@jclark.com)
+
+ * grops/ps.cc (ps_printer::ps_printer): Use MAX_LINE_LENGTH for
+ initializing `out'. Reduce MAX_LINE_LENGTH from 79 to 72.
+
+ * grops/ps.cc (ps_printer::~ps_printer): Output %%CreationDate
+ comment. Include <time.h>.
+
+Wed Dec 15 14:14:00 1993 James Clark (jjc@jclark.com)
+
+ * grops/ps.cc (is_small_h, is_small_v): Deleted.
+ (ps_printer::flush_sbuf): Use absolute motion only at beginning of
+ lines.
+
+Tue Dec 14 10:06:34 1993 James Clark (jjc@jclark.com)
+
+ * troff/input.cc (read_request): Only print a prompt if reading
+ from the terminal. Also clearerr on EOF if reading from the
+ terminal. Declare isatty.
+
+Mon Nov 29 08:38:15 1993 James Clark (jjc@jclark.com)
+
+ * refer/label.y: Rename map_t to map_func and extractor_t to
+ extractor_func.
+
+Sat Oct 30 06:38:12 1993 James Clark (jjc@jclark.com)
+
+ * include/assert.h: Don't use volatile.
+ * libgroff/assert.cc: Likewise.
+
+Fri Oct 29 15:00:23 1993 James Clark (jjc@jclark.com)
+
+ * troff/input.cc (abort_request): Look at character in tok before
+ calling get_copy().
+
+Thu Oct 28 14:09:48 1993 James Clark (jjc@jclark.com)
+
+ * troff/troff.h (NO_RETURN): Deleted.
+ * troff/div.cc (cleanup_and_exit): Don't declare aas NO_RETURN.
+ * troff/input.cc (exit_troff): Likewise
+
+ * Makefile.in: Remove `Making ...' messages since GNU make now
+ gives these.
+
+ * configure.in: Use AC_HAVE_HEADERS(unistd.h) instead of AC_UNISTD_H.
+
+Wed Oct 27 11:12:51 1993 James Clark (jjc@jclark.com)
+
+ * tmac/tmac.s (@init): Initialize PO to \n(.o here, rather than
+ to constant 1 inch.
+
+Sat Oct 23 10:03:52 1993 James Clark (jjc@jclark.com)
+
+ * tmac/tmac.e (hl): Use \n[.in] rather than \n(.i.
+
+Thu Oct 14 12:09:45 1993 James Clark (jjc@jclark.com)
+
+ * eqn/delim.cc (delim_box::compute_metrics): Don't increase
+ MARK_REG if there was no left delimiter.
+
+Sat Oct 2 19:54:47 1993 James Clark (jjc@jclark.com)
+
+ * pic/troff.cc (troff_output::text): Set line thickness to
+ relative before outputting text.
+
+ * tmac/tmac.e (@k): Don't zero ?T.
+ ((z): Likewise.
+
+Sat Sep 25 11:08:43 1993 James Clark (jjc@jclark.com)
+
+ * tmac/tmac.e ($p): Handle possibility that $3 is empty.
+
+Wed Aug 18 08:51:41 1993 James Clark (jjc@jclark.com)
+
+ * troff/input.cc (decode_args): Warn about unquoted tabs (from
+ Paul Eggert).
+
+Tue Aug 10 08:38:32 1993 James Clark (jjc@jclark.com)
+
+ * troff/input.cc (ignoring): New variable.
+ (ignore): Set ignoring during call to do_define_macro.
+ (do_define_macro): Clear ignoring before interpolating terminating
+ macro.
+ (copy_mode_error): New function.
+ (get_char_for_escape_name, read_long_escape_name,
+ interpolate_arg): Use copy_mode_error.
+ (warning_table): Add WARN_IG.
+ * troff/troff.h (WARN_IG): Declare.
+ (WARN_TOTAL): Change accordingly.
+
+ * groff/pipeline.c (strsignal): Rename to xstrsignal.
+ * groff/groff.cc (strsignal): Delete declaration.
+
+Fri Jul 16 01:43:12 1993 James Clark (jjc@jclark.com)
+
+ * troff/div.cc (page_offset): Use 'm' as default scaling.
+
+Sat Jul 3 09:11:38 1993 James Clark (jjc@jclark.com)
+
+ * nroff/nroff.sh: Ignore -u.
+
+Wed Jun 9 12:17:27 1993 James Clark (jjc@jclark.com)
+
+ * Makefile.in (MDEFINES): Pass down MAKEOVERRIDES.
+
+Fri Jun 4 17:35:47 1993 James Clark (jjc@jclark.com)
+
+ * tmac/tmac.s (par*box-draw): Set adjustment mode to l while
+ drawing box.
+ (B2): With -Tascii, leave additional vertical space before
+ and after. Ensure that the left and right indent is restored to
+ what it was even if the point size changes. Don't call
+ par@finish. Change the indent, line length and title length
+ directly. With -Tascii, make the width of the box 1n less.
+ (B1): Remember 1n at the current point size. Don't call
+ par@reset. Change the indent, line length and title length
+ directly. Ensure that the temporary indent is preserved.
+ (par*box-mark-top): Turn off no spacing mode.
+
+Thu Jun 3 17:47:14 1993 James Clark (jjc@jclark.com)
+
+ * Makefile.in (dist): Use .gz suffix.
+
+Thu May 27 20:04:59 1993 James Clark (jjc@jclark.com)
+
+ * troff/input.cc (main): Add return 0.
+ * pic/main.cc (main): Use return instead of exit.
+ * tbl/main.cc (main): Likewise.
+ * eqn/main.cc (main): Likewise.
+ * grops/ps.cc (main): Likewise.
+ * grotty/tty.cc (main): Likewise.
+ * groff/groff.cc (main): Likewise.
+ * grodvi/dvi.cc (main): Likewise.
+ * refer/refer.cc (main): Likewise.
+ * indxbib/indxbib.cc (main): Likewise.
+ * lkbib/lkbib.cc (main): Likewise.
+ * soelim/soelim.cc (main): Likewise.
+ * addftinfo/addftinfo.cc (main): Likewise.
+ * acgroff.m4 (GROFF_PROG_CCC, GROFF_CC_COMPILE_CHECK,
+ GROFF_COOKIE_BUG, GROFF_CC_ANSI_BUG): Likewise.
+
+ * troff/token.h (process_input_stack): Don't declare as static.
+ * troff/input.cc: Likewise.
+
+ * troff/node.c (invalidate_fontno): Make it a static member of
+ class font_family. Change callers.
+ * troff/node.c: Change declaration.
+
+ * tbl/main.cc (struct input_entry_format): Add explicit public
+ specifier.
+ * tbl/table.cc (struct text_stuff, struct single_hline_stuff,
+ struct double_hline_stuff): Likewise.
+ * tbl/table.h (struct entry_format): Likewise.
+ * pic/object.h (struct saved_state): Likewise.
+
+ * include/stringclass.h: Add forward declarations of friend
+ functions that are later declared as inline. Don't include inline
+ specifier in friend declaration.
+
+ * libgroff/lib.h: Declare popen and pclose.
+ * acgroff.m4 (GROFF_POPEN): New macro.
+ * configure.in: Call it.
+
+ * include/lib.h (PI): New constant. Undef first if necessary.
+ * tfmtodit/tfmtodit.cc (main): Use PI rather than M_PI.
+ * grops/ps.cc (degrees, radians): Likewise.
+ * libgroff/font.cc (font::get_skew): Likewise.
+
+ * grops/ps.cc (is_ascii): New function.
+ (ps_output::put_string): Use is_ascii. Use csprint rather than
+ isprint.
+ (ps_printer::define_encoding): Use csspace.
+ * libgroff/strtol.c (ISASCII): New macro.
+ (strtol): Cast arguments to is*() and tolower() to unsigned char.
+ Use ISASCII rather than isascii.
+ * libgroff/cmap.cc: Use isascii() only if <ctype.h> defines it.
+ * libgroff/cset.cc: Likewise.
+ * libdriver/input.cc: Include cset.h.
+ (do_file, get_integer, possibly_get_integer): Use csdigit() rather
+ than isdigit().
+
+ * refer/refer.cc (main): Use %ld rather than %d for longs.
+
+ * libbib/index.cc (index_search_item_iterator::get_tag): Use
+ S_ISREG macro.
+
+ * addftinfo/addftinfo.cc (param_t): Add explicit `int'.
+
+Mon May 24 08:51:37 1993 James Clark (jjc@jclark.com)
+
+ * troff/input.cc (hyphenation_code): Skip white space between
+ char/code pairs.
+
+Sun May 16 08:15:52 1993 James Clark (jjc at jclark.com)
+
+ * tbl/table.h (table::entry_list_tailp): New member.
+ (table::table): Initialize it.
+ (table::add_entry): Use entry_list_tailp to avoid O(n^2)
+ behaviour.
+
+Sat May 15 17:26:00 1993 James Clark (jjc at jclark.com)
+
+ * grotty/tty.cc (tty_printer::add_char): Don't discard characters
+ with negative horizontal positions. Remove casts of glyph::hpos to
+ int.
+ (USHRT_MAX): Delete definition.
+ (SHRT_MAX, SHRT_MIN): New definitions.
+ (glyph::hpos): Change type to short.
+ (tty_printer::end_page): Output multiple backspaces if necessary.
+ Remove casts of glyph::hpos to int.
+
+Fri May 7 12:14:37 1993 James Clark (jjc at jclark.com)
+
+ * tmac/tmac.s (@RT): New definition.
+
+Thu May 6 21:36:54 1993 James Clark (jjc at jclark.com)
+
+ * refer/refer.cc (do_file): Make sure current_filename is set when
+ filename is "-".
+
+ * pic/common.cc (common_output::dot_line): Handle zero length
+ lines.
+
+Sun May 2 19:54:16 1993 James Clark (jjc at jclark.com)
+
+ * tmac/tmac.s (par@reset): Get value for .hy for \n[HY].
+ (par@init): Initialize \n[HY].
+
+Mon Apr 26 11:43:16 1993 James Clark (jjc at jclark.com)
+
+ * troff/dictionary.cc (dictionary::remove): Continue when
+ r < j < i.
+
+Sun Apr 25 11:03:00 1993 James Clark (jjc at jclark.com)
+
+ * Makefile.com (.y.cc): Avoid ending up with two versions of
+ $(YTABH).
+
+Thu Apr 22 21:03:45 1993 James Clark (jjc at jclark.com)
+
+ * tmac/tmac.dvi (\(,c): Define only if it does not exist.
+ (\(,C): Likewise. Also fix typo.
+
+Wed Apr 21 08:47:32 1993 James Clark (jjc at jclark.com)
+
+ * lib.h: Delete extraneous semi-colon.
+
+ * Add pso request: `so' from a pipe.
+ * troff/input.c (file_iterator::file_iterator): Add 3rd argument.
+ (file_iterator::close): New function.
+ (file_iterator::~file_iterator, file_iterator::next_file): Use
+ file_iterator::close.
+ (file_iterator::backtrace): Say `process' rather than `file' when
+ the stream is popened.
+ (pipe_source): New function.
+ (init_input_requests): Bind ".pso" to pipe_source.
+
+Tue Apr 20 00:02:26 1993 James Clark (jjc at jclark.com)
+
+ * afmtodit/afmtodit.pl: Avoid single quotes in comments.
+
+ * pfbtops/pfbtops.c: Output 64 characters per line. Output hex
+ digits in lower case.
+
+Mon Apr 19 09:55:57 1993 James Clark (jjc at jclark)
+
+ * Version 1.08 released.
+
+ * Makefile.in (dist): Insert || true after ln -s commands that
+ might fail.
+
+ * mm: Update to mm 1.16.
+
+ * acgroff.m4 (GROFF_CSH_HACK): New macro.
+ * configure.in: Call GROFF_CSH_HACK. Substitute for
+ SH_SCRIPT_SED_CMD.
+ * Makefile.in (SH_SCRIPT_SED_CMD): New variable. Include in
+ MDEFINES.
+ * nroff/Makefile.sub (nroff): New target.
+ (install_data): Install nroff.
+ * eqn/Makefile.sub (neqn): Sed with SH_SCRIPT_SED_CMD.
+ * grog/Makefile.sub (grog): Sed grog.sh with SH_SCRIPT_SED_CMD.
+
+Sat Apr 17 08:24:28 1993 James Clark (jjc at jclark)
+
+ * eqn/Makefile.sub (neqn): Add chmod +x.
+
+ * grog/Makefile.sub (grog): Remove spurious semi-colon.
+
+Fri Apr 16 22:41:57 1993 James Clark (jjc at jclark)
+
+ * troff/input.cc (string_iterator::string_iterator()): Initialize
+ lineno and count.
+
+Tue Apr 13 10:22:28 1993 James Clark (jjc at jclark)
+
+ * troff/div.cc (macro_diversion::space,
+ top_level_diversion::space): Don't set high_water_mark.
+ (macro_diversion::output, top_level_diversion::output): Don't
+ include post line space in high water mark.
+
+Wed Apr 7 12:48:18 1993 James Clark (jjc at jclark)
+
+ * eqn/eqn.y: Don't define YYDEBUG.
+ * pic/pic.y: Likewise.
+
+Mon Apr 5 10:15:15 1993 James Clark (jjc at jclark)
+
+ * tmac/tmac.e ([3): Add space after comma following editors.
+ Change double spaces to single spaces.
+ ([4): Change double spaces to single spaces.
+
+ * grops/ps.h (USE_PS_ADOBE_2_0): New flag for broken_flags.
+ * grops/ps.cc (ps_printer::~ps_printer): If the USE_PS_ADOBE_2_0
+ bit is set in broken_flags, use 2.0 rather than 3.0 as the version
+ after %!PS-Adobe- (for Newsprint).
+
+ * troff/div.cc (top_level_diversion::begin_page): When
+ before_first_page is 1, set page_number to 1.
+
+Sun Apr 4 14:28:53 1993 James Clark (jjc at jclark)
+
+ * eqn/box.cc (box::top_level): Protect equation with \&.
+
+Sat Apr 3 23:27:25 1993 James Clark (jjc at jclark)
+
+ * groff/groff.cc (possible_command::set_name): Delete old name.
+
+ * groff/groff.cc (possible_command::~possible_command): Use
+ a_delete.
+
+ * troff/node.cc (troff_output_file::begun_page): New member.
+ (troff_output_file::troff_output_file): Initialize it.
+ (troff_output_file::really_begin_page): Only output V command if a
+ page has been begun.
+
+ * pic/pic.y (placeless_element): Delete argument to PRINT after
+ use.
+
+Fri Apr 2 11:31:02 1993 James Clark (jjc at jclark)
+
+ * Make wrapman work.
+ * troff/div.h (class top_level_diversion): Replace
+ first_page_begun by before_first_page (with opposite sense).
+ * Change first_page_begun to before_first_page inverting sense.
+ * troff/div.cc (class nl_reg): New class.
+ (init_div_requests): Use class nl_reg for \n(nl.
+ (top_level_diversion::begin_page): Don't call
+ output_file::begin_page if before_first_page is 2;
+ reset before_first_page afterwards. If have_next_page_number is
+ false, then always increment page_number.
+ * tmac/tmac.an: Set traps within TH rather than at the top-level.
+ Restore compatibility mode after loading, and then disable
+ compatibility mode in TH.
+
+Thu Apr 1 11:09:34 1993 James Clark (jjc at jclark)
+
+ * grotty/tty.cc (tty_printer::end_page): Don't discard characters
+ past last line.
+ * troff/node.h (output_file::trailer): Declare.
+ * troff/div.cc (cleanup_and_exit): Call output_file::trailer().
+ * troff/node.cc (output_file::trailer): New function.
+ (troff_output_file::~troff_output_file): Move most code into...
+ (troff_output_file::trailer): New function.
+ (class troff_output_file): Delete page_length member. Declare
+ trailer().
+ (troff_output_file::really_begin_page): Use current page length
+ for final V command.
+
+ * tbl/main.cc (struct options): New decimal_point_char member.
+ (options::options): Initialize this.
+ (process_options): Implement decimalpoint option.
+ (process_data): Pass decimal_point_char option to table::table.
+ * tbl/table.h (class table): New decimal_point_char member.
+ (table::table): Add additional argument.
+ * tbl/table.cc (find_dot): Rename to find_decimal_point. Add
+ second argument specifying decimal point character. Use this
+ instead of '.'.
+ (table::table): Initialize decimal_point_char.
+ (table::add_entry): Change call to find_dot.
+
+ * troff/input.cc (get_copy, token::next): Implement \V.
+ (interpolate_environment_variable): New function.
+
+Tue Mar 30 14:41:39 1993 James Clark (jjc at jclark)
+
+ * pic/lex.cc (lookup_keyword): Rename MIN to K_MIN, MAX to K_MAX.
+ * pic/pic.y: Likewise.
+
+ * grotty/tty.cc (tty_printer::add_char, tty_printer::end_page):
+ Add casts to int.
+ * refer/ref.cc (reference::insert_field, reference::delete_field):
+ Likewise.
+ * troff/number.cc (parse_term): Likewise.
+
+ * acgroff.m4 (GROFF_PROG_YACC): New macro.
+ * configure.in: Use GROFF_PROG_YACC.
+
+ * acgroff.m4 (GROFF_PROG_CCC): Don't add -O automatically for gcc
+ and g++.
+ * Makefile.in (OPTIMIZE): New define.
+ (DEBUG): Empty by default.
+ (CCFLAGS, CFLAGS): Include $(OPTIMIZE).
+
+ * acgroff.m4 (GROFF_SYS_SIGLIST): Don't quote program.
+ (GROFF_ARRAY_DELETE): Likewise.
+ (GROFF_CC_COMPILE_CHECK): Quote use of $2 and $3.
+
+ * troff/env.cc (trie::~trie): Make virtual to shut up g++.
+
+ * devps/psstrip.sed: Use different delimiter on last line (so that
+ it works with BSD 4.4 sed.)
+
+Mon Mar 29 17:07:14 1993 James Clark (jjc at jclark)
+
+ * devps/psstrip.sed: Delete comments.
+
+ * acgroff.m4 (AC_GETOPT): Don't test whether <unistd.h> declares
+ optind, opterr, optarg.
+ * lib.h: When UNISTD_H_DECLARES_GETOPT is defined, declare optind,
+ opterr, optarg.
+
+Sun Mar 28 17:44:25 1993 James Clark (jjc at jclark)
+
+ * Makefile.in (check): Dummy target.
+
+Wed Mar 3 04:53:38 1993 James Clark (jjc at jclark)
+
+ * Version 1.07 released.
+
+ * Integrate mm 1.11.
+
+ * tbl/table.cc (alphabetic_block_entry::print): start_row was used
+ where start_col was meant.
+
+Thu Feb 25 07:55:36 1993 James Clark (jjc at jclark)
+
+ * grog/grog.sh, grog/grog.pl: Recognize PH and SA as -mm macros.
+
+Wed Feb 24 10:15:34 1993 James Clark (jjc at jclark)
+
+ * troff/input.cc (token::next): Make \z\o'...' and similar things
+ work.
+
+ * env.h (MARGIN_CHARACTER_ON, MARGIN_CHARACTER_NEXT): New
+ constants.
+ (environment): Add margin_character_flags member.
+ * env.cc (environment::environment(symbol),
+ environment::environment(const environment *): Initialize
+ margin_character_flags.
+ (margin_character): Rewrite.
+ (environment::output_line): Add a margin character if
+ margin_character_flags is non-zero. Turn off the
+ MARGIN_CHARACTER_NEXT bit. If that makes margin_character_flags
+ zero, use margin_character_node without copying and then set
+ margin_character_node to 0.
+
+ * devps/DESC.in: Change minimum size to 1000.
+
+Tue Feb 23 14:57:49 1993 James Clark (jjc at jclark)
+
+ * troff/symbol.h (symbol::hash): Change return type to unsigned
+ long.
+ * troff/dictionary.cc (dictionary::lookup, dictionary::remove):
+ Add casts to int.
+
+ * test-groff: Use -r rather than -x.
+
+ * grops/psfig.diff: Include in distribution again.
+
+Mon Feb 22 09:10:44 1993 James Clark (jjc at jclark)
+
+ * Makefile.in (dist): Use gzip.
+
+Sun Feb 21 11:12:53 1993 James Clark (jjc at jclark)
+
+ * acgroff.m4 (GROFF_GETOPT): Check for declaration of getopt() in
+ unistd.h as well as in stdlib.h.
+ * include/lib.h: Include <stdlib.h> is STDLIB_H_DECLARES_GETOPT is
+ defined; otherwise include <sys/types.h> and <unistd.h> if
+ UNISTD_H_DECLARES_GETOPT is defined.
+
+ * configure.in: use builtin(include, ... rather than include(...
+ * configure: Regenerate with autoconf 1.3.
+
+ * libdriver/print.cc (printer::adjust_arc_center): Use new
+ algorithm suggested by Andy Fyfe.
+
+ * libdriver/printer.cc (printer::adjust_arc_center): New function.
+ * include/printer.h: Declare this.
+ * grops/ps.cc (ps_printer::draw): Use it.
+ * grodvi/dvi.cc (dvi_printer::draw): Use it.
+
+Fri Feb 19 23:13:51 1993 James Clark (jjc at jclark)
+
+ * Makefile.comm (.man.n): Replace macrodir by tmacdir.
+
+Thu Feb 11 16:46:59 1993 James Clark (jjc at jclark)
+
+ * eqn/main.cc (main): Handle "eqn -".
+
+Mon Jan 4 20:29:56 1993 James Clark (jjc at jclark)
+
+ * tmac/tmac.e (++): Install fix from comp.bugs.4sd.
+
+ * mm: Integrate version 1.08.
+
+ * pic/troff.cc (troff_output::finish_picture): Set
+ EQN_NO_EXTRA_SPACE reg to 0 rather than removing it.
+ * eqn/box.cc (box::extra_space): Set EQN_NO_EXTRA_SPACE_REG to 0
+ if it's not defined. Check whether the register is non-zero rather
+ than whether it's not defined.
+ * tmac.e ({, <): Make argument to \x zero if \n(0x is non-zero.
+
+ * indxbib/indxbib.cc: Move all signal handling into...
+ * indxbib/signal.c: New file.
+ * configure.in: Call AC_RETSIGTYPE.
+
+ * acgroff.m4 (GROFF_STRUCT_EXCEPTION): New macro.
+ * configure.in: Call GROFF_STRUCT_EXCEPTION.
+ * libgroff/matherr.c: Protect with ifdef HAVE_STRUCT_EXCEPTION.
+
+ * troff/input.cc (token::token, token::operator=): Work round SGI
+ C++ bug.
+ * pic/object.cc (position::position): Likewise.
+
+Mon Dec 28 21:50:21 1992 James Clark (jjc at jclark)
+
+ * pic/pic.h: Move declaration of hypot().
+
+Wed Dec 16 12:28:29 1992 James Clark (jjc at jclark)
+
+ * pic/pic.h: Declare hypot().
+
+ * pic/pic.h: Define M_PI if necessary.
+
+Thu Dec 10 12:03:29 1992 James Clark (jjc at jclark)
+
+ * tmac/tmac.e (re): Add alternative version that doesn't use groff
+ `.ta T' feature.
+
+ * devps/prologue.ps (RE): Handle the possibility that the old font
+ doesn't have a FontName entry.
+
+Wed Dec 2 10:25:29 1992 James Clark (jjc at jclark)
+
+ * tmac/tmac.e (fam): Redefine to set family in environment 2.
+ (@C): Use @fam not fam.
+
+Thu Nov 26 16:01:25 1992 James Clark (jjc at jclark)
+
+ * lookbib/lookbib.cc (main): Change type of start to const char *.
+ * lkbib/lkbib.cc (main): Likewise.
+
+ * eqn/lex.cc (definition::definition): Don't use member
+ initializer syntax for members of anonymous unions.
+
+ * troff/input.cc (input_stack::backtrace): Change type of to const
+ char *.
+
+Wed Nov 25 13:43:09 1992 James Clark (jjc at jclark)
+
+ * include/stringclass.h (class string): Declare inline friend
+ functions as inline in class declaration.
+ * troff/hvunits.h (class hunits, class vunits): Likewise.
+ * include/refid.h (class reference_id): Likewise
+ * troff/troff.h (points_to_units(units), scale(units, double)):
+ Delete declarations.
+ * libdriver/input.cc (get_char): Delete declaration.
+ * include/lib.h: Change 2nd argument of getopt from const char **
+ to char **.
+ * troff/symbol.cc (symbol::symbol): Cast `new char *[n]' to `const
+ char **' before assigning to a `const char **'.
+ * tbl/table.cc: Delete extra declarations of prints().
+
+Tue Nov 24 14:33:13 1992 James Clark (jjc at jclark)
+
+ * libgroff/font.cc (font::load_desc): Cast `new char *[n]' to `const
+ char **' before assigning to a `const char **'.
+
+ * libgroff/errarg.cc (errarg::errarg): Don't use member
+ initializer syntax for members of anonymous unions.
+
+Sat Nov 21 05:02:23 1992 James Clark (jjc at jclark)
+
+ * mm: Integrate version 1.07.
+
+Tue Nov 17 16:44:27 1992 James Clark (jjc at jclark)
+
+ * troff/input.c (translate2): Rename to
+ (translate_no_transparent).
+ (init_input_requests): Rename tr2 to trnt.
+
+Mon Nov 16 09:49:32 1992 James Clark (jjc at jclark)
+
+ * troff/charinfo.h (class charinfo): Add transparent_translate field.
+ (charinfo::set_translation, charinfo::set_special_translation):
+ Add second argument that specifies value for
+ transparent_translate.
+ (charinfo::get_translation, charinfo::get_special_translation):
+ Add optional second argument that specifies whether translation is
+ being used for transparent throughput.
+ * troff/input.cc (charinfo::set_translation,
+ charinfo::set_special_translation): Handle second argument.
+ (charinfo::charinfo): Initialize transparent_translate.
+ (translate): Split main part off into
+ (do_translate): New function. Pass argument saying whether
+ translation applies to transparent throughput.
+ (translate2): New request.
+ (init_input_requests): Bind translate2 to `tr2'.
+
+Wed Nov 11 11:43:20 1992 James Clark (jjc at jclark)
+
+ * tbl/table.h (class table): Add `nokeep' flag.
+ * tbl/main.cc (process_options): Handle `nokeep' option.
+ * tbl/table.cc (table::init_output, table::do_row, table::do_top,
+ table::do_bottom): Don't output keep/release macro definitions or
+ calls when `nokeep' option has been specified.
+
+Sat Nov 7 01:28:33 1992 James Clark (jjc at jclark)
+
+ * tmac/tmac.Xps (Xps-char): Use " as delimiter for \Z.
+
+Wed Nov 4 16:29:04 1992 James Clark (jjc at jclark)
+
+ * tbl/table.cc (table_entry::divert, block_entry::do_divert,
+ block_entry::divert, alphabetic_block_entry::divert): Add extra
+ argument giving column separation.
+ (table::compute_widths): Pass column separation to
+ table_entry::divert().
+ (block_entry::do_divert): If an entry spans multiple columns and a
+ minimumum width has been specified for each column, then set the
+ line length to the sum of the widths (plus possibly the column
+ separations).
+
+ * troff/input.cc (set_escape_char): Don't set the escape_char
+ until after calling has_arg().
+
+Tue Nov 3 11:23:27 1992 James Clark (jjc at jclark)
+
+ * tbl/table.cc (table::do_top): Add missing \s0 for double box
+ case.
+
+ * tbl/table.cc (table::print_double_hline): Avoid extra new line
+ in case where r > nrows - 1.
+
+ * tbl/table.cc (BODY_HEIGHT): Deleted.
+ (LINE_SEP): New definition.
+ (table::print_single_hline, table::print_double_hline,
+ table::compute_vrule_top_adjust, table::compute_vrule_bot_adjust,
+ table::do_row, table::do_top): Use LINE_SEP space before a line
+ instead of \n[.v]-BODY_HEIGHT-BODY_DEPTH.
+
+ * tbl/table.cc (text_entry::print_contents): New function.
+ (text_string_name, right_text_string_name): Deleted.
+ (TEXT_STRING, RIGHT_TEXT_STRING): Deleted.
+ (simple_text_entry::do_width, numeric_text_entry::do_width,
+ alphabetic_text_entry::do_width): Don't store the contents of the
+ entry in a string.
+ (left_text_entry::simple_print, right_text_entry::simple_print,
+ center_text_entry::simple_print,
+ alphabetic_text_entry::simple_print,
+ numeric_text_entry::simple_print): Print the entry directly
+ instead of using the stored string.
+
+Fri Oct 30 10:39:32 1992 James Clark (jjc at jclark)
+
+ * devps/Makefile: Strip PostScript files.
+ * devps/prologue: Rename to...
+ * devps/prologue.ps.
+ * devps/psstrip.sed: New file.
+ * devps/download: Use .pfa rather than .ps for installed versions
+ of fonts.
+
+Thu Oct 29 09:14:43 1992 James Clark (jjc at jclark)
+
+ * troff/env.cc (input_trap): Give a warning if the argument is out
+ of range.
+
+ * troff/env.cc (adjust): Treat negative argument as missing. Round
+ argument > 5 down to 5.
+
+ * troff/env.cc (center, right_justify): Make negative argument zero.
+
+ * troff/div.cc (page_offset, vertical_position_traps): Treat
+ invalid argument as missing.
+ * troff/env.cc (line_spacing, line_length, title_length, indent,
+ underline, hyphen_line_max_request, control_char,
+ no_break_control_char, widow_control_request, adjust, input_trap,
+ point_size): Likewise.
+ * troff/node.cc (ligature, kern_request, bold_font, track_kern,
+ constant_space): Likewise.
+ * troff/input.cc (compatible, shift, warn_request,
+ set_escape_char): Likewise.
+
+ * tbl/main.cc (format::format): Avoid doing `new int[0]'.
+ * tbl/table.cc (table::table): Likewise.
+
+ * Makefile.dev (install_dev): depends on $(DEVFILES).
+
+Wed Oct 28 08:30:57 1992 James Clark (jjc at jclark)
+
+ * devX75, devX75-12, devX100, devX100-12: New directories.
+ * Makefile.in: Add these to DEVDIRS.
+
+ * troff/Makefile.sub, eqn/Makefile.sub, indxbib/Makefile.sub,
+ afmtodit/Makefile.sub, tmac/Makefile.sub, nroff/Makefile.sub,
+ grog/Makefile.sub, mm/Makefile.sub (uninstall_sub): New target.
+ * Makefile.in (uninstall, uninstall_sub, uninstall_dirs): New
+ targets.
+ * Makefile.ccpg, Makefile.cpg, Makefile.dev, Makefile.man
+ (uninstall): New target.
+ * Makefile.comm (uninstall, uninstall_sub, uninstall_man,
+ uninstall_prog, uninstall_dev): New targets.
+
+ * troff/div.cc (return_request): Treat an invalid argument as
+ missing.
+
+Mon Oct 26 11:33:47 1992 James Clark (jjc at jclark)
+
+ * tmac/tmac.e ((f): Set up the environment even when there's a
+ current diversion. Transperently throughput a call to @N.
+ (@N): New macro.
+
+Thu Oct 22 05:05:59 1992 James Clark (jjc at jclark)
+
+ * tbl/table.cc (table::compute_vrule_top_adjust): Round adjustment
+ up to vertical resolution.
+
+ * tbl/table.cc (table::do_row): Change row number after printing
+ stuff list.
+
+ * pic/lex.cc (get_token_after_dot): Make .left and .right work.
+
+Wed Oct 21 14:46:45 1992 James Clark (jjc at jclark)
+
+ * Rename CHANGES to NEWS.
+
+Tue Oct 20 23:25:21 1992 James Clark (jjc at jclark)
+
+ * libgroff/new.cc (operator new): Avoid calling malloc(0).
+
+Mon Oct 19 09:10:13 1992 James Clark (jjc at jclark)
+
+ * man.ultrix: Removed.
+
+Sun Oct 18 06:35:15 1992 James Clark (jjc at jclark)
+
+ * Makefile.comm (extraclean): Delete files whose names begin with
+ `='.
+
+ * pic/troff.cc (troff_output::text): Fix typo in implementation of
+ aligned text.
+
+Sat Oct 10 09:32:29 1992 James Clark (jjc at jclark)
+
+ * troff/env.cc (hyphenate_request, vertical_spacing, no_number):
+ * troff/div.cc (page_length, need_space, space_request): Treat
+ invalid optional argument as missing.
+ * troff/env.cc (number_lines): If the first argument is present
+ but not a number, turn on line numbering, don't change the next
+ line number and parse the remaining arguments.
+
+ * tmac/tmac.e (@q): Do the `ne' before changing to environment 2.
+
+Thu Oct 8 10:24:40 1992 James Clark (jjc at jclark)
+
+ * eqn/box.h: Change declaration accordingly.
+ * eqn/box.cc (set_gsize): Change return type to int. Return 0 if
+ the specified size was bad but don't give an error. Check for
+ overflow.
+ * eqn/main.cc (main): Change caller. Leave validation to set_gsize.
+ * eqn/lex (do_size): Likewise.
+
+Wed Oct 7 09:48:59 1992 James Clark (jjc at jclark)
+
+ * acgroff.m4 (GROFF_PROG_CCC): Use fopen when checking for C++
+ compatible headers.
+
+Sun Oct 4 18:24:02 1992 James Clark (jjc at jclark)
+
+ * tbl/table.cc (table::init_output): Improve error message when
+ table won't fit on one page.
+
+Fri Oct 2 10:41:40 1992 James Clark (jjc at jclark)
+
+ * pic/troff.cc (troff_output::start_picture): Generate line
+ containing a horizontal motion equal to the width of the picture.
+
+ * groff/groff.cc (main): Allow PROG_PREFIX to be set at runtime
+ using GROFF_COMMAND_PREFIX environment variable.
+
+Fri Sep 25 11:40:40 1992 James Clark (jjc at jclark)
+
+ * mdate.sh: Use $NF rather than $(NF).
+
+Tue Sep 22 09:47:24 1992 James Clark (jjc at jclark)
+
+ * pic/main.cc (main): Use %1 not %c in argument to warning.
+
+ * eqn/main.cc (main): Output code to check that geqn was given the
+ correct -T option.
+
+Mon Sep 21 10:59:16 1992 James Clark (jjc at jclark)
+
+ * Makefile.in (dist): Instead of doing `make -f ../Makefile', do
+ `ln -s ../Makefile .; make; rm -f Makefile'.
+
+ * troff/hyphen: Rename to...
+ * troff/hyphen.us:
+ * troff/input.cc (main): Delete -H option. Don't call
+ read_hyphen_file().
+ * troff/env.cc: Include searchpath.h and macropath.h.
+ (exception_dictionary): Deleted.
+ (ht): Deleted.
+ (read_hyphen_file): Deleted.
+ (hyphenation_language): New struct.
+ (class trie, class hyphen_trie): Move declarations up.
+ (trie_node::~trie_node): Deleted.
+ (trie::delete_trie_node): New function.
+ (trie::do_delete): New pure virtual function.
+ (hyphen_trie::do_delete): New function.
+ (trie::~trie): New function.
+ (hyphen_trie::~hyphen_trie): New function.
+ (trie::clear): No need to chcek that tp is not 0.
+ (current_language, language_dictionary): New variables.
+ (hyphen_word): Give an error if no current language. Use
+ exceptions dictionary in current language.
+ (hyphen_trie::read_patterns_file): Find file using macro_path.
+ Allow comments (starting with %) in patterns file. Don't make it
+ a fatal error if the file can't be found.
+ (hyphenate): Return if no current language. Get the exceptions
+ dictionary and the hyphenation patterns from the current language.
+ (set_hyphenation_language): New variable.
+ (hyphenation_patterns_file): New function.
+ (hyphenation_language_reg): New class.
+ (hyphenation_language_reg::get_string): New function.
+ (init_hyphen_requests): Bind "hla" to set_hyphenation_language and
+ "hpf" to hyphenation_patterns_file. Initialize `.hla' number
+ register.
+ * groff/groff.cc (main, help, synopsis): Delete -H option.
+ * include/Makefile.sub: Don't define HYPHENFILE.
+ * Makefile.in: Delete hyphenfile variable and remove from MDEFINES.
+ * Makefile.comm (.man.n): Don't substitute for HYPHENFILE.
+ * tmac/troffrc: Set hyphenation language to `us'. Load `hyphen.us'
+ hyphenation patterns.
+
+Sun Sep 20 09:33:02 1992 James Clark (jjc at jclark)
+
+ * eqn/neqn.sh: New file.
+ * eqn/Makefile.sub: Handle neqn.sh.
+
+ * eqn/eqn.h: Declare `nroff' variable.
+ * eqn/box.cc (param_table): Add `nroff' param.
+ (nroff): Define it.
+ * eqn/lex.cc (yylex): Handle TDEFINE and NDEFINE using `nroff'
+ variable.
+ * tmac/eqnrc: Set `nroff' to 1 for -Tascii or -Tlatin1.
+
+ * troff/troff.h (WARN_FONT): New warning.
+ (WARN_TOTAL): Change accordingly.
+ * troff/input.cc (DEFAULT_WARNING_MASK): Include WARN_FONT.
+ (warning_table): Add WARN_FONT.
+ * troff/node.cc (mount_font_no_translate): Pass argument to
+ font::load_font. If this is non-zero, give a warning.
+ Don't give an error message when accessing a font that has already
+ been found to be invalid.
+ * include/font.h (font::load, font::load_font): Add additional
+ optional argument which suppresses error message if the font is
+ not found.
+ * libgroff/font.cc (font::load_font): Handle additional argument.
+ (font::load): Add additional argument. If this is non-null, set it
+ to 1 and don't give error message.
+
+ * include/printer.h (printer::end_page): Add argument giving
+ length of page.
+ * libdriver/input.cc (do_file): Pass this.
+ * grops/ps.cc (ps_printer::end_page): Add argument.
+ * grodvi/dvi.cc (dvi_printer::end_page,
+ draw_dvi_printer::end_page): Add argument.
+ * grotty/tty.cc (class tty_printer): Remove lines_per_page and
+ columns_per_page members. New member nlines.
+ (DEFAULT_LINES_PER_PAGE): Deleted.
+ (tty_printer::tty_printer): Don't compute lines_per_page from
+ font::paperlength. Don't compute columns_per_page from
+ font::paperwidth.
+ (tty_printer::add_char): Don't check horizontal position against
+ columns_per_page. Grow glyphs vector if neccessary.
+ (tty_printer::end_page): Add argument giving page_length in units.
+ Discard lines past end of page.
+
+Wed Sep 16 06:29:52 1992 James Clark (jjc at jclark)
+
+ * tmac/tmac.tty-char: Fix definition of \(/l.
+
+ * tmac/tmac.X: Define \(en.
+
+Tue Sep 15 10:37:13 1992 James Clark (jjc at jclark)
+
+ * acgroff.m4 (GROFF_PRINT): If a system has lpr and lp but not
+ lpq, then use lp rather than lpr.
+
+ * tmac/tmac.s (par@reset): Don't call `ad'.
+ (par*env-init): Call `ad'.
+
+Sun Sep 13 18:48:20 1992 James Clark (jjc at jclark)
+
+ * mdate.sh: Use $(NF) instead of $6 to extract year from output of
+ date.
+
+ * troff/symbol.cc: #undef BLOCK_SIZE if it's defined.
+ * indxbib/indxbib.cc: Likewise.
+
+Sun Sep 6 09:44:46 1992 James Clark (jjc at jclark)
+
+ * libgroff/putenv.c: New file.
+ * libgroff/Makefile.sub: Add putenv.c to CSRCS.
+ * Makefile.in: Say that putenv.o can be one of LIBOBJS.
+ * configure.in: Test for putenv with AC_REPLACE_FUNCS. Test for
+ stdlib.h with AC_HAVE_HEADERS.
+
+Sat Sep 5 18:11:52 1992 James Clark (jjc at jclark)
+
+ * indxbib/dirnamemax.c: Include <sys/dir.h> only if <dirent.h>
+ does not exist.
+
+Fri Sep 4 09:43:26 1992 James Clark (jjc at jclark)
+
+ * eqn/box.cc (gsize): Make it an int.
+ (set_gsize): Parse argument handling increment or decrement.
+ (box::top_level): Convert gsize to a string.
+
+ * troff/input.cc (exit_troff): Make buf unsigned char [].
+ Call to make_temp_iterator casts buf to char*.
+
+ * Makefile.in ($(TARGETS), dot): Pass $(MDEFINES) to recursive makes.
+
+ * Makefile.ccpg (depend.temp): Depends on $(YTABC).
+ * Makefile.cpg (depend.temp): Likewise.
+
+ * Makefile.dep: Remove Makefile.dep from $(REALCLEANFILES).
+
+ * Makefile.comm: Add y.output to MOSTLYCLEANFILES.
+
+Thu Sep 3 08:01:55 1992 James Clark (jjc at jclark)
+
+ * tmac/tmac.s (B, I, BI, CW): Rewrite avoiding aliases.
+
+Tue Sep 1 18:24:53 1992 James Clark (jjc at jclark)
+
+ * Version 1.06 released.
+
+ * Integrate mm 1.04.
+
+Fri Aug 28 11:28:19 1992 James Clark (jjc at jclark)
+
+ * Makefile.comm, Makefile.ccpg, Makefile.cpg: Fix TAGS target.
+
+Thu Aug 27 11:03:33 1992 James Clark (jjc at jclark)
+
+ * afmtodit/afmtodit.pl: Add -n option that disables generation of
+ ligatures command.
+ * devps/generate/Makefile (CR, CB, CI, CBI): Pass -n flag to
+ afmtodit. Regenerate.
+
+ * tmac/tmac.e ()z): Adjust _b if necessary so as to avoid moving
+ @f back past the current position.
+
+ * tmac/tmac.e: Change calls to @R so that comments are not part of
+ arguments.
+
+Tue Aug 25 10:42:07 1992 James Clark (jjc at jclark)
+
+ * configure.in: Check for mkstemp with AC_HAVE_FUNCS.
+
+ * acgroff.m4 (GROFF_PROG_CCC): Don't check for <osfcn.h>. Instead
+ check that we can link a call to a function declared in <stdio.h>.
+ (GROFF_UNISTD_H): New macro.
+ * configure.in: Call it.
+ * Makefile.in: Document it.
+ * include/posix.h: New file.
+ * troff/troff.h: Don't include <osfcn.h>
+ * troff/input.cc: Include posix.h.
+ * libgroff/new.cc, libgroff/tmpfile.cc: Include posix.h rather than
+ osfcn.h.
+ * indxbib/indxbib.cc, libbib/{search.cc,linear.cc,index.cc}:
+ Include posix.h rather <sys/types.h>, <sys/stat.h>, <osfcn.h>,
+ <fcntl.h>.
+ * indxbib/indxbib.cc (S_IRUSR, S_IRGRP, S_IROTH): Delete definitions.
+ * libbib/index.cc (S_ISREG, O_RDONLY): Delete definitions.
+ * libbib/search.cc (O_RDONLY): Delete definition.
+ * refer/refer.cc, include/driver.h, pic/pic.h, groff/groff.cc:
+ Don't include <osfcn.h>.
+
+ * acgroff.m4 (GROFF_TIME_T): New macro.
+ * configure.in: Call it.
+ * Makefile.in: Document it.
+
+ * acgroff.m4 (GROFF_TRADITIONAL_CPP): New macro.
+ * configure.in: Call it.
+ * Makefile.in: Document -DTRADITIONAL_CPP.
+ * include/ptable.h: Don't include generic.h.
+ (name2): Define it.
+
+ * tmac/tmac.s (][): Make [T1 and [T2 aliases for [T.
+ Afterwards remove [T1 and [T2.
+ (ref*spec!0, ref*spec!2): Use T1 rather than T.
+ (ref*spec!1, ref*spec!4, ref*spec!4): Use T2 rather than T.
+ (ref*add-T2): Renamed from ref*add-T.
+ (ref*add-T1): New macro.
+
+Mon Aug 24 11:11:11 1992 James Clark (jjc at jclark)
+
+ * acgroff.m4 (AC_PROG_CCC): Use GROFF_EXIT rather than exit 1.
+
+ * libbib/index.cc: Include <fcntl.h>.
+ (O_RDONLY): Define if necessary.
+ (make_index_search_item, index_search_item_iterator::get_tag,
+ index_search_item::check_files): Use O_RDONLY.
+ * libbib/seach.cc: Include <fcntl.h>, <sys/types.h>, <sys/stat.h>.
+ (O_RDONLY): Define if necessary.
+ (search_list::add_file): Use O_RDONLY.
+ * indxbib/indxbib.cc: Include <fcntl.h>, <sys/types.h>,
+ <sys/stat.h>.
+ (S_IRUSR, S_IRGRP, S_IROTH): Define if necessary.
+ (main): Use these.
+
+ * libbib/index.cc (S_ISREG): Define it if necessary.
+ (index_search_item::load): Use S_ISREG.
+
+ * include/driver.h: Include <errno.h>.
+
+Sun Aug 23 11:32:18 1992 James Clark (jjc at jclark)
+
+ * eqn/box.cc (body_height): Increase default value to 85.
+ (body_depth): Increase default value to 35.
+
+Fri Aug 21 05:34:42 1992 James Clark (jjc at jclark)
+
+ * eqn/pbox.h (SAVE_FONT_STRING): Define it.
+ * eqn/box.cc (box::top_level): Hide use of \R in a string that is
+ protected from expansion with \E.
+
+ * acgroff.m4 (GROFF_PAGE): Use `case' to test domain.
+
+ * Makefile (Makefile): New target.
+
+ * Makefile.sub (configure, distfiles): New targets.
+
+ * acgroff.m4 (GROFF_BROKEN_SPOOLER_FLAGS): Avoid using ${var:-val}
+ construct.
+
+Thu Aug 20 12:27:26 1992 James Clark (jjc at jclark)
+
+ * eqn/box.cc (param_table): Add body_height and body_depth.
+
+ * eqn/lex.cc (def_table): Make circumflex in hat_def roman.
+
+Tue Aug 18 16:24:25 1992 James Clark (jjc at jclark)
+
+ * psbb/Makefile.sub: Don't link with libgroff.a.
+
+ * acgroff.m4 (GROFF_PUTENV): New macro.
+ * configure.in: Call GROFF_PUTENV.
+ * Makefile.in: Document STDLIB_H_DECLARES_PUTENV.
+ * groff/groff.cc: Don't declare putenv if STDLIB_H_DECLARES_PUTENV
+ is defined.
+
+ * troff/env.cc (distribute_space): Rename force_forward argument
+ to force_reverse. Reverse the list if force_reverse is true.
+
+Mon Aug 17 17:49:05 1992 James Clark (jjc at jclark)
+
+ * tmac/tmac.an: Don't define a string `T'. Just define Tm.
+
+ * eqn/pile.cc (matrix_box::compute_metrics): Don't allow computed
+ height or depth to be negative. Guard against SUP_RAISE quantity
+ being negative.
+
+Sat Aug 15 08:18:54 1992 James Clark (jjc at jclark)
+
+ * devps/generate/textmap: Add `an' (arrowhorizex).
+ * tmac/tmac.ps: \(an overlaps horizontally.
+ * tmac/tmac.dvi, tmac/tmac.tty: Add `an'.
+
+ * devps/symbolchars: Add arrowverttp, arrowvertbt.
+ * devps/textmap: Add arrowvertex.
+ * eqn/delim.cc (delim_table): Add uparrow, downarrow and
+ updownarrow delimiters.
+ * tmac/tmac.ps, tmac/tmac.X: Add definition of \(va.
+
+ * tbl/table.cc (simple_entry::position_vertically,
+ block_entry::position_vertically): For a centered entry, perform
+ the motion in two stages.
+
+ * refer/refer.cc (split_punct): Don't call lookup_token if there
+ is no token.
+
+Fri Aug 14 11:14:58 1992 James Clark (jjc at jclark)
+
+ * troff/input.cc (token::next): Delete token_node after copying
+ token.
+
+ * grodvi/grodvi.cc (dvi_printer::dvi_printer): Initialize
+ cur_point_size.
+
+ * libdriver/printer.cc (printer::load_font): Delete old_font_table.
+
+ * grops/ps.cc (ps_printer::define_encoding): Delete elements of vec.
+
+Tue Aug 11 13:50:38 1992 James Clark (jjc at jclark)
+
+ * grops/ps.cc (usage): -b option takes an argument.
+
+ * devps/prologue (PLG): New procedure.
+ * grops/ps.cc (main, usage): New -g option.
+ (ps_printer::~ps_printer): If guess_flag is set, guess the paper
+ length using PLG.
+
+Mon Aug 10 11:17:53 1992 James Clark (jjc at jclark)
+
+ * include/cset.h: Include <limits.h> if we have it.
+
+ * libgroff/illegal.cc: New file.
+ * include/lib.h (illegal_input_char): Use table.
+ * troff/input.cc (ESCAPE_RIGHT_PARENTHESIS): Renumber to 0206.
+ * pic/lex.cc (ARG1): Renumber to 14.
+ * eqn/lex.cc (ARG1: Likewise.
+
+ * troff/Makefile.sub (majorminor.cc): Handle 3 part versions
+ (eg 1.05.90) correctly.
+
+Sun Aug 9 13:35:43 1992 James Clark (jjc at jclark)
+
+ * tmac/tmac.e (sr): Deleted. Set $r and $R directly.
+ Rename $r and $R registers to $v and $V.
+ ($r, $R): Initialize to 0.
+ (@v, @V): New macros.
+ (sz): Call @v.
+ (@M): Call @V.
+
+ * troff/input.cc (main, usage): Add -R option that says not to
+ load troffrc.
+ * eqn/main.cc (main, usage): Rename -n to -R.
+
+Sat Aug 8 00:16:00 1992 James Clark (jjc at jclark)
+
+ * devps/DESC.in: Leave font positions 5-9 blank.
+ * devdvi/DESC.in: Likewise.
+
+ * grog/grog.pl: Handle `.PS <file' correctly.
+
+ * troff/input.cc (input_stack::push): Improve error message when
+ input stack limit exceeded.
+
+Fri Aug 7 13:08:16 1992 James Clark (jjc at jclark)
+
+ * refer/refer.cc (main): Fix typo in handling of `a' option.
+
+ * refer/refer.cc (do_bib): In state START after a newline remain
+ in state START.
+
+ * groff/groff.sh: Deleted.
+ * groff/Makefile.sub: Delete handling of groff.sh.
+
+ * pic/troff.cc (troff_output::text): Test \n(0p rather than \*(.T
+ to determine whether to use \X'ps:...'.
+ * tmac/troffrc: Set 0p register to 0.
+ * tmac/tmac.ps: Set 0p register to 1.
+
+ * groff/groff.cc: Support -X option. Give warning for -TXps and
+ transform to -X -Tps. Pass troff a -r.X=1 option if -X is used.
+ * tmac/troffrc: Support -r.X=1.
+
+ * pic/troff.cc (troff_output::dot): Don't test
+ zero_length_line_flag.
+
+Thu Aug 6 13:32:08 1992 James Clark (jjc at jclark)
+
+ * include/lib.h: Declare getopt() and friends unless
+ STDLIB_H_DECLARES_GETOPT is defined.
+
+ * doc/chars.tr: Delete.
+ * man/groff_char.man: New file.
+
+Wed Aug 5 00:38:58 1992 James Clark (jjc at jclark)
+
+ * tmac/tmac.e (np, bu): Test \n($p with string expression in case
+ user has changed register format.
+
+Mon Aug 3 11:22:18 1992 James Clark (jjc at jclark)
+
+ * groff/groff.cc: Get rid of device_table. Get postprocessor from
+ `postpro' command in DESC file. Get spooler command from `print'
+ command in DESC file. Execute spooler command with /bin/sh.
+
+ * groff/groff.cc: Split Unix-specific parts into...
+ * groff/pipeline.c: New file.
+
+ * LICENSE: Delete.
+ * COPYING: New file.
+ * all files: Update copyright notices.
+
+ * Rearrange files. Redo Makefiles. Use autoconf.
+
+Sat Aug 1 09:36:50 1992 James Clark (jjc at jclark)
+
+ * troff/input.c (charinfo_to_node_list): Interpret character
+ definition with escape_char of `\'.
+
+Tue Jul 28 12:20:12 1992 James Clark (jjc at jclark)
+
+ * lib/strerror.c, lib/iftoa.c, lib/itoa.c: Don't include lib.h.
+ Define INT_DIGITS as big enough for 64-bit integer.
+ * lib/strtol.c: Don't include lib.h.
+ * lib/lib.h: Delete ifdef __cplusplus stuff.
+
+Mon Jul 27 11:08:50 1992 James Clark (jjc at jclark)
+
+ * ps/devps/Makefile: Add DESC to DEVICEFILES. Separate out rule
+ for making DESC. Make $(FONTS) depend on DESC. afmtodit should
+ get DESC from current directory.
+
+Sun Jul 26 15:38:26 1992 James Clark (jjc at jclark)
+
+ * tbl/main.c (main): Always reset the line number when reading
+ from stdin.
+
+ * tbl/table.c (table::print_single_hline, table::print_double_hline,
+ table::define_bottom_macro, table::do_row, table::do_top): Round
+ vertical spacing up to vertical resolution.
+
+Fri Jul 24 14:32:07 1992 James Clark (jjc at jclark)
+
+ * ps/ps.h (enum resource_type): Avoid comma at end of
+ enumerator-list.
+ * dvi/dvi.c (class dvi_printer): Likewise.
+ * dvi/tfmtodit.c (gf::load): Likewise.
+ * refer/label.y (struct expression): Likewise.
+ * refer/refer.c (class label_processing_state): Likewise.
+ * refer/indxbib.c (do_file): Likewise.
+ * troff/troff.c (enum warning_type): Likewise.
+ * tbl/main.c (process_data): Likewise.
+ * troff/charinfo.h (class charinfo):
+
+Wed Jul 22 09:17:58 1992 James Clark (jjc at jclark)
+
+ * dvi/devdvi/textt.map: Add entry for `-'. Regenerate fonts.
+
+Tue Jul 21 11:39:26 1992 James Clark (jjc at jclark)
+
+ * groff.c: Move to new groff subdirectory.
+ * groff/Makefile: New file.
+ * Makefile: Remove handling of groff.c. Add groff to SUBDIRS.
+
+ * man/mdate.sh: Use ls -L if supported.
+
+ * Consolidate all header files produced by gendef into lib/defs.h.
+ * lib/macropath.c, lib/fontfile.c, lib/device.c: Include defs.h.
+ Don't include path.h.
+ * lib/Makefile (path.h): Don't generate.
+ * troff/input.c: Include defs.h. Don't include config.h.
+ * troff/Makefile (config.h): Don't generate.
+ * refer/index.h: Don't include suffix.h.
+ * refer/index.c: Include defs.h.
+ * refer/indxbib.c: Include defs.h.
+ * refer/refer.h, refer/lkbib.h: Don't include path.h. Include
+ defs.h.
+ * refer/Makefile (suffix.h, path.h): Don't generate.
+ * groff.c: Don't include config.h. Include defs.h.
+ * Makefile (config.h): Don't generate.
+ (lib/defs.h): Generate.
+ (topclean): Remove lib/defs.h.
+
+Mon Jul 20 10:12:57 1992 James Clark (jjc at jclark)
+
+ * lib/malloc.c, lib/getpagesize.h: Deleted.
+ * Makefile: Add COOKIE_BUG configuration option. Delete malloc
+ related stuff.
+ * lib/Makefile: Delete malloc-related stuff.
+ * lib/new.c: Workaround COOKIE_BUG if necessary.
+
+ * refer/lkbib.c, refer/indxbib.c: Don't include refer.h. Include
+ needed header files directly.
+ * refer/refer.h: Omit definition of DEFAULT_INDEX.
+ * Makefile: Include definition of DEFAULT_INDEX in path.h.
+
+Sun Jul 19 10:19:22 1992 James Clark (jjc at jclark)
+
+ * lib/font.c (FONT_COMMAND_HANDLER): Pass command name and single
+ argument.
+ * lib/font (font::load_desc, font::load): Don't split argument of
+ unknown command.
+ (font::handle_unknown_font_command): Change type.
+ * ps/ps.c (ps_font::handle_unknown_font_command,
+ handle_unknown_desc_command): Change type.
+ * dvi/dvi.c (dvi_font::handle_unknown_font_command): Change type.
+
+Fri Jul 17 11:12:49 1992 James Clark (jjc at jclark)
+
+ * lib/font.h (font::handle_unknown_font_command): Add file and
+ line arguments.
+ * lib/font.c (font::handle_unknown_font_command):
+ * ps/ps.c (ps_font::handle_unknown_font_command):
+ * dvi/dvi.c (dvi_font::handle_unknown_font_command): Add file and
+ lineno arguments. Use _with_file_and_line functions for error
+ reporting.
+
+ * lib/fontfile.c (font::unknown_desc_command_handler): New static
+ data member.
+ * lib/font.c (font::set_unknown_desc_command_handler): New
+ function.
+ (font::load_desc): For unknown commands, call
+ unknown_desc_command_handler if not null.
+ * lib/font.h (class font): Declare them.
+ (FONT_COMMAND_HANDLER): New typedef.
+ * ps/ps.c (handle_unknown_desc_command): New function.
+ (main): Set bflag if we had a -b option. Call
+ font::set_unknown_desc_command_handler.
+ (broken.h): Don't include.
+ * ps/Makefile: No need for broken.h. Pass BROKEN_SPOOLER_FLAGS to
+ submake
+ * ps/devps/Makefile: Add `broken' command to DESC file using
+ BROKEN_SPOOLER_FLAGS.
+
+ * macros/tmac.e ([, ]): Add as synonyms for { and }.
+
+ * macros/tmac.e ($p): Only exdent if \$3 > 0.
+
+ * macros/tmac.e (@R, @S): New macros.
+ Declare @, po, $0, $i, $p, df, so, fu, bt, *, ?a, ?b, ?C, ?e, ?H,
+ ?I, ?n, ?o, ?R, ?s, ?T, ?W, ?w registers with @R.
+ Declare $H, $[0-9], .. macros with @S.
+ Declare |0, |1, |2, |3 strings with @S.
+
+ * macros/tmac.e (@S): Rename to @U.
+
+ * macros/tmac.e (@z): Define @b and bp as empty instead of
+ deleting them,
+
+ * macros/tmac.e (@m): Deleted.
+ (@h): Don't call @m.
+ (@z): Don't set @m trap.
+
+ * macros/tmac.e ($h, $f): Define |z as empty string.
+
+ * macros/tmac.e (@D): Rework to avoid unbalanced .el requests.
+ (@q): Likewise.
+
+ * macros/tmac.e (@h): Set ?H, ?C , ?s registers to 0 rather than
+ removing them.
+ ()f): Likewise for * register.
+
+ * macros/tmac.e (sr): Don't ever scale the arguments. If the third
+ argument is missing, don't change $R. Call sr with three
+ arguments when initializing.
+
+Thu Jul 16 12:17:12 1992 James Clark (jjc at jclark)
+
+ * macros/tmac.e (sr): New macro.
+ Initialize $r and $R using sr.
+
+ * macros/tmac.e (,): Delete \*(#[.
+
+ * troff/env.c (set_tabs): Read the tab type even if the position
+ is bad. Allow the position of the first tab stop to be negative.
+
+Wed Jul 15 13:14:37 1992 James Clark (jjc at jclark)
+
+ * refer/dirnamemax.c: Use pathconf() if <unistd.h> defines
+ _POSIX_VERSION.
+ * refer/Makefile: Compile dirnamemax.c using -DHAVE_UNISTD_H
+ rather than -DPATHCONF_MISSING.
+ * Makefile: Get rid of PATHCONF_MISSING.
+
+ * refer/map.c: New file.
+ * refer/index.c: Interface to mmap through map.c. Rename map_size
+ to map_len.
+ * refer/Makefile: Handle map.c.
+ * Makefile: Include -DHAVE_MMAP in OLDCFLAGS rather than CFLAGS.
+
+Tue Jul 14 14:15:20 1992 James Clark (jjc at jclark)
+
+ * Makefile: RANLIB should be `true' if there is no ranlib.
+ * lib/Makefile (libgroff.a): Simplify.
+ * driver/Makefile (libdriver.a): Simplify.
+
+ * Makefile: Change -DWAIT_COREDUMP_0200 to -DWCOREFLAG=0200.
+ * groff.c (WCOREDUMP): Use WCOREFLAG. Define only if not already
+ defined.
+
+Sat Jul 11 09:19:17 1992 James Clark (jjc at jclark)
+
+ * troff/env.c (compare_ranges): Declare as extern "C".
+
+ * troff/input.c (init_registers): Use `struct tm' instead of `tm'.
+
+ * macros/tmac.s, macros/tmac.e: Change .nx /dev/null to .nx.
+
+Wed Jul 8 11:52:27 1992 James Clark (jjc at jclark)
+
+ * pic/troff.c (troff_output::text): Merge in grops_output::text,
+ but conditionalize use of \X based on \*(.T.
+ (grops_output::*): Deleted.
+ * pic/output.h: Delete declaration of make_grops_output.
+ * pic/main.c (main): Ignore -p and -x. driver_extension_flag is 1
+ by default. -n sets it to 0.
+ (usage): Corresponding changes.
+ * groff.c (main): Don't pass -x or -p to pic.
+ * groff.sh: Likewise.
+
+ * ps/ps.c (ps_printer::do_exec, ps_printer::do_file): Force ndefs
+ to be non-zero.
+
+ * ps/devps/afmtodit: Change calculation of asc_boundary and
+ desc_boundary. Make these bounds inclusive.
+ * ps/devps: Regenerate font files.
+
+Tue Jul 7 13:14:15 1992 James Clark (jjc at jclark)
+
+ * macros/tmac.latin1: New file.
+ * macros/tmac.tty-char: Use tmac.latin1.
+ (tmac.tty-tr): Deleted.
+ * macros/Makefile: Install tmac.latin1.
+ * macros/tmac.dvi: Use tmac.latin1.
+ * macros/troffrc: Translate \[char160] onto no-break space here.
+ * macros/{tmac.dvi,tmac.ps,tmac.tty,tmac.X75}: Don't do it here.
+
+Mon Jul 6 11:06:52 1992 James Clark (jjc at jclark)
+
+ * macros/tmac.Xps: Use `do' request.
+
+ * macros/tmac.ps: Use `do' request.
+
+ * macros/tmac.e (@C): Use `do' request.
+
+ * macros/tmac.X, macros/tmac.Xps: Moved from xditview.
+ * macros/Makefile: Install tmac.X*.
+
+ * tty/tmac.tty, tty/tmac.tty-char: Move to macros.
+ * tty/Makefile: Don't install tmac.tty*.
+ * macros/Makefile: Install tmac.tty*.
+
+ * dvi/tmac.dvi: Move to macros.
+ * dvi/Makefile: Don't install tmac.dvi.
+ * macros/Makefile: Install tmac.dvi.
+
+ * ps/tmac.ps*: Move to macros.
+ * ps/Makefile: Don't install tmac.ps*.
+ * macros/Makefile: Install tmac.ps*.
+
+ * eqn/box.c: Provide draw_lines parameter corresponding to -D
+ option.
+ * macros/eqnrc: Set draw_lines parameter based on device.
+ * groff.c: Don't pass -D flag to eqn.
+ * groff.sh: Likewise.
+ * eqn/main.c: Warn about use of -D.
+
+ * troff/input.c (process_startup_file): New function.
+ (main): Call process_startup_file().
+ * macros/troffrc: New file.
+ * macros/Makefile: Install troffrc.
+ * groff.c (main): Don't pass extra -m option to troff. For a
+ pseudo device pass the name of the pseudo device to troff using
+ -d.
+ * groff.sh: Likewise.
+ * groff.c (possible_command::prepend_arg): Deleted.
+
+ * troff/input.c (do_request): New function.
+ (init_input_requests): Bind "do" to do_request.
+
+ * eqn/main.c (main): Instead of loading eqnchar from device directory,
+ load eqnrc from macro directory.
+ * macros/eqnrc: New file.
+ * macros/Makefile: Install eqnrc.
+ * ps/devps/eqnchar: Deleted.
+ * ps/devps/Makefile: Don't install eqnchar.
+ * dvi/devdvi/eqnchar: Deleted.
+ * dvi/devdvi/Makefile: Don't install eqnchar.
+ * groff.c (main): Pass -M to eqn. Don't pass -F to eqn. New
+ variable optM.
+
+ * lib/device.[ch]: New files.
+ * lib/font.h (font::set_device_name, font::get_device_name):
+ Deleted.
+ * lib/fontfile.c: Use device.h.
+ * lib/Makefile: Handle device.[ch]. Make paths.h define DEVICE.
+ * troff/input.c: Delete definition of `device'.
+ (main): Don't initialize device.
+ * troff/troff.h: Include device.h rather than declaring device.
+ * troff/Makefile: No need to handle DEVICE.
+ * driver/input.c: Include device.h. Don't use
+ font::{set,get}_device_name.
+ * groff.c, Makefile: Rename device.h to config.h.
+ * groff.c: Use library device variable.
+ * eqn/main.c: Use library device variable.
+ * eqn/Makefile: No need to handle DEVICE.
+
+ * lib/searchpath.[ch]: New files.
+ * lib/Makefile: Handle searchpath.[ch].
+ * troff/input.c (open_file, init_dirs): Deleted.
+ (macro_dirs): Deleted.
+ (open_mac_file, macro_source): Use class search_path.
+ (add_string, struct string_list): Move definition.
+ (main): Change -M option to use macro_path. Delete call to
+ init_dirs().
+ * lib/fontfile.c (font::command_line_font_dir, font::open_file):
+ Rewrite to use class search_path.
+ * lib/font.h, lib/fontfile.c (font::cl_font_dirs): Deleted.
+ * lib/Makefile: fontfile.c depends on searchpath.h.
+ * lib/Makefile: Rename fontpath.h to paths.h. Make paths.h define
+ MACROPATH.
+ * lib/macropath.[ch]: New files.
+ * troff/Makefile: No need to handle MACROPATH.
+
+ * troff/input.c: Delete DUMP code.
+ * lib/fontfile.c, lib/font.h: Delete
+ font::forget_command_line_font_dirs.
+
+ * troff/input.c (push_token): New function.
+ (handle_first_page_transition): Use push_token().
+ (process_input_stack): Change handling of a space at the beginning
+ of the line.
+
+Sun Jul 5 17:11:09 1992 James Clark (jjc at jclark)
+
+ * troff/input.c (font_dirs): Delete unused variable.
+
+ * eqn/lex.c (do_set): Correct error messages.
+
+Sat Jul 4 10:20:55 1992 James Clark (jjc at jclark)
+
+ * troff/input.c (do_define_string): Allow the string name to be
+ followed immediately by a tab.
+ (define_character): Likewise.
+
+Thu Jul 2 10:59:15 1992 James Clark (jjc at jclark)
+
+ * ps/ps.c (ps_printer::draw): When drawing an arc, don't allow k to
+ be negative.
+
+ * troff/input.c (input_iterator::is_file): New virtual function.
+ (file_iterator::is_file): New function.
+ (input_stack::end_file): New function.
+ (input_stack::next_file): Handle the situation where there is no
+ file on the input stack correctly. Avoid making two passes over
+ the input stack.
+ (next_file): Make the filename optional; in this case call
+ input_stack::end_file().
+
+Wed Jul 1 10:17:25 1992 James Clark (jjc at jclark)
+
+ * dvi/tmac.dvi: Change the definitions of \(ul and _ so that they
+ produce a real _ charater when the current font is CW and _
+ otherwise.
+
+ * lib/errarg.c (errarg::errarg(const char *)): Invert conditional
+ expression to work around gcc 2.2 bug.
+
+Wed Jun 24 08:12:24 1992 James Clark (jjc at jclark)
+
+ * eqn/main.c (main): Don't give an error if we can't find eqnchar.
+
+ * troff/env.c (environment::add_padding): New function.
+ (environment::add_char): Use add_padding().
+ (environment::space): Likewise.
+ (environment::wrap_up_field): Add some padding if there is none
+ and there's no current tab.
+ * troff/env.h: Declare environment::add_padding.
+
+Mon Jun 22 08:37:45 1992 James Clark (jjc@jclark)
+
+ * pic/pic.y: undef fmod and rand before declaring them.
+
+Sun Jun 14 11:40:18 1992 James Clark (jjc@jclark)
+
+ * troff/input.c (main): If the DESC file specifies a font name of
+ 0, then leave the corresponding font position empty.
+
+ * nroff.sh: New file.
+ * Makefile (install.nobin): Install nroff.sh.
+
+ * tty/devlatin1/R.proto: Add ao as synonym for de.
+ * tty/tmac.tty-char: Define ao as o.
+
+ * tty/dev{ascii,latin1}/R.proto: Add aq.
+ * tty/tmac.tty-char: Delete definition of aq.
+
+Mon Jun 8 11:43:20 1992 James Clark (jjc@jclark)
+
+ * troff/input.c (init_charset_table): Don't translate 0240.
+ * ps/tmac.ps: Translate char160 to space.
+ * dvi/tmac.dvi: Likewise.
+ * tty/tmac.tty: Likewise.
+
+Sun Jun 7 10:52:35 1992 James Clark (jjc@jclark)
+
+ * dvi/tmac.dvi: Add support for all Latin-1 characters.
+
+ * macros/tmac.s: Delete definitions of \(rg, \(ah, \(ad, \(a-,
+ \(ao, \(ac, \(ho, \(-D, \(Sd, \(TP, \(Tp, \(ss, \(AE, \(ae, \(OE,
+ \(oe, \(r?, \(r!.
+
+ * tty/tmac.tty-char: Add \(ah.
+
+ * dvi/tmac.dvi: Add definitions of Tp, TP, Sd, -D, ho.
+ No need to define \(FM and \(!/. Conditionalize all character
+ definitions.
+
+ * ps/devps/lgreekmap: Add +h, +f, +p.
+
+ * ps/tmac.psnew: New file.
+ * ps/Makefile: Install tmac.psnew.
+
+ * troff/input.c (charinfo_to_node_list): Don't ever interpret
+ character definitions in compatible mode.
+
+ * troff/input.c (remove_character): New function.
+ (init_input_requests): Bind remove_character to "rchar".
+
+ * ps/tmac.psold: New file.
+ * ps/Makefile: Install tmac.psold.
+ * ps/tmac.ps: Load tmac.psold. Move definitions of ISO Latin-1
+ characters into tmac.psold. Make these definitions unconditional.
+
+ * tty/tmac.tty-char: Define \n(_C only if it is not already defined.
+
+ * ps/tmac.ps: Don't define \('c and \('C.
+
+ * ps/devps/textmap: Move Greek characters to...
+ * ps/devps/symbolchars:
+
+Sat Jun 6 16:41:17 1992 James Clark (jjc@jclark)
+
+ * ps/devps/text.enc: Add quotesingle.
+ * ps/devps/textmap: Add +h, +f, +p, Fn, Bq, bq, aq, lz.
+ * tty/tmac.tty-char: Likewise.
+ * dvi/devdvi/texmi.map: Add +h, +f, +p.
+ * dvi/devdvi/texi.map: Add Fn.
+ * dvi/devdvi/msam.map: Add lz.
+ * dvi/tmac.dvi: Handle Bq, bq, aq.
+
+ * pic/lex.c (get_token): Recognize 'th.
+ * pic/map.y: Allow `expr'th in contexts where ORDINAL was allowed.
+
+Fri Jun 5 11:20:46 1992 James Clark (jjc@jclark)
+
+ * ps/devps/textmap: Move di, mu, +- to...
+ * ps/devps/symbolchars:
+
+ * macros/tmac.s (@XS): Don't call par@reset or fi.
+ (XA): Call LP. Turn off adjustment. Reduce line length.
+
+ * macros/tmac.s: Initially alias XS to LP.
+ (XS): Rename to @XS.
+ (cov*ab-init): Alias XS to @XS.
+
+Thu Jun 4 09:12:05 1992 James Clark (jjc@jclark)
+
+ * troff/token.h: Delete TOKEN_CHAR_HEIGHT, TOKEN_CHAR_SLANT,
+ TOKEN_FONT_NAME, TOKEN_FONT_POSITION, TOKEN_SIZE tokens.
+ (token::is_size, token::changes_env): Deleted.
+ * troff/number.c (parse_term): No need to process \s explicitly.
+ Call tok.next() only after scale indicator has been processed.
+ * troff/input.c (do_overstrike, do_bracket): No need to process \s,
+ \f etc explicitly.
+ (token::next): Handle \s, \f, \S, \H immediately rather than
+ returning them as tokens.
+ (token::operator==, token::description, token::add_to_node_list,
+ token::process): Remove handling of deleted tokens.
+
+ * troff/env.c (environment::add_char): When adding padding
+ indicator character, call start_line() if necessary.
+
+Wed Jun 3 09:55:50 1992 James Clark (jjc@jclark)
+
+ * ps/devps/afmtodit: Don't output 0 kerns.
+
+ * ps/devps/afmtodit: Remove directory from name of encoding in
+ font description file.
+
+ * ps/devps/afmtodit: Improve error messages.
+
+ * ps/devps/afmtodit: Allow DESC file to be specified with -d.
+
+ * ps/devps/Makefile: Incorporate FontMakefile. Rework.
+ * ps/devps/FontMakefile: Deleted.
+ * ps/devps/afmname: New file.
+
+ * ps/devps/symbol.sed: New file.
+ * ps/devps/symbol.diff: Deleted.
+ * ps/devps/FontMakefile: Generate symbol.afm using symbol.sed.
+ Generate zapfdr.afm from zapfd.afm.
+
+ * tty/tmac.tty (tty-char): Prefix definition with ".
+
+ * macros/tmac.an (TP): Don't start a diversion if one has already
+ been started.
+
+ * tty/tmac.tty-char: Add Latin-1 characters.
+
+ * tty/tmac.tty-char: Incorporate suggestions from Paul Eggert.
+
+Tue Jun 2 00:54:34 1992 James Clark (jjc@jclark)
+
+ * tbl/table.c (table::allocate): Delete old_vline, old_entry.
+ Move declaration of struct horizontal_span.
+
+ * tbl/table.c (table::table): Initialize span_list.
+ (table::~table): Delete span_list.
+
+ * lib/ptable.h (PTABLE(T)::~PTABLE(T)): Delete v.
+
+ * ps/devps/Makefile: Avoid dependency on GNU make.
+
+ * ps/tmac.ps: Check that character does not already exist before
+ defining it.
+
+ * tty/tmac.tty: Add definitions of \(ff, \(!=, \(==, \(~=, \(sq,
+ \(OE, \(oe, \(AE, \(ae, \(lh, \(rh. Delete definitions of \(en,
+ \(ru, \(ul, \(br, \(bv, \(sl which are in the font description
+ files.
+
+ * tty/tmac.tty-char: New file.
+ * tty/Makefile: Install tmac.tty-char.
+ * tty/tmac.tty: Move definitions of \(ua, \(da, \(uA, \(dA into
+ tmac.tty-char.
+
+ * tty/tmac.tty: Fix definition of \(34.
+
+ * tty/dev{ascii,latin1}/R.proto: Add ha and ti. Map
+ bracket-drawing characters onto |. Add *o.
+
+ * troff/env.c (environment::wrap_up_tab): Increment field_spaces
+ only if current_field.
+
+ * troff/dictionary.c (dictionary::lookup): Free old_table after
+ rehashing.
+
+Mon Jun 1 10:15:22 1992 James Clark (jjc@jclark)
+
+ * tty/dev{ascii,latin1}/R.proto: Add uppercase Greek characters
+ whose glyphs are identical to glyphs of some Roman character.
+
+ * tty/devlatin1/R.proto (bu): Deleted.
+ * tty/devascii/R.proto (bu): Deleted.
+ * tty/tmac.tty: Add definition of \(bu.
+
+ * eqn/main.c (do_file): Pass FILE as argument.
+ (main): Automatically load eqnchar. New options -F and -n.
+ Pass do_file an opened FILE.
+ * groff.c: Don't pass eqnchar to eqn. Pass -F options onto eqn.
+ No need to include font.h.
+ * groff.sh: Likewise. Don't need to use - for standard input.
+ Prefix files with -- if first file starts with -.
+
+ * macros/tmac.e: Conditionalize use of \$* on \n(.g.
+
+ * troff/env.c (environment::possibly_break_line): Don't set line
+ to 0 across call to output_line(). Don't call output_line() until
+ after discarding nodes after break.
+
+Sun May 31 10:45:29 1992 James Clark (jjc@jclark)
+
+ * request.h (macro::empty): Declare it.
+ * input.c (macro::empty): New method.
+ (interpolate_macro): Don't give a WARN_SPACE if the two-character
+ macro is empty.
+
+Sat May 30 10:27:15 1992 James Clark (jjc@jclark)
+
+ * troff/env.c (environment::start_field): Decrement space_total
+ when a space is frozen.
+
+Fri May 22 14:34:38 1992 James Clark (jjc@jclark)
+
+ * macros/tmac.an (R): Delete macro.
+
+ * troff/input.c (get_copy, token::next): Support \# (like \" but
+ newline is ignored).
+
+ * troff/input.c (token::next): Fix error message in 'Y' case.
+
+Thu May 21 09:26:24 1992 James Clark (jjc@jclark)
+
+ * eqn/delim.c (define_extensible_string): Recognize any prefix of
+ a delimiter name.
+
+Fri May 15 10:20:41 1992 James Clark (jjc at jclark)
+
+ * c++test.c: Include <osfcn.h>.
+
+ * lib/strtol.c, lib/getcwd.c, ps/psbb.c: Declare errno in case
+ <errno.h> doesn't.
+
+Fri May 8 09:37:19 1992 James Clark (jjc at jclark)
+
+ * tbl/table.c (table::divide_span): Don't count column separation
+ if expand was specified.
+
+ * tbl/main.c (process_format): Don't ignore width specs in
+ continued format. Give warning for changing equal widths or
+ column separation in continued format.
+ (process_data): Set column separation, minimum width, equal
+ columns at end of table.
+
+Thu May 7 08:50:40 1992 James Clark (jjc at jclark)
+
+ * troff/node.c (kern_pair_node::add_discretionary_hyphen,
+ node::add_discretionary_hyphen): Use soft_hyphen_char.
+ (set_soft_hyphen_char): New function.
+ (init_node_requests): Bind to shc. Initialize soft_hyphen_char.
+
+ * Makefile (c++tested): Give more helpful message if test fails.
+
+Tue May 5 10:58:39 1992 James Clark (jjc at jclark)
+
+ * troff/input.c (init_charset_table): Translate 0240 to
+ an unbreakable space.
+
+ * troff/token.h (token::hyphen_indicator): New function.
+ * troff/charinfo.h (TRANSLATE_HYPHEN_INDICATOR): New special
+ translation.
+ * troff/input.c (translate): Allow translation to \%.
+ * troff/node.c (node::add_char): Handle
+ TRANSLATE_HYPHEN_INDICATOR.
+ (make_node): Don't allow TRANSLATE_HYPHEN_INDICATOR here.
+
+ * troff/input.c (init_charset_table): Don't set BREAK_AFTER flag
+ for \(hy.
+
+ * tty/devlatin1/R.proto: \(hy and - should print as 055.
+
+Tue Apr 21 09:24:42 1992 James Clark (jjc at jclark)
+
+ * groff.c (run_commands): If the last command gets a SIGPIPE send
+ a SIGPIPE to all children than haven't yet terminated. When
+ command terminates, set pid field to -1.
+
+Fri Apr 17 11:20:48 1992 James Clark (jjc at jclark)
+
+ * groff.c (main): Pass an appropriate -filename option to gxditview.
+
+Thu Apr 16 15:11:40 1992 James Clark (jjc at jclark)
+
+ * Makefile.bd (install): Remove existing program before copying.
+
+ * Makefile, */Makefile, Makefile.bd, groff.sh, groff.c: Allow
+ programs which have Unix counterparts to be installed with
+ user-specified prefix.
+
+ * troff/input.c (exit_troff): Don't check if exit_started.
+ (exit_request): Don't call exit_troff if exit_started.
+
+ * Makefile.bd (install.mm): Rename to install.dwbmm.
+
+Tue Apr 14 10:05:10 1992 James Clark (jjc at jclark)
+
+ * driver/input.c (do_file): Add missing break for '#' case.
+
+Mon Apr 13 10:11:02 1992 James Clark (jjc at jclark)
+
+ * troff/input.c (input_stack::clear): Clear past any boundaries and
+ then add the boundaries back.
+
+ * troff/input.c (exit_troff): Return immediately if already
+ exiting.
+
+ * macros/tmac.s (pg@end-text): New macro. Use pg@end-text for the
+ end macro.
+ (pg*end-page): If the text has ended and there are no more
+ footnotes or keeps, exit.
+
+ * macros/doc-ditroff (Lq, Rq): Define as \(lq and \(rq.
+
+ * troff/input.c (init_charset_table): Make \(rq transparent by
+ default.
+
+ * macros/tmac.an: Define lq and rq strings.
+
+ * macros/tmac.s (Q, U): Define as \(lq and \(rq.
+
+Sun Apr 12 12:54:37 1992 James Clark (jjc at jclark)
+
+ * troff/env.c (environment::final_break): New function.
+ (environment::newline): Set prev_line_interrupted to 2 if
+ exit_started.
+ * troff/env.h: Declare environment::final_break.
+ * troff/input.c (exit_troff): Call environment::final_break()
+ instead of environment::do_break().
+
+ * macros/Makefile: Install man.local if $(MACRODIR)/man.local
+ doesn't already exist.
+ * macros/man.local: New file.
+ * macros/tmac.an: Load man.local.
+ * macros/man.ultrix: New file.
+
+Sat Apr 11 17:32:04 1992 James Clark (jjc at jclark)
+
+ * troff/input.c (exit_groff): Rename to...
+ (exit_troff): New function.
+
+ * troff/div.c (exit_started, done_end_macro,
+ seen_last_page_ejector): New global variables.
+ (began_page_in_end_macro): New static variable.
+ (exit_flag): Deleted.
+ (top_level_diversion::top_level_diversion): Initialize
+ last_page_count.
+ (top_level_diversion): More elaborate test for whether
+ cleanup_and_exit() should be called.
+ Set began_page_in_end_macro if the end macro isn't yet finished.
+ * troff/div.h (top_level_diversion::last_page_count): New data
+ member.
+ (top_level_diversion::set_last_page): New function.
+ (exit_started, done_end_macro, seen_last_page_ejector): Declare.
+ * troff/env.c (do_break): Zero prev_line_interrupted.
+ * troff/input.c (exit_flag): Delete declaration.
+ (LAST_PAGE_EJECTOR): New magic cookie.
+ (token::next): Handle LAST_PAGE_EJECTOR.
+ (exit_groff): Set exit_started and done_end_macro instead of
+ exit_flag. Call top_level_diversion::set_last_page. Push a
+ LAST_PAGE_EJECTOR instead of calling push_page_ejector(). Do
+ another ejection after setting seen_last_page_ejector.
+
+Thu Apr 9 04:37:11 1992 James Clark (jjc at jclark)
+
+ * etc/grog.sh, etc/grog.sh: Recognize -me sh macro.
+
+ * macros/tmac.e (TH): Make sure there's room for the initial
+ header.
+
+ * macros/tmac.s (par@init): Make PD and DD at least \n(.V.
+ Set FVS in points rather than units.
+
+Mon Apr 6 11:21:32 1992 James Clark (jjc at jclark)
+
+ * troff/div.c (top_level_diversion::add_trap): Don't consider the
+ position of empty slots.
+
+Fri Apr 3 10:46:45 1992 James Clark (jjc at jclark)
+
+ * ps/devps/S: Fix height and depth of parenrightex.
+ * ps/devps/symbol.diff: Regenerate.
+
+Sat Mar 28 21:17:52 1992 James Clark (jjc at jclark)
+
+ * tmac.e (u): Do underlining as in -mgs.
+
+Fri Mar 27 09:23:44 1992 James Clark (jjc at jclark)
+
+ * tty/tty.c (tty_printer::end_page): If overstriking is
+ suppressed, still turn overstruck horizontal and vertical lines
+ into +.
+
+ * lib/new.c: Back out Feb 24 change; no longer needed with gcc
+ 2.1.
+
+ * refer/label.y (format_expr::evaluate): Avoid use of %0*d.
+
+Wed Mar 18 09:29:10 1992 James Clark (jjc at jclark)
+
+ * Version 1.05 released.
+
+Tue Mar 17 16:50:45 1992 James Clark (jjc at jclark)
+
+ * tty/tty.c: Instead of keeping an array of glyphs and then
+ sorting it, keep a ordered linked list of glyphs for each line.
+
+ * driver/driver.h: Include stddef.h.
+
+ * tty/tty.c (compare_glyph):
+ * refer/refer.c (rcompare):
+ * troff/env.c (compare_ranges): Arguments of qsort comparison
+ function should be const void *.
+
+ * troff/number.c (parse_term):
+ * dvi/dvi.c (draw_dvi_printer::draw): Avoid initialization in
+ switch statement.
+
+ * refer/label.y (consider_authors): Don't access variables
+ constructed under a condition outside that condition: put braces
+ round for statement containing declaration; redeclare use of same
+ variable later.
+
+ * pic/pic.y (text_expr): Delete production that allows
+ parenthesised text_expr.
+ (expr): Allow a conditional_expr to appear in parentheses.
+ (conditional_expr): Rename to any_expr.
+
+ * mm: Install new version 1.01 from jh.
+
+ * lib/font.c (font::get_width): Cache scaled widths.
+ (font::font): Initialize widths_cache.
+ (font::~font): Destroy widths_cache.
+ * lib/font.h: Add font::widths_cache. Declare font_widths_cache.
+
+Mon Mar 16 10:16:10 1992 James Clark (jjc at jclark)
+
+ * c++test.c, c++test.ref: New files.
+ * Makefile: Check that the C++ compiler works.
+
+ * ps/tmac.pspic (PSPIC): Do a break.
+
+ * ps/tmac.ps: Move definition of PSPIC into...
+ * ps/tmac.pspic: New file.
+ (PSPIC): Draw box around picture, but make it invisible to grops.
+ * ps/tmac.ps: Load tmac.pspic.
+ * ps/Makefile: Install tmac.pspic.
+
+Sun Mar 15 14:18:08 1992 James Clark (jjc at jclark)
+
+ * lib/font.c (scale_round): If n is negative,
+ subtract .5 before truncating floating point result.
+
+ * lib/fontfile.c: Include <errno.h>.
+
+Tue Mar 10 14:17:03 1992 James Clark (jjc at jclark)
+
+ * driver/input.c (get_char): Inline. Don't update current_lineno.
+ Change callers to up date current_lineno if necessary.
+ Use get_char() instead of getc(current_file).
+
+Sun Mar 8 18:05:28 1992 James Clark (jjc at jclark)
+
+ * ps/tmac.ps: Fix up spacing of \(mo and \(nm.
+
+Fri Mar 6 19:38:58 1992 James Clark (jjc at jclark)
+
+ * tty/tty.c (tmac.tty): Define \(rg as (R).
+
+Tue Mar 3 10:11:25 1992 James Clark (jjc at jclark)
+
+ * lib/lib.h: New define a_delete.
+ * Use a_delete instead of delete when deleting an array of objects
+ without destructors.
+
+ * lib/lib.h: Rename adelete to ad_delete.
+ * Change uses of adelete.
+
+Mon Mar 2 12:41:05 1992 James Clark (jjc at jclark)
+
+ * eqn/eqn.y: Include lib.h.
+
+ * troff/node.c (grow_font_table): Delete old_font_table.
+
+ * mm: Install new version from jh.
+
+Fri Feb 28 10:42:23 1992 James Clark (jjc at jclark)
+
+ * tbl/table.h (format_type): Make global instead of local to class
+ entry_format. Prefix enumerators with FORMAT_.
+ * tbl/table.c, tbl/main.c: Corresponding changes.
+ * refer/token.h (token_type): Make global. Prefix enumerators
+ with TOKEN_.
+ * refer/token.[ch]: Corresponding changes.
+ * Makefile: Get rid of -DNO_NESTED_TYPES configuration option.
+
+ * troff/div.c (node::set_vertical_size): Don't name argument.
+
+Thu Feb 27 10:29:19 1992 James Clark (jjc at jclark)
+
+ * Makefile: New configuration option ARRAY_DELETE_NEEDS_SIZE.
+ * lib/lib.h: Define adelete accordingly.
+ * pic/object.c (graphic_object::graphic_object):
+ * tbl/main.c (format::~format):
+ * tbl/table.c (table::~table):
+ * refer/ref.c (reference::~reference, reference::merge,
+ reference::insert_field, reference::delete_field): Use adelete.
+
+ * Makefile: Change NESTED_TYPES to NO_NESTED_TYPES.
+ * refer/token.h:
+ * tbl/table.h: Corresponding changes.
+
+ * common.c (common_output::dashed_arc, common_output::dotted_arc):
+ Ensure total_angle is positive.
+
+Wed Feb 26 08:49:26 1992 James Clark (jjc at jclark)
+
+ * refer/ref.c (reference::merge, reference::insert_field,
+ reference::delete_field): Avoid delete[0].
+
+ * refer/token.c (init_special_chars): Move calls to cmupper
+ outside calls to init_two_char_letter to work around bug in gcc
+ 2.0.
+
+Mon Feb 24 14:20:00 1992 James Clark (jjc at jclark)
+
+ * lib/new.c (operator new): Use __builtin_new for g++.
+
+ * pic/object.c (graphic_object::~graphic_object): Don't use
+ delete [] on 0.
+
+ * pic/object.c (output::compute_scale): Initialize max_width and
+ max_height.
+
+Sat Feb 15 09:55:20 1992 James Clark (jjc at jclark)
+
+ * troff/input.c (write_request): Call fflush.
+
+ * troff/node.h (class composite_node): Move declaration to node.c
+ * troff/input.c (charinfo_to_node): Rename to ...
+ (charinfo_to_node_list): Return node list rather than composite
+ node.
+ * troff/node.c (make_composite_node): New function.
+ (make_node, add_char): Call make_composite_node instead of
+ charinfo_to_node.
+ (class composite_node): Add a tfont * member. Delete font_size
+ member.
+ (composite_node::composite_node, composite_node::copy,
+ composite_node::size): Corresponding changes.
+ (composite_node::tprint): Provide constant spacing, emboldening
+ and track kerning as specified in tfont.
+ (composite_node::width): Change width calculation accordingly.
+ * troff/env.h (environment::composite): New member.
+ (environment::is_composite, environment::set_composite): New
+ functions.
+ * troff/env.c (environment::environment): Initialize composite.
+ * troff/input.c (charinfo_to_node): Call
+ environment::set_composite.
+ * troff/node.c (make_composite_node, make_glyph_node): Use the
+ plain version of the tfont if the environment is composite.
+
+ * troff/node.c (font_info::get_space_width): Additional argument
+ giving space_size. Handle constant space correctly. Scale by
+ space_size unless constant spaced.
+ (env_sentence_space_width): New function.
+ * troff/node.h: Declare it.
+ * troff/env.h (environment::get_space_size,
+ environment::get_sentence_space_size,
+ environment::get_narrow_space_width,
+ environment::get_half_narrow_space_width): Make inline.
+ (environment::get_space_width): Make inline. Just call
+ env_space_width.
+ * troff/env.c: Delete definitions for funtions made inline.
+ (environment::space_newline, environment::space): Use
+ env_sentence_space_width(). Don't scale by space_size.
+ * troff/node.h: Move declarations of env*space_width() functions
+ into env.h.
+
+Sat Feb 8 09:30:22 1992 James Clark (jjc at jclark)
+
+ * macros/tmac.s (PS): Don't try to set negative indent.
+
+Thu Feb 6 09:00:35 1992 James Clark (jjc at jclark)
+
+ * pic/pic.y: Fix min function.
+
+Tue Jan 28 07:52:29 1992 James Clark (jjc at jclark)
+
+ * man/mdate.sh: Clear LANGUAGE.
+
+Sun Jan 19 13:02:41 1992 James Clark (jjc at jclark)
+
+ * pic/pic.y, pic/lex.c: Rename COMMAND token to COMMAND_LINE.
+ * pic/lex.c: New COMMAND keyword.
+ * pic/pic.y (print_args, print_arg): New rules.
+ (placeless_element): Use print_args for PRINT.
+ New COMMAND element.
+
+Tue Jan 7 13:14:31 1992 James Clark (jjc at jclark)
+
+ * troff/input.c (terminal): Handle missing argument correctly.
+
+ * pic/pic.y (text_expr): New rule.
+
+ * pic/pic.y: Implement := operator.
+
+Sun Jan 5 10:23:02 1992 James Clark (jjc at jclark)
+
+ * etc/grog.pl, etc/grog.sh: Distinguish old and new versions of
+ mdoc.
+
+Sat Jan 4 14:42:26 1992 James Clark (jjc at jclark)
+
+ * ps/devps/dingbatsrmap: Include this in the distribution.
+
+ * macros/tmac.doc: Replace with new version from 2nd Networking
+ Release. Fix loading of doc-* files.
+ * macros/{doc-common,doc-ditroff,doc-nroff,doc-syms}: New files.
+ * macros/tmac.doc.old: New file. Apply fixes that had been
+ applied to old tmac.doc.
+ * macros/tmac.andoc: Check that we're running under groff.
+ * macros/Makefile: Rework.
+
+Fri Jan 3 13:27:51 1992 James Clark (jjc at jclark)
+
+ * tbl/table.h (format_type):
+ * refer/token.h (token_type): If NESTED_TYPES is defined, use
+ typedef to make these types visible at file scope.
+ * Makefile: Add NESTED_TYPES configuration option.
+
+ * troff/div.c (mark): At the top level use the value of
+ nl_reg_contents rather than the current vertical position.
+
+Thu Jan 2 10:34:51 1992 James Clark (jjc at jclark)
+
+ * tty/tty.c: Implement \D for horizontal or vertical lines.
+ (tty_printer::set_char): Use vec_used+2 as serial number.
+ Don't allow size of vector to exceed USHRT_MAX-2.
+ Split off part into...
+ (tty_printer::add_char): New function.
+ (tty_printer::draw): New function.
+ (compare_glyph): Handle equal serial numbers.
+ (tty_printer::end_page): Handle overstruck characters from \D.
+ (main, usage): Implement -d option.
+
+Mon Dec 23 10:37:51 1991 James Clark (jjc at jclark)
+
+ * tbl/main.c (process_format):
+ * eqn/text.c (split_text):
+ * troff/input.c (token::next): Use inner block for declarations
+ with initializers in switch statement.
+
+Mon Dec 16 20:52:03 1991 James Clark (jjc at jclark)
+
+ * pic/common.c (common_output::dash_line): Cope with zero-length
+ lines.
+
+Sun Nov 17 12:04:08 1991 James Clark (jjc at jclark)
+
+ * Version 1.04 released.
+
+Wed Nov 13 05:27:21 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.an (TH): Define a macro an-init to define variables
+ based on command line arguments.
+ (an-header): Call it.
+
+Sun Nov 3 12:07:34 1991 James Clark (jjc at jclark)
+
+ * Makefile (install.mm): Rename to install.dwbmm.
+
+ * Makefile: Integrate mm.
+ * mm: New directory.
+
+Wed Oct 30 10:11:34 1991 James Clark (jjc at jclark)
+
+ * refer/dirnamemax.c: If PATHCONF_MISSING is defined, include
+ <sys/types.h>.
+
+ * pic/troff.c (troff_output::simple_spline,
+ troff_output::simple_polygon): Rename variable `v' to `d' to avoid
+ shadowing parameter.
+
+ * lib/tmpfile.c (xtmpfile): Declare dir as const char *.
+
+ * lib/ptable.h: Add explicit casts when converting from unsigned
+ long to unsigned.
+
+ * dvi/devdvi/{SA,SB,msam.map,msbm.map}: New files.
+ * dvi/devdvi/Makefile: Install SA, SB.
+
+ * refer/indxbib.c: Add declaration of mktemp.
+
+ * refer/lookbib.c: Add declaration of isatty.
+
+Fri Oct 25 09:00:17 1991 James Clark (jjc at jclark)
+
+ * pic/lex.c (interpolate_macro_with_args): While collecting
+ arguments, keep track of whether we're in a string.
+
+Wed Oct 23 08:42:48 1991 James Clark (jjc at jclark)
+
+ * ps/tmac.ps (PSPIC): Do the .sp after the \X, and move the \X
+ down with \v, so as to avoid problems with top of page trap
+ setting no space mode.
+
+Tue Oct 22 17:38:49 1991 James Clark (jjc at jclark)
+
+ * eqn/lex.c (get_delimited_text): Allow tab before macro body.
+
+Tue Oct 15 17:24:53 1991 James Clark (jjc at jclark)
+
+ * ps/psrm.c (ps_get_line): Fix bug when lines longer than 255.
+ Improve error message.
+
+Fri Oct 11 11:09:38 1991 James Clark (jjc at jclark)
+
+ * ps/psrm.c (print_ps_string): Don't pass negative numbers to
+ printf("%03o");
+
+Wed Oct 9 17:50:14 1991 James Clark (jjc at jclark)
+
+ * groff.c (possible_command::execp): Always use _exit() after a
+ failed exec.
+
+ * Makefile: Add HAVE_UNION_WAIT, HAVE_PID_T, WAIT_COREDUMP_0200,
+ NO_SYS_WAIT_H configuration options.
+ * groff.c: Use these options. Use POSIX-style macros to extract
+ fields from the status returned by wait().
+
+Fri Oct 4 12:12:27 1991 James Clark (jjc at jclark)
+
+ * tbl/table.c (table::compute_separation_factor): Allow the
+ separation factor to drop to 0.
+
+Tue Oct 1 18:12:38 1991 James Clark (jjc at jclark)
+
+ * refer/search.c: Include <errno.h>.
+
+Sun Sep 29 08:40:57 1991 James Clark (jjc at jclark)
+
+ * pic/pic.y (YYDEBUG): Don't define for Borland C++.
+
+ * lib/lib.h: #ifdef out declarations of itoa and iftoa for Borland
+ C++.
+
+ * pic/lex.c (input_stack::bol): Move definition out of class body.
+
+ * pic/main.c: On MSDOS munge argv[0].
+
+ * lib/ptable.h: Define name2 as _Paste2 for Borland C++.
+
+ * lib/ptable.c (hash_string): Use unsigned long rather than
+ unsigned.
+ (next_ptable_size): Use unsigned rather than int. Give an error
+ message if we've hit the largest table size.
+ * lib/ptable.c: Corresponding changes. Also use unsigneds for the
+ table size.
+
+ * pic/object.h (object_spec): Make flags unsigned long. Declare
+ flags as const unisgned long rather than as enums.
+
+ * pic/output.c: Deleted.
+
+ * pic/troff.c (troff_output::simple_ellipse): Remove spurious %.
+
+ * tbl/table.c (simple_entry::note_double_vrule_on_{left,right}):
+ Add additional argument.
+ (line_entry::note_double_vrule_on_{left,right}): Set value of
+ douvle_vrule_on_{right,left} flag according to argument.
+ (simple_line_entry::simple_print,
+ simple_line_entry::double_line_print): If adjacent to double vrule
+ on a corner extend rather than shorten the rule by half the double
+ vrule sep.
+
+ * troff/number.c (parse_term): In checking for overflow, handle the
+ case where the current horizontal position is negative.
+
+Thu Sep 12 08:26:09 1991 James Clark (jjc at jclark)
+
+ * pic/object.c (draw_arrow): Check for object having zero length.
+
+Wed Sep 11 10:32:38 1991 James Clark (jjc at jclark)
+
+ * eqn/main.c (do_file): Split off inline equation handling into...
+ (inline_equation): New function. Search for starting delimiter
+ using...
+ (delim_search): New function. Don't recognize a delimiter that
+ occurs in the name of an escape sequence, number register, string
+ etc.
+
+Tue Sep 10 04:01:11 1991 James Clark (jjc at jclark)
+
+ * eqn/delim.c (delim_box::compute_metrics): Don't call
+ define_extensible_string if left is 0.
+ (delim_box::output): Don't print the left delimiter if left is 0.
+ (delim_box::debug_print): Check for left == 0 before calling printf.
+
+Fri Aug 23 13:02:30 1991 James Clark (jjc at jclark)
+
+ * troff/Makefile (majorminor.c): Include only digits in
+ minor_version.
+
+Thu Aug 22 09:35:37 1991 James Clark (jjc at jclark)
+
+ * refer/dirnamemax.c: new file.
+ * refer/genlimits.c: Deleted.
+ * refer/indxbib.c (main): Use dir_name_max() instead of NAME_MAX.
+ Don't check path length.
+ * refer/Makefile: Add dir_name_max.o; delete genlimits.
+ * Makefile: Add PATHCONF_MISSING option.
+
+ * refer/indxbib.c (get_cwd): New function.
+ (main): Use get_cwd().
+ * lib/getcwd.c: New file.
+ * Makefile: Delete -DHAVE_GETWD. Include GETCWD variable. Pass
+ GETCWD in SUBFLAGS.
+ * lib/Makefile: Compile getcwd.o.
+
+ * ps/tmac.psatk (psatk-defs): Define showpage after pushing
+ userdict.
+
+ * refer/indxbib.c (main): Check success of mktemp.
+
+ * lib/tmpfile.c: New file.
+ * lib/Makefile: Add tmpfile.c.
+ * lib/lib.h: Declare xtmpfile(); include <stdio.h>.
+ * ps/ps.h: Delete declaration of mktemp().
+ * ps/ps.c (ps_printer::ps_printer): Use xtmpfile().
+ * refer/refer.c (divert_to_temporary_file): Use xtmpfile().
+ * driver/driver.h: No need now to include errno.h.
+
+ * everywhere: Set errno to 0 before calling fopen().
+
+ * eqn/eqn.h, etc/soelim.c, driver/driver.h, etc/addftinfo.c,
+ dvi/tfmtodit.c, groff.c, refer/index.c, refer/linear.c,
+ refer/lookbib.c, refer/refer.h, ps/psbb.c: Include <errno.h>.
+
+Mon Aug 19 10:52:18 1991 James Clark (jjc at jclark)
+
+ * troff/env.h (translate_space_to_dummy): Declare it.
+ * troff/env.c (environment::space_newline, environment::space):
+ If translate_space_to_dummy is set then make the width of spaces 0.
+ * troff/input.c (translate): If the second character of a
+ translation is a space, translate to unbreakable space. If the
+ first character is a space, set or clear translate_space_to_dummy
+ according to whether the second character is \&. Weird!
+
+Tue Jul 30 10:03:56 1991 James Clark (jjc at jclark)
+
+ * groff.c (run_commands): Don't use non-zero exit code because a
+ command gets SIGPIPE.
+
+ * groff.c, groff.sh: Use -mXps with -TXps.
+
+ * ps/ps.c (ps_printer::special): Move call to flush_sbuf() into...
+ (ps_printer::do_exec, ps_printer::do_file, ps_printer::do_def,
+ ps_printer::do_mdef, ps_printer::do_import): Call flush_sbuf().
+ (ps_printer::special): New specials invis and endinvis.
+ (ps_printer::do_invis, ps_printer::do_endinvis): New functions.
+ (ps_printer::set_char, ps_printer::draw): Return if invis_count>0.
+ (ps_printer::end_page): Check that invis_count == 0.
+ (ps_printer::invis_count): New member.
+ (ps_printer::ps_printer): Initialize invis_count to 0.
+
+ * troff/env.c (environment::hyphenate_line): Hyphenation
+ indicator at beginning of word inhibits splitting after -, \(em
+ etc.
+
+ * pic/pic.y (element): Allow another element to follow } without
+ any intervening separator.
+
+Mon Jul 22 12:27:37 1991 James Clark (jjc at jclark)
+
+ * pic/lex.c (get_delimited): Allow tabs before delimiter.
+
+Wed Jul 17 10:59:08 1991 James Clark (jjc at jclark)
+
+ * groff.c: Get rid of HAVE_UNION_WAIT stuff. Instead suppress
+ declaration of wait() in header files.
+ * Makefile: Get rid of -DHAVE_UNION_WAIT.
+
+ * tbl/table.c (alphabetic_text_entry::add_tab): New function.
+
+ * lib/lib.h: Declare return type of strerror as char *.
+
+ * man/Makefile: Add g flag to sed substitutions.
+ * Makefile (shgroff, bindist): Likewise.
+
+Sun Jul 14 11:57:02 1991 James Clark (jjc at jclark)
+
+ * ps/ps.c (ps_printer::do_import): Move push of userdict into...
+ * ps/devps/prologue (PBEGIN): Define showpage after pushing
+ userdict.
+
+Sat Jul 13 20:53:04 1991 James Clark (jjc at jclark)
+
+ * ps/devps/prologue (PBEGIN): Zap any definition of showpage in
+ userdict.
+
+Fri Jul 12 07:10:09 1991 James Clark (jjc at jclark)
+
+ * man/mdate.sh: Handle the fact that BSD ls -l does not print the
+ group.
+
+Sun Jul 7 08:00:23 1991 James Clark (jjc at jclark)
+
+ * troff/input.c (define_number_reg): If currently undefined,
+ don't define it if the argument is an invalid expression.
+
+ * Makefile: Ignore return value of `if' commands without `else'
+ parts.
+
+ * Makefile: Split up CPPDEFINES into a series of separate
+ configuration options.
+
+ * troff/input.c (init_registers): Use time_t instead of long
+ unless LONG_FOR_TIME_T is defined. Use returned result rather
+ than passing pointer.
+ * Makefile: Document LONG_FOR_TIME_T as a CPPDEFINE.
+
+ * lib/Makefile (fontpath.h): Use gendef.
+
+Thu Jul 4 09:48:05 1991 James Clark (jjc at jclark)
+
+ * troff/input.c (input_iterator::shift): Delete argument name.
+ * troff/node.c (suppress_output_file::really_begin_page,
+ suppress_output_file::really_transparent_char, node::ascii_print,
+ node::tprint): Delete names of unused arguments.
+
+Wed Jul 3 17:34:57 1991 James Clark (jjc at jclark)
+
+ * refer/label.y (string): Pass $4 to command_error.
+
+Tue Jul 2 15:06:01 1991 James Clark (jjc at jclark)
+
+ * Version 1.03 released.
+
+Sat Jun 29 08:14:01 1991 James Clark (jjc at jclark)
+
+ * Makefile: Pass definition of SHELL in SUBFLAGS.
+
+ * gendef: New file.
+ * Makefile, eqn/Makefile, refer/Makefile, troff/Makefile,
+ ps/Makefile: Use gendef to construct header files that are
+ constructed from the Makefile.
+
+ * macros/Makefile: make all should build stripped version of tmac.e.
+
+ * refer/Makefile (clean): Remove y.output.
+
+Fri Jun 28 09:44:36 1991 James Clark (jjc at jclark)
+
+ * ps/pfbtops.c (main): Add -v option which prints out a version
+ number.
+ * ps/Makefile (pfbtops): Link with libgroff.a.
+
+Fri Jun 21 07:43:23 1991 James Clark (jjc at jclark)
+
+ * refer/search.h (linear_searcher::get_nkeys): Delete declaration.
+ * refer/linear.c (linear_searcher::get_nkeys): Delete definition.
+
+ * refer/lkbib.c (main): Always terminate reference with blank
+ line.
+ * refer/lookbib.c (main): Likewise.
+
+ * refer/linear.c (file_buffer::load): Check that the file is not a
+ binary file.
+
+ * refer/Makefile (genlimits): Possibly add -DHAVE_SYS_DIR_H.
+ (genlimits.c): Include <sys/dir.h> if HAVE_SYS_DIR_H is defined.
+ Delete second inclusion of <sys/param.h>.
+
+Tue Jun 18 01:32:26 1991 James Clark (jjc at jclark)
+
+ * troff/token.h (token::special): Deleted.
+
+ * tbl/main.c (process_format): Rework so that opt->tab_char is
+ recognized only when appropriate.
+
+ * ps/Makefile (clean): Remove pfbtops.
+
+Sun Jun 16 09:37:19 1991 James Clark (jjc at jclark)
+
+ * lib/font.c (text_file::next): Don't return if we have got a
+ blank line.
+
+Fri Jun 14 09:52:26 1991 James Clark (jjc at jclark)
+
+ * refer/refer.c (store_reference): Get hash code from old_table[i]
+ when rehashing the table.
+
+Thu Jun 13 01:26:43 1991 James Clark (jjc at jclark)
+
+ * eqn/box.c (box::top_level): Save size and prev size using \R and
+ restore it afterwards. Set the size to the size at the beginning
+ of the line.
+ * eqn/pbox.h: Declare SAVED_INLINE_PREV_SIZE_REG,
+ SAVED_INLINE_SIZE_REG, and SAVED_SIZE_REG.
+
+ * refer/Makefile (limits.h): Use ./genlimits.
+
+Wed Jun 12 16:05:34 1991 James Clark (jjc at jclark)
+
+ * refer/index.c: Delete declarations of stat() and fstat().
+
+Tue Jun 11 14:52:49 1991 James Clark (jjc at jclark)
+
+ * tty/tmac.tty: Add character definitions for \(>= and \(<=.
+
+Mon Jun 10 22:49:48 1991 James Clark (jjc at jclark)
+
+ * etc/grog.sh, etc/grog.pl: Change regex for .PS.
+
+Fri Jun 7 09:13:06 1991 James Clark (jjc at jclark)
+
+ * troff/input.c (token::get_char): Handle \e.
+
+ * refer/linear.c: Delete declarations of fstat() and stat().
+
+Wed Jun 5 09:11:59 1991 James Clark (jjc at jclark)
+
+ * troff/node.c, troff/env.c, troff/input.c, Makefile: Remove
+ OP_DELETE_BROKEN stuff, since we now have a fix for g++.
+
+Mon Jun 3 13:41:32 1991 James Clark (jjc at jclark)
+
+ * troff/input.c (do_define_macro): Improve error handling for end
+ of file while defining macro.
+
+Sun Jun 2 10:20:24 1991 James Clark (jjc at jclark)
+
+ * eqn/box.h: Fix declaration of set_gsize.
+ * eqn/box.c (set_gsize): Make argument const char *.
+ (gsize): Declare as char *.
+ * eqn/main.c (main): Don't convert gsize to int.
+ * eqn/lex.c (do_gsize): Pass char * to set_gsize.
+
+ * Version 1.02 released.
+
+Sat Jun 1 12:19:46 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.andoc: New file.
+ * macros/Makefile: Install tmac.andoc.
+
+ * troff/node.c, troff/env.c, troff/input.c: Conditionalize use of
+ operator new and delete on OP_DELETE_BROKEN not being defined.
+ * Makefile: Mention OP_DELETE_BROKEN.
+
+Mon May 27 13:49:07 1991 James Clark (jjc at jclark)
+
+ * Makefile (bindist): Pass SUBFLAGS.
+
+Sun May 26 14:13:22 1991 James Clark (jjc at jclark)
+
+ * Makefile, groff.c: Pass definitions to groff.c via device.h.
+
+ * tty/tty.c (tty_font::load_tty_font): Avoid shadowing
+ parameter.
+
+ * ps/Makefile, ps.c: Pass BROKEN_SPOOLER_FLAGS via broken.h.
+
+ * ps/ps.h, ps/psrm.c: Make comment_table and
+ header_comment_table local to resource_manager::process_file.
+
+ * groff.sh: With -TXps pass -printCommand option to gxditview.
+
+ * groff.c (possible_command::print): Implement using
+ append_arg_to_string.
+
+ * xditview: Merge in new implementation with own ChangeLog.
+
+Sat May 25 18:33:20 1991 James Clark (jjc at jclark)
+
+ * groff.c (main): Implement PRINT_OPTION.
+ (append_arg_to_string): New command.
+ (device_table): Set PRINT_OPTION flag for Xps.
+
+Fri May 24 09:48:58 1991 James Clark (jjc at jclark)
+
+ * troff/groff.h: Rename to troff.h.
+
+ * pic/lex.c (lookup_keyword, docmp): New functions.
+ (get_token): Use new lookup_keyword.
+ Don't include key.h.
+ * pic/key.[ch], pic/pic.gperf: Deleted.
+ * pic/Makefile: Remove gperf stuff.
+
+ * pic/Makefile, pic/output.h: Move definition of TEX_SUPPORT
+ into output.h.
+ * pic/tex.c: Move include of pic.h before test of TEX_SUPPORT.
+
+ * troff/Makefile, troff/node.c: Move definition of
+ STORE_WIDTH into node.c.
+
+ * etc/grog.pl, etc/grog.sh: Support -mdoc.
+
+Thu May 23 12:30:49 1991 James Clark (jjc at jclark)
+
+ * dvi/devdvi/texr.map, dvi.devdvi/texi.map,
+ dvi/devdvi/texb.map: Add lq and rq.
+ dvi/devdvi: Regenerate fonts.
+ * ps/devps/textmap: Add lq and rq.
+ * ps/devps: Regenerate fonts.
+ * tty/devascii/R.proto, tty/devlatin1/R.proto: Add lq and rq.
+ * macros/tmac.e: Define \*(lq and \*(rq to be \(lq and \(rq.
+
+ * pic/object.c (position_rectangle): When checking radius
+ cope with possiblity that width or height is negative.
+ (box_object::box_object): Have separate xrad and yrad with
+ signs matching signs of dim components.
+ (box_object::{north,south}_{east,west}): Use xrad and yrad.
+ (box_object::print): With rounded boxes use absolute values
+ for dim and rad arguments.
+
+ * lib/Makefile, lib/fontfile.o: Pass definition of FONTPATH
+ in fontpath.h.
+
+ * eqn/Makefile, eqn/main.c: Pass definition of DEVICE in device.h.
+
+ * various files: Add explicit destructors to keep Saber CC +d
+ happy.
+
+Wed May 22 11:37:11 1991 James Clark (jjc at jclark)
+
+ * eqn/box.c (box::top_level): Restore fonts correctly after
+ font changes in line containing inline equation. Also
+ restore previous font as well as current font.
+ * eqn/pbox.h: Define necessary string and register names.
+
+ * troff/input.c (token::next): Case 'R' calls do_register.
+ (do_register): New function.
+
+Tue May 21 11:28:23 1991 James Clark (jjc at jclark)
+
+ * groff.c, groff.sh: Support Xps device. Allow each device
+ to have a pseudo_name and a real_name.
+
+ * groff.c (run_commands): Don't print `Broken pipe' messages.
+
+ * ps/pfbtops.c: New file.
+ * ps/Makefile: Add pfbtops.
+
+ * troff/number.c (parse_term): Improved error message.
+
+Mon May 20 11:22:14 1991 James Clark (jjc at jclark)
+
+ * groff.c, groff.sh, etc/grog.sh, etc/grog.pl: Support grefer.
+
+ * Makefile: Integrate refer.
+ * refer: New directory.
+ * man/grefer.man, man/glookbib.man, man/gindxbib.man,
+ man/lkbib.man: New files.
+ * man/Makefile: Support refer man pages.
+
+ * lib/lib.h: Declare is_prime.
+ * lib/prime.c: New file.
+
+ * troff/input.c (macro_source): New function.
+ (init_input_requests): Bind "mso" to macro_source.
+
+ * troff/env.c (environment::possibly_break_line): Maintain
+ pointer to pointer to node to be split in ndp so as to avoid
+ using address of freed node.
+
+ * troff/env.c (environment::hyphenate_line): Maintain pointer to
+ pointer to first node to be hyphenated in startp so as to
+ avoid using address of freed node.
+
+ * troff/env.c (class trie, class hyphen_trie): Make the
+ elements of the trie be of type char not unsigned char.
+ Declare arguments to be const char* instead of unsigned char *.
+
+ * troff/env.c (hyphenate): Initialize hbuf[0].
+
+ * troff/input.c (set_string): Declare p to be char * and cast
+ *p to unsigned char when necessary.
+
+ * troff/input.c (do_define_macro): Declare s to be const
+ char*. Cast element to unisgned char when necessary, Declare
+ d to be an int. Handle EOF better.
+
+ * troff/Makefile, troff/input.c: Different scheme for passing
+ definitions of MACROPATH, HYPHENFILE and DEVICE.
+
+Tue May 14 13:41:36 1991 James Clark (jjc at jclark)
+
+ * tty/devascii/R.proto: Delete entry for em.
+ * tty/devlatin1/R.proto: Likewise.
+
+Sat May 11 11:13:28 1991 James Clark (jjc at jclark)
+
+ * troff/input.c (translate): Stop when we get a space. Treat eof
+ like newline.
+
+ * macros/tmac.an (IP): Only pass quoted argument to TP when \n(.$>1.
+
+Wed Apr 24 19:24:33 1991 James Clark (jjc at jclark)
+
+ * tbl/main.c (process_format): A font name following a `f'
+ modifier that starts with a digit can be only one character long.
+ Also deal with EOF on the second character of the font name.
+
+Wed Apr 17 11:23:43 1991 James Clark (jjc at jclark)
+
+ * troff/input.c (token::next): Turn \~ into an
+ unbreakable_space_node.
+ * troff/node.c (unbreakable_space_node): New class.
+ * troff/node.h: Declare it.
+
+Tue Apr 16 10:47:12 1991 James Clark (jjc at jclark)
+
+ * dvi/dvi.c (dvi_printer::set_char): Make code an int. Check that
+ it's >= 0, before outputting it as a single byte.
+
+Mon Apr 15 11:20:23 1991 James Clark (jjc at jclark)
+
+ * lib/font.c: Make font_char_metric::code an int.
+ (font::get_code): Change return type to int.
+ (font::load): Allow code to be arbitrary integer.
+ * lib/font.h (font::get_code): Change return type to int.
+ (font::number_to_index): Change argument type to int.
+ * troff/input.c (token::next): In case 'N', allow any value.
+ Store value in token::val.
+ (token::operator==): For TOKEN_NUMBERED_CHAR test equality of val.
+ (token::get_char, token::add_to_node_list, token::process): Get
+ number from val.
+ (charinfo::set_number): Change argument to int.
+ (charinfo::get_number): Require that NUMBERED flag be set.
+ (get_charinfo_by_number): Store numbered characters not between 0
+ and 255 in a dictionary.
+ * troff/charinfo.h (get_charinfo_by_number): Change argument type
+ to int.
+ (charinfo::number): Change type to int.
+ (charinfo::set_number): Change type of set_number to int.
+ * troff/node.c (troff_output_file::put_char_width,
+ troff_output_file::put_char): Test whether character is numbered
+ using charinfo::numbered().
+ * driver/printer.c (printer::set_numbered_char): Allow arbitrary
+ values of num.
+ * lib/nametoindex.c: New implementation to cope with arbitrary
+ number characters.
+
+ * troff/input.c (token::operator==): Test val for
+ TOKEN_CHAR_HEIGHT, TOKEN_CHAR_SLANT, TOKEN_FONT_POSITION, and
+ TOKEN_SIZE.
+
+ * man/Makefile: Add definiton of BROKEN_SPOOLER_FLAGS.
+ (.man.n): sed out @BROKEN_SPOOLER_FLAGS@.
+
+Sun Apr 14 12:57:00 1991 James Clark (jjc at jclark)
+
+ * ps/devps/zapfdr.ps: Don't copy UniqueID. Avoid use of newdict
+ variable.
+
+ * all Makefiles: rm targets of cp and >.
+
+ * xditview/xtotroff.c (MapFont): Unlink troff_name before opening
+ it.
+
+ * eqn/lex.c (def_table): Add dollar.
+
+Sat Apr 13 13:02:44 1991 James Clark (jjc at jclark)
+
+ * troff/input.c (do_width): Push back newline before closing delim
+ like do_bracket.
+
+Fri Apr 12 15:16:03 1991 James Clark (jjc at jclark)
+
+ * groff.c (possible_command::prepend_arg): New function.
+ (main): Prepend device -m option.
+ * groff.sh: Put device -m options before command-line options.
+
+Tue Apr 9 10:24:43 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.an (IP): Quote argument to TP.
+
+ * ps/ps.c (main): New option -b, which sets...
+ (broken_flags): New variable.
+ (ps_printer::~ps_printer): Incorporate the setup section in the
+ prolog if (broken_flags & NO_SETUP_SECTION).
+ (ps_printer::begin_page): Generate {Begin,End}PageSetup comments.
+ (ps_printer::merge_download_fonts, ps_printer::merge_import_fonts,
+ ps_printer::merge_ps_fonts, ps_printer::print_font_comment,
+ ps_printer::print_needed_font_comment,
+ ps_printer::print_supplied_font_comment,
+ ps_printer::print_include_font_comments,
+ ps_printer::lookup_doc_font, ps_printer::download_fonts,
+ ps_printer::read_download_file, read_document_fonts, add_font,
+ skip_line, parse_fonts_arg, document_font::document_font,
+ document_font::~document_font, document_font::download,
+ ps_output::include_file): Deleted.
+ (ps_printer::~ps_printer): Generate %%EOF. Generate %!PS-Adobe-3.0
+ rather than %!PS-Adobe-2.0. Make calls to
+ resource_manager::need_font for each font that we used. Replace
+ calls to merge_ps_fonts, merge_download_fonts, print_font_comment,
+ print_supplied_font_comment, print_needed_font_comment by call to
+ resource_manager::print_header_comments. Output %%Orientation
+ comment. Output %%Requirements: numcopies comment if ncopies > 1.
+ Don't output the prolog directly. Instead call
+ resource_manager::output_prolog. Only define #copies when ncopies
+ > 1. Delete calls to print_include_font_comments and
+ download_fonts. Add call to resource_manager::document_setup.
+ (ps_printer::do_file): Call resource_manager::import_file instead
+ of including it ourselves.
+ (ps_printer::do_import): Likewise. Also don't call
+ merge_import_fonts. Push userdict on the dictionary stack before
+ and pop it afterwards.
+ Move declaration of ps_output into ps.h.
+ * ps/psrm.c: New file implementing resource_manager class.
+ * ps/ps.h: New file declaring ps_output and resource_manager
+ classes.
+ * ps/devps/zapfdr.ps:
+ * ps/devps/symbolsl.ps:
+ * ps/devps/prologue: Use 3.0 conventions.
+ * ps/Makefile: Pass definition of BROKEN_SPOOLER_FLAGS in DEFINES.
+ Add default definition of BROKEN_SPOOLER_FLAGS.
+ * Makefile: New variable BROKEN_SPOOLER_FLAGS. Add
+ BROKEN_SPOOLER_FLAGS to SUBFLAGS.
+
+Mon Apr 8 09:26:54 1991 James Clark (jjc at jclark)
+
+ * etc/grog.pl: New file.
+ * Makefile (GROG): New variable.
+ Add GROG to SUBFLAGS.
+ * etc/Makefile (GROG): New variable.
+ (install.nobin): Install $(GROG) rather than grog.sh.
+
+Thu Apr 4 11:36:45 1991 James Clark (jjc at jclark)
+
+ * eqn/special.c (special_box::compute_metrics): Make the input and
+ output strings the same. Get the new height and depth from the
+ predefined height and depth registers. Also make subscript kern
+ and skew available.
+ (special_box::compute_subscript_kern, special_box::compute_skew):
+ New functions.
+
+ * eqn/box.c (pointer_box::compute_skew,
+ simple_box::compute_metrics, box::top_level)
+ * eqn/text.c (prime_box::compute_metrics,
+ prime_box::comput_subscript_kern)
+ * eqn/limit.c (limit_box::compute_metrics):
+ * eqn/delim.c (build_extensible, delim_box::compute_metrics):
+ * eqn/sqrt.c (sqrt_box::compute_metrics): Protect possibly
+ negative numbers in `nr' requests with a leading 0.
+
+Wed Apr 3 15:58:23 1991 James Clark (jjc at jclark)
+
+ * eqn/special.c: New file.
+ * eqn/eqn.y: Declare token SPECIAL. Make it right associative.
+ Add new rule for simple.
+ * eqn/lex.c (token_table): Add SPECIAL.
+ * eqn/box.h: Declare make_special_box.
+ * eqn/Makefile: Add special.[co].
+
+Sat Mar 30 10:57:53 1991 James Clark (jjc at jclark)
+
+ * ps/devps/prologue: Possibly set packing to true while defining.
+ Create grops dictionary here. Initialize local variables before
+ defining procedures.
+ (PICTURE): Rename to PBEGIN. Also do save, noop showpage, count
+ the dictionary stack. Set strokeadjust and overprint to false if
+ the relevant operators are defined.
+ (PEND): New procedure.
+ * ps/ps.c (ps_printer::~ps_printer): In the prolog just include
+ prologue. Do everything else in the setup section.
+ (ps_printer::do_import): Just call PBEGIN and PEND around the
+ picture. Also push userdict before, and pop it afterwards.
+
+Wed Mar 27 07:59:50 1991 James Clark (jjc at jclark)
+
+ * troff/node.c (bracket_node::tprint): Brackets were being printed
+ 1m too low.
+
+ * macros/tmac.an (SH, SS): Set fill mode.
+
+Tue Mar 26 07:46:31 1991 James Clark (jjc at jclark)
+
+ * troff/div.c (top_level_diversion::begin_page): Set
+ high_water_mark to 0.
+
+Fri Mar 22 09:19:46 1991 James Clark (jjc at jclark)
+
+ * man/mdate.sh: New file.
+ * man/mdate.c: Deleted.
+ * man/Makefile: Use mdate.sh instead of mdate.
+ (mdate): Deleted.
+
+ * eqn/lex.c (do_gsize): Supply missing argument to error message.
+
+Tue Mar 19 11:06:50 1991 James Clark (jjc at jclark)
+
+ * man/mdate.c: New file.
+ * man/*.man: Replace modification date by @MDATE@.
+ * man/Makefile (.man.n): Replace @MDATE@ by `mdate $<`.
+ (mdate): New target.
+
+ * lib/font.c (text_file::next): Deal with arbitrarily long lines.
+ Remove illegal input characters.
+
+Mon Mar 18 08:32:25 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.s (pg*start-col): Do .ns *after* running the hooks.
+
+Sat Mar 16 03:52:25 1991 James Clark (jjc at jclark)
+
+ * troff/div.c (begin_page): Change behaviour when
+ !first_page_begun and !break_flag.
+
+ * troff/input.c (do_name_test): Return 0 if argument is empty.
+
+ * troff/input.c (read_long_escape_name): Require closing ] to be
+ at same input level as opening [.
+
+ * troff/input.c (read_increment_and_escape_name): New function.
+ (get_copy, process_input_stack): Use this for \n.
+
+Fri Mar 15 00:31:48 1991 James Clark (jjc at jclark)
+
+ * troff/div.c (top_level_diversion::begin_page): Ignore the
+ current value of page_number if !first_page_begun.
+
+ * groff.c (main): Fix declaration of buf.
+
+ * troff/input.c (do_name_test): New function.
+ (token::next): Implement \A.
+ (token::next): Implement \e by turning it into a TOKEN_ESCAPE.
+ (token::description, token::add_to_node_list, token::process):
+ Handle TOKEN_ESCAPE.
+ * troff/token.h: New token TOKEN_ESCAPE.
+
+Thu Mar 14 10:22:26 1991 James Clark (jjc at jclark)
+
+ * pic/main.c (do_picture): Allow space before and after filename
+ following `<'. Check that the filename is not empty.
+
+Wed Mar 13 12:49:40 1991 James Clark (jjc at jclark)
+
+ * Version 1.01 released.
+
+ * dvi/devdvi/CompileFonts: Add cm*ss10 fonts.
+
+ * dvi/tmac.dvi: ftr HR to H.
+
+ * macros/tmac.e: Round up computation of $r.
+
+ * xditview/tmac.X: Don't give up completely in compatibility mode.
+ Use \n(.s instead of \n[.s].
+
+ * dvi/tmac.dvi: Don't give up completely in compatibility mode.
+ Use \(ci instead of \[ci]. Use \n(.s instead of \n[.s].
+ Add u to factors inside \s[...]. Rename frac to dvi-frac.
+ Translate \(FM onto \[prime] and \(!/ onto \[slashnot]; use these
+ short names in the char definitions.
+
+ * ps/tmac.ps: Don't give up completely in compatibility mode.
+ Fix the fraction definitions to use \n(.s and \(f/. Add an extra
+ quote in front of \n(.s. Add u to factors inside \s[...].
+
+Mon Mar 11 12:01:20 1991 James Clark (jjc at jclark)
+
+ * tty/tmac.tty: Call the nroff request.
+
+ * macros/tmac.e ((x, )x): Better definitions that work properly
+ in a diversion.
+ (@0, @1): Helper macros for (x.
+
+ * macros/tmac.e ($s, hl): Use \l rather than \D.
+
+ * tty/tmac.tty: Make it work better in compatibility mode.
+ (pchar): Rename to tty-char.
+
+ * macros/tmac.e (@E): New macro.
+ (r, i, b, rb, bi): Use @E.
+
+ * macros/tmac.e (@F): Don't use (;...) syntax.
+
+ * macros/tmac.e: Remove mention of \*(||/revisions. Mention that
+ it was modified for groff.
+
+ * macros/tmac.e: Make sure \n(ps and \n(es are >= \n(.V.
+
+ * macros/tmac.e (<., .>): Removed.
+ ([., .]): If \n(.V>=1v, use [] instead of superscripting.
+
+ * macros/tmac.e: Remove check that groff is being used.
+
+ * macros/tmac.e (@C): Change families only if using groff; turn
+ compatibility mode off while changing familes. Save compatibility
+ mode before changing families and restore it afterwards.
+
+ * macros/tmac.e (@h): Remove test for offset + line length.
+
+ * macros/tmac.e (sorry): Rename to @S. Use \$1 instead of \$0
+ (lo, th, ac): Define to call @S instead of using als.
+
+ * macros/tmac.e: Make $r and $R now contain \n(.v*100/\n(.sp, ie
+ the ratio of the vertical spacing to the point size in units
+ expressed as a percentage. Use these instead of $10r and $10R,
+ Delete $10r and $10R.
+
+ * lib/font.c (font::load): In default computation of space_width,
+ divide by sizescale. Use scale_round.
+
+ * macros/tmac.an (TP): Don't call `nf'.
+ (an-do-tag): Don't call `fi'.
+
+Sun Mar 10 09:52:35 1991 James Clark (jjc at jclark)
+
+ * troff/input.c (process_input_stack): Handle the case where
+ spaces at the beginning of an input line are followed by a
+ newline.
+
+Thu Mar 7 20:18:07 1991 James Clark (jjc at jclark)
+
+ * groff.c (device_table): Add PIC_X_OPTION for dvi device.
+ * groff.sh: Use pic -x with the dvi device.
+
+ * dvi/devdvi/FontMakefile (H): Don't use -s.
+
+ * dvi/devdvi/HI, dvi/devdvi/HB: New files.
+ * dvi/devdvi/Makefile: Add HI and HB to FONTS.
+ * dvi/devdvi/FontMakefile: Add rules for HI and HB. Include these
+ in FONTS.
+
+Mon Mar 4 13:20:14 1991 James Clark (jjc at jclark)
+
+ * ps/psfig.diff: New file.
+ * ps/tmac.psfig: New file.
+
+Sat Mar 2 00:15:09 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.s (]=, ref*do-tl, ref*bib-print): Deleted.
+ (]-): Don't call ref*do-tl.
+
+ * macros/tmac.s (ref*end-print): Use XP if [F not defined.
+
+ * macros/tmac.s (ref*normal-print): Call FS rather than fn@do-FS.
+ (fn@do-FS): Rename to fn*do-FS.
+
+ * troff/input.c (transparent_translate): New function.
+ (process_input_stack): Apply transparent_translate before calling
+ diversion::transparent_output(unsigned char).
+
+Wed Feb 27 00:13:25 1991 James Clark (jjc at jclark)
+
+ * troff/input.c (do_define_macro): Define the macro before calling
+ skip_line.
+
+ * xditview/Makefile: Add DEVICES variable. Change install target
+ to use this.
+
+Tue Feb 26 10:46:22 1991 James Clark (jjc at jclark)
+
+ * groff.c (run_commands): Handle the possibility that there are
+ child processes other than those forked by us.
+
+Sun Feb 24 21:32:30 1991 James Clark (jjc at jclark)
+
+ * lib/string.c (string::append): New function.
+ * lib/stringclass.h: Declare it.
+
+Thu Feb 21 11:49:26 1991 James Clark (jjc at jclark)
+
+ * eqn/main.c (main): New option -N which sets
+ no_newline_in_delim_flag.
+ (do_file): If no_newline_in_delim_flag is set don't allow newlines
+ in delimiters.
+ * groff.c (main): Pass -N on to eqn.
+ (help, synopsis): Mention -N.
+ * groff.sh: Implement -N.
+
+Wed Feb 20 15:16:10 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.s (]=, ref*bib-print, ref*do-tl): New macros.
+ (]-): Call ref*do-tl if ref*need-tl is non-zero.
+ (XP): Allow as initializer.
+
+Tue Feb 19 14:09:06 1991 James Clark (jjc at jclark)
+
+ * troff/env.c (environment::wrap_up_field): If field_spaces are
+ non-zero and we have a current_tab, subtract padding from
+ tab_distance. If this makes tab_distance <= 0, use the next tab
+ stop instead. If there isn't any next tab or it's a left tab,
+ wrap up the current tab.
+ (environment::start_field): Initialize tab_precedes_field.
+ (environment::wrap_up_tab): If there's a current field, update
+ pre_field_width, field_distance and tab_precedes_field.
+ * troff/env.h (environment::tab_precedes_field): New member.
+
+Fri Feb 15 01:24:00 1991 James Clark (jjc at jclark)
+
+ * ps/ps.c (ps_printer::do_file): New function.
+ (ps_printer::special): Bind to `file' special.
+ (ps_printer::do_exec): Set ndefined_styles to 0.
+
+Sat Feb 9 03:03:04 1991 James Clark (jjc at jclark)
+
+ * eqn/text.c (split_text): Grok \* and similar escapes sequences.
+ Avoid stripping first character from the start of unrecognized
+ escapes. Use lex_error instead of error to report errors.
+ * eqn/lex.c (get_token): Rework handling of escapes.
+ (lex_error): Move declaration into...
+ * eqn/eqn.h.
+
+ * xditview/xditview.c (main): Make -page option work.
+
+ * Makefile: Correct comment about -DBROKEN_SPOOLER and pageview.
+
+Wed Feb 6 12:28:43 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.s (B2): Correct size of box.
+
+Tue Feb 5 00:37:35 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.s (B2): Postpone drawing the box until in the
+ top-level diversion.
+
+ * tty/tmac.tty: Add font translations for C, CR, CW.
+
+ * groff.c (synopsis, help): Document -i.
+ * groff.sh: Implement -i.
+
+ * macros/tmac.s (@NH): Put a `.' after multi-part numbers.
+ Simplify the construction of SN.
+
+ * troff/number.c (parse_term): Give `|' a higher precedence.
+ * tbl/table.c (numeric_text_entry::simple_print): Parenthesise
+ accordingly.
+
+ * macros/tmac.s (B2): Use par@finish instead of par@reset.
+
+Mon Feb 4 12:36:09 1991 James Clark (jjc at jclark)
+
+ * lib/string.c (string::move): New function.
+ * lib/stringclass.h: Declare it.
+
+Sat Feb 2 16:02:16 1991 James Clark (jjc at jclark)
+
+ * troff/env.c (distribute_space): Add optional argument
+ `force_forward'.
+ (environment::wrap_up_field): Call distribute_space with
+ `force_forward' argument of 1.
+
+Fri Feb 1 19:36:33 1991 James Clark (jjc at jclark)
+
+ * lib/string.c, lib/stringclass.h (string::operator+=(char)):
+ Inline it. Move reallocation into...
+ (string::grow1): New function.
+ * pic/Makefile, tbl/Makefile, eqn/Makefile, ps/Makefile: Redo
+ dependencies to include library header files.
+ * lib/Makefile: Make string.c and lf.c depend on stringclass.h.
+
+Thu Jan 31 15:02:27 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.s (@NH): Use the same number registers than -ms does
+ for the heading level counters. Use the same string that -ms does
+ for the number for this heading.
+
+Wed Jan 30 14:25:40 1991 James Clark (jjc at jclark)
+
+ * lib/new.c (operator new): Cast result of malloc to char *.
+
+ * troff/input.c (spring_trap, lookup_request): Add assert that nm
+ is not null.
+
+Tue Jan 29 18:08:05 1991 James Clark (jjc at jclark)
+
+ * groff.c (main): Support -i.
+
+Sun Jan 27 13:23:17 1991 James Clark (jjc at jclark)
+
+ * pic/pic.h: Include <osfcn.h>.
+
+ * ps/ps.c: Add declaration of mktemp.
+
+ * Makefile: Add -DHAVE_UNION_WAIT option for CPPDEFINES.
+ * groff.c: If HAVE_UNION_WAIT is defined, declare wait()'s
+ argument as union wait *.
+ (run_commands): If HAVE_UNION_WAIT is defined cast wait()'s
+ argument to union wait *.
+
+Sat Jan 26 12:04:52 1991 James Clark (jjc at jclark)
+
+ * tty/tmac.tty: Add definition of \(co.
+
+ * pic/object.c (make_arc): Only increase radius when radius
+ strictly less than d.
+ (arc_object::update_bounding_box): May need to add 4.0 to end_quad
+ more than once.
+
+ * troff/env.c (environment::environment(symbol),
+ environment::environment(const environment *)): Initialize
+ input_trap_count.
+
+Sat Jan 19 08:18:35 1991 James Clark (jjc at jclark)
+
+ * tbl/main.c (main): Add exit(0).
+
+ * ps/ps.c (ps_printer::~ps_printer): Use fseek instead of rewind.
+
+ * pic/main.c (main):
+ * eqn/main.c (main):
+ * tbl/main.c (main):
+ * etc/soelim.c (main):
+ * driver/printer.c (printer::~printer):
+ * troff/node.c (real_output_file::~real_output_file,
+ real_output_file::flush): Check for errors on stdout.
+
+ * most files: Add 1991 to copyright notice.
+
+ * macros/tmac.s: Don't test \n(.x and \n(.y.
+
+ * troff/input.c (token::next): Rename `escape_char' label to
+ `handle_escape_char' and `normal_char' label to
+ `handle_normal_char'.
+
+Thu Jan 17 15:46:35 1991 James Clark (jjc at jclark)
+
+ * groff.c (main, synopsis, help): Support -a option.
+ * groff.sh: Likewise. Also eliminate Zflag variable by adding -z
+ to trflags while parsing options.
+
+Tue Jan 15 13:07:27 1991 James Clark (jjc at jclark)
+
+ * troff/number.c (parse_term): With `m', `M' and `n' scale
+ indicators, convert scale factor to hunits before scaling.
+
+Mon Jan 14 12:39:12 1991 James Clark (jjc at jclark)
+
+ * lib/font.c (scale_round): Better test for overflow when n is
+ negative.
+
+Thu Jan 10 11:10:56 1991 James Clark (jjc at jclark)
+
+ * tbl/main.c (process_format): Add second argument of type
+ options*. Change callers. Allow opt->tab_char as well as '\t'
+ between format items.
+
+Mon Jan 7 12:30:18 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.an (PD): With no arguments, make sure register PD is
+ at least \n[.V].
+ (TH): Call PD with no argument, instead of setting register PD
+ directly.
+
+Sun Jan 6 11:18:39 1991 James Clark (jjc at jclark)
+
+ * Version 1.00 released.
+
+Sat Jan 5 08:44:30 1991 James Clark (jjc at jclark)
+
+ * ps/tmac.ps, xditview/tmac.X: Add font translation of C to CR.
+
+ * dvi/devdvi/DESC: Mount CW instead of CR.
+
+ * dvi/tmac.dvi: Add definition of \(tm.
+
+ * dvi/devdvi/texsy.map: Add lh, and rh.
+ * dvi/devdvi/texex.map: Add lt, rt, lb, rb, lk, rk.
+ * dvi/devdvi/texmi.map: Add *o. Regenerate fonts.
+
+ * dvi/devdvi/FontMakefile: Generate H from cmss10.
+ * dvi/devdvi/Makefile: Install H.
+ * dvi/devdvi/H: New file.
+
+Fri Jan 4 15:04:57 1991 James Clark (jjc at jclark)
+
+ * troff/env.c (vertical_spacing): Don't allow vertical spacing to
+ be 0.
+
+Thu Jan 3 13:41:19 1991 James Clark (jjc at jclark)
+
+ * macros/tmac.s (@EN): Add \n(.V to the argument to ds@need.
+
+ * macros/tmac.pic (PS): Avoid attempting to set negative indent.
+
+ * macros/tmac.s (@EN): Handle the case where the equation is empty
+ but the label is not.
+
+Wed Jan 2 10:31:44 1991 James Clark (jjc at jclark)
+
+ * troff/groff.h: New warning category WARN_SPACE.
+ * troff/input.c: Add WARN_SPACE to DEFAULT_WARNING_MASK. Add
+ WARN_SPACE to warning_table.
+ (interpolate_macro): Give a warning of type WARN_SPACE if the name
+ is longer than two characters and is not defined, but the first
+ two characters do make a defined name.
+
+ * PROBLEMS: New file.
+
+ * CHANGES: New file.
+ * README-0.6, README-1.00: Deleted.
+
+ * groff.c, groff.sh: Add X75-12 and X100-12 devices.
+ * xditview/devX75/Makefile: Make devX75-12.
+ * xditview/devX100/Makefile: Make devX100-12.
+
+ * xditview/devX100/eqnchar, xditview/devX75/eqnchar,
+ dvi/devdvi/eqnchar, ps/devps/eqnchar: Remove use of \R.
+
+Tue Jan 1 19:24:01 1991 James Clark (jjc at jclark)
+
+ * README-0.7: Rename to README-1.00.
+
+ * macros/tmac.pic: New file.
+ * macros/Makefile (install.nobin): Install tmac.pic.
+
+Mon Dec 31 10:40:53 1990 James Clark (jjc at jclark)
+
+ * troff/env.c (hyphen_word): Correct the test for whether the
+ token is a hyphen. Reset npos to 0.
+
+ * macros/tmac.s (par@sup-start, par@sup-end): New implementations.
+
+Sun Dec 30 15:53:13 1990 James Clark (jjc at jclark)
+
+ * macros/tmac.s (ds*common-end): Call par*reset.
+ (PE): Likewise.
+ (par@reset-indent): Deleted.
+
+ * macros/tmac.s (@IP): Divert the label.
+
+Sat Dec 29 14:33:32 1990 James Clark (jjc at jclark)
+
+ * xditview/draw.c (setGC): Use a line width of .1m rather than
+ .04m by default; round rather than truncate value.
+
+ * tbl/table.c (class empty_entry): New class.
+ (empty_entry::empty_entry, empty_entry::line_type): New functions.
+ (table::add_entry): Represent empty entries by objects of type
+ empty_entry.
+ (table_entry::line_type): Return -1.
+ (table::determine_row_type): Ignore entries with line_type 0.
+ Treat type -1 as non-lines.
+
+Fri Dec 28 15:04:41 1990 James Clark (jjc at jclark)
+
+ * ps/devps/textmap, xditview/libXdvi/DviChar.c, tty/devlatin1/R.proto,
+ macros/tmac.s: Rename \(-d to \(Sd.
+
+Thu Dec 27 12:35:47 1990 James Clark (jjc at jclark)
+
+ * ps/devps/textmap: Add `sd', `/_' and `3d' characters.
+ * xditview/libXdvi/DviChar.c: Likewise.
+ * dvi/devdvi/texsy.map: Add `<<', `>>'.
+
+Wed Dec 26 13:33:23 1990 James Clark (jjc at jclark)
+
+ * troff/div.c (top_level_diversion::begin_page): Call
+ init_output() if the_output is 0.
+
+Sat Dec 22 12:35:29 1990 James Clark (jjc at jclark)
+
+ * troff/input.c: Replace ESCAPE_E by ESCAPE_e and ESCAPE_C by
+ ESCAPE_c.
+ (get_copy): Turn \E into ESCAPE_E.
+ (token::process, asciify): Handle ESCAPE_E.
+
+ * macros/tmac.s (ds*common-end, par@reset): Add `.rj 0'.
+ (RD): New macro.
+ (DS): Implement `.DS R'.
+
+Fri Dec 21 11:41:53 1990 James Clark (jjc at jclark)
+
+ * macros/tmac.s (FS): New macro.
+
+ * macros/tmac.s (fn@do-FS): Use @LP instead of LP.
+
+ * macros/tmac.s (cov*tl-init): Remove after first execution
+ instead of aliasing to @nop. Call top of page macro explicitly
+ instead of setting trap; call @init first. Set pg@top as top of
+ page macro.
+ (cov*auto-init): Deleted. Set cov*tl-init instead of
+ cov*auto-init as top of page trap.
+ (TL, LP): Do a break instead of calling cov*tl-init.
+ (cov*print): With RP format but no TL, alias FS and FE to @FS and
+ @FE; in this case also give a warning and always start another
+ page. No need to set pg@top here.
+ (cov*tl-init): Rename to cov*first-page-init.
+
+ * macros/tmac.s (RP): Do `.pn 0'.
+ (cov*tl-init): With RP format don't do `.pn 0'.
+
+ * macros/tmac.s (pg@cs-top): Set no space mode.
+
+ * macros/tmac.s (par@TL, par@AU, par@AI): New macros.
+ (cov*ab-init): Alias TL, AU and AI to these.
+
+Thu Dec 20 10:10:50 1990 James Clark (jjc at jclark)
+
+ * macros/tmac.s (@EQ): Move the space before the equation into @EN
+ (@EN): Do nothing unless \n[dl] is > 0.
+
+Tue Dec 18 12:20:47 1990 James Clark (jjc at jclark)
+
+ * pic/object.c (ellipse_object::radius): New function.
+
+ * VERSION: Change version to 0.7.
+
+ * tbl/table.c (block_entry::do_divert): Declare return type as
+ void.
+ (block_entry::divert, alphabetic_block_entry::divert): Return 1.
+
+Mon Dec 17 12:30:34 1990 James Clark (jjc at jclark)
+
+ * troff/column.c: New file.
+ * troff/Makefile: Corresponding changes.
+
+ * troff/hvunits.c (scale(vunits, vunits, vunits)): New function.
+ Friend of vunits.
+
+ * troff/div.c (top_level_diversion::space): If the space causes
+ the first-page transition and springs a trap, truncate the space
+ to 0.
+
+Fri Dec 14 12:30:02 1990 James Clark (jjc at jclark)
+
+ * ps/ps.c (ps_printer::do_import): Add a `clear' after including
+ the document.
+
+ * pic/troff.c (troff_output::line_thickness,
+ troff_output::set_fill): Do a horizontal motion to compensate for
+ the width of the \D escape sequence.
+
+Thu Dec 13 10:17:14 1990 James Clark (jjc at jclark)
+
+ * xditview/tmac.X: Reinstate definition of \(rn, but only for X100
+ (not X75).
+
+ * eqn/sqrt.c (sqrt_box::compute_metrics): Supply missing argument
+ to printf.
+
+ * tbl/table.c (simple_entry::simply_print): Don't declare as pure.
+ Supply empty definition.
+ (text_entry::simple_print, simple_text_entry::simple_print):
+ Delete declarations.
+ (table::add_entry): Represent empty entries by objects of type
+ `simple_entry'.
+
+Wed Dec 12 08:50:48 1990 James Clark (jjc at jclark)
+
+ * troff/Makefile: Remove -DHYPHEN_CONTROL from DEFINES.
+
+ * tbl/table.c (left_text_entry::add_tab): New function.
+
+ * macros/tmac.s: Make @RT an alias for par@reset. Make RT
+ initialize like LP.
+
+Mon Dec 10 11:19:55 1990 James Clark (jjc at jclark)
+
+ * troff/env.c (environment::start_field): Give an error message if
+ there is no next tab.
+
+Sun Dec 9 11:46:40 1990 James Clark (jjc at jclark)
+
+ * troff/env.c (hyphenate): Skip initial elements with zero
+ hyphenation code.
+
+ * macros/tmac.s (par@init): Keep VS in points rather than units.
+
+Sat Dec 8 23:00:27 1990 James Clark (jjc at jclark)
+
+ * pic/main.c (main): Implement `-c' option.
+ * pic/output.h: Declare make_tpic_output().
+ * pic/tex.c (tex_output::set_pen_size): Make it virtual and
+ protected.
+ (tpic_output): New class.
+ (tpic_output::tpic_output, tpic_output::set_pen_size,
+ tpic_output::command, make_tpic_output): New functions.
+
+Fri Dec 7 11:57:41 1990 James Clark (jjc at jclark)
+
+ * tbl/main.c (main): Call `.ab' if \n(.g is false. Define TS/TE
+ if they're not already defined.
+ * tbl/table.c (init_output): Don't test \n(.g.
+
+ * troff/input.c (do_if_request): Delete `g' condition. Recognize
+ `d', `r' and `c' conditions even in compatibility mode.
+
+Tue Dec 4 09:13:47 1990 James Clark (jjc at jclark)
+
+ * ps/tmac.ps (ps-bb): Protect against negative numbers in bounding
+ box.
+
+Mon Dec 3 07:18:26 1990 James Clark (jjc at jclark)
+
+ * troff/env.h (environment::prev_line_interrupted): New member.
+ (environment::get_prev_line_interrupted): New function.
+ * troff/env.c (environment::newline): Set prev_line_interrupted.
+ (environment::environment(const environment *),
+ environment::environment(symbol)): Initialize
+ prev_line_interrupted.
+ * troff/input.c (process_input_stack): Don't give special
+ treatment to space and newline at the beginning of the line if the
+ previous line was interrupted.
+
+Sat Dec 1 15:48:37 1990 James Clark (jjc at jclark)
+
+ * eqn/eqn.y: Disallow PRIME by itself.
+ * eqn/lex.c (token_table): Bind `opprime' instead of `prime' to
+ PRIME.
+ (def_table): Remove definition of '. Define prime to be `.
+
+ * eqn/eqn.y: Split off part of rule `script' into a new rule
+ `nonsup'.
+
+Fri Nov 30 10:23:44 1990 James Clark (jjc at jclark)
+
+ * macros/tmac.s ({, }): New string aliases.
+
+Thu Nov 29 11:34:40 1990 James Clark (jjc at jclark)
+
+ * README-0.7: New file.
+
+Wed Nov 28 10:09:57 1990 James Clark (jjc at jclark)
+
+ * macros/tmac.s: New file.
+ * man/groff_ms.man: New file.
+ * Makefile: Add definition of TMAC_S. Pass TMAC_S in SUBFLAGS.
+ * Makefile.bd: Similarily.
+ * man/Makefile: Add groff_ms.n to MAN7PAGES. Replace @TMAC_S@. Add
+ definition of TMAC_S.
+ * macros/Makefile: Add definition of TMAC_S. Install tmac.s.
+ * macros/TODO: New file.
+
+Sat Nov 24 20:04:54 1990 James Clark (jjc at jclark)
+
+ * troff/env.c (right_justify): New function.
+ (init_env_requests): Bind this to request "rj".
+ (center_lines): Set right_justify_lines to 0. If we get a bad
+ integer, center 1 line.
+ (environment::environment(symbol), environment::environment(const
+ environment *)): Initialize right_justify_lines.
+ (environment::get_right_justify_lines): New function.
+ (init_env_requests): Bind this to number_register ".rj".
+
+ * troff/env.c (environment::choose_breakpoint): Implement
+ hyphenation_margin and hyphenation_space.
+ (environment::get_hyphenation_space,
+ environment::get_hyphenation_margin): New functions.
+ (init_env_requests): Bind these to .hys and .hym.
+ (hyphenation_space_request, hyphenation_margin_request): New
+ functions
+ (init_env_requests): Bind these to hys and hym.
+ (environment::environment(symbol), environment::environment(const
+ environment *)): Initialize hyphenation_margin and
+ hyphenation_space.
+ * troff/env.h: Corresponding changes to class environment.
+
+Fri Nov 23 09:08:16 1990 James Clark (jjc at jclark)
+
+ * troff/div.c (blank_line): Always do a break.
+
+ * eqn/box.c (do_text): Turn off escapes while appending text to
+ string.
+
+Thu Nov 22 10:58:59 1990 James Clark (jjc at jclark)
+
+ * troff/input.c (while_break_request, while_continue_request): New
+ functions.
+ (init_input_requests): Bind these to "break" and "continue".
+ (while_depth, while_break_flag): New variables.
+ (while_request): Update while_depth. Break out of loop if
+ while_break_flag is set.
+
+Wed Nov 21 10:54:40 1990 James Clark (jjc at jclark)
+
+ * tbl/table.c (init_span_reg): Initialize span_width_reg to \n(.H
+ rather than 0.
+
+Mon Nov 19 00:45:03 1990 James Clark (jjc at jclark)
+
+ * Makefile: Include -DBROKEN_SPOOLER by default. Expand comment.
+
+ * stringify: New file.
+ * Makefile (groff.o): Use stringify.
+
+ * xditview/tmac.X: Remove definition of \(rn.
+ * xditview/libXdvi/DviChar.c: Remove radicalex from
+ Adobe_symbol_map.
+
+Sat Nov 17 10:44:58 1990 James Clark (jjc at jclark)
+
+ * tbl/table.c (table::add_entry): Allow alphabetic text blocks.
+ (alphabetic_block_entry::alphabetic_block_entry,
+ alphabetic_block_entry::divert, alphabetic_block_entry::print):
+ New functions.
+ (block_entry::divert): Split off body into ...
+ (block_entry::do_divert): If the block is alphabetic, subtract 2n
+ from the line length; also update the span width to dl+2n, and the
+ alphabetic span width to dl.
+
+ * driver/input.c (do_file): While reading argument to D command,
+ when expanding buffer, multiply szp by sizeof(int) rather than 2
+ in the argument to memcpy.
+
+ * tbl/table.c (compute_span_width): Add 2n rather than 1n to the
+ width of alphabetic columns.
+
+Fri Nov 16 06:34:27 1990 James Clark (jjc at jclark)
+
+ * troff/node.c (lookup_family): Supply second argument to lookup.
+
+ * troff/dictionary.c (dictionary::lookup): After an unsuccesful
+ search, return immediately if v is 0.
+
+ * pic/troff.c: Define EQN_NO_EXTRA_SPACE_REG.
+ (troff_output::start_picture): Set this reg.
+ (troff_output::end_picture): Remove this reg
+ * eqn/box.c (box::extra_space): Don't produce `\x's if
+ EQN_NO_EXTRA_SPACE_REG is defined.
+
+ * eqn/eqn.y: Allow just a PRIME to be a `simple'.
+ * eqn/text.c (split_text): Map ' to \(fm when it's the first
+ character.
+
+Thu Nov 15 10:35:06 1990 James Clark (jjc at jclark)
+
+ * macros/tmac.e: Use font 3 instead of B in $c. Remove `bd'
+ requests.
+
+ * troff/div.c (top_level_diversion::top_level_diversion):
+ Initialize page_number to 0.
+
+Wed Nov 14 21:41:58 1990 James Clark (jjc at jclark)
+
+ * groff/troff (environment::environment(const environment *)):
+ Initialize name to e->name, rather than "anonymous".
+
+Sat Nov 10 01:59:37 1990 James Clark (jjc at jclark)
+
+ * xditview/libXdvi/Dvi.c (ShowDvi): If eof is encountered, reset
+ requested_page. Split middle part into ...
+ (FindPage): New function.
+ (SetValues): If we don't yet know the last page, and the requested
+ page is greater than the current page, call FindPage.
+ Update the font_map_string before doing this.
+
+ * xditview/tmac.X: Add definitions of \(sq, \(ga, \(dg and \(dd.
+ Translate \(lh and \(rh into left and right double arrows.
+
+ * troff/node.c (class hyphen_inhibitor_node): New class.
+ (hyphen_inhibitor_node::hyphen_inhibitor_node,
+ hyphen_inhibitor_node::copy, hyphen_inhibitor_node::same,
+ hyphen_inhibitor_node::type,
+ hyphen_inhibitor_node::get_hyphenation_type): New functions.
+ (node::add_discretionary_hyphen): Use hyphen_inhibitor_node rather
+ than dbreak_node(0, 0) to represent a `\%' at the beginning of a
+ word.
+
+Fri Nov 9 16:05:38 1990 James Clark (jjc at jclark)
+
+ * troff/node.h (dummy_node::get_hyphenation_type,
+ transparent_dummy_node::get_hyphenation_type): Declare them.
+ * troff/node.c: (dummy_node::get_hyphenation_type,
+ transparent_dummy_node::get_hyphenation_type): New functions.
+
+Wed Nov 7 10:09:06 1990 James Clark (jjc at jclark)
+
+ * xditview/libXdvi/draw.c: If M_PI not defined after including
+ math.h, then define it.
+
+ * xditview/Makefile: Add definition of AR. Pass it to the submake
+ in libXdvi.
+ * xditview/libXdvi/Makefile: Add definitions of AR and RANLIB.
+
+Tue Nov 6 10:14:27 1990 James Clark (jjc at jclark)
+
+ * troff/dictionary.h (object_dictionary::alias): Declare return
+ value as int.
+ * troff/dictionary.c (object_dictionary::alias): Return non-zero
+ if the old name was defined.
+ * troff/input.c (alias_macro): Give a warning if the old name was
+ not defined.
+ * troff/reg.c (alias_reg): Likewise.
+
+Mon Nov 5 00:31:39 1990 James Clark (jjc at jclark)
+
+ * troff/input.c (token::next): Delete implementation of \R.
+
+ * macros/Makefile: Strip comments from tmac.e while installing it.
+
+ * troff/input.c: New variable `nroff_mode'.
+ (troff_request, nroff_request): New functions.
+ (init_input_requests): Bind `troff' and `nroff' to troff_request
+ and nroff_request.
+ (do_if_request): Compute results of t and n conditions from
+ nroff_mode.
+
+ * text/text.c (split_text): Fix typo in >=.
+
+ * eqn/lex.c: Add definition of `==' to def_table.
+
+Fri Nov 2 02:49:09 1990 James Clark (jjc at jclark)
+
+ * pic/tex.c (tex_output::start_picture): Change the definitions of
+ \graph and \graphtemp so that they work properly with Plain TeX.
+
+ * pic/tex.c (tex_output::solid_arc): Ensure that the second angle
+ argument to `ar' is not less than the first.
+
+ * pic/pic.y: Allow a comma between elements of the variable list
+ in the argument to `reset'.
+
+ * pic/object.c (arc_object::arc_object): Fix computation of
+ radius.
+
+ * eqn/main.c (main): Add exit(0).
+
+Thu Nov 1 02:03:50 1990 James Clark (jjc at jclark)
+
+ * troff/div.c (begin_page): Test no_space_mode after doing the
+ break, but still push the page ejector cookie before doing the
+ break. Also set the next page number after doing the break.
+
+ * xditview/xditview.c (NewFile): Don't set the title and icon name
+ if this is the first file and its name is `-'.
+ * groff/groff.c: Define a new device flag XT_OPTION. Set it for
+ the X75 and X100 devices.
+ (main): If a device has the XT_OPTION flag set and there's exactly
+ one file argument, pass the driver -xrm and -title options to set
+ the icon name and window title to the name of the file.
+
+ * troff/env.c (environment_switch): If there was an argument but
+ it wasn't a valid number or name, then pop an environment but
+ don't give an error message on underflow.
+
+ * troff/number.c (start_number): Correct spelling in error message.
+
+ * troff/input.c (token::delimiter): Don't print an error message
+ if err is false.
+
+ * xditview/libXdvi/parse.c (ParseInput): In case 'D', only call
+ ParseDrawFunction if dw->display_enable is true.
+
+Wed Oct 31 05:49:50 1990 James Clark (jjc at jclark)
+
+ * pic/pic.y: Parse text positioning like normal attributes, so as
+ to allow `"text" at 0,0 ljust'. Don't allow `center' as a
+ positioning attribute.
+
+Mon Oct 29 22:50:38 1990 James Clark (jjc at jclark)
+
+ * tbl/main.c (process_data): When in state START while reading a
+ text block, don't change to state MIDDLE if c is a newline.
+
+Sun Oct 28 21:59:56 1990 James Clark (jjc at jclark)
+
+ * dvi/dvi.c (dvi_printer::begin_page): Rename `i' variable to `j'
+ so as to avoid shadowing parameter.
+
+Wed Oct 24 18:35:39 1990 James Clark (jjc at jclark)
+
+ * tbl/table.c (trim_space): Deleted.
+ (table::add_entry): Don't call trim_space.
+
+Mon Oct 22 03:48:39 1990 James Clark (jjc at jclark)
+
+ * VERSION: Change version to 0.6.
+
+ * troff/number.c (parse_expr): Make == work.
+
+Sat Oct 20 11:28:17 1990 James Clark (jjc at jclark)
+
+ * man/grog.man: New file.
+ * man/Makefile: Add grog.n to MAN1PAGES.
+ * etc/grog.sh: New file.
+ * etc/Makefile: Install grog.sh as grog.
+
+Fri Oct 19 11:17:15 1990 James Clark (jjc at jclark)
+
+ * troff/input.c (token::next): Implement \E.
+
+Thu Oct 18 11:56:24 1990 James Clark (jjc at jclark)
+
+ * xditview/tmac.X: Change font translations to match tmac.ps.
+
+ * troff/input.c (non_empty_name_warning): Don't give a warning if
+ `\{' terminates the name.
+
+Tue Oct 16 10:04:23 1990 James Clark (jjc at jclark)
+
+ * ps/devps/symbol.diff: New file.
+ * ps/devps/FontMakefile: Mention symbol.diff.
+
+Sun Oct 14 11:46:46 1990 James Clark (jjc at jclark)
+
+ * troff/node.c (font_position): Use get_long_name to read the
+ external_name.
+
+ * troff/env.c (environment_switch): If we get a number that's < 0
+ or >= NENVIRONMENTS, treat it like a name.
+ Change NENVIRONMENTS to 10.
+
+ * troff/groff.h: Remove definition of FONTS_MAX.
+ * troff/node.h (class font_family): Make map a pointer instead of
+ an array. Add a map_size member. Make it a class. Make nm const
+ and public. Make invalidate_fontno a friend.
+ * troff/node.c: Define font_table_size. Make font_info a pointer
+ rather than an array.
+ (class troff_output_file): Allocate font_position dynamically. Add
+ nfont_positions member.
+ (troff_output_file::set_font): Grow font_position if necessary.
+ (troff_output_file::~troff_output_file): Delete font_position.
+ (troff_output_file::troff_output_file): Allocate font_position.
+ (grow_font_table): New function.
+ (troff_output_file::really_begin_page,
+ troff_output_file:really_copy_page): Use nfont_positions rather
+ than FONTS_MAX.
+ (mount_font_no_translate, mount_style): Call grow_font_table if
+ necessary.
+ (font_family::font_family): Allocate map.
+ (font_family::make_definite): Grow map if necessary. Use
+ font_table_size instead of FONTS_MAX.
+ (font_family::~font_family): New function.
+ (invalidate_fontno): Use font_family::map_size.
+ (get_fontno, env_space_width, env_half_narrow_space_width,
+ env_narrow_space_width, symbol_fotno, is_good_fontno,
+ get_bold_fontno, make_glyph_node): Use font_table_size rather than
+ FONTS_MAX.
+ (next_available_font_position): Never return 0.
+
+Fri Oct 12 10:17:52 1990 James Clark (jjc at jclark)
+
+ * ps/tmac.ps: Add font translations for compatibility with dpost.
+
+Thu Oct 11 12:09:03 1990 James Clark (jjc at jclark)
+
+ * eqn/pile.c: Rename default_baseline_sep to baseline_sep.
+ Move BASELINE_SEP_FORMAT and COLUMN_WIDTH_FORMAT into pbox.h.
+ Move definitions baseline_sep, shift_down, column_sep,
+ matrix_side_sep into...
+ * eqn/box.c: Add them to param_table.
+ * eqn/pbox.h: Add declarations to pbox.h.
+
+ * troff/input.c (set_string): Cast value to unsigned char *.
+
+ * troff/token.h (process_input_stack): Declare it static before
+ declaring it a friend.
+
+Wed Oct 10 09:59:13 1990 James Clark (jjc at jclark)
+
+ * dvi/devdvi/texex.map: Fix positions of extensible brace middle
+ and bottom.
+ * dvi/devdvi/EX: Regenerate.
+
+ * troff/input.c (init_charset_table): Make ", ', ), ], *, \(dg
+ transparent.
+
+Tue Oct 9 08:34:02 1990 James Clark (jjc at jclark)
+
+ * eqn/lex.c: In defaults_table, make definition of `dot' call
+ `dot_def'. Don't explicitly make it roman. Similarily for other
+ accents.
+
+ * pic/lex.c (for_input::for_input): Add by_is_multiplicative
+ argument.
+ (for_input::get, for_input::peek): Use this.
+ (do_for): Add by_is_multiplicative argument.
+ * pic/pic.y: Change optional_by clause to allow '*' after `by'.
+ Change semantic value of optional_by to be a double plus a flag
+ saying whethet the by clause is multiplicative.
+
+ * eqn/lex.c (get_delimited_text): Remember location of start of
+ definition. Improve error handling when EOF is encountered.
+
+ * lib/font.h: Rename handle_x_command to
+ handle_unknown_font_command.
+ * lib/font.c (font::load): Call handle_unknown_font_command for
+ any unknown command in the font description file. Don't call
+ handle_x_command. Include the name of the command in the argv.
+ Improve message for unknown command after kernpairs or charset
+ command.
+ * ps/ps.c (ps_font::handle_x_command): Rename to
+ handle_unknown_font_command. Remove message about `x download'
+ command. Give error message for wrong number of arguments.
+ * ps/devps/afmtodit: Generate `encoding' instead of `x encoding'.
+ * dvi/dvi.c (dvi_font::handle_x_command): Rename to
+ handle_unknown_font_command. Give an error message for wrong
+ number of arguments. Rename design_size to designsize.
+ * dvi/tfmtodit.c (main): Generate `checksum' instead of `x
+ checksum', `designsize' instead of `design_size'.
+
+Mon Oct 8 00:38:55 1990 James Clark (jjc at jclark)
+
+ * eqn/*.[chy]: Change underaccent to uaccent.
+
+ * eqn/eqn.y: Add rule for underaccent. Declare UNDERACCENT token;
+ give it the same precedence as ACCENT.
+ * eqn/other.c (make_underaccent_box): New function.
+ * eqn/box.h: Declare it.
+ * eqn/lex.c: Add UNDERACCENT to token_table. Add utilde to
+ def_table.
+
+Sun Oct 7 11:25:16 1990 James Clark (jjc at jclark)
+
+ * pic/pic.y (reset_all): New function. Called in rule for RESET.
+ (parse_init): Call reset_all.
+ (define_variable): When defining scale reset only those
+ pre-defined variables that are scaled.
+ (defaults_table): Add `scale' as non-scaled value.
+
+ * pic/pic.y: Redo parsing of text adjustments: parse adjustments
+ together with the text; allow any number of positioning words;
+ allow center as a positioning word.
+
+ * pic/object.c (output::compute_scale): Get picture maximum height
+ and width from variables called maxpswid and maxpsht.
+ * pic/pic.y: Add maxpswid and maxpsht to defaults_table.
+
+Sat Oct 6 10:16:56 1990 James Clark (jjc at jclark)
+
+ * pic/object.c (object_spec::make_text): Multiply textht by number
+ of text items.
+
+ * pic/pic.y: Allow `sprintf("string", expr,...)' wherever text can
+ occur.
+ (do_sprintf): New function.
+ (pic.gperf): Add sprintf token.
+ (text, sprintf): New rules.
+
+ * pic/pic.y: `rand()' with no arguments returns a random number
+ in the range [0,1).
+
+ * pic/pic.y: Allow a bare expression to be an attribute: change
+ precedences to support this. Change optional_ordinal rule to
+ optional_ordinal_last to avoid reduce/reduce conflict.
+ * pic/object.c (object_spec::object_spec): Initialize direction.
+
+ * pic/pic.y: Implement ^ operator meaning exponentiation.
+
+ * troff/node.h: Add default argument to mount_font.
+ * troff/node.c (font_position): Read an optional third argument
+ giving the external_name.
+ (mount_font): Add optional argument giving the external_name.
+ (mount_font_not_translate): Have additional argument giving
+ external name. Use this name to load the font. Pass both names
+ to font_info::font_info.
+ (font_info::font_info): Have additional argument giving
+ external_name.
+ (class tfont): New member external_name.
+ (font_info::get_tfont): Use external name to construct tfont_spec.
+
+Fri Oct 5 04:03:13 1990 James Clark (jjc at jclark)
+
+ * eqn/lex.c (init_table): Add argument giving device. Define
+ name of device to be "1".
+ (do_ifdef): Counts as true if the argument has been defined with
+ `define'.
+ * eqn/main.c (main): Call init_table with device argument. Make
+ device local to main.
+ * eqn/eqn.h: Change declaration of init_table. Remove declaration
+ of device.
+
+ * pic/lex.c (get_delimited): Allow text to be delimited by
+ matching {}s. Don't recognize ending delimiter within a string.
+
+ * troff/input.c (get_delim_name): New function.
+ (token::next): Implement \C.
+
+ * lib/font.c (font::load): Grok ---. Add an alias for each
+ character based on its code.
+ (font::get_code_width): Deleted.
+ * lib/font.h (class font): Declare font::number_to_index().
+ Remove declaration of font::get_code_width.
+ * lib/nametoindex.c (font::name_to_index): Add 512 rather than 256
+ to indices of named characters.
+ (font::number_to_index): New function.
+ * troff/input.c (font::number_to_index): New function.
+ (get_charinfo_by_number, charinfo::get_number,
+ charinfo::set_number): New functions.
+ (token::next): Turn \N into a TOKEN_NUMBERED_CHAR.
+ (token::process, token::description, token::get_char,
+ token::add_to_node_list, token::operator==): Handle
+ TOKEN_NUMBERED_CHAR.
+ * troff/charinfo.h: Declare get_charinfo_by_number,
+ charinfo::get_number, charinfo::set_number. Add NUMBERED flag to
+ charinfo class.
+ (charinfo::numbered): New function.
+ * troff/token.h: Add TOKEN_NUMBERED_CHAR.
+ * troff/env.h (class environment): Remove declaration of ...
+ * troff/env.c (environment::make_numbered_char_node): Deleted.
+ * troff/node.c (make_numbered_node): Deleted.
+ (class numbered_glyph_node): Remove.
+ (troff_output_file::put_char_width, troff_output_file::put_char):
+ Handle numbered chars.
+ (troff_output_file::numbered_char): Removed.
+ (tfont::get_code_width): Removed.
+ (make_glyph_node): Don't search special fonts for numbered
+ characters.
+ * troff/node.h: Remove declaration of make_numbered_node.
+ * driver/input.c (do_file): Handle N command.
+ * driver/printer.h: Add declaration of ...
+ * driver/printer.c (printer::set_numbered_char): New function.
+ * dvi/tfmtodit.c (main): Generate unnamed entries.
+ * ps/devps/afmtodit: Likewise.
+ * xditview/xtotroff.c (MapFont): Likewise.
+ * xditview/libXdvi/parse.c (ParseInput): Grok N command.
+
+ * tbl/main.c (process_format): If multiple widths are specified
+ for a column but all the widths are the same, don't give an error
+ message.
+
+ * tbl/table.c (table::do_row): If the current row is all lines and
+ the stuff doesn't contains a line, mark the top of the row after
+ printing stuff before the row. If the current row is not all
+ lines and the stuff doesn't contain a line, don't unnecessarily
+ mark the top of the row before printing the stuff.
+
+Mon Oct 1 11:42:00 1990 James Clark (jjc at jclark)
+
+ * troff/groff.h: Remove MAX_PATH.
+ * troff/input.c (open_file): Dynamically allocate space for the
+ path.
+ (open_mac_file, process_macro_file): Corresponding changes.
+
+Sun Sep 23 18:56:26 1990 James Clark (jjc at jclark)
+
+ * troff/node.h (class output_file): Make copy_file pure. Add
+ vspace method ifdef COLUMN. Add is_printing method.
+ * troff/node.c: Add class printing_reg. Add class
+ real_output_file. Derive other output_file classes from
+ real_output_file; in these classes rename begin_page to
+ really_begin_page, print_line to really_print_line, copy_file to
+ really_copy_file, transparent_char to really_transparent_char.
+ Move output_file::flush to real_output_file. Add printing member
+ to class output_file.
+ * troff/div.h: Remove printing member from top_level_diversion.
+ Add vspace member function to class diversion ifdef COLUMN. Add
+ some declarations ifdef COLUMN.
+ * troff/div.c (top_level_diversion::copy_file,
+ top_level_diversion::transparent_output,
+ top_level_diversion::output): Don't test printing member before
+ output.
+ * troff/input.c: Handle initial variable_space_request ifdef
+ COLUMN.
+ * troff/Makefile: Add column.c but comment it out. Add -DCOLUMN
+ but comment it out.
+
+Sat Sep 22 11:32:22 1990 James Clark (jjc at jclark)
+
+ * troff/div.c (diversion::need): Make any space forced. If we
+ sprung a trap, set truncated_space to minus the distance to the
+ trap and set needed_space to the amount that was needed.
+ (top_level_diversion::space): A forced space turns no_space_mode
+ off.
+ (class constant_vunits_reg): New class.
+ (init_div_requests): Implement number registers .trunc and .ne
+ using constant_vunits_reg.
+ (class truncated_space_reg): Deleted.
+
+ * troff/div.h: Don't have a no_space_mode member in diversion.
+ Instead have it in top_level_diversion.
+ * troff/div.c (diversion::diversion): Don't initialize
+ no_space_mode.
+ (top_level_diversion::top_level_diversion): Initialize
+ no_space_mode.
+ (no_space, restore_spacing): Do nothing if curdiv != topdiv.
+ (macro_diversion::output): Don't clear no_space_mode.
+
+ * troff/input.c (diverted_space_node::reread): Don't call
+ environment::do_break. In fill mode, act like a blank line.
+ (diverted_copy_file_node::reread): Don't call
+ environment::do_break.
+
+ * troff/div.c (blank_line): New function.
+ * troff/div.h: Declare it.
+ * troff/input.c (process_input_stack): Call it.
+
+ * troff/div.c (truncated_space_reg::get_string): New function.
+ (init_div_requests): Bind to .trunc.
+ (space_request, top_level_diversion::space,
+ top_level_diversion::output, macro_diversion::space,
+ macro_diversion::output): Update truncated_space.
+ (macro_diversion::output): Redo calculations when trap sprung.
+ (macro_diversion::output, macro_diversion::space): No need for
+ trap_flag.
+
+ * troff/div.c (top_level_diversion::output): Set nl_reg_contents
+ after truncating post line spacing.
+
+Fri Sep 21 11:27:25 1990 James Clark (jjc at jclark)
+
+ * ps/devps/prologue (MF, SF): Make them work even if setfont is
+ defined as a procedure rather than as an operator.
+
+Thu Sep 20 12:55:05 1990 James Clark (jjc at jclark)
+
+ * troff/div.c (macro_diversion::space): Ignore no_space_mode.
+
+Wed Sep 19 10:54:37 1990 James Clark (jjc at jclark)
+
+ * troff/div.c (top_level_diversion::output): Merge
+ output_file::print_line and output_file::end_of_line member
+ functions.
+ * troff/div.h (class output_file):
+ * troff/node.c (troff_output_file::print_line,
+ troff_output_file::end_of_line, output_file::end_of_line,
+ ascii_output_file::print_line, suppress_output_file::print_line):
+ Corresponding changes.
+
+Tue Sep 18 11:31:47 1990 James Clark (jjc at jclark)
+
+ * troff/input.c (token::next): Don't give a warning for `\.'.
+
+ * troff/env.c (environment::get_center_lines): New function.
+ (init_env_requests): Bind number register .ce to it.
+ * troff/env.h: Declare it.
+ * tbl/table.c (table::init_output): Define reset macro to restore
+ .ce. If center option not given, store .ce in SAVED_CENTER_REG.
+ Then do .ce 0.
+ (table::print): If center option not given, then imply center
+ option if SAVED_CENTER_REG > 0.
+
+Mon Sep 17 09:19:19 1990 James Clark (jjc at jclark)
+
+ * ps/devps/Makefile: Remove T from FONTS. Remove TSymbol.ps and
+ Troff.ps from DOWNLOAD.
+
+ * troff/Makefile: Change comment in DEFINES to avoid confusing
+ System V make.
+
+ * ps/ps.c (ps_printer::do_exec): Allow newlines within PostScript
+ code. Don't try to catch errors with stopped.
+ (check_line_lengths): New function.
+ * ps/devps/prologue (EXEC): Deleted.
+ (EBEGIN, EEND): New procedures.
+
+Sun Sep 16 14:51:15 1990 James Clark (jjc at jclark)
+
+ * troff/input.c: Include request.h before node.h.
+ * troff/node.c: Likewise.
+ * troff/env.c: Likewise.
+ * troff/div.c: Likewise.
+ * troff/node.h (class special_node): Store argument as a macro
+ rather than a char *.
+ * troff/node.c (special_node::special_node, special_node::copy):
+ Grok this.
+ (special_node::~special_node): Deleted.
+ (special_node::tprint): Deleted.
+ (special_node::tprint_start, special_node::tprint_end,
+ special_node::tprint_char): New functions.
+ (troff_output_file::special): Deleted.
+ (troff_output_file::start_special, troff_output_file::end_special,
+ troff_output_file::special_char): New functions.
+ * troff/input.c (special_node::tprint): New function.
+ (do_special): Use macro not char *.
+ (do_transparent_macro): Deleted.
+ (token::next): Don't call do_transparent_macro.
+
+ * troff/input.c (token::next): Add 'Y' case.
+ (do_transparent_macro): New function.
+ * troff/node.c (troff_output_file::special): Handle newlines with
+ argument using new continuation convention.
+ * driver/input.c (get_string): Cope with continuation convention.
+ (do_file): Don't call skip_line after calling get_string(1).
+ * ps/ps.c (ps_printer::special, ps_printer::do_import,
+ ps_printer::do_def, ps_printer::do_exec): Cope with newlines in
+ arg.
+ * xditview/libXdvi/parse.c (ParseInput): Ignore lines starting
+ with +.
+
+Sat Sep 15 19:00:10 1990 James Clark (jjc at jclark)
+
+ * troff/input.c (asciify): By default, illegal input characters
+ should return empty string.
+
+ * troff/input.c (copy_file): Handle first page transition like title.
+ (token::next, process_input_stack): Grok COPY_FILE_REQUEST.
+
+ * troff/input.c (token::next): Improve error message for EOF after
+ escape character.
+ (input_char_description): New function.
+ (get_char_for_escape_name): Use input_char_description.
+ (token::next): Warn about unrecognized escape sequences.
+ (warning_table): Add WARN_ESCAPE.
+ * troff/groff.h: Declare WARN_ESCAPE. Change WARN_TOTAL
+ accordingly.
+
+ * troff/token.h: Remove declaration of process_input_stack.
+
+ * troff/input.c: Remove declaration of init_hyphen_requests.
+ * troff/request.h: Correct spelling in declaration of same.
+
+ * troff/input.c (token::next): Check whether escape_char is 0.
+
+Fri Sep 14 12:09:25 1990 James Clark (jjc at jclark)
+
+ * groff.c (main, usage, help): Implement -P and -L options.
+ * groff.sh: Likewise.
+
+ * troff/input.c (token::next): Use some gotos to avoid code
+ duplication.
+
+ * troff/input.c (get_long_name, get_name, read_long_ecsape_name):
+ Avoid calling symbol::symbol if name empty.
+
+Thu Sep 13 06:21:45 1990 James Clark (jjc at jclark)
+
+ * troff/input.c (init_input_requests): Make \n(.x return the major
+ version number and \n(.y return the minor version number.
+ * troff/Makefile: Construct file majorminor.c defining
+ major_version and minor_version automatically from ../VERSION.
+
+ * troff/node.c (class glyph_node): Make operator new and operator
+ delete public.
+ (class ligature_node): Similarily.
+
+ * troff/input.c (operator==(const macro &, const macro &)): New
+ function.
+ (non_interpreted_node::same): Use this.
+ (string_iterator::string_iterator): Make macro& argument const.
+
+ * troff/input.c (input_iterator::get): New function. Don't make
+ asciify_macro or class non_interpreted_node friends of class
+ input_iterator.
+ (non_interpreted_node::interpret): Use input_iterator::get.
+ (asciify_macro): Likewise.
+
+ * troff/input.c (~token_node, ~string_iterator, ~arg_list,
+ ~non_interpreted_node): Deleted.
+ * troff/node.c: (~suppress_output_file, ~ascii_output_file):
+ Deleted.
+
+ * troff/symbol.h: Make all symbol member functions const.
+
+ * lib/strtol.c: New file.
+ * lib/Makefile: Add strtol.c.
+ * Makefile: Define STRTOL as strtol.o to include strtol in
+ libgroff.a.
+
+Wed Sep 12 10:00:49 1990 James Clark (jjc at jclark)
+
+ * pic/troff.c (troff_output::simple_circle): Divide by scale.
+
+Tue Sep 11 14:17:16 1990 James Clark (jjc at jclark)
+
+ * troff/input.c (do_special): Use input_level.
+
+ * troff/token.h (TOKEN_BACKSPACE): New token.
+ (token::backspace): New function.
+ * troff/input.c (token::description, token::next, token::process):
+ Grok TOKEN_BACKSPACE.
+ (do_special): Turn TOKEN_BACKSPACE back into \b.
+
+ * troff/token.h (token::leader): New function.
+ * troff/input.c (do_special): Turn TOKEN_LEADER back into \001.
+
+ * troff/input.c (do_special): Turn TOKEN_TAB back into \t.
+
+ * troff/input.c (do_special): Use token::description in error
+ message.
+
+Mon Sep 10 11:06:27 1990 James Clark (jjc at jclark)
+
+ * troff/input.c (decode_args): Combine quoted and
+ quote_input_level variables. Make it a for (;;) loop.
+
+ * troff/input.c (get_char_for_escape_name): Check for \001 and \b.
+
+ * troff/input.c (read_long_escape_name): The test for whether to
+ expand buffer was off by 1.
+ (read_string): Similarily.
+
+Fri Sep 7 11:45:50 1990 James Clark (jjc at jclark)
+
+ * troff/input.c: Use `const int' rather than `static const int'.
+
+ * troff/div.h (diversion::copy_file): Declare as pure virtual.
+ (macro_diversion::copy_file): New function.
+ * troff/node.h: New class diverted_copy_file_node.
+ * troff/node.c: Implement it.
+ * troff/input.c (copy_file): Use diversion::copy_file. Handle
+ first page transition by pushing a diverted_copy_file_node.
+ * troff/input.c (token::next, process_input_stack): Don't handle
+ COPY_FILE_REQUEST.
+
+Thu Sep 6 13:29:10 1990 James Clark (jjc at jclark)
+
+ * ps/ps.c (flush_sbuf): Remember to add sbuf_kern when checking
+ whether space widths need adjusting.
+
+ * troff/charinfo.h: Generalize translated_to_space to
+ special_translation so as to allow translation to \&.
+ * troff/input.c (translate): Allow translation to \&.
+ (charinfo::*): Corresponding changes.
+ * troff/node.c (make_node, node::add_char): Corresponding changes.
+ * troff/node.h (dummy_node::dummy_node): Allow optional first
+ argument.
+
+ * lib/lib.h: Make codes 0200 to 0237 illegal input characters.
+ * troff/token.h: Remove TOKEN_TITLE. Remove token::title. Add
+ TOKEN_REQUEST.
+ * troff/input.c (token::next): Turn a TITLE_REQUEST into a
+ TOKEN_REQUEST with an argument of TITLE_REQUEST.
+ (token::process): Grok that.
+ * troff/input.c (copy_file): Handle first page transition like
+ title by pushing a COPY_FILE_REQUEST cookie.
+ (token::next, process_input_stack): Grok that.
+ * troff/node.h (output_file::copy_file): Add x and y arguments.
+ Make it non-pure.
+ * troff/div.c (top_level_diversion::copy_file): Supply them.
+ * troff/node.c (troff_output_file::copy_file): Add x and y
+ arguments; moveto specified position. Invalidate font_position
+ array after copying file.
+ (output_file::copy_file): New function.
+ (suppressed_output_file::copy_file, ascii_output::copy_file):
+ Removed.
+ * troff/input.c (transparent_file): New function.
+ (init_input_requests): Bind to "trf".
+ (token::next): Handle TRANSPARENT_FILE_REQUEST cookie.
+ (process_input_stack): Likewise.
+
+ * troff/Makefile: Add ../lib/lib.h to GROFF_H.
+
+ * troff/node.c (init_node_requests): New number registers .kern
+ pointing to global_kern_mode, and .lg pointing to
+ global_ligature_mode.
+
+ * troff/node.c (ligature): Don't change it if we get a bad
+ integer.
+
+ * troff/input.c (do_define_string): Don't strip tabs.
+
+ * troff/input.c (asciify_macro): Make the string_iterator auto.
+
+ * troff/node.c (init_font_requests): Rename to...
+ (init_node_requests):
+ * troff/node.h: Change declaration.
+ * troff/input.c (main): Change call.
+
+ * troff/input.c (node::reread, diverted_space_node::reread): New
+ methods.
+ (process_input_stack): Call reread rather than
+ get_diverted_space_node.
+ * troff/node.c (node::get_diverted_space_node,
+ diverted_space_node::get_diverted_space_node): Removed.
+ * troff/node.h: Declare reread methods instead of
+ get_diverted_space_node methods. Make `n' member private.
+ * troff/input.c: (token::diverted_space): Removed.
+ * troff/token.h: Removed declaration.
+
+
+Tue Sep 4 00:48:04 1990 James Clark (jjc at jclark)
+
+ * eqn/script.c (script_box::compute_metrics): Don't let
+ SUP_RAISE_FORMAT become negative.
+
+ * tbl/table.c (table::do_row): Entries that don't end in the
+ this row shouldn't make the row non-blank.
+
+ * tbl/table.c (table::make_columns_equal): Only set the width of
+ columns which are marked as equal.
+
+ * tbl/main.c (process_data): Before issuing excess data error,
+ if last character was a newline unget it; then get it again after
+ the error. Also include the contents of the entry in the message.
+
+ * groff.c: New file.
+ * Makefile: Build groff from groff.c. Make it possible to use
+ either groff.sh or groff.c as groff.
+ * Makefile.bd: Similarily.
+
+Mon Sep 3 09:39:49 1990 James Clark (jjc at jclark)
+
+ * groff.sh: Don't delay expansion of $@ in assignment to files.
+ Remove occurrences of \".
+
+Sun Sep 2 09:56:59 1990 James Clark (jjc at jclark)
+
+ * all Makefiles: Simplify and rearrange.
+
+ * Makefile: Handle fmod like malloc.
+ * lib/Makefile: Similarily.
+ * lib/fmod.c: Remove #ifdef NEED_FMOD.
+
+ * Makefile: Rename OPTIMISE to OPTIMIZE.
+
+ * groff.sh: Remove assignment to PATH.
+ * Makefile: Remove SHPATH variable.
+ * Makefile.bd: Similarily.
+
+ * groff.sh: Add -V option to print the pipeline instead of
+ executing it.
+
+Fri Aug 31 00:56:46 1990 James Clark (jjc at jclark)
+
+ * lib/font.c: Split off file searching into ...
+ * lib/fontfile.c: New file.
+
+ * lib/strerror.c (strerror): Use `Error %d' for unknown errors.
+
+Thu Aug 30 13:13:55 1990 James Clark (jjc at jclark)
+
+ * tbl/table.c (table::do_hspan): Delete assertion that e != 0.
+ Also change misleading comment.
+ (table::do_vspan): Change similarily misleading comment.
+ * tbl/main.c (process_data): A format row with an explicit `s'
+ uses up a data line, even if all the other columns are `_' or `='.
+
+ * troff/input.c (token::description): Fix description of
+ TOKEN_DUMMY and TOKEN_EMPTY.
+
+Wed Aug 29 04:12:08 1990 James Clark (jjc at jclark)
+
+ * groff.sh: Fix description of -Z in help message.
+
+Tue Aug 28 07:28:33 1990 James Clark (jjc at jclark)
+
+ * pic/object.c (object_spec::make_object): Allow negative and zero
+ line thicknesses.
+ * pic/pic.y: Give linethick default value of -1.0.
+ * pic/troff.c (troff_output::troff_output): Initialize
+ last_line_thickness to BAD_THICKNESS.
+ (troff_output::finish_picture): Set thickness to BAD_THICKNESS.
+ (troff_output::line_thickness): Canonicalize negative thicknesses
+ to RELATIVE_THICKNESS.
+ * pic/tex.c (tex_output::set_pen_size): Silently map negative line
+ thicknesses to DEFAULT_PEN_SIZE. Canonicalize negative pen sizes
+ to -1.0.
+ (tex_output::start_picture): Set pen_size to -2.0.
+
+ * ps/ps.c (ps_printer::set_line_thickness): If line_thickness is
+ 0, then use 0 linewidth.
+ (ps_printer::ps_printer): Initialize line_thickness to -1.
+
+ * pic/troff.c (troff_output::simple_ellipse): Divide by scale.
+
+ * ps/devps/symbolchars: Remove `or'.
+ * ps/tmac.ps: Implement \(or with .char.
+
+ * ps/devps/symbolchars: Move most characters into textmap.
+ * ps/devps/textmap: Add names for troff bracket characters. Remove
+ ul, ru, br, bv.
+
+ * ps/devps/TSymbol.ps: Removed.
+ * ps/devps/FontMakefile: Make S from Symbol not TSymbol.
+ * ps/tmac.ps: Do with .char what TSymbol did.
+ * ps/devps/download: Remove TSymbol.
+
+ * ps/devps/T: Removed.
+ * ps/devps/Troff.ps: Removed.
+ * ps/devps/Troff.afm: Removed.
+ * ps/tmac.ps: Implement \(ru, \(ul, and \(br with .char.
+ * ps/devps/download: Remove Troff.
+ * ps/devps/FontMakefile: Remove T target.
+ * ps/devps/DESC-A4: Remove T from font list.
+ * ps/devps/DESC-letter: Likewise.
+
+ * troff/input.c (macro_to_node): Rename to ...
+ (charinfo_to_node): Don't pass mac argument. Temporarily remove the
+ character's definition while processing it.
+ * troff/node.c (node::add_char, make_node): Change calls to
+ macro_to_node accordingly.
+
+ * troff/input.c (token::next): Translate \_ to \(ul.
+
+ * tty/devascii/R.proto: Add `|'.
+ * tty/devlatin1/R.proto: Likewise.
+
+Mon Aug 27 11:25:41 1990 James Clark (jjc at jclark)
+
+ * man: Put the version number in all the man pages.
+
+Sun Aug 26 11:40:05 1990 James Clark (jjc at jclark)
+
+ * Makefile.bd: New file.
+ * README.bd: New file.
+
+ * VERSION: New file.
+ * lib/version.c: Removed.
+ * lib/Makefile: Create version.c from ../VERSION. Remove version.c
+ in clean target.
+
+ * troff/input.c (main): Get hyphen_file from GROFF_HYPHEN
+ environment variable.
+
+ * all Makefiles: Split install target into install.bin for
+ binaries, and install.nobin for everything else.
+ * Makefile: Add bindist target.
+
+ * man/afmtodit.man: New file.
+ * man/Makefile: Add afmtodit.n to MAN1PAGES.
+ * ps/devps/Makefile: Add textmap to DEVICEFILES. Install afmtodit
+ in BINDIR.
+ * ps/Makefile: Pass BINDIR to make install in devps.
+
+ * ps/ps.c (ps_printer::set_char): Do nothing if the character is
+ the space character.
+
+ * ps/devps/FontMakefile: Rename symbol.afm to tsymbol.afm.
+
+Sat Aug 25 15:39:03 1990 James Clark (jjc at jclark)
+
+ * ps/ps.c: Redo font downloading.
+ * ps/devps/download: New file.
+ * ps/devps/Makefile: Add download to DEVICEFILES.
+ * ps/devps/afmtodit: Remove -d option.
+ * ps/devps/FontMakefile: Don't use -d option with afmtodit.
+ * ps/devps/symbosl.ps: Add %%DocumentFonts comment.
+ * ps/devps/zapfdr.ps: Likewise.
+ * ps/devps/TSymbol.ps: Likewise.
+
+Fri Aug 24 20:10:30 1990 James Clark (jjc at jclark)
+
+ * groff.sh: Initialize dev to ${GROFF_TYPESETTER:-@DEVICE@}.
+
+Thu Aug 23 10:03:47 1990 James Clark (jjc at yquem)
+
+ * ps/ps.c (ps_output::include_file): If BROKEN_SPOOLER is defined,
+ then strip the first line if it starts with %.
+ * Makefile: Add a comment about this.
+
+ * man/tfmtodit.man: New file.
+ * man/Makefile: Add tfmtodit.n to MAN1PAGES.
+ * dvi/Makefile: Install tfmtodit in BINDIR.
+
+ * dvi/tfmtodit.c (usage): Mention -v option.
+
+Wed Aug 22 09:56:36 1990 James Clark (jjc at yquem)
+
+ * troff/node.c (troff_output_file::end_of_line): Call do_motion.
+ * troff/node.c (troff_output_file::transparent_char): Don't call
+ flush_tbuf.
+
+ * eqn: Add check_tabs method to most box classes.
+ * eqn/box.c (box::top_level): Call check_tabs.
+
+ * eqn/script.c (script_box::output): Use \Z.
+ * eqn/limit.c (limit_box::output): Use \Z.
+
+ * eqn/box.c (box::top_level): Use itoa.
+
+Tue Aug 21 09:29:28 1990 James Clark (jjc at yquem)
+
+ * dvi/tmac.dvi: Add font translations for CR, C, TT.
+ * dvi/devdvi/Makefile: Don't make links to CW.
+
+ * ps/tmac.ps: Add font translations for C, CW, CO, CX, CD, H, HO,
+ HX, HD.
+ * xditview/tmac.X: Likewise.
+
+ * troff/node.c: Add font translation feature.
+ (get_font_translation): New function.
+ (symbol_fontno): Translate the font name.
+ (mount_font_no_translate): Rename to mount_font to this.
+ (mount_font): New function.
+ (font_family::make_definite): Call mount_font_no_translate instead
+ of mount_font.
+ (mount_style): Translate the font name.
+ (font_translate): New function.
+ (init_font_requests): Bind "ftr" to font_translate.
+
+ * ps/devps/prologue (SN): New procedure that rounds a position to
+ the nearest (pixel + (.25,.25)).
+ (DL): Use SN to round endpoints.
+
+ * lib/version.c: Changed version to 0.5.
+
+Sat Aug 18 04:43:21 1990 James Clark (jjc at yquem)
+
+ * Makefile: Move definition of PAGE to the very beginning, so that
+ people are less likely to miss it.
+
+Fri Aug 17 02:15:11 1990 James Clark (jjc at yquem)
+
+ * man/Makefile: Don't need to sed out @UPCASE_PROG_PREFIX@.
+
+ * troff/env.c (environment::choose_breakpoint): Make `can't find
+ breakpoint' error a warning of type WARN_BREAK. Change message to
+ `can't break line'.
+ * troff/groff.h: Declare WARN_BREAK with code 4; change WARN_INPUT to
+ code 040000.
+ * troff/input.c: Add WARN_BREAK to warning_table. Include
+ WARN_BREAK in DEFAULT_WARNING_MASK.
+
+ * tty/tmac.tty: Add definition of \(+-.
+
+ * groff.sh: Remove `--' option to set command.
+
+ * dvi/devdvi/texsy.map: Remove duplicate md entry.
+
+ * ps/devps/eqnchar: Better definition of cdot using md.
+ * dvi/devdvi/eqnchar: Likewise.
+ * xditview/devX100/eqnchar: Likewise.
+ * xditview/devX75/eqnchar: Likewise.
+ * eqn/lex.c: Add definition of cdot.
+
+Thu Aug 16 09:33:57 1990 James Clark (jjc at yquem)
+
+ * troff/input.c (get_optional_char): New function.
+ * troff/input.c (set_page_character): Use get_optional_char(),
+ rather than has_arg() and tok.get_char(1).
+ * troff/env.c (tab_character, leader_character, hyphen_char,
+ field_characters): Likewise.
+ (margin_character): Likewise. Also always delete the
+ margin_character_node.
+
+ * troff/input.c (token::get_char): Use token::description.
+
+ * troff/input.c (has_arg): Don't skip over tab and \}.
+ * troff/number.c (start_number): Give a warning if the number
+ starts with \} (WARN_RIGHT_BRACE) or tab (WARN_TAB).
+
+Wed Aug 15 10:04:37 1990 James Clark (jjc at yquem)
+
+ * troff/input.c (empty_name_warning, non_empty_name_warning): New
+ functions.
+ (get_name, get_long_name): Use these. Rename `warn' argument to
+ `required'.
+
+ * troff/node.c (get_fontno): Test that the symbol is not null.
+
+ * troff/input.c (token::description): New function.
+ * troff/number.c (parse_term): Use token::description in `numeric
+ expression expected' message.
+ * troff/groff.h: Add WARN_MISSING.
+ * troff/number.c (start_number): New function.
+ * troff/number.c (get_vunits, get_hunits, get_number, get_integer,
+ get_incr_number): Use start_number().
+ * troff/input.c (DEFAULT_WARNING_MASK): Enable WARN_NUMBER by
+ default.
+ * troff/input.c (get_name, get_long_name): Use WARN_MISSING.
+ * troff/reg.c (alter_format): Use WARN_MISSING. Also use
+ token::descripion.
+ * troff/input.c (token::get_char): Use WARN_MISSING.
+ * troff/input.c (token::delimiter): Use token::description.
+ * troff/env.c (environment_switch): Back out Aug 3 change.
+ * troff/input.c (has_arg): Skip over \}s and tabs but give a
+ warning.
+ * troff/token.h (token::tab): New function.
+ * troff/node.c (get_fontno): Use tok.skip() rather than has_arg().
+ * troff/reg.c (alter_format): Likewise.
+ * troff/node.c (bold_font): Use has_arg() rather than tok.skip().
+
+Tue Aug 14 10:11:21 1990 James Clark (jjc at yquem)
+
+ * troff (most files): Redo warnings. Divide warnings into various
+ categories; warning() has an additional first argument indicating
+ the category it falls into.
+ * troff/input.c (main): -w now takes an argument. New option -W.
+ (enable_warning, disable_warning): New functions.
+
+ * ps/devps/afmtodit: Add -a option to lie about the italic angle.
+ * ps/devps/FontMakefile: Pretend TI has an angle of 7.
+
+Mon Aug 13 10:11:16 1990 James Clark (jjc at yquem)
+
+ * ps/devps/eqnchar: Better definitions of dotdot, vec, dyad, inf.
+ * xditview/devX100/eqnchar: Likewise. Remove definition of dot.
+ * xditview/devX75/eqnchar: Likewise.
+ * dvi/devdvi/eqnchar: Better definitions of vec, dyad, dotdot.
+
+ * eqn/other.c: When bar or over applies to a single character
+ don't produce an overline_box or an underline_box. Instead produce
+ an accent_box or an underaccent_box, with the accent a line
+ whose width is accent_width. New classes underaccent_box,
+ overline_char_box and underline_char_box.
+ * eqn/box.h: Move overline_box, underline_box, accent_box class
+ declarations into eqn/other.c. Add declarations of
+ make_underline_box, make_overline_box, make_accent_box.
+ * eqn/eqn.y: Call make_overline_box, make_underline_box
+ make_accent_box instead of constructors.
+ * eqn/pbox.h, eqn/box.c: Add accent_width parameter.
+
+ * eqn/other.c: Add accent_box::~accent_box.
+ * eqn/box.h: Declare it.
+
+ * groff.sh: With -Tps, use eqn -D.
+
+ * eqn/other.c (overline_box::output): Use \Z. If draw_flag use \D
+ rather than \l.
+ (underline_box::output): Similarily.
+ (accent_box::output): Use \Z.
+
+ * xditview/tmac.X: Add definitions of ~ and ^ (so that they are a
+ bit smaller.)
+
+Sun Aug 12 09:41:15 1990 James Clark (jjc at yquem)
+
+ * troff/div.c (top_level_diversion::transparent_output(unsigned
+ char)): Use asciify.
+ * troff/input.c (asciify): Don't make it static.
+ * troff/token.h (asciify): Declare it.
+
+ * troff/input.c (get_name, get_long_name, token::get_char,
+ token::delimiter): Add an extra default argument which says
+ whether a warning should be printed.
+ * troff: Pass a non-zero argument to one of these rather than
+ printing a warning directly.
+
+Sat Aug 11 09:02:21 1990 James Clark (jjc at yquem)
+
+ * troff: Consistently use symbol::is_null.
+
+ * troff/dictionary.h: Move some inline functions into
+ dictionary.c.
+
+ * troff/request.h: Move inline functions into input.c.
+ (request_or_macro::invoke): Make it pure.
+
+ * troff/input.c, troff/reg.h: New class `constant_int_reg'.
+ * troff/input.c (init_input_requests): Use class constant_int_reg.
+ (class compatible_reg): Deleted.
+ * troff/div.c (init_div_requests): Use class constant_int_reg.
+ (class last_post_line_extra_space_reg): Deleted.
+
+ * troff/env.c (tab_character): Don't change the tab character if
+ we get an invalid argument.
+ (hyphen_char): Similarily.
+
+ * troff/reg.c (alter_format): Check that nm is not null.
+
+ * Makefile, groff.sh: Make it possible to customize the commands
+ used for printing PostScript and dvi files. Also make it possible
+ to customize the path used by groff.sh.
+
+ * eqn/eqn.y: Make `left' right associative.
+
+Fri Aug 10 18:20:39 1990 James Clark (jjc at yquem)
+
+ * pic/pic.h: Added definition of M_SQRT2 for those systems that
+ don't have it.
+
+ * pic/pic.h: Removed definition of INT_MAX.
+
+ * troff/node.c (italic_corrected_node::vertical_extent): Omit
+ `return'.
+
+ * troff/input.c (token::next): Handle \R like \n.
+
+Tue Aug 7 09:46:33 1990 James Clark (jjc at yquem)
+
+ * ps/tmac.pc (PSPIC): Simplify.
+
+ * troff/env.c (tab_stops::to_string):
+ * pic/pic.y (object_type_name):
+ * pic/troff.c (simple_output::line):
+ * pic/tex.c (tex_output::spline):
+ * pic/object.c (object_spec::make_object):
+ * tbl/main.c (process_data): Add cases to switch statements to
+ avoid cfront warnings. (Some of these are spurious, since the
+ switch already has a default case.)
+
+ * ps/tmac.ps (PSPIC): Reformatted. Prefix all local names with
+ `ps-'. Don't test systat; instead check number of arguments to
+ ps-bb.
+
+Mon Aug 6 00:13:07 1990 James Clark (jjc at yquem)
+
+ * macros/tmac.e: Do not decrease the page offset by 0.5i.
+
+ * ps/ps.c (ps_printer::ps_printer): Use mktemp instead of tempnam.
+ Unlink the file as soon as we have opened it, so that we don't
+ have to bother with signal handlers.
+ (handler): Deleted.
+ (fatal_error_exit): Deleted.
+ (main): Don't call signal.
+
+ * dvi/tfmtodit.c: Add -k option so that kerns with the skewchar
+ can be ignored.
+ * dvi/devdvi/Makefile: Use the -k option with S and MI.
+
+ * pic/pic.y: If there is a label, or an nth construction before
+ the first `.' in the argument to `with', ignore it and generate a
+ warning.
+ * pic/lex.c (lex_warning): New function.
+
+ * tbl/table.c (table::init_output): In section keep and release
+ macro, use 0 indent when diverting and the correct indent when
+ rereading.
+
+ * troff/input.c (interpolate_number_format): Do not interpolate
+ anything if the number register is not defined.
+
+ * tbl/main.c (process_data): Don't add entry when col >= ncolumns.
+
+Sat Aug 4 08:12:05 1990 James Clark (jjc at yquem)
+
+ * ps/devps/prologue (PICTURE): Set components of graphics state to
+ their default values.
+
+ * ps/devps/text.enc: Add trademark
+ * ps/devps/textmap: Add names for club, spade, heart, diamond,
+ carriagereturn, suchthat. Use Upsilon1 rather than Upsilon.
+ * ps/devps/symbolchars: Add names for summation and product.
+
+ * dvi/devdvi/texsy.map: Add names for club, spade, heart, diamond,
+ suchthat. Add pp. Add upper-case letters.
+
+ * xditview/libXdvi/DviChar.c: Add names for club, spade, heart,
+ diamond, carriagereturn, suchthat. Use Upsilon1 rather than
+ Upsilon.
+
+ * dvi/devdvi/texsy.map: Rename lA (left angle bracket) to la, and
+ rA (right angle bracket) to ra. Introduce names for double-headed
+ arrows and double-barred arrows: <>, va, lA, rA, hA, uA, dA, vA.
+ * ps/devps/textmap: Likewise for ps device.
+ * xditview/libXdvi/DviChar.c: Likewise for X100 and X75 devices.
+ * tty/devascii/R.proto: Rename lA to la and rA to ra.
+ * tty/devascii/R.proto: Likewise.
+ * tty/tmac.tty: Provide definitions for \(<>, \(lA, \(rA, \(hA,
+ \(uA, \(dA.
+ * eqn/delim.c: In delim_table, rename \(lA to \(la and \(rA to \(ra.
+
+ * xditview/tmac.X: Add definitions for \(fi \(fl \(ff \(Fi \(Fl.
+
+ * eqn/lex.c: Added definitions of `approx', `grad' and `del' to
+ def_table.
+
+Fri Aug 3 09:59:27 1990 James Clark (jjc at yquem)
+
+ * troff/div.c (when_request): Use symbol::is_null rather than
+ has_arg to determine whether we have an argument.
+ (change_trap): Remove the trap if we get an invalid number. Give
+ an error if we don't get at least the macro name.
+ (diversion_trap): Remove trap if we get an invalid name or number.
+
+ * troff/env.c (environment_switch): Pop if we get an invalid
+ symbol or numeric expression.
+
+ * troff/input.c (do_define_macro): If EOF is encoutered while
+ defining the macro, do tok.next() before returning.
+
+ * troff/token.h (has_arg): Move definition from here, to ...
+ * troff/input.c (has_arg): ... here
+
+ * troff/env.c (space_size): Do nothing if we get an invalid argument.
+ * troff/input.c (shift): Likewise.
+
+ * pic/lex.c (get_token_after_dot): Accept `.center' as a synonym
+ for `.c'.
+
+ * pic/troff.c (troff_output::start_picture): Comment out calls to
+ `..'.
+
+ * eqn/main.c (do_file): Subtract 1 from current_lineno if
+ interpret_lf_args succeeds.
+
+ * eqn/main.c (do_file): Don't recognize delimiter if preceded by
+ \\. This avoids problems with \$N.
+
+ * groff.sh: Pass -C to preprocessors.
+
+ * lib/lf.c (interpret_lf_args): Be more flexible.
+
+ * tbl/main.c (main): Add -C option.
+ (table_input::get): Do not recognize TE if followed by character
+ other than a space or newline unless -C option given.
+ (process_input_file): Likewise for lf, TS.
+ (process_data): Likewise for lf in text blocks.
+
+ * eqn/main.c (main): Add -C option.
+ (do_file): Don't recognize EQ, EN or lf if followed by character
+ other than space or newline unless -C option given.
+ * eqn/lex.c (file_input::read_line): Similarily.
+ * eqn/eqn.h: Declare compatible_flag.
+
+ * etc/soelim.c (main): Add -C option.
+ (interpret_lf_args): Use version in libgroff.
+ (do_file):
+
+ * pic/main.c (main): Add -C option, which sets compatible_flag.
+ (top_input::get), (top_input::peek): If -C option not given,
+ do not recognize .PS/.PE/.PF/.lf if followed by a character
+ other than space or newline.
+ * pic/lex.c (file_input::read_line): Similarily.
+ * pic/pic.h: Add declaration of compatible_flag.
+
+Thu Aug 2 11:11:27 1990 James Clark (jjc at yquem)
+
+ * ps/tmac.ps (PSPIC): Avoid use of `echo -n'.
+
+ * troff/node.c, troff/node.h: Add `asciify' methods to classes
+ derived from node. New class space_char_hmotion_node.
+ * troff/input.c (asciify_macro): New function.
+ * troff/input.c (init_input_requests): New request `asciify' bound
+ to asciify_macro.
+ * macros/mm.diff: New file.
+ * Makefile: In install.mm target use `patch' to apply
+ macros/mm.diff.
+
+ * troff/input.c (macro::print_size): Just print the size in bytes.
+
+ * troff/div.c (return_request): Correct the argument
+ interpretation.
+
+Wed Aug 1 12:38:36 1990 James Clark (jjc at yquem)
+
+ * troff/node.h (class composite_node): Add sz member.
+ * troff/node.c (composite_node::size): Return sz.
+ * troff/input.c (macro_to_node): Use the initial size in the
+ environment as the size of the composite_node.
+
+ * troff/node.c (node::zero_width_tprint): Provide a reasonable
+ default.
+
+Tue Jul 31 10:07:10 1990 James Clark (jjc at yquem)
+
+ * troff/div.c (change_trap): If we get a bad number expression,
+ do nothing.
+
+Mon Jul 30 10:30:49 1990 James Clark (jjc at yquem)
+
+ * lib/matherr.c (matherr): Define this only if math.h defines
+ TLOSS.
+
+Sun Jul 29 10:34:27 1990 James Clark (jjc at yquem)
+
+ * troff/div.c (macro_diversion::distance_to_next_trap): If there
+ no diversion trap return vunits(INT_MAX - vresolution).
+
+Sat Jul 28 14:28:14 1990 James Clark (jjc at yquem)
+
+ * troff/input.c (do_zero_width): New implementation that doesn't
+ use a temporary environment. Use instead:
+ (token::add_to_node_list): New function.
+ * troff/env.c (environment::get_prev_char_height),
+ (environment::get_prev_char_height),
+ (environment::get_prev_char_skew): New functions.
+ (environment::get_prev_char): New function.
+ (environment::get_prev_char_width): Change to use get_prev_char.
+ (init_env_request): Implement new registers .cht, .cdp, .csk.
+ * eqn/sqrt.c (sqrt_box::output): Don't rely upon the argument to
+ \Z being processed in a separate environment.
+
+Fri Jul 27 10:21:25 1990 James Clark (jjc at yquem)
+
+ * tbl/table.c: Removed TABLE_BOTTOM_REG.
+
+ * tbl/table.c (table::init_output): In the section release macro,
+ give a warning message if the section won't fit on one page.
+
+ * tbl/table.c (table::do_top): Emit table keep only if table is
+ boxed.
+ (table::do_bottom): Likewise for table release.
+ (table::table), (table::add_vertical_rule): Remove reference to
+ keep member.
+ * tbl/table.h: Remove keep member.
+
+ * tbl/table.c: New register SUPPRESS_BOTTOM_REG. In
+ SECTION_RELEASE_MACRO, if there's not enough space before the next
+ trap to output the diversion, call T# ourselves, set
+ SUPPRESS_BOTTOM_REG to 1, spring the trap, then set
+ SUPPRESS_BOTTOM_REG back to 0. In T#, do nothing if
+ SUPPRESS_BOTTOM_REG is non-zero. In T#, always mark the current
+ vertical position and return to it before turning traps on again.
+
+Thu Jul 26 02:54:32 1990 James Clark (jjc at yquem)
+
+ * troff/node.c, troff/node.h: In classes derived from node,
+ replace prev_char_width method by last_char_node method.
+ * troff/env.c (environment::get_prev_char_width): Use
+ node::last_char_node rather than node::get_prev_char_width.
+
+ * Makefile: Added comment about -fno-inline on 68030-based
+ Apollos.
+
+ * troff/reg.c (number_format_to_ascii), eqn/delim.c (DELIM_TABLE_SIZE),
+ tty/tty.c (tty_font::load_tty_font), dvi/tfmtodit.c (main): Cast
+ expressions using sizeof to int.
+ * dvi/dvi.c (dvi_font::handle_x_command): Avoid long->int warnings.
+
+ * macros/tmac.e (TS): Don't move @f back past the current
+ position.
+
+Wed Jul 25 09:11:08 1990 James Clark (jjc at yquem)
+
+ * ps/ps.c (main): Buffer stderr.
+ * dvi/dvi.c (main): Likewise.
+ * tty/tty.c (main): Likewise.
+
+ * ps/ps.c (ps_printer::do_import): Improve error handling.
+
+ * troff/input.c (abort_request): Use asciify.
+
+ * driver/printer.h (printer::draw), driver/printer.c (printer::draw),
+ ps/ps.c (ps_printer::draw), dvi/dvi.c (dvi_printer::draw): Make
+ type of first argument int rather than char. This works around a
+ bug on the 68030 based Apollo using g++ 1.37.1.
+
+ * tbl/table.h (class table): Add `keep' member.
+ * tbl/table.c (table::table): Initialize `keep'.
+ (table::add_vertical_rule): Set `keep' to 1.
+ (table::do_top): Only emit table keep macro is `keep' is non-zero.
+ (table::do_bottom): Likewise for table release macro.
+ (table::do_row): Emit section keep macro even if the row is 0.
+
+Tue Jul 24 08:35:07 1990 James Clark (jjc at yquem)
+
+ * macros/tmac.e (@C): Preserve the font family across the change
+ in environments.
+
+Mon Jul 23 10:15:23 1990 James Clark (jjc at yquem)
+
+ * lib/font.c: Initialize font::hor and font::vert to 1.
+ (font::load_desc): Check the values of font::hor and font::vert.
+
+ * lib/lib.h: Added definition of INT_DIGITS. Fix it so that it can
+ be included in a C compilation.
+ (iftoa): Use INT_DIGITS. Include lib.h.
+ (itoa): Likewise.
+ (as_string): Likewise.
+ * tbl/table.c: Removed definition of INT_DIGITS.
+ * eqn/box.c (box::top_level): Use INT_DIGITS + 1 instead of 12.
+ * troff/input.c (input_input_requests): Likewise.
+ * ps/ps.c (make_encoding_name): Likewise.
+ (ps_printer::set_style): Likewise.
+ (ps_output::put_number): Use 1 + INT_DIGITS + 1 instead of 12.
+
+ * tty/devascii/R.proto: Map fm onto '.
+ * tty/devlatin1/R.proto: Likewise.
+
+Sat Jul 21 12:45:07 1990 James Clark (jjc at yquem)
+
+ * tbl/table.c: Use ' instead of DELIMITER_CHAR in places where the
+ argument to \w is at a different input level.
+
+ * tbl/table.c (table::init_output): Define a new macro
+ REPEATED_VPT_MACRO, like vpt but if in a diversion also
+ transparently outputs itself.
+ (table::define_bottom_macro): Use REPEATED_VPT_MACRO instead of
+ vpt.
+ (table::do_row): Likewise.
+
+ * tbl/table.c (vertical_rule::print): Prefix the .sp -1 line with
+ TRANSPARENT_STRING_NAME.
+
+ * tbl/table.c (table::init_output): In the table release macro
+ print an error message and don't produce any output if after
+ issuing the need request the table still will not fit. Also
+ remove the diversion after bringing it back.
+
+ * tbl/table.c (table::init_output): Define a new macro
+ REPEATED_MARK_MACRO, like mk but if in a diversion also
+ transparently outputs itself.
+ (table::do_row): Mark row_top_reg using REPEATED_MARK_MACRO. This
+ is necessary because .TH might not call .T#.
+ (table::do_top): Likewise TOP_REG.
+ (table::define_bottom_macro): If TOP_REG is no longer valid, use
+ #T - DOUBLE_LINE_SEP rather than #T. This is necessary because the
+ table header might contain just the two top rules.
+
+Fri Jul 20 10:51:42 1990 James Clark (jjc at yquem)
+
+ * troff/div.c: Implement new request `ptr' to print all traps.
+
+ * troff/env.c (init_env_requests): Implement `.tabs' reg with
+ init_string_env_reg.
+ * troff/env.c (class tab_reg): Deleted.
+
+Thu Jul 19 12:07:16 1990 James Clark (jjc at yquem)
+
+ * troff/div.c: New number register .pn returns the number of the
+ next page as set by the pn request.
+
+ * macros/tmac.an: Redid headers and footers. Number each manual
+ entry starting from 1 unless \nC is > 0, like Sun. Added an
+ optional 5th argument to .TH which specifies the manual name and
+ appears in the center of the header. Understand the X, P and D
+ registers like Sun.
+
+Wed Jul 18 10:23:31 1990 James Clark (jjc at yquem)
+
+ * troff/env.c (init_env_requests): New number register `.lt' to
+ return the title length.
+
+ * troff/node.h (class transparent_dummy_node): New class.
+ * troff/node.c (class transparent_dummy_node): Provide member
+ functions.
+ * troff/env.c (interrupt): Add a transparent_dummy_node, rather
+ than a dummy_node.
+
+ * troff/input.c (token::next): New escape sequence \).
+ * troff/input.c (get_copy): Recognize \) in copy mode.
+
+ * troff/input.c (input_stack::clear): New function.
+ * troff/input.c (exit_request): Use input_stack::clear.
+
+ * troff/token.h: Removed TOKEN_NO_PRINT_CHAR.
+ * troff/input.c (token::process): Removed case TOKEN_NO_PRINT_CHAR.
+
+ * troff/env.c: Move set_page_character to input.c. Move
+ page_character to input.c also.
+ * troff/env.c (title): Split off the reading of the parts of the
+ title into read_title_parts.
+ * troff/input.c (read_title_parts): New function. Check the
+ input_level when testing whether a token matches the delimiter.
+
+ * troff/input.c (exit_request): New function.
+ * troff/input.c (init_input_requests): Bind ex request to
+ exit_request rather than exit_groff.
+
+ * troff/input.c (exit_groff): Call tok.next() before
+ process_input_stack().
+
+Mon Jul 16 09:47:23 1990 James Clark (jjc at yquem)
+
+ * troff/env.c: ifdef widow control support on WIDOW_CONTROL.
+ * troff/env.h: ditto.
+ * troff/input.c: ditto.
+
+ * troff/env.c (environment::is_empty): Test pending_lines.
+
+ * troff/env.c (environment::have_pending_lines): Removed.
+
+ * troff/input.c: Add request to flush pending lines from the
+ environment.
+
+ * troff/env.c, troff/env.h: Add automatic widow control feature.
+
+ * troff/input.c (exit_groff): Do process_input_stack() after
+ do_break() but before setting exit_flag to 2.
+
+ * troff/input.c: Remove FLUSH_PENDING_LINES and
+ TOKEN_FLUSH_PENDING_LINES. Instead, flush pending lines from
+ environment after END_TRAP token seen, but only if there aren't
+ any more traps still unfinished.
+ * troff/token.h: Remove TOKEN_FLUSH_PENDING_LINES.
+
+Sun Jul 15 10:50:08 1990 James Clark (jjc at yquem)
+
+ * troff/env.c: Rename the `retain_size' member of class
+ pending_output_line to `no_fill'.
+
+ * troff/env.c (title): When the line is output, make the
+ retain_size argument !fill.
+
+ * troff/node.h: Add `hyphenated' member to struct breakpoint.
+ * troff/node.c (space_node::get_breakpoints),
+ (dbreak_node::get_breakpoints): Fill this in.
+ * troff/env.c: Allow specification of maximum number of
+ consecutive hyphenated lines.
+
+ * troff/env.c (environment::is_empty): Add test for !current_tab.
+
+Sat Jul 14 11:23:01 1990 James Clark (jjc at yquem)
+
+ * troff/env.c (environment::hyphenate_line): Don't completely give
+ up if the word is not to be hyphenated; continue so that breaks
+ can be made at break_char_node's.
+
+ * lib/lib.h: Only define INT_MAX if it's not already defined;
+ undef INT_MIN if it's already defined.
+
+ * Makefile: Make it easy to define CFRONT_ANSI_BUG.
+
+ * lib/lib.h: If CFRONT_ANSI_BUG is defined, cast INT_MIN to long.
+ This works around a bug in AT&T C++ 2.0 used with an ANSI C
+ compiler.
+
+ * macros/tmac.an (an-header): Set no-space mode.
+
+ * macros/tmac.an (TH): Start a new page if necessary.
+
+ * Started using ChangeLog at version 0.4.
+
+Local Variables:
+version-control: never
+End:
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 00000000..a27d5a3a
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,35 @@
+To install groff, follow the instructions in the file INSTALL.gen.
+
+This file contains information that supplements those instructions.
+
+groff is written in C++, so you will need a C++ compiler. The C++
+source files use a suffix of `.cc', so your C++ compiler must be able
+to handle this. If you don't already have a C++ compiler, I suggest
+gcc 2.7.1 or later (gcc version 2 includes GNU C++ as well as GNU C).
+From gcc 2.5, it is no longer necessary to install libg++: the C++
+header files needed by groff are created by the gcc installation
+process. To override configure's choice of C++ compiler, you can set
+the CXX environment variable.
+
+If you have a library that provides a faster malloc than your system's
+usual malloc, it is good idea to include it in LIBS. For example,
+using the malloc that comes with GNU Emacs version 20 can give a
+worthwhile (and sometimes spectacular) performance improvement.
+
+When you have built groff, you can use the test-groff script to try
+groff out on one of the man pages. (Use the .n files not the .man
+files.) The test-groff script sets up environment variables to allow
+groff to run without being installed. The current directory must be
+the build directory when the script is run. For example, you could do
+
+ ./test-groff -man -Tascii groff/groff.n | less
+
+If you want to install gxditview (an X11 previewer), follow the
+instructions in the INSTALL file in the xditview directory.
+
+To get PostScript versions of the documentation resp. reference files for
+the `me' macros and the `pic' preprocessor, simply say `make' in the
+`doc' subdirectory.
+
+If you have problems, read the PROBLEMS file. If this doesn't help
+send a bug report using the form in the file BUG-REPORT.
diff --git a/INSTALL.gen b/INSTALL.gen
new file mode 100644
index 00000000..50dbe439
--- /dev/null
+++ b/INSTALL.gen
@@ -0,0 +1,183 @@
+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/MORE.STUFF b/MORE.STUFF
new file mode 100644
index 00000000..e2058ede
--- /dev/null
+++ b/MORE.STUFF
@@ -0,0 +1,23 @@
+More stuff for groff
+====================
+
+grap
+----
+
+An implementation of Kernighan & Bentley's grap language for typesetting
+graphs. Written by Ted Faber <faber@lunabase.org>. The actual version
+can be found at
+
+ http://www.lunabase.org/~faber/Vault/software/grap/
+
+miscellaneous
+-------------
+
+. Dr. Robert Hermann's groff gems are available from
+
+ http://www.eas.slu.edu/People/RBHerrmann/GROFF/index.html
+
+ At present there are examples for
+
+ o creating business cards
+ o using groff to make large format posters for presentations
diff --git a/Makefile.ccpg b/Makefile.ccpg
new file mode 100644
index 00000000..02b5d66b
--- /dev/null
+++ b/Makefile.ccpg
@@ -0,0 +1,33 @@
+# Makefile.ccpg
+MAKEFILEPARTS=\
+ $(top_srcdir)/Makefile.comm \
+ $(top_builddir)/Makefile.cfg \
+ $(srcdir)/Makefile.sub \
+ $(top_srcdir)/Makefile.ccpg \
+ Makefile.dep
+
+all: $(PROG) $(MANPAGES)
+
+$(PROG): $(OBJS) $(XLIBS)
+ $(LINK.cc) -o $@ $(OBJS) $(XLIBS) $(LIBS) $(MLIB)
+
+install_bin: install_prog
+install_prog: $(PROG)
+install_data: install_man
+install_man: $(MANPAGES)
+uninstall_sub: uninstall_prog uninstall_man
+depend: depend_src
+depend.temp: $(GENSRCS) $(YTABC)
+distfiles: $(YTABC)
+TAGS: TAGS_src
+TAGS_src: $(CCSRCS) $(CSRCS) $(GRAM) $(HDRS)
+Makefile: $(MAKEFILEPARTS)
+Makefile.dep:
+ touch Makefile.dep
+$(MANPAGES): $(top_srcdir)/VERSION $(top_srcdir)/REVISION
+
+pure: $(PROG).pure
+
+$(PROG).pure: $(OBJS) $(XLIBS)
+ $(PURIFY) $(PURIFYCCFLAGS) \
+ $(LINK.cc) -o $@ $(OBJS) $(XLIBS) $(LIBS) $(MLIB)
diff --git a/Makefile.comm b/Makefile.comm
new file mode 100644
index 00000000..866d5e6d
--- /dev/null
+++ b/Makefile.comm
@@ -0,0 +1,259 @@
+# Copyright (C) 1989-2000 Free Software Foundation, Inc.
+# Written by James Clark (jjc@jclark.com)
+#
+# This file is part of groff.
+#
+# groff 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.
+#
+# groff 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 groff; see the file COPYING. If not, write to the Free Software
+# Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Makefile.comm
+#
+SHELL=/bin/sh
+INCLUDES=-I. -I$(srcdir) \
+ -I$(top_builddir)/src/include -I$(top_srcdir)/src/include
+ALL_CCFLAGS=$(INCLUDES) $(CCDEFINES) $(CCFLAGS) $(CPPFLAGS)
+COMPILE.cc=$(CCC) $(ALL_CCFLAGS) -c
+ALL_CFLAGS=$(CDEFINES) $(CFLAGS) $(CPPFLAGS)
+COMPILE.c=$(CC) $(ALL_CFLAGS) -c
+LINK.cc=$(CCC) $(CCFLAGS) $(LDFLAGS)
+LINK.c=$(CC) $(CFLAGS) $(LDFLAGS)
+LIBGROFF=$(top_builddir)/src/libs/libgroff/libgroff.a
+LIBBIB=$(top_builddir)/src/libs/libbib/libbib.a
+LIBDRIVER=$(top_builddir)/src/libs/libdriver/libdriver.a
+MLIB=
+XLIBS=
+YTABH=
+YTABC=
+GRAM=
+LIBCLEAN=
+CLEANADD=
+MOSTLYCLEANFILES=$(MANCLEAN) $(PROG) $(OBJS) $(GENSRCS) $(GENHDRS) \
+ depend.temp core y.output $(CLEANADD)
+CLEANFILES=$(LIBCLEAN)
+DISTCLEANFILES=TAGS Makefile Makefile.dep
+REALCLEANFILES=$(YTABC) $(YTABH)
+NAMEPREFIX=
+HDRS=
+MANPAGES=$(MAN1) $(MAN5) $(MAN7)
+MANCLEAN=$(MANPAGES)
+fontsubdir=$(fontdir)/dev$(DEV)
+
+all install install_bin install_data TAGS depend distfiles uninstall_sub:
+
+install: prefix_must_exist install_bin install_data
+uninstall: uninstall_sub
+pure:
+
+.PHONY: all clean distclean mostlyclean realclean extraclean depend distfiles
+.PHONY: install install_bin install_data prefix_must_exist
+.PHONY: uninstall uninstall_sub
+.PHONY: pure
+
+prefix_must_exist:
+ @test -d $(prefix) \
+ || (echo ; \
+ echo The prefix directory \`$(prefix)\' doesn\'t exist; \
+ echo ; \
+ exit 1)
+
+mostlyclean:
+ -rm -f $(MOSTLYCLEANFILES)
+
+clean:
+ -rm -f $(CLEANFILES) $(MOSTLYCLEANFILES)
+
+distclean:
+ -rm -f $(DISTCLEANFILES) $(CLEANFILES) $(MOSTLYCLEANFILES)
+
+realclean:
+ -rm -f $(REALCLEANFILES) $(DISTCLEANFILES) $(CLEANFILES) \
+ $(MOSTLYCLEANFILES)
+
+extraclean:
+ -rm -f $(DISTCLEANFILES) $(CLEANFILES) $(MOSTLYCLEANFILES) \
+ \#* *~ =* core junk grot old temp tmp tem
+
+.SUFFIXES:
+.SUFFIXES: .o .cc .c .y .man .n
+
+.cc.o:
+ $(COMPILE.cc) $<
+
+.c.o:
+ $(COMPILE.c) $<
+
+.y.cc:
+ if test -n "$(YTABH)"; then \
+ $(YACC) $(YACCFLAGS) -d $<; \
+ else \
+ $(YACC) $(YACCFLAGS) $<; \
+ fi
+ mv y.tab.c $@
+# Avoid ending up with two versions of $(YTABH).
+ if test -n "$(YTABH)"; then \
+ if test -f $(srcdir)/$(YTABH); then \
+ rm -f $(YTABH); \
+ mv y.tab.h $(srcdir)/$(YTABH); \
+ else \
+ mv y.tab.h $(YTABH); \
+ fi; \
+ fi
+
+version=`cat $(top_srcdir)/VERSION`
+# No additional number for the groff archive if revision is zero
+revision=`sed -e 's/^0$$//' -e 's/^[1-9].*$$/.&/' $(top_srcdir)/REVISION`
+
+.man.n:
+ @echo Making $@ from $<
+ @-rm -f $@
+ @sed -e "s;@FONTDIR@;$(fontdir);g" \
+ -e "s;@FONTPATH@;$(fontpath);g" \
+ -e "s;@MACRODIR@;$(tmacdir);g" \
+ -e "s;@MACROPATH@;$(tmacpath);g" \
+ -e "s;@DEVICE@;$(DEVICE);g" \
+ -e "s;@DEFAULT_INDEX@;$(indexdir)/$(indexname);g" \
+ -e "s;@DEFAULT_INDEX_NAME@;$(indexname);g" \
+ -e "s;@INDEX_SUFFIX@;$(indexext);g" \
+ -e "s;@COMMON_WORDS_FILE@;$(common_words_file);g" \
+ -e "s;@MAN1EXT@;$(man1ext);g" \
+ -e "s;@MAN5EXT@;$(man5ext);g" \
+ -e "s;@MAN7EXT@;$(man7ext);g" \
+ -e "s;@TMAC_S_PREFIX@;$(tmac_s_prefix);g" \
+ -e "s;@TMAC_M_PREFIX@;$(tmac_m_prefix);g" \
+ -e "s;@TMAC_AN_PREFIX@;$(tmac_an_prefix);g" \
+ -e "s;@TMAC_MDIR@;$(tmacdir)/mm;g" \
+ -e "s;@BROKEN_SPOOLER_FLAGS@;$(BROKEN_SPOOLER_FLAGS);g" \
+ -e "s;@VERSION@;$(version)$(revision);g" \
+ -e "s;@MDATE@;`$(SHELL) $(top_srcdir)/mdate.sh $<`;g" \
+ -e "s;@g@;$(g);g" \
+ -e "s;@G@;`echo $(g) | tr [a-z] [A-Z]`;g" \
+ $< >$@
+
+.PHONY: install_man
+install_man:
+ -test -d $(manroot) || $(mkinstalldirs) $(manroot)
+ -test -d $(man1dir) || $(mkinstalldirs) $(man1dir)
+ @-pages="$(MAN1)"; \
+ for p in $$pages; do \
+ prog=`basename $$p .n`; \
+ target=$(man1dir)/$(NAMEPREFIX)$$prog.$(man1ext); \
+ rm -f $$target; \
+ echo $(INSTALL_DATA) $$p $$target; \
+ $(INSTALL_DATA) $$p $$target; \
+ done
+ -test -d $(man5dir) || $(mkinstalldirs) $(man5dir)
+ @-pages="$(MAN5)"; \
+ for p in $$pages; do \
+ target=$(man5dir)/`basename $$p .n`.$(man5ext); \
+ rm -f $$target; \
+ echo $(INSTALL_DATA) $$p $$target; \
+ $(INSTALL_DATA) $$p $$target; \
+ done
+ -test -d $(man7dir) || $(mkinstalldirs) $(man7dir)
+ @-pages="$(MAN7)"; \
+ for p in $$pages; do \
+ target=$(man7dir)/`basename $$p .n`.$(man7ext); \
+ rm -f $$target; \
+ echo $(INSTALL_DATA) $$p $$target; \
+ $(INSTALL_DATA) $$p $$target; \
+ done
+
+.PHONY: uninstall_man
+uninstall_man:
+ @-pages="$(MAN1)"; \
+ for p in $$pages; do \
+ target=$(man1dir)/$(NAMEPREFIX)`basename $$p .n`.$(man1ext); \
+ echo rm -f $$target; \
+ rm -f $$target; \
+ done
+ @-pages="$(MAN5)"; \
+ for p in $$pages; do \
+ target=$(man5dir)/`basename $$p .n`.$(man5ext); \
+ echo rm -f $$target; \
+ rm -f $$target; \
+ done
+ @-pages="$(MAN7)"; \
+ for p in $$pages; do \
+ target=$(man7dir)/`basename $$p .n`.$(man7ext); \
+ echo rm -f $$target; \
+ rm -f $$target; \
+ done
+
+.PHONY: install_prog
+install_prog:
+ -test -d $(bindir) || $(mkinstalldirs) $(bindir)
+ rm -f $(bindir)/$(NAMEPREFIX)$(PROG)
+ $(INSTALL_PROGRAM) $(PROG) $(bindir)/$(NAMEPREFIX)$(PROG)
+
+.PHONY: uninstall_prog
+uninstall_prog:
+ -rm -f $(bindir)/$(NAMEPREFIX)$(PROG)
+
+.PHONY: install_dev
+install_dev:
+ -test -d $(datadir) || $(mkinstalldirs) $(datadir)
+ -test -d $(datasubdir) || $(mkinstalldirs) $(datasubdir)
+ -test -d $(fontdir) || $(mkinstalldirs) $(fontdir)
+ -test -d $(fontsubdir) || $(mkinstalldirs) $(fontsubdir)
+ -if test -d $(srcdir)/generate; then \
+ test -d $(fontsubdir)/generate || \
+ $(mkinstalldirs) $(fontsubdir)/generate; \
+ fi
+ -for f in $(DEVFILES); do \
+ rm -f $(fontsubdir)/$$f; \
+ if test -f $$f; then \
+ $(INSTALL_DATA) $$f $(fontsubdir)/$$f; \
+ else \
+ $(INSTALL_DATA) $(srcdir)/$$f $(fontsubdir)/$$f; \
+ fi; \
+ done
+
+.PHONY: uninstall_dev
+uninstall_dev:
+ -for f in $(DEVFILES); do rm -f $(fontsubdir)/$$f; done
+ -if test -d $(fontsubdir)/generate; then \
+ rmdir $(fontsubdir)/generate; \
+ fi
+ -rmdir $(fontsubdir)
+
+.PHONY: depend_src
+depend_src: depend.temp
+ mv depend.temp Makefile.dep
+
+depend.temp: FORCE
+ > depend.temp;
+ test -z "$(CCSRCS)$(YTABC)" \
+ || $(CCC) $(ALL_CCFLAGS) -MM $(CCSRCS) $(YTABC) >>depend.temp
+ test -z "$(CSRCS)" \
+ || $(CC) $(ALL_CFLAGS) -MM $(CSRCS) >>depend.temp
+ if test -n "$(YTABH)"; then \
+ sed -e 's|$(YTABH)|$(YTABC)|g' depend.temp >depend.temp1; \
+ mv depend.temp1 depend.temp; \
+ fi
+
+.PHONY: TAGS_src
+TAGS_src:
+ $(ETAGS) $(ETAGSFLAGS) $(CCSRCS) $(CSRCS)
+ test -z "$(GRAM)$(HDRS)" \
+ || $(ETAGS) $(ETAGSFLAGS) -a $(ETAGSCCFLAG) $(GRAM) $(HDRS)
+
+Makefile:
+ -rm -f Makefile
+ echo srcdir=$(srcdir) >>Makefile
+ echo VPATH=$(VPATH) >>Makefile
+ cat $(MAKEFILEPARTS) /dev/null >>Makefile
+
+FORCE:
+
+.NOEXPORT:
diff --git a/Makefile.cpg b/Makefile.cpg
new file mode 100644
index 00000000..4cb514f4
--- /dev/null
+++ b/Makefile.cpg
@@ -0,0 +1,27 @@
+# Makefile.cpg
+MAKEFILEPARTS=\
+ $(top_srcdir)/Makefile.comm \
+ $(top_builddir)/Makefile.cfg \
+ $(srcdir)/Makefile.sub \
+ $(top_srcdir)/Makefile.cpg \
+ Makefile.dep
+
+all: $(PROG) $(MANPAGES)
+
+$(PROG): $(OBJS) $(XLIBS)
+ $(LINK.c) -o $@ $(OBJS) $(XLIBS) $(LIBS) $(MLIB)
+
+install_bin: install_prog
+install_prog: $(PROG)
+install_data: install_man
+install_man: $(MANPAGES)
+uninstall_sub: uninstall_prog uninstall_man
+depend: depend_src
+depend.temp: $(GENSRCS) $(YTABC)
+distfiles: $(YTABC)
+TAGS: TAGS_src
+TAGS_src: $(CCSRCS) $(CSRCS) $(GRAM) $(HDRS)
+Makefile: $(MAKEFILEPARTS)
+Makefile.dep:
+ touch Makefile.dep
+$(MANPAGES): $(top_srcdir)/VERSION $(top_srcdir)/REVISION
diff --git a/Makefile.dev b/Makefile.dev
new file mode 100644
index 00000000..ae9a6722
--- /dev/null
+++ b/Makefile.dev
@@ -0,0 +1,4 @@
+all: $(DEVFILES)
+install_data: install_dev
+uninstall_sub: uninstall_dev
+install_dev: $(DEVFILES)
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 00000000..0567f1dc
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,489 @@
+# Copyright (C) 1989-2000 Free Software Foundation, Inc.
+# Written by James Clark (jjc@jclark.com)
+#
+# This file is part of groff.
+#
+# groff 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.
+#
+# groff 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 groff; see the file COPYING. If not, write to the Free Software
+# Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Define `page' to be letter if your PostScript printer uses 8.5x11
+# paper (USA) and define it to be A4, if it uses A4 paper (rest of the
+# world).
+PAGE=@PAGE@
+
+# Normally the Postscript driver, grops, produces output that conforms
+# to version 3.0 of the Adobe Document Structuring Conventions.
+# Unfortunately some spoolers and previewers can't handle such output.
+# The BROKEN_SPOOLER_FLAGS variable tells grops what it should do to
+# make its output acceptable to such programs. This variable controls
+# only the default behaviour of grops; the behaviour can be changed at
+# runtime by the grops -b option (and so by groff -P-b).
+# Use a value of 0 if your spoolers and previewers are able to handle
+# conforming PostScript correctly.
+# Add 1 if no %%{Begin,End}DocumentSetup comments should be generated;
+# this is needed for early versions of TranScript that get confused by
+# anything between the %%EndProlog line and the first %%Page: comment.
+# Add 2 if lines in included files beginning with %! should be
+# stripped out; this is needed for the OpenWindows 2.0 pageview previewer.
+# Add 4 if %%Page, %%Trailer and %%EndProlog comments should be
+# stripped out of included files; this is needed for spoolers that
+# don't understand the %%{Begin,End}Document comments. I suspect this
+# includes early versions of TranScript.
+# Add 8 if the first line of the PostScript output should be %!PS-Adobe-2.0
+# rather than %!PS-Adobe-3.0; this is needed when using Sun's Newsprint
+# with a printer that requires page reversal.
+BROKEN_SPOOLER_FLAGS=@BROKEN_SPOOLER_FLAGS@
+
+# DEVICE is the default device.
+DEVICE=ps
+
+# PSPRINT is the command to use for printing a PostScript file,
+# for example `lpr'.
+PSPRINT=@PSPRINT@
+
+# DVIPRINT is the command to use for printing a TeX dvi file,
+# for example `lpr -d'.
+DVIPRINT=@DVIPRINT@
+
+# Prefix for names of programs that have Unix counterparts.
+# For example, if `g' is `g' then troff will be installed as
+# gtroff. This doesn't affect programs like grops or groff that have
+# no Unix counterparts. Note that the groff versions of eqn and tbl
+# will not work with Unix troff.
+g=@g@
+
+# Common prefix for installation directories.
+# Used in definitions of exec_prefix, datasubdir, fontpath, manroot.
+# This must already exist when you do make install.
+prefix=@prefix@
+
+exec_prefix=@exec_prefix@
+
+# bindir says where to install executables.
+bindir=$(exec_prefix)/bin
+
+# datasubdir says where to install data files
+datadir=$(prefix)/share
+datasubdir=$(datadir)/groff
+
+# fontdir says where to install dev*/*.
+fontdir=$(datasubdir)/font
+
+# fontpath says where to look for dev*/*.
+fontpath=.:$(fontdir):/usr/lib/font
+
+# tmacdir says where to install macros.
+tmacdir=$(datasubdir)/tmac
+
+# tmacpath says where to look for macro files.
+tmacpath=.:$(tmacdir)
+
+# sys_tmac_prefix is prefix (if any) for system macro packages
+sys_tmac_prefix=@sys_tmac_prefix@
+
+# tmac_wrap is list of system macro packages that should be made
+# available to groff by creating a corresponding macro package
+# in the groff macro directory that references the system macro
+# package.
+tmac_wrap=@tmac_wrap@
+
+# If there is a groff version of a macro package listed in $(tmac_wrap),
+# then the groff version will be installed with a prefix of this.
+# Don't make this empty.
+tmac_prefix=g
+
+# The groff -mm macros will be available as -m$(tmac_m_prefix)m.
+tmac_m_prefix=\
+ `for i in $(tmac_wrap) ""; do case "$$i" in m) echo $(tmac_prefix);; esac; done`
+# The groff -ms macros will be available as -m$(tmac_s_prefix)s.
+tmac_s_prefix=\
+ `for i in $(tmac_wrap) ""; do case "$$i" in s) echo $(tmac_prefix);; esac; done`
+# The groff -man macros will be available as -m$(tmac_an_prefix)an.
+tmac_an_prefix=\
+ `for i in $(tmac_wrap) ""; do case "$$i" in an) echo $(tmac_prefix);; esac; done`
+
+# Extension to be used for refer index files. Index files are not
+# sharable between different architectures, so you might want to use
+# different suffixes for different architectures. Choose an extension
+# that doesn't conflict with refer or any other indexing program.
+indexext=.i
+
+# Directory containing the default index for refer.
+indexdir=/usr/dict/papers
+
+# The filename (without suffix) of the default index for refer.
+indexname=Ind
+
+# common_words_file is a file containing a list of common words.
+# If your system provides /usr/lib/eign it will be copied onto this,
+# otherwise the supplied eign file will be used.
+common_words_file=$(datasubdir)/eign
+
+# manroot is the root of the man page directory tree.
+manroot=$(prefix)/man
+
+# man1ext is the man section for user commands.
+man1ext=1
+man1dir=$(manroot)/man$(man1ext)
+
+# man5ext is the man section for file formats.
+man5ext=5
+man5dir=$(manroot)/man$(man5ext)
+
+# man7ext is the man section for macros.
+man7ext=7
+man7dir=$(manroot)/man$(man7ext)
+
+# DEFINES should include the following:
+# -DHAVE_MMAP if you have mmap() and <sys/mman.h>
+# -DARRAY_DELETE_NEEDS_SIZE if your C++ doesn't understand `delete []'
+# -DHAVE_SYS_SIGLIST if you have sys_siglist[]
+# -DWCOREFLAG=0200 if the 0200 bit of the status returned by
+# wait() indicates whether a core image was
+# produced for a process that was terminated
+# by a signal
+# -DHAVE_UNISTD_H if you have <unistd.h>
+# -DHAVE_CC_OSFCN_H if you have a C++ <osfcn.h>
+# -DHAVE_DIRENT_H if you have <dirent.h>
+# -DHAVE_LIMITS_H if you have <limits.h>
+# -DHAVE_CC_LIMITS_H if you have a C++ <limits.h>
+# -DHAVE_SYS_DIR_H if you have <sys/dir.h>
+# -DHAVE_STDLIB_H if you have <stdlib.h>
+# -DHAVE_RENAME if you have rename()
+# -DHAVE_MKSTEMP if you have mkstemp()
+# -DSTDLIB_H_DECLARES_GETOPT if your C++ <stdlib.h> declares getopt()
+# -DUNISTD_H_DECLARES_GETOPT if your C++ <unistd.h> declares getopt()
+# -DSTDLIB_H_DECLARES_PUTENV if your C++ <stdlib.h> declares putenv()
+# -DSTDIO_H_DECLARES_POPEN if your C++ <stdio.h> declares popen()
+# -DSTDIO_H_DECLARES_PCLOSE if your C++ <stdio.h> declares pclose()
+# -DHAVE_SYS_NERR if you have sysnerr in <errno.h> or <stdio.h>
+# -DHAVE_SYS_ERRLIST if you have sys_errlist in <errno.h> or
+# <stdio.h>
+# -DMATH_H_DECLARES_HYPOT if you have hypot() in <math.h>
+# -DTRADITIONAL_CPP if your C++ compiler uses a traditional
+# (Reiser) preprocessor
+# -DLONG_FOR_TIME_T if localtime() takes a long * not a time_t *
+# -DHAVE_STRUCT_EXCEPTION if <math.h> defines struct exception
+# -DRETSIGTYPE=int if signal handlers return int not void
+DEFINES=@DEFS@
+
+# Include fmod.o, strtol.o, getcwd.o, strerror.o, putenv.o in LIBOBJS if
+# your C library is missing the corresponding function.
+LIBOBJS=@LIBOBJS@
+
+# CCC is the compiler for C++ (.cc) files.
+CCC=@CXX@
+CC=@CC@
+# CCDEFINES are definitions for C++ compilations.
+CCDEFINES=$(DEFINES)
+# CDEFINES are definitions for C compilations.
+CDEFINES=$(DEFINES)
+
+CCFLAGS=@CXXFLAGS@
+CFLAGS=@CFLAGS@
+LDFLAGS=@LDFLAGS@
+YACC=@YACC@
+YACCFLAGS=-v
+
+LIBS=@LIBS@
+LIBM=@LIBM@
+RANLIB=@RANLIB@
+INSTALL=@INSTALL@
+INSTALL_PROGRAM=@INSTALL_PROGRAM@
+INSTALL_DATA=@INSTALL_DATA@
+LN_S=@LN_S@
+AR=ar
+ETAGS=etags
+ETAGSFLAGS=
+# Flag that tells etags to assume C++.
+ETAGSCCFLAG=-C
+# Full path to perl.
+PERLPATH=@PERLPATH@
+# Sed command with which to edit sh scripts.
+SH_SCRIPT_SED_CMD=@SH_SCRIPT_SED_CMD@
+
+srcdir=@srcdir@
+top_srcdir=@top_srcdir@
+VPATH=@srcdir@
+top_builddir=@top_builddir@
+
+# the program to create directory hierarchies
+mkinstalldirs=$(top_srcdir)/mkinstalldirs
+
+PURIFY=purify
+PURIFYCCFLAGS=
+#PURIFYCCFLAGS=-g++=yes \
+# -collector=`dirname \`$(CCC) -print-libgcc-file-name\``/ld
+
+# Passing down MAKEOVERRIDES prevents $(MAKE) from containing a second
+# copy of $(MDEFINES) when making individual directories; this could
+# cause the argument list to become too long on some systems.
+MDEFINES= \
+ "MAKEOVERRIDES=$(MAKEOVERRIDES)" \
+ "PAGE=$(PAGE)" \
+ "BROKEN_SPOOLER_FLAGS=$(BROKEN_SPOOLER_FLAGS)" \
+ "DEVICE=$(DEVICE)" \
+ "PSPRINT=$(PSPRINT)" \
+ "DVIPRINT=$(DVIPRINT)" \
+ "top_srcdir=$(top_srcdir)" \
+ "top_builddir=$(top_builddir)" \
+ "prefix=$(prefix)" \
+ "exec_prefix=$(exec_prefix)" \
+ "bindir=$(bindir)" \
+ "g=$(g)" \
+ "datadir=$(datadir)" \
+ "datasubdir=$(datasubdir)" \
+ "fontdir=$(fontdir)" \
+ "fontpath=$(fontpath)" \
+ "tmacdir=$(tmacdir)" \
+ "tmacpath=$(tmacpath)" \
+ "indexext=$(indexext)" \
+ "indexdir=$(indexdir)" \
+ "indexname=$(indexname)" \
+ "common_words_file=$(common_words_file)" \
+ "manroot=$(manroot)" \
+ "man1ext=$(man1ext)" \
+ "man1dir=$(man1dir)" \
+ "man5ext=$(man5ext)" \
+ "man5dir=$(man5dir)" \
+ "man7ext=$(man7ext)" \
+ "man7dir=$(man7dir)" \
+ "mkinstalldirs=$(mkinstalldirs)" \
+ "tmac_wrap=$(tmac_wrap)" \
+ "sys_tmac_prefix=$(sys_tmac_prefix)" \
+ "tmac_an_prefix=$(tmac_an_prefix)" \
+ "tmac_s_prefix=$(tmac_s_prefix)" \
+ "tmac_m_prefix=$(tmac_m_prefix)" \
+ "CCC=$(CCC)" \
+ "CC=$(CC)" \
+ "CCDEFINES=$(CCDEFINES)" \
+ "CDEFINES=$(CDEFINES)" \
+ "CCFLAGS=$(CCFLAGS)" \
+ "CFLAGS=$(CFLAGS)" \
+ "LDFLAGS=$(LDFLAGS)" \
+ "YACC=$(YACC)" \
+ "YACCFLAGS=$(YACCFLAGS)" \
+ "LIBM=$(LIBM)" \
+ "LIBS=$(LIBS)" \
+ "LIBOBJS=$(LIBOBJS)" \
+ "RANLIB=$(RANLIB)" \
+ "AR=$(AR)" \
+ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+ "INSTALL_DATA=$(INSTALL_DATA)" \
+ "ETAGS=$(ETAGS)" \
+ "ETAGSFLAGS=$(ETAGSFLAGS)" \
+ "ETAGSCCFLAG=$(ETAGSCCFLAG)" \
+ "PERLPATH=$(PERLPATH)" \
+ "SH_SCRIPT_SED_CMD=$(SH_SCRIPT_SED_CMD)" \
+ "PURIFY=$(PURIFY)" \
+ "PURIFYCCFLAGS=$(PURIFYCCFLAGS)"
+
+SHELL=/bin/sh
+INCDIRS=src/include
+LIBDIRS=\
+ src/libs/libgroff \
+ src/libs/libdriver \
+ src/libs/libbib
+CCPROGDIRS=\
+ src/roff/groff \
+ src/roff/troff \
+ src/preproc/tbl \
+ src/preproc/pic \
+ src/preproc/eqn \
+ src/preproc/refer \
+ src/preproc/soelim \
+ src/devices/grops \
+ src/devices/grotty \
+ src/devices/grodvi \
+ src/devices/grolj4 \
+ src/devices/grohtml \
+ src/utils/tfmtodit \
+ src/utils/hpftodit \
+ src/utils/lookbib \
+ src/utils/indxbib \
+ src/utils/lkbib \
+ src/utils/addftinfo
+CPROGDIRS=src/utils/pfbtops
+PROGDIRS=$(CCPROGDIRS) $(CPROGDIRS)
+DEVDIRS=\
+ font/devps \
+ font/devdvi \
+ font/devascii \
+ font/devlatin1 \
+ font/devutf8 \
+ font/devX75 \
+ font/devX75-12 \
+ font/devX100 \
+ font/devX100-12 \
+ font/devlj4 \
+ font/devhtml
+OTHERDIRS=\
+ man \
+ tmac \
+ src/utils/afmtodit \
+ src/roff/grog \
+ src/roff/nroff \
+ contrib/mm
+ALLDIRS=$(INCDIRS) $(LIBDIRS) $(PROGDIRS) $(DEVDIRS) $(OTHERDIRS)
+EXTRADIRS=\
+ fonts/devps/generate \
+ fonts/devdvi/generate \
+ src/xditview \
+ doc
+DISTDIRS=$(ALLDIRS) $(EXTRADIRS)
+TARGETS=all install install_bin install_data clean distclean mostlyclean \
+ realclean extraclean distfiles TAGS depend uninstall_sub
+
+do=all
+dodirs=$(ALLDIRS) dot
+# Default target for subdir_Makefile
+subdir=troff
+
+
+$(TARGETS):
+ @$(MAKE) $(MDEFINES) do=$@ $(dodirs)
+
+dot: FORCE
+ @$(MAKE) $(MDEFINES) srcdir=$(srcdir) VPATH=$(srcdir) \
+ -f $(top_srcdir)/Makefile.comm \
+ -f $(top_srcdir)/Makefile.sub $(do)
+
+$(LIBDIRS): FORCE
+ @if test $(srcdir) = .; \
+ then srcdir=.; \
+ else srcdir=`cd $(srcdir); pwd`/$@; \
+ fi; \
+ test -d $@ || $(mkinstalldirs) $@; \
+ cd $@; \
+ $(MAKE) $(MDEFINES) srcdir=$$srcdir VPATH=$$srcdir \
+ -f $(top_srcdir)/Makefile.comm \
+ -f $$srcdir/Makefile.sub \
+ -f $(top_srcdir)/Makefile.lib \
+ -f Makefile.dep $(do)
+
+$(CPROGDIRS): FORCE
+ @if test $(srcdir) = .; \
+ then srcdir=.; \
+ else srcdir=`cd $(srcdir); pwd`/$@; \
+ fi; \
+ test -d $@ || $(mkinstalldirs) $@; \
+ cd $@; \
+ $(MAKE) $(MDEFINES) srcdir=$$srcdir VPATH=$$srcdir \
+ -f $(top_srcdir)/Makefile.comm \
+ -f $$srcdir/Makefile.sub \
+ -f $(top_srcdir)/Makefile.cpg \
+ -f Makefile.dep $(do)
+
+$(CCPROGDIRS): FORCE
+ @if test $(srcdir) = .; \
+ then srcdir=.; \
+ else srcdir=`cd $(srcdir); pwd`/$@; \
+ fi; \
+ test -d $@ || $(mkinstalldirs) $@; \
+ cd $@; \
+ $(MAKE) $(MDEFINES) srcdir=$$srcdir VPATH=$$srcdir \
+ -f $(top_srcdir)/Makefile.comm \
+ -f $$srcdir/Makefile.sub \
+ -f $(top_srcdir)/Makefile.ccpg \
+ -f Makefile.dep $(do)
+
+$(DEVDIRS): FORCE
+ @if test $(srcdir) = .; \
+ then srcdir=.; \
+ else srcdir=`cd $(srcdir); pwd`/$@; \
+ fi; \
+ test -d $@ || $(mkinstalldirs) $@; \
+ cd $@; \
+ $(MAKE) $(MDEFINES) srcdir=$$srcdir VPATH=$$srcdir \
+ -f $(top_srcdir)/Makefile.comm \
+ -f $$srcdir/Makefile.sub \
+ -f $(top_srcdir)/Makefile.dev $(do)
+
+$(INCDIRS) $(OTHERDIRS): FORCE
+ @if test $(srcdir) = .; \
+ then srcdir=.; \
+ else srcdir=`cd $(srcdir); pwd`/$@; \
+ fi; \
+ test -d $@ || $(mkinstalldirs) $@; \
+ cd $@; \
+ $(MAKE) $(MDEFINES) srcdir=$$srcdir VPATH=$$srcdir \
+ -f $(top_srcdir)/Makefile.comm \
+ -f $$srcdir/Makefile.sub \
+ -f $(top_srcdir)/Makefile.man $(do)
+
+version=`cat $(top_srcdir)/VERSION`
+# No additional number for the groff archive if revision is zero
+revision=`sed -e 's/^0$$//' -e 's/^[1-9].*$$/.&/' $(top_srcdir)/REVISION`
+
+.PHONY: dist
+dist:
+ -rm -fr tmp
+ mkdir tmp
+ for d in $(DISTDIRS); do \
+ $(mkinstalldirs) tmp/$$d; \
+ done
+ srcdir=`cd $(srcdir); pwd`; \
+ cd tmp; \
+ $(LN_S) ../Makefile .; \
+ $(LN_S) $$srcdir/* . 2>/dev/null || true; \
+ for d in $(DISTDIRS); do \
+ (cd $$d; $(LN_S) $$srcdir/$$d/* . 2>/dev/null || true); \
+ done; \
+ $(MAKE) srcdir=$$srcdir VPATH=$$srcdir extraclean; \
+ for d in $(EXTRADIRS); do \
+ (cd $$d; $(MAKE) extraclean); \
+ done; \
+ rm -f Makefile; \
+ $(LN_S) $$srcdir/Makefile.init Makefile
+ mv tmp groff-$(version)$(revision)
+ rm -f groff-$(version)$(revision).tar.gz
+ tar cfh - groff-$(version)$(revision) | \
+ gzip -c >groff-$(version)$(revision).tar.gz
+ rm -fr groff-$(version)$(revision)
+
+# $(PROGDIRS): libgroff
+# grops grotty grodvi: libdriver
+# refer lookbib indxbib lkbib: libbib
+# $(LIBDIRS) $(PROGDIRS): include
+
+.PHONY: $(ALLDIRS) dot $(TARGETS) FORCE
+
+subdir_Makefile: Makefile.cfg
+ $(MAKE) do=Makefile $(subdir)
+
+Makefile.cfg: Makefile
+ >Makefile.cfg
+ for var in $(MDEFINES); do \
+ echo "$$var" >>Makefile.cfg; \
+ done
+
+Makefile: Makefile.in
+ $(SHELL) config.status
+
+.PHONY: uninstall
+uninstall: uninstall_sub uninstall_dirs
+
+.PHONY: uninstall_dirs
+uninstall_dirs:
+# Use rmdir here so that the directories are only removed if they're empty
+ -rmdir $(man1dir) $(man5dir) $(man7dir) $(manroot) \
+ $(tmacdir) $(fontdir) $(bindir) $(datasubdir) $(datadir)
+
+
+.PHONY: check
+check:
+
+FORCE:
+
+.NOEXPORT:
diff --git a/Makefile.init b/Makefile.init
new file mode 100644
index 00000000..024f4869
--- /dev/null
+++ b/Makefile.init
@@ -0,0 +1,25 @@
+# Copyright (C) 1989-2000 Free Software Foundation, Inc.
+# Written by James Clark (jjc@jclark.com)
+#
+# This file is part of groff.
+#
+# groff 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.
+#
+# groff 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 groff; see the file COPYING. If not, write to the Free Software
+# Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+SHELL=/bin/sh
+
+.PHONY: all
+all:
+ $(SHELL) configure
+ $(MAKE) all
diff --git a/Makefile.lib b/Makefile.lib
new file mode 100644
index 00000000..8861360e
--- /dev/null
+++ b/Makefile.lib
@@ -0,0 +1,20 @@
+LIBCLEAN=lib$(LIB).a
+MAKEFILEPARTS=\
+ $(top_srcdir)/Makefile.comm \
+ $(top_builddir)/Makefile.cfg \
+ $(srcdir)/Makefile.sub \
+ $(top_srcdir)/Makefile.lib \
+ Makefile.dep
+
+all: lib$(LIB).a
+
+lib$(LIB).a: $(OBJS)
+ $(AR) r $@ $?
+ $(RANLIB) $@
+
+depend: depend_src
+depend.temp: $(GENSRCS)
+TAGS: $(CCSRCS) $(CSRCS)
+Makefile: $(MAKEFILEPARTS)
+Makefile.dep:
+ touch Makefile.dep
diff --git a/Makefile.man b/Makefile.man
new file mode 100644
index 00000000..2fecd115
--- /dev/null
+++ b/Makefile.man
@@ -0,0 +1,5 @@
+all: $(MANPAGES)
+install_data: install_man
+install_man: $(MANPAGES)
+uninstall_sub: uninstall_man
+$(MANPAGES): $(top_srcdir)/VERSION $(top_srcdir)/REVISION
diff --git a/Makefile.sub b/Makefile.sub
new file mode 100644
index 00000000..ab72a5f7
--- /dev/null
+++ b/Makefile.sub
@@ -0,0 +1,7 @@
+DISTCLEANFILES=config.status config.log config.cache Makefile
+CLEANADD=Makefile.cfg conftest*
+
+distfiles: configure
+
+configure: configure.in aclocal.m4
+ cd $(srcdir); autoconf
diff --git a/NEWS b/NEWS
new file mode 100644
index 00000000..f0c69438
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,893 @@
+This file describes recent user-visible changes in groff. Bug fixes
+are not described. There are more details in the man pages.
+
+VERSION 1.16
+============
+
+Groff
+-----
+
+Some additions to the font description files have been implemented for
+better support of HTML output:
+
+ The new format of lines in the `charset' subsection of font description
+ files is
+
+ name metrics type code [entity_name] [-- comment]
+
+ Currently, only the font description files in devhtml use the optional
+ entity_name string to define the glyph entities in HTML. Everything
+ after the entity_name field is ignored; in case this field isn't used,
+ two hyphen characters are now necessary to start a comment.
+
+ Two new requests are available in DESC files (currently used only with
+ grohtml):
+
+ use_charnames_in_special
+ This command indicates that troff should encode named characters
+ inside special commands.
+
+ pass_filenames
+ requests that troff tells the driver the source file name being
+ processed. This is achieved by another tcommand: `F filename'.
+
+Troff
+-----
+
+To solve a problem with the .PSPIC macro which needs the `-U' switch of
+troff to access an external program (psbb), a new request .psbb is now
+available to get the bounding box of a PostScript image file. The values
+(in PostScript units) are returned in the new read-only number registers
+`llx', `lly', `urx', and `ury'. Consequently, .PSPIC has been adapted to
+use the new request, and the psbb program has been removed.
+
+A new number predefined writable number register, `year', has been added.
+It contains the current year.
+
+A new read-only register, `.Y', has been added. It contains the revision
+number of the groff package.
+
+`\fP' now behaves as expected in situations like the following where the
+font `foo' is undefined:
+
+ .B bold text
+ normal text \f[foo]bar\fP normal text
+
+Previously, the text after \fP has appeared as bold.
+
+The macro files `tmac.a4' (for specifying A4 paper format) and `tmac.trace'
+(a debugging aid) are now installed also.
+
+A new resource file, `troffrc-end', is now available. It is invoked after
+all user-specified macros. Currently used by the html device to include
+tmac.html; thus no need for users to specify -mhtml anymore.
+
+Grotty
+------
+
+Bruno Haible <haible@clisp.cons.org> contributed support for UTF8 output.
+
+Grohtml
+-------
+
+Added .LINE macro to tmac.arkup.
+
+The obsolete `.LINK' macro has been removed.
+
+.URL, .FTP, and .MAILTO now accept an optional third argument which will
+be immediately appended to the second argument (to be used with punctuation,
+for example).
+
+Pic
+---
+
+Added the `srand' command to set the seed for a new sequence of the
+pseudo-random numbers to be returned by `rand'.
+
+VERSION 1.13, 1.14, 1.15
+========================
+
+Bug fixes only; no user-visible changes.
+
+VERSION 1.12
+============
+
+Finally, there are new maintainers for groff. Mailing lists and a CVS
+repository are available also. See the file README for details. Not
+all reported bug could be fixed, so please send mails again if
+something is still not working.
+
+Most of the installation problems should have vanished now (most
+notably the $(tmac_wrap) bug).
+
+There is now a man page called groff_man.man which documents the
+basics of the -man macros. It has been originally written by Susan
+G. Kleinmann <sgk@debian.org>.
+
+A (still incomplete) groff reference manual in texinfo format
+originally contributed by Trent A. Fisher <trent@gnurd.portland.or.us>.
+
+me.man and msafer.man have been renamed to groff_me.man
+resp. groff_msafer.man for consistency.
+
+Default strings for macros in doc-common resp. tmac.an no longer
+contain the word `UNIX'.
+
+groff should now be Y2k safe (fixes contributed by Paul Eggert
+<eggert@twinsun.com>).
+
+Following the GNU standards, groff will now use the prefix
+`/usr/local/' as the default instead of replacing an existent groff
+binary.
+
+groff, troff, nroff, and pic now support the -U flag to activate unsafe
+behaviour (without -msafer); the -S flag for using the -msafer macros
+is now the default.
+
+Grohtml
+-------
+
+This is a new output device for producing HTML output contributed by
+Gaius Mulley <gaius@glam.ac.uk>. It is still very alpha but has been
+included into the distribution so that a lot of people have a chance
+to test it. Bug reports are highly welcome.
+
+Grolj4
+------
+
+Duplex printing support has been contributed by Jeffrey Copeland
+<jeff@opennt.com>.
+
+Soelim
+------
+
+Added -I option for defining include paths (patch contributed by Peter
+Miller <peterm@jna.com.au>).
+
+Gxditview
+---------
+
+Fallback resources added (patch contributed by Larry Jones
+<larry.jones@sdrc.com>).
+
+Will now support 8 gray levels.
+
+mm
+--
+
+New version 1.32 (contributed by Joergen Haegg <jh@axis.com>).
+
+VERSION 1.11
+============
+
+Complete documentation for pic is now in the file doc/pic.ms. It was
+contributed by Eric S. Raymond, <esr@thyrsus.com>, who is emphatically
+*not* volunteering to take over groff as he is way overworked with
+half a dozen other projects.
+
+VERSION 1.10
+============
+
+The directory where data files are installed has been changed from
+/usr/local/lib/groff to /usr/local/share/groff to comply with the
+latest GNU coding standards.
+
+By default groff programs with Unix equivalents are installed with a
+"g" prefix unless there is an existing (non-groff) troff installation.
+
+A new approach is used to make system macro packages available to
+groff. Instead of simply including /usr/lib/tmac in the list of
+directories searched by groff, the installation process creates for
+each system macro package a wrapper macro package in the groff macro
+directory that references the system macro package. The groff macro
+packages are now installed with a leading "g" prefix if there is a
+system version of the same macro package, and otherwise without the
+"g" prefix, with the exception that the groff version of -me which is
+always installed as -me.
+
+There is a new device, lj4, for the HP LaserJet 4 (and PCL5
+compatibles).
+
+Groff
+-----
+
+groff has a -S option that prevents the use of unsafe features in pic
+and troff. This uses a new -S option of pic and the -msafer macros
+for troff.
+
+Troff
+-----
+
+The `blm' request specifies a macro to be invoked when a blank line is
+encountered.
+
+Pic
+---
+
+A -S (safer) option disables the sh command.
+
+Grops
+-----
+
+The -m option enables manual feed.
+
+VERSION 1.09
+============
+
+\(rn will now produce a character that has the traditional metrics,
+and will form corners with \(ul and \(br. This means that it will not
+align properly with \(sr. Instead there's a new character
+\[radicalex] which aligns with \(sr; this is used by eqn for doing
+square roots.
+
+Troff
+-----
+
+The `pso' request allows you to read from the standard output of a
+command.
+
+Grops
+-----
+
+The PSPIC macro has options to allow the horizontal alignment of the
+graphic to be specified.
+
+VERSION 1.08
+============
+
+Troff
+-----
+
+The escape sequence \V[xxx] will interpolate the value of the
+environment variable xxx.
+
+Tbl
+---
+
+The decimalpoint option can be used to specify the character to be
+recognized as the decimal point character in place of the default
+period.
+
+VERSION 1.07
+============
+
+Groff
+-----
+
+The environment variable GROFF_COMMAND_PREFIX can be used to control
+whether groff looks for `gtroff' or `troff' (similarily for the
+preprocessors.)
+
+Troff
+-----
+
+Multilingual hyphenation is supported by new `hpf' and `hla' requests,
+and by a `\n[.hla]' number register. The -H option has been removed.
+Files of hyphenation patterns can have comments.
+
+When a font cannot be found, troff gives a warning (of type `font',
+enabled by default) instead of an error.
+
+There's a new request `trnt' that's like `tr' except that it doesn't
+apply to text transparently throughput into a diversion with \!.
+
+Tbl
+---
+
+There is a `nokeep' option which tells tbl not to use diversions to
+try to keep the table on one page.
+
+Eqn
+---
+
+Setting the parameter `nroff' to a non-zero value causes `ndefine' to
+behave like `define' and `tdefine' to be ignored. This is done by
+eqnrc when the current device is ascii or latin1. There's a `neqn'
+script that just does `eqn -Tascii'.
+
+Grotty
+------
+
+grotty uses whatever page length was specified using the `pl' request
+rather than using the paperlength command in the DESC file. The
+paperwidth command in the DESC file is also ignored.
+
+VERSION 1.06
+============
+
+The programs in groff that have Unix counterparts can now be installed
+without a leading `g' prefix. See the `g' variable in the Makefile.
+
+The g?nroff script simulates the nroff command using groff.
+
+New special characters \(+h, \(+f, \(+p, \(Fn, \(Bq, \(bq, \(aq, \(lz,
+\(an. See groff_char(7).
+
+^L is now a legal input character.
+
+Groff
+-----
+
+The Xps pseudo-device has disappeared. Instead there is a new -X
+option that tells groff to use gxditview instead of the usual
+postprocessor. (So instead of -TXps, use -XTps or just -X if your
+default device is ps.)
+
+The postprocessor to be used for a particular device is now specified
+by a `postpro' command in the DESC file rather than being compiled
+into groff. Similarly the command to be used for printing (with the
+-l option) is now specified by a `print' command in the DESC file.
+
+The groff command no longer specifies eqnchar as an input file for
+eqn. Instead eqn automatically loads a file `eqnrc'. The groff
+command no longer passes the -D option to eqn. Instead eqnrc sets the
+draw_lines parameter.
+
+The groff command no longer tells troff to load a device-specific
+macro file. This is handled instead by the `troffrc' file, which is
+always loaded by troff.
+
+The shell script version of groff has been removed.
+
+Troff
+-----
+
+The `rchar' request removes a character definition established with `char'.
+
+Compatibility mode is disabled and the escape character is set to `\'
+while a character definition is being processed.
+
+The `\#' escape sequence is like `\"' except that the terminating
+newline is ignored.
+
+The `shc' request tells troff which character to insert (instead of
+the default \(hy) when a word is hyphenated at a line break.
+
+A font name of 0 (zero) in the DESC file will cause no font to be
+mounted on the corresponding font position. This is useful for
+arranging that special fonts are mounted on positions on which users
+are not likely explicitly to mount fonts. All groff devices now avoid
+initially mounting fonts on positions 5-9.
+
+The `do' request allows a single request or macro to be interpreted
+with compatibility mode disabled.
+
+troff automatically loads a file `troffrc' before any other input file.
+This can be prevented with the -R option. This file is responsible
+for loading the device-specific macros.
+
+Pic
+---
+
+The -x option has been removed and a -n option has been added. By
+default, pic now assumes that the postprocessor supports groff
+extensions. The -n option tells pic to generate output that works
+with ditroff drivers. The -z option now applies only to TeX mode.
+
+The -p option has been removed. Instead if the -n option is not
+specified, pic generates output that uses \X'ps: ...' if the \n(0p
+register is non-zero and tmac.ps sets this register to 1.
+
+In places where you could 1st or 5th you can now say `i'th or `i+1'th
+(the quotes are required).
+
+Eqn
+---
+
+Eqn now automatically reads a file `eqnrc' from the macro directory.
+This performs the same role that the eqnchar files used to. This can
+be prevented by the -R option.
+
+Setting the draw_lines parameter to a non-zero value causes lines to
+be drawn using \D rather than \l. The -D option is now obsolete.
+
+`uparrow', `downarrow' and `updownarrow' can be used with `left' and
+`right'.
+
+The amount of extra space added before and after lines containing
+equations can be controlled using the `body_height' and `body_depth'
+parameters.
+
+Grops
+-----
+
+Font description files have been regenerated from newer AFM files.
+You can get access to the additional characters present in the text
+fonts in newer PostScript printers by using -mpsnew.
+
+The default value of the -b option is specified by a `broken' command
+in the DESC file.
+
+With the -g option, grops will generate PostScript code that guesses
+the page height. This allows documents to be printed on both letter
+(8.5x11) and A4 paper without change.
+
+Grodvi
+------
+
+ISO Latin-1 characters are available with -Tdvi. Format groff_char(7)
+with groff -Tdvi for more information.
+
+Grotty
+------
+
+The -mtty-char macros contain additional character definitions for
+use with grotty.
+
+Macros
+------
+
+In previous releases the groff -me macros treated the $r and $R number
+registers in a way that was incompatible with the BSD -me macros. The
+reason for this was that the approach used by the BSD -me macros does
+not work with low resolution devices such as -TX75 and -TX100.
+However, this caused problems with existing -me documents. In this
+release, the vertical spacing is controlled by the $v and $V registers
+which have the same meaning as $r and $R in earlier groff releases.
+In addition, if the $r or $R register is set to a value that would be
+correct for for the BSD -me macros and a low resolution device is not
+being used, then an appropriate value for the $v or $V register will
+be derived from the $r or $R register.
+
+The groff -me macros work with -C and (I think) with Unix troff.
+
+For backward compatibility with BSD -me, the \*{ and \*} strings are
+also available as \*[ and \*]. Of course, \*[ will only be usable
+with -C.
+
+The \*T string has been deleted. Use \*(Tm instead.
+
+Xditview
+--------
+
+The `n', Space and Return keys are bound to the Next Page action. The
+`p', BackSpace and Delete keys are bound to the Previous Page action.
+The `q' key is bound to the Quit action.
+
+The `r' key is bound to a rerasterize action that reruns groff, and
+redisplays the current page.
+
+VERSION 1.05
+============
+
+Pic
+---
+
+There is a alternative assignment operator `:=' which interacts
+differently with blocks.
+
+There is a new command `command', which allows the values of variables
+to be passed through to troff or TeX.
+
+The `print' command now accepts multiple arguments.
+
+String comparison expressions (using `==' or `!=') are allowed in more
+contexts.
+
+Grotty
+------
+
+Horizontal and vertical lines drawn with \D'l ...' will be rendered
+using -, | and + characters. This is intended to give reasonable
+results with boxed tables. It won't work well with pic.
+
+Macros
+------
+
+The -mdoc macros have been upgraded to the version in the second
+Berkeley networking release. This version is not completely
+compatible with earlier versions; the old version is still available
+as -mdoc.old. The grog script has been enhanced so that it can
+usually determine whether a document requires the old or new versions.
+
+With -TX75, -TX100 and -TXps, the PSPIC macro will produce a box
+around where the picture would appear with -Tps.
+
+VERSION 1.04
+============
+
+An implementation of the -mm macros is included.
+
+The directory in which temporary files are created can be controlled
+by setting the GROFF_TMPDIR or TMPDIR environment variables.
+
+Pic
+---
+
+Some MS-DOS support (see pic/make-dos-dist).
+
+Grops
+-----
+
+There are two new \X commands (\X'ps: invis' and \X'ps: endinvis')
+which make it possible to have substitute characters that are
+displayed when previewing with -TXps but ignored when printing with
+grops.
+
+Xditview
+--------
+
+Support for scalable fonts.
+
+VERSION 1.03
+============
+
+No changes other than bug fixes.
+
+VERSION 1.02
+============
+
+There is an implementation of refer and associated programs. groff -R
+preprocesses with grefer; no mechanism is provided for passing
+arguments to grefer because most grefer options have equivalent
+commands which can be included in the file. grog also supports refer.
+
+There is an alternative perl implementation of the grog script.
+
+The code field in lines in the charset section of font description
+files is now allowed to contain an arbitrary integer (previously it
+was required to lie between 0 and 255). Currently grops and grodvi
+use only the low order 8 bits of the value. Grodvi will use the
+complete value; however, this is unlikely to be useful with
+traditional TeX tools (.tfm files only allow 8 bit character codes.)
+
+Left and right double quotes can be obtained with \(lq and \(rq
+respectively.
+
+There is a new program called pfbtops which translates PostScript
+fonts in pfb format to ASCII.
+
+A slightly modified version of the Berkeley tmac.doc is included.
+
+Troff
+-----
+
+In long escape names the closing ] is now required to be at the same
+input level as the opening [.
+
+The \A'S' escape sequence returns 1 or 0 according as S is or is not
+suitable for use as a name.
+
+\~ produces an unbreakable space that can be stretched when the line
+is adjusted.
+
+The `mso' request is like the `so' request except that it searches for
+the file in the same directories in which tmac.X is searched for when
+the -mX option is given.
+
+The escape sequence `\R' is similar to the `nr' request.
+
+Eqn
+---
+
+A new `special' primitive allows you to add new types of unary
+constructs by writing a troff macro.
+
+Pic
+---
+
+The implementation no longer uses gperf.
+
+Grops
+-----
+
+The compile-time -DBROKEN_SPOOLER option has been replaced by a
+BROKEN_SPOOLER_FLAGS option. This allows more precise control over
+how grops should workaround broken spoolers and previewers. There is
+a new -b option that can change this at run-time.
+
+Grops now generates PostScript that complies with version 3.0 of the
+Document Structuring Convention.
+
+The resource management component of grops (the part that deals with
+imported documents and downloadable fonts) has been rewritten and now
+supports version 3.0 of the Document Structuring Conventions. The
+%%DocumentFonts comment is no longer supported; you must use the
+%%Document{Needed,Supplied}{Fonts,Resources} comments instead
+(or as well.)
+
+tmac.psatk contains some macros that support the mechanism used by the
+Andrew Toolkit for including PostScript graphics in troff documents.
+
+Xditview
+--------
+
+Parts of xditview have been rewritten so that it can be used with the
+output of gtroff -Tps. groff -TXps will run gtroff -Tps with
+gxditview.
+
+There is a new menu entry `Print' which brings up a dialog box for
+specifying a command with which the file being previewed should be
+printed.
+
+Xditview now uses imake.
+
+VERSION 1.01
+============
+
+The groff command now understands the gtroff `-a' and `-i' options.
+
+With the `m' and `n' scale indicators, the scale factor is rounded
+horizontally before being applied. This makes (almost) no difference
+for devices with `hor' equal to 1, but it makes groff with -Tascii or
+-Tlatin1 behave more like nroff in its treatment of these scale
+indicators. Accordingly tmac.tty now calls the `nroff' request so
+that the `n' condition will be true.
+
+The device-specific macros (tmac.ps, tmac.dvi, tmac.tty and tmac.X)
+have been made to work at least somewhat with -C. In particular the
+special characters defined by these macros now work with -C.
+
+groff -Tdvi -p will now pass pic the -x flag; this will enable filling
+of arrowheads and boxes, provided that your dvi driver supports the
+latest version of the tpic specials.
+
+Eqn
+---
+
+There is a new `-N' option that tells eqn not to allow newlines in
+delimiters. This allows eqn to recover better from missing closing
+delimiters. The groff command will pass on a `-N' option to eqn.
+
+Grops
+-----
+
+You can now use psfig with grops. See the file ps/psfig.diff. I do
+not recommend using psfig for new documents.
+
+The command \X'ps: file F' is similar to \X'ps: exec ...' except that
+the PostScript code is read from the file F instead of being contained
+within the \X command. This was added to support psfig.
+
+Grodvi
+------
+
+There are font files HB and HI corresponding to cmsssbx10 and cmssi10.
+
+Macros
+------
+
+The groff -me macros now work with the -C option. As a result, they
+may also work with Unix nroff/troff.
+
+In -me, the $r and $R number registers now contain the line spacing as
+a percentage of the pointsize expressed in units (normally about 120).
+The previous definition was useless with low resolution devices such
+as X75 and X100.
+
+VERSION 1.00
+============
+
+A -ms-like macro-package is now included.
+
+The name for the Icelandic lowercase eth character has been changed
+from \(-d to \(Sd.
+
+Troff
+-----
+
+There is a new request `nroff', which makes the `n' built-in condition
+true and the `t' built-in condition false; also a new request `troff'
+which undoes the effect of the `nroff' request. This is intended only
+for backward compatibility: it is usually better to test \n(.H or
+\n(.V or to use the `c' built-in condition.
+
+The \R escape sequence has been deleted. Use \E instead.
+
+There are `break' and `continue' requests for use with the `while'
+request.
+
+There is a request `hym' that can ensure that when the current
+adjustment mode is not `b' a line will not be hyphenated if it is no
+more than a given amount short, and a request `hys' that can ensure
+that when the current adjustment mode is `b' a line will not be
+hyphenated if it can be justified by adding no more than a given
+amount of extra space to each word space.
+
+There is a request `rj' similar to `ce' that right justifies lines.
+
+A warning of type `space' will be given when a call is made to an
+undefined request or macro with a name longer than two characters, and
+the first two characters of the name make a name that is defined.
+This is intended to find places where a space has been omitted been a
+request or macro and its argument. This type of warning is enabled by
+default.
+
+Pic
+---
+
+A comma is permitted between the arguments to the `reset' command.
+
+For use with TeX, there is a new `-c' option that makes gpic treat
+lines beginning with `.' in a way that is more compatible with tpic
+(but ugly).
+
+Eqn
+---
+
+It is no longer necessary to add `space 0' at the beginning of
+complicated equations inside pictures.
+
+`prime' is now treated as an ordinary character, as in Unix eqn. The
+previous behaviour of `prime' as an operator can now be obtained using
+`opprime'.
+
+Xditview
+--------
+
+There are two new devices X75-12 and X100-12 which are the same as X75
+and X100 except that they are optimized for documents that use mostly
+12 point text.
+
+VERSION 0.6
+===========
+
+The installation process has been refined to make it easy for you to
+share groff with someone who has the same type of machine as you but
+does not have a C++ compiler. See the end of the INSTALL file for
+details.
+
+There is a man page for the tfmtodit program which explains how to use
+your own fonts with groff -Tdvi.
+
+There is a man page for afmtodit which explains how to use your own
+PostScript fonts with groff -Tps.
+
+The \N escape sequence is now fully supported. It can now be used to
+access any character in a font by its output code, even if it doesn't
+have a groff name. This is made possible by a convention in the font
+files that a character name of `---' refers to an unnamed character.
+The drivers now all support the `N' command required for this. The font
+description files have been updated to include unnamed characters.
+
+The `x' command in font description files has been removed: instead
+any unknown commands are automatically made available to the drivers.
+If you constructed your own font files with an earlier version of
+tfmtodit or afmtodit, you must construct them again using the current
+version.
+
+Characters between 0200 and 0237 octal are no longer legal input
+characters. Note that these are not used in ISO 8859.
+
+A command called `grog' has been added, similar to the `doctype'
+command described in Kernighan and Pike.
+
+Groff
+-----
+
+The groff command has some new options: -V prints the pipeline
+instead of executing it; -P passes an argument to the postprocessor,
+-L passes an argument to the spooler.
+
+There is a C++ implementation of the groff command. This handles some
+things slightly better than the shell script. In particular, it can
+correctly handle arguments containing characters that have a special
+meaning to the shell; it can give an error message when child
+processes other than the last in the pipeline terminate abnormally;
+its exit status can take account of the exit statuses of all its child
+processes; it is a little more efficient; when geqn is used, it
+searches for the eqnchar file in the same way that font metric files
+are searched for, rather than expecting to find it in one particular
+directory.
+
+Gtroff
+------
+
+There is font translation feature: For example, you can tell gtroff to
+use font `HR' whenever font `H' is requested with the line
+ .ftr H HR
+This would be useful for a document that uses `H' to refer to
+Helvetica.
+
+There are some new number registers: `.kern' contains the current kern
+mode, `.lg' the current ligature mode, `.x' the major version number,
+`.y' the minor version number, `.ce' the number of lines to be
+centered in the current environment, `.trunc' the amount of vertical
+space truncated by the most recently sprung vertical position trap,
+`.ne' the amount of vertical space needed in the last `ne' request
+that caused a vertical position trap to be sprung.
+
+The `cf' request now behaves sensibly in a diversion. If used in a
+diversion, it will now arrange for the file to be copied to the output
+when the diversion is reread.
+
+There is a new request `trf' (transparent file) similar to `cf', but
+more like `\!'.
+
+There is a new escape sequence `\Y[xxx]', roughly equivalent to
+`\X'\*[xxx]'', except that the contents of string or macro xxx are not
+interpreted, and xxx may contain newlines. This requires an output
+format extension; the drivers have been modified to understand this.
+Grops has also been modified to cope with newlines in the arguments to
+\X commands; grops has a new \X command mdef, which is like def except
+that it has a first argument giving the number of definitions.
+
+There is a new warning category `escape' which warns about unknown
+escape sequences.
+
+The `fp' request now takes an optional third argument giving the external
+name of the font.
+
+The `\_' character is now automatically translated to `\(ul' as in troff.
+
+The environment variable `GROFF_HYPHEN' gives the name of the file
+containing the hyphenation patterns.
+
+There is a `\C'xxx'' escape sequence equivalent to `\[xxx]'.
+
+Characters ", ', ), ], *, \(dg are now initially transparent for the purposes
+of end of sentence recognition.
+
+There is an anti-recursion feature in the `char' request, so you can
+say `.char \(bu \s+2\(bu\s-2'.
+
+The limit on the number of font positions has been removed.
+Accordingly `\n[.fp]' never returns 0.
+
+The restriction on the number of numbered environments has been removed.
+
+There is a new escape sequence `\E' that makes it possible to
+guarantee that an escape sequence won't get interpreted in copy-mode.
+The `\R' escape sequence is accordingly now deprecated.
+
+Gpic
+----
+
+Arguments of the form `X anything X' (in the `copy thru', `sh', `for',
+`if' and `define' constructs) can now be of the form `{ anything }'.
+
+If the `linethick' variable is negative (as it now is initially),
+lines will be drawn with a thickness proportional to the current point
+size.
+
+The `rand' function now takes no arguments and returns a number between
+0 and 1. The old syntax is still supported.
+
+`^' can be used in expressions to indicate exponentiation.
+
+In the `for' construct the argument to the by clause can be prefixed
+by `*' to indicate that the increment is multiplicative.
+
+A bare expression may be used as an attribute. If the current
+direction is `dir', then an attribute `expr' is equivalent to
+`dir expr'
+
+There is a `sprintf' construct that allows numbers to be formatted and used
+wherever a quoted string can be used.
+
+The height of a text object without an explicit height attribute is
+the number of text strings associated with the object times the value
+of the `textht' variable.
+
+The maximum height and width of a picture is controlled by the
+`maxpswid' and `maxpsht' variables.
+
+Gtbl
+----
+
+Gtbl can now handle gracefully the situation where the `ce' request
+has been applied to a table.
+
+Geqn
+----
+
+The `ifdef' primitive has been generalized.
+
+A tilde accent can be put underneath a box using `utilde'. This
+defined using a general `uaccent' primitive.
+
+Grops
+-----
+
+There is a new PostScript font downloading scheme which handles font
+downloading for imported illustrations. Previously, the name of the
+file containing the font was given in the `x download' line in the
+groff font metric file. Now, there is a `download' file which says
+for each PostScript font name which file contains that font. Grops
+can also now handle inter-font dependencies, where one downloadable
+font depends on some other (possibly downloadable) font.
+
+The `T' font has been removed. The characters it used to provide are
+now provided by `char' definitions in tmac.ps. TSymbol.ps has also
+been removed, and the tweaks it provided are now provided by `char'
+definitions.
diff --git a/PROBLEMS b/PROBLEMS
new file mode 100644
index 00000000..dbadbdee
--- /dev/null
+++ b/PROBLEMS
@@ -0,0 +1,575 @@
+This file describes various problems that have been encountered in
+compiling, installing and running groff. Suggestions for additions or
+other improvements to this file are welcome.
+
+* My document says that the current year is 19100, not 2000.
+
+In groff, as in traditional troff, the yr number register yields the
+year minus 1900. Unfortunately, there is a longstanding bug in the
+Troff User's Manual <http://cm.bell-labs.com/cm/cs/cstr/54.ps.gz>,
+which incorrectly claims that yr is the last two digits of the year.
+This claim was never true of either Unix troff or of groff.
+
+If your text looks like this:
+
+ .\" Wrong:
+ This document was formatted in 19\n(yr.
+
+you can correct it as follows:
+
+ This document was formatted in \n[year].
+
+or, if you want to be portable to older troff versions, as follows:
+
+ .nr y4 1900+\n(yr
+ This document was formatted in \n(y4.
+
+* I get lots of `numeric overflow' error messages whenever I run
+groff; I compiled groff with AT&T C++ 2.0 with an ANSI C compiler.
+
+Make sure -DCFRONT_ANSI_BUG is included in DEFINES in the top-level
+Makefile. If that doesn't solve the problem, define INT_MIN as
+-INT_MAX in libgroff/lib.h.
+
+* I get errors when I try to compile groff with Sun C++ version 5.0 or 5.1.
+
+This is a known problem; see Sun bug #4301919. As of this writing, no
+patch is available. Use GCC 2.95.2 or later instead.
+
+* I get errors when I try to compile groff with Sun C++ version 3 or
+earlier.
+
+Groff requires header files that are moderately compatible with AT&T
+C++ and ANSI C. With some versions of Sun C++, the supplied header
+files need some of the following changes to meet this requirement:
+<string.h> must declare the mem* functions, (just add `#include
+<memory.h>' to <string.h>); the first argument to fopen and freopen
+should be declared as `const char *'; the first argument to fread
+should be declared as `void *'; the first argument to fwrite should be
+declared as `const void *'; malloc should be declared to return `void
+*'; in <alloca.h>, the declaration `extern "C" { void
+*__builtin_alloca(int); }' should be added; declarations of getopt(),
+optarg, optind and opterr should be added to <stdlib.h>; in
+<sys/signal.h> the return type and the second argument type of
+signal() should be changed to be `void (*)(int)'.
+
+You can either change them in place, or copy them to some other
+directory and include that directory with a -I option.
+
+* I get errors when I try to compile groff with DEC C++.
+
+Fix the declaration of write() in <unistd.h> so that the second
+argument is a const char *. Fix the declaration of open() in
+<sys/file.h> so that the first argument is a const char *.
+
+* On Ultrix, the make stops with the message
+
+ *** Error code 1
+
+ Stop.
+
+for no apparent reason.
+
+Use GNU make.
+
+* I'm having problems compiling groff on 386BSD 0.1.
+
+If you're using ash as /bin/sh, you'll need the following patch.
+
+*** gendef.sh.org Sun Jun 30 13:30:36 1991
+--- gendef.sh Sun Feb 28 10:23:49 1993
+***************
+*** 3,9 ****
+ file=$1
+ shift
+
+! defs="#define $1"
+ shift
+ for def
+ do
+--- 3,10 ----
+ file=$1
+ shift
+
+! x=$1
+! defs="#define $x"
+ shift
+ for def
+ do
+
+You'll also need to change dirnamemax.c so that it doesn't use
+pathconf().
+
+* While compiling on Xenix, ranlib libgroff.a fails.
+
+The system ranlib can't handle externals longer than 40 characters.
+Use the ranlib included in demon.co.uk:/pub/xenix/g++-1.40.3a.v1
+instead.
+
+* Groff can't handle my troff document. It works fine with AT&T troff.
+
+Read the section on incompatibilities in gtroff(1). Try using the -C
+option. Alternatively there's the sed script in tmac/fixmacros.sed
+which will attempt to edit a file of macros so that it can be used
+with groff without the -C flag.
+
+* groff -Tdvi produces dvi files that use fonts at weird magnifications.
+
+Yes, it does. You may need to compile fonts with Metafont at these
+magnifications. The CompileFonts script in the devdvi/generate
+directory may help you to do this. (It will take a *long* time.)
+
+* pic output is not centered horizontally; pictures sometimes run off
+the bottom of the page.
+
+The macro package you are using is not supplying appropriate definitions
+of PS and PE. Give groff a -mpic option.
+
+* I'm having problems including PostScript illustrations using the PSPIC
+macro.
+
+A PostScript document must meet three requirements in order to be
+included with the PSPIC macro: it must comply with the Adobe Document
+Structuring Conventions; it must contain a BoundingBox line; it must
+be ``well-behaved''. The BoundingBox line should be of the form:
+
+ %%BoundingBox: llx lly urx ury
+
+where llx, lly, urx, ury are the coordinates of the lower left x,
+lower left y, upper right x, upper right y of the bounding box of
+marks on the page expressed as integers in the default PostScript
+coordinate system (72 units per inch, origin at bottom left corner).
+A useful tactic is to print out the illustration by itself (you may
+need to add a `showpage' at the end), and physically measure the
+bounding box. For more detail on these requirements, read the
+specification of Encapsulated PostScript format. (This is available
+from the Adobe file server; send a message with a body of `help' to
+ps-file-server@adobe.com.)
+
+* I've configured groff for A4 paper, but gtroff still seems to think
+that the length of a page (as returned by \n(.p) is 11 inches.
+
+This is intentional. The PAGE option is used only by grops. For
+compatibility with ditroff, the default page length in gtroff is
+always 11 inches. The page length can be changed with the `pl'
+request.
+
+* Groff doesn't use the font names I'm used to.
+
+Use the `ftr' request. See gtroff(1).
+
+* I get errors using the Unix -ms macros with groff -e -C.
+
+Apply this change:
+
+*** /usr/lib/ms/ms.eqn Tue Apr 25 02:14:28 1989
+--- ms.eqn Sun Nov 11 10:33:59 1990
+***************
+*** 22,29 ****
+ ..
+ . \" EN - end of a displayed equation
+ .de EN
+! .if !\\*(10 .br
+ .di
+ .rm EZ
+ .nr ZN \\n(dn
+ .if \\n(ZN>0 .if \\n(YE=0 .LP
+--- 22,30 ----
+ ..
+ . \" EN - end of a displayed equation
+ .de EN
+! .if \\n(.k>0 .br
+ .di
++ .ds 10 \\*(EZ\\
+ .rm EZ
+ .nr ZN \\n(dn
+ .if \\n(ZN>0 .if \\n(YE=0 .LP
+
+
+* gpic doesn't accept the syntax `chop N M' for chopping both ends of a
+line.
+
+The correct syntax is `chop N chop M'.
+
+* With gpic -t, when I print `line ->; box' using a dvi to ps
+program, the arrow head sticks through into the inside of the box.
+
+The dvi to ps program should be modified to set the line cap and
+line join parameters to 1 while printing tpic specials.
+
+* When I print the output groff -Tps, the output is always shifted up
+by about 0.7 inches; I'm using 8.5x11 inch paper.
+
+Make sure that PAGE is defined to be `letter' in the top-level
+Makefile.
+
+* When I try to print the output of groff -Tps, I get no output at all
+from the printer, and the log file shows the error
+%%[ error: undefined; offendingcommand: BP ]%%
+I'm using TranScript spooling software.
+
+This is a bug in the page reversal filter in early versions of
+TranScript. Change the `broken' parameter in
+/usr/local/lib/groff/font/devps/DESC to 7.
+
+* When I preview groff -Tps output using the Sun OpenWindows 2.0 pageview
+program, all the pages are displayed on top of each other.
+
+This is a defect in pageview. Change the `broken' parameter in
+/usr/local/lib/groff/font/devps/DESC to 2.
+
+* With groff -TX75, -TX100 or -X, I can only view the first page.
+
+The left mouse button brings up a menu that allows you to view other
+pages.
+
+* When I print the output of groff -Tdvi, I just get a black dot in
+upper left corner.
+
+Some dvi drivers (notably early versions of xtex) do not correctly
+handle dvi files that use a resolution different from that used by dvi
+files produced by TeX. Try getting a more up to date driver.
+
+* I get lots of errors when I use groff with the AT&T -mm macros.
+
+The AT&T -mm macros need a few changes to work with groff; `make
+install.dwbmm' will copy your -mm macros to groff's macro directory
+and make the necessary changes. You may need to edit the commands for
+the install.mm target in the Makefile. Alternatively use the groff
+-mm macros.
+
+* gtroff doesn't understand lines like `.ce99' with no space between
+the name of the request or macro and the arguments.
+
+Gtroff requires a space between macro or request and its arguments
+because it allows the use of long names for macros and requests. You
+can use the -C option or the `cp' request to put gtroff into a
+compatibility mode in which it is not possible to use long names for
+macros but in which no space is required between macros and their
+arguments. The use of compatibility mode is strongly discouraged.
+
+* gtroff gives warnings about lines like
+ .ev \" a comment
+(with a tab after the .ev).
+
+A tab character cannot be used as a substitute for a space character
+(except in one case: between a control character at the beginning of a
+line and the name of a macro or request). For example, in Unix troff
+ .ps \" restore the previous point size
+(with a tab after the .ps) will NOT restore the previous point-size;
+instead it will be silently ignored. Since this is very likely to be
+an error, gtroff can give a warning about it. If you want to align
+comments, you can do it like this:
+ .ev\" \" a comment
+
+* I don't like the page headers and footers produced by groff -man.
+
+There seem to be many different styles of page header and footer
+produced by different versions of the -man macros. You will need to
+modify macros/tmac.an to suit your personal taste. For example, if
+you want the center of the page header to say
+ System Programmer's Manual
+you will need to change the line
+ .el .ds an-extra3 \"System Programmer's Manual
+to
+ .el .ds an-extra3 System Programmer's Manual
+
+* While formatting a manual page, groff complains about not being able to
+break lines. The problem seems to be caused by a line like:
+ .TP \w'label'+2
+
+The -man documentation says that the default scale indicator for TP
+macro is `n'. The groff -man macros implement this correctly, so that
+the argument will be evaluated as if it were
+ \w'label'n+2n
+The Unix -man macros don't implement this correctly (probably because
+it's hard to do in Unix troff); they just append `n' to the entire
+argument, so that it will be evaluated as if it were
+ \w'label'u+2n
+The solution is to fix the manual page:
+ .TP \w'label'u+2
+
+* I'm having problems formatting Ultrix man pages with groff -man.
+
+The Ultrix man pages use a number of non-standard extensions to the
+Unix man macros. One solution is to use the Ultrix -man macros with
+groff. Rename /usr/local/lib/groff/tmac/tmac.an to
+/usr/local/lib/groff/tmac/tmac.an.gnu, copy /usr/lib/tmac/tmac.an to
+/usr/local/lib/groff/tmac/tmac.an and apply the following patch (from
+Frank Wortner):
+
+*** /usr/local/lib/groff/tmac/tmac.an Wed Sep 9 12:29:28 1992
+--- /usr/lib/tmac/tmac.an Fri Jul 24 19:58:19 1992
+***************
+*** 489,495 ****
+ . \" make special case of shift out of italic
+ .de }S
+ .ds ]F
+! .if \\$12 .if !\\$5 .ds ]F \^
+ .ie !\\$4 .}S \\$2 \\$1 "\\$3\f\\$1\\$4\\*(]F" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+ .el \\$3
+ .}f
+--- 489,495 ----
+ . \" make special case of shift out of italic
+ .de }S
+ .ds ]F
+! .if \\$12 .if !\\$5 .ds ]F\^
+ .ie !\\$4 .}S \\$2 \\$1 "\\$3\f\\$1\\$4\\*(]F" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+ .el \\$3
+ .}f
+
+Another possible solution is to install tmac/man.ultrix as
+/usr/local/lib/groff/tmac/man.local.
+
+* I'm having problems formatting HP-UX 9.0 man pages with groff -man.
+
+Rename /usr/local/lib/groff/tmac/tmac.an to (for example)
+/usr/local/lib/groff/tmac/tmac.gan, copy HP's tmac.an into
+/usr/local/lib/groff/tmac/tmac.an, and either put `.cp 1' at the
+beginning or filter it (and any files it .so's) through
+tmac/fixmacros.sed.
+
+* I'm having problems formatting man pages produced by the perl
+wrapman script.
+
+Some versions of wrapman have a superfluous blank line before the .TH
+line. This must be deleted. Then either use groff -C, or apply the
+following patch:
+
+*** wrapman.~2~ Sun Jan 19 12:10:24 1992
+--- wrapman Tue Aug 10 02:06:41 1993
+***************
+*** 35,41 ****
+ $line1 .= <IN> if $line1 =~ /eval/;
+ $line1 .= <IN> if $line1 =~ /argv/;
+ $line2 = <IN>;
+! next if $line2 eq "'di';\n";
+
+ # Pull the old switcheroo.
+
+--- 35,41 ----
+ $line1 .= <IN> if $line1 =~ /eval/;
+ $line1 .= <IN> if $line1 =~ /argv/;
+ $line2 = <IN>;
+! next if $line2 eq "'di ';\n" || $line2 eq "'di';\n";
+
+ # Pull the old switcheroo.
+
+***************
+*** 49,56 ****
+
+ print OUT $line1;
+ print OUT <<EOF;
+! 'di';
+! 'ig00';
+ #
+ # $header
+ #
+--- 49,58 ----
+
+ print OUT $line1;
+ print OUT <<EOF;
+! 'di ';
+! 'ds 00 \\"';
+! 'eo ';
+! 'ig 00 ';
+ #
+ # $header
+ #
+***************
+*** 72,85 ****
+
+ # These next few lines are legal in both Perl and nroff.
+
+! $null.00; # finish .ig
+
+ 'di \\" finish diversion--previous line must be blank
+ .nr nl 0-1 \\" fake up transition to first page again
+ .nr % 0 \\" start at page 1
+! '; __END__ ##### From here on it's a standard manual page #####
+ .TH $PROG 1 "$month $mday, 19$year"
+- .AT 3
+ .SH NAME
+ $prog \\- whatever
+ .SH SYNOPSIS
+--- 74,87 ----
+
+ # These next few lines are legal in both Perl and nroff.
+
+! $null.00 ; # finish .ig
+! 'ec \\';
+
+ 'di \\" finish diversion--previous line must be blank
+ .nr nl 0-1 \\" fake up transition to first page again
+ .nr % 0 \\" start at page 1
+! .\\"'; __END__ ##### From here on it's a standard manual page #####
+ .TH $PROG 1 "$month $mday, 19$year"
+ .SH NAME
+ $prog \\- whatever
+ .SH SYNOPSIS
+
+
+* When I preview documents using -TX75 or -TX100, the layout is not the same
+as when I print the document with -Tps: the line and page breaks come
+in different places.
+
+Use groff -X -Tps.
+
+* When I try to run gxditview, I get the error:
+Error: Widget viewport has zero width and/or height
+
+This error means you haven't correctly installed the application
+defaults file, GXditview.ad; ``make install'' does this for you
+automatically, so either you didn't do ``make install'', or you don't
+have imake configured correctly.
+
+* groff uses up an enormous amount of memory processing large files.
+I'm using 386BSD 0.1.
+
+386BSD includes an old version of g++, 1.39, which has a bug that
+causes a major memory leak in gtroff. Apply the following fix to g++
+and recompile groff:
+
+*** cplus-decl.c.~1~ Mon Aug 6 05:28:59 1990
+--- cplus-decl.c Wed Jun 5 08:55:04 1991
+***************
+*** 7951,7961 ****
+
+ /* At the end, call delete if that's what's requested. */
+ if (TREE_GETS_DELETE (current_class_type))
+ exprstmt = build_method_call (build1 (NOP_EXPR, TYPE_POINTER_TO (current_class_type), error_mark_node),
+ get_identifier (OPERATOR_DELETE_FORMAT),
+! build_tree_list (NULL_TREE, integer_zero_node),
+ NULL_TREE, LOOKUP_NORMAL);
+ else if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
+ exprstmt = build_x_delete (ptr_type_node, current_class_decl, 0);
+ else
+ exprstmt = 0;
+--- 7951,7961 ----
+
+ /* At the end, call delete if that's what's requested. */
+ if (TREE_GETS_DELETE (current_class_type))
+ exprstmt = build_method_call (build1 (NOP_EXPR, TYPE_POINTER_TO (current_class_type), error_mark_node),
+ get_identifier (OPERATOR_DELETE_FORMAT),
+! build_tree_list (NULL_TREE, current_class_decl),
+ NULL_TREE, LOOKUP_NORMAL);
+ else if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
+ exprstmt = build_x_delete (ptr_type_node, current_class_decl, 0);
+ else
+ exprstmt = 0;
+
+* Where can I get grap?
+
+Grap is not freely available, but there is a nawk script implementing
+an extended subset of grap available for ftp as
+ftp.informatik.uni-rostock.de:/pub/local/software/prag-1.0.shar.gz.
+
+* How can I use groff with an old LaserJet printer that doesn't work
+with groff -Tlj4?
+
+You have at least 3 options:
+
+- use groff -Tps with GNU Ghostscript;
+
+- use groff -Tdvi with a TeX .dvi to Laserjet driver;
+
+- use groff with the LaserJet driver in Chris Lewis' psroff package
+(available for ftp from:
+ftp.uunet.ca:/distrib/chris_lewis/psroff3.0pl17).
+
+* Groff seems to generate level 3 Postscript, but my printer is only a
+level 1 or 2 PostScript printer.
+
+In fact groff generates only level 1 PostScript. The `%!PS-Adobe-3.0'
+comment at the beginning of PostScript output generated by groff
+indicates that the file conforms to version 3.0 of the Adobe Document
+Structuring Conventions. The output generated by groff should be
+printable on any PostScript printer. Problems with groff output's not
+printing are most often caused by the spooling system.
+
+* The \n(st and \n(sb registers don't seem to work. I thought \w set
+them to the height and depth of its argument, but the registers always
+seem to be 0.
+
+\n(st and \n(sb aren't supposed to give the height and depth of the
+string rather they give the minimum and maximum vertical displacement
+of the baseline. For example for \v'2u'\v'-3u', \n(st will be 1 and
+\n(sb will be -2. The height and depth of the string is available in
+the \n[rst] and \n[rsb] registers: these are groff extensions.
+
+* On an SGI system, how can I make the man command use groff?
+
+From David Hinds <dhinds@allegro.stanford.edu> (some of these steps
+are unnecessary if you install with the `g' Makefile variable defined
+as empty):
+
+Create a script called 'eqn':
+
+ > #!/bin/sh
+ > if [ ${1:-""} = /usr/pub/eqnchar ] ; then shift ; fi
+ > geqn $*
+
+and a script called 'neqn':
+
+ > #!/bin/sh
+ > if [ ${1:-""} = /usr/pub/eqnchar ] ; then shift ; fi
+ > geqn -Tascii $*
+
+and do:
+
+ > ln -s gnroff nroff
+
+and edit the end of the gnroff script to be:
+
+ > rest=`echo ${1+"$@"} | sed -e 's+/usr/lib/tmac+/usr/local/lib/groff/tmac+'`
+ > exec groff -Wall -mtty-char $T $opts $rest
+
+To get PostScript output from 'man -t', you also need to create a
+'psroff' script similar to 'nroff'. Here are the context diffs:
+
+*** /usr/local/bin/nroff Sat Feb 13 15:51:09 1993
+--- /usr/local/bin/psroff Sat Feb 13 17:45:46 1993
+***************
+*** 1,8 ****
+ #!/bin/sh
+! # Emulate nroff with groff.
+
+ prog="$0"
+! T=-Tascii
+ opts=
+
+ for i
+--- 1,8 ----
+ #!/bin/sh
+! # Emulate psroff with groff.
+
+ prog="$0"
+! T=-Tps
+ opts=
+
+ for i
+***************
+*** 25,30 ****
+--- 25,33 ----
+ -Tascii|-Tlatin1)
+ T=$1
+ ;;
++ -t)
++ # ignore -- default is send to stdout
++ ;;
+ -T*)
+ # ignore other devices
+ ;;
+***************
+*** 49,53 ****
+ rest=`echo ${1+"$@"} | sed -e 's+/usr/lib/tmac+/usr/local/lib/groff/tmac+'`
+
+ # This shell script is intended for use with man, so warnings are
+ # probably not wanted. Also load nroff-style character definitions.
+! exec groff -Wall -mtty-char $T $opts $rest
+--- 52,56 ----
+ rest=`echo ${1+"$@"} | sed -e 's+/usr/lib/tmac+/usr/local/lib/groff/tmac+'`
+
+ # This shell script is intended for use with man, so warnings are
+! # probably not wanted.
+! exec groff -Wall $T $opts $rest
diff --git a/PROJECTS b/PROJECTS
new file mode 100644
index 00000000..82c6d65c
--- /dev/null
+++ b/PROJECTS
@@ -0,0 +1,16 @@
+Here are some things that would be useful additions to groff:
+
+ grap
+
+ -mv macros (for typesetting viewgraphs and slides)
+
+ a deroff that understands long names
+
+ a page-makeup postprocessor and associated macro package
+ (like pm and -mpm)
+
+ a complete, self-contained manual -- first results can be found in
+ doc/groff.texinfo.
+
+If you want to work on one of these, you should probably post to
+gnu.groff.bug to see if anyone else has gotten there first.
diff --git a/README b/README
new file mode 100644
index 00000000..266651ac
--- /dev/null
+++ b/README
@@ -0,0 +1,84 @@
+This is the GNU groff document formatting system. The version number
+is given in the file VERSION.
+
+Included in this release are implementations of troff, pic, eqn, tbl,
+refer, the -man macros and the -ms macros, and drivers for PostScript,
+TeX dvi format, HP LaserJet 4 printers, HTML format (still alpha), and
+typewriter-like devices. Also included is a modified version of the
+Berkeley -me macros, an enhanced version of the X11 xditview
+previewer, and an implementation of the -mm macros contributed by
+Joergen Haegg (jh@axis.se).
+
+See the file INSTALL for installation instructions. You will require
+a C++ compiler.
+
+The file NEWS describes recent user-visible changes to groff.
+
+Groff is free software. See the file COPYING for copying permission.
+
+The file PROBLEMS describes various problems that have been
+encountered in compiling, installing, and running groff.
+
+For the moment, the documentation assumes that you are already
+familiar with the Unix versions of troff, -man, -ms and the
+preprocessors.
+
+The most recent released version of groff is always available by
+anonymous ftp from ftp.gnu.org in the directory pub/gnu/groff.
+
+A CVS repository is now available, containing the current development
+version of groff. You can access it with the commands
+
+ export CVSROOT=:pserver:anoncvs@anoncvs.ffii.org:/var/cvs
+ cvs login
+ cvs -z9 co groff
+
+(if the prompt for the password appears, just press the enter key).
+After a successful login you no longer need the first two commands; an
+update of a checked out repository should be done with
+
+ cvs -z9 update -d
+
+Please read the info pages of cvs for further details.
+
+Alternatively, you can download snapshots (which are updated twice a
+day) from
+
+ ftp://ftp.ffii.org/pub/groff/devel/groff-current.tar.gz
+
+or a diff file relative to the latest official groff release as
+
+ ftp://ftp.ffii.org/pub/groff/devel/groff-<version>-current.diff.gz
+
+Assuming that groff-<version>.tar.gz and
+groff-<version>-current.diff.gz are in the same directory, do the
+following to apply the diff file:
+
+ tar xzvf groff-<version>.tar.gz
+ cd groff-<version>
+ gunzip -c ../groff-<version>-current.diff.gz | patch -p1
+
+Please report bugs using the form in the file BUG-REPORT; the idea of
+this is to make sure that FSF has all the information it needs to fix
+the bug. At the very least, read the BUG-REPORT form and make sure
+that you supply all the information that it asks for. Even if you are
+not sure that something is a bug, report it using BUG-REPORT: this
+will enable us to determine whether it really is a bug or not.
+
+Three mailing lists are available:
+
+ bug-groff@gnu.org for reporting bugs
+ groff@gnu.org for general discussion of groff
+ groff-commit@ffii.org a read-only list showing logs of
+ commitments to the CVS repository
+
+Note that groff@gnu.org is an alias for groff@ffii.org; you must be
+subscribed to the `groff' and `groff-commit' lists to send mails.
+
+To subscribe, send a mail to <list>-request@<domain> (example:
+groff-request@ffii.org) with the word `subscribe' in either the
+subject or body of the email (don't include the quotes).
+
+GNU groff was written by James Clark <jjc@jclark.com>. It is now
+maintained by Ted Harding <ted.harding@nessie.mcc.ac.uk> and Werner
+Lemberg <wl@gnu.org>.
diff --git a/REVISION b/REVISION
new file mode 100644
index 00000000..573541ac
--- /dev/null
+++ b/REVISION
@@ -0,0 +1 @@
+0
diff --git a/TODO b/TODO
new file mode 100644
index 00000000..d78292a2
--- /dev/null
+++ b/TODO
@@ -0,0 +1,24 @@
+Better selection of paper sizes with -Tps.
+
+Make -Tlj4 work with -X.
+
+Guess man5ext and man7ext variables.
+
+Provide man.sun implementing .TX.
+
+Improve GROFF_PRINT macro in aclocal.m4.
+
+Provide a `check' target.
+
+Provide a `bindist' target.
+
+Implement tmac.bib in terms of tmac.s.
+
+Support long options using GNU getopt.
+
+Catch the following error in -me:
+.(z
+.(l C
+.)z
+
+Arrows for next/previous page from R5 xditview.
diff --git a/VERSION b/VERSION
new file mode 100644
index 00000000..e7151969
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+1.16
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 00000000..1a278c2b
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,464 @@
+dnl Autoconf macros for groff.
+dnl Copyright (C) 1989, 1990, 1991, 1992, 1995 Free Software Foundation, Inc.
+dnl
+dnl This file is part of groff.
+dnl
+dnl groff is free software; you can redistribute it and/or modify it under
+dnl the terms of the GNU General Public License as published by the Free
+dnl Software Foundation; either version 2, or (at your option) any later
+dnl version.
+dnl
+dnl groff is distributed in the hope that it will be useful, but WITHOUT ANY
+dnl WARRANTY; without even the implied warranty of MERCHANTABILITY or
+dnl FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+dnl for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License along
+dnl with groff; see the file COPYING. If not, write to the Free Software
+dnl Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+dnl
+dnl
+AC_DEFUN(GROFF_PRINT,
+[if test -z "$PSPRINT"; then
+ AC_CHECK_PROGS(LPR,lpr)
+ AC_CHECK_PROGS(LP,lp)
+ if test -n "$LPR" && test -n "$LP"; then
+ # HP-UX provides an lpr command that emulates lpr using lp,
+ # but it doesn't have lpq; in this case we want to use lp
+ # rather than lpr.
+ AC_CHECK_PROGS(LPQ,lpq)
+ test -n "$LPQ" || LPR=
+ fi
+ if test -n "$LPR"; then
+ PSPRINT="$LPR"
+ elif test -n "$LP"; then
+ PSPRINT="$LP"
+ fi
+fi
+AC_SUBST(PSPRINT)
+AC_MSG_CHECKING([for command to use for printing PostScript files])
+AC_MSG_RESULT($PSPRINT)
+# Figure out DVIPRINT from PSPRINT.
+AC_MSG_CHECKING([for command to use for printing dvi files])
+if test -n "$PSPRINT" && test -z "$DVIPRINT"; then
+ if test "X$PSPRINT" = "Xlpr"; then
+ DVIPRINT="lpr -d"
+ else
+ DVIPRINT="$PSPRINT"
+ fi
+fi
+AC_SUBST(DVIPRINT)
+AC_MSG_RESULT($DVIPRINT)])dnl
+dnl
+dnl
+dnl Bison generated parsers have problems with C++ compilers other than g++.
+dnl So byacc is preferred over bison.
+dnl
+AC_DEFUN(GROFF_PROG_YACC,
+[AC_CHECK_PROGS(YACC, byacc 'bison -y', yacc)])
+dnl
+dnl
+dnl GROFF_CSH_HACK(if hack present, if not present)
+dnl
+AC_DEFUN(GROFF_CSH_HACK,
+[AC_MSG_CHECKING([for csh hash hack])
+cat <<EOF >conftest.sh
+#!/bin/sh
+true || exit 0
+export PATH || exit 0
+exit 1
+EOF
+chmod +x conftest.sh
+if echo ./conftest.sh | (csh >/dev/null 2>&1) >/dev/null 2>&1; then
+ AC_MSG_RESULT(yes); $1
+else
+ AC_MSG_RESULT(no); $2
+fi
+rm -f conftest.sh])dnl
+dnl
+dnl
+dnl From udodo!hans@relay.NL.net (Hans Zuidam)
+dnl
+AC_DEFUN(GROFF_ISC_SYSV3,
+[AC_MSG_CHECKING([for ISC 3.x or 4.x])
+changequote(,)dnl
+if grep '[34]\.' /usr/options/cb.name >/dev/null 2>&1
+changequote([,])dnl
+then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(_SYSV3)
+else
+ AC_MSG_RESULT(no)
+fi])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_POSIX,
+[AC_MSG_CHECKING([whether -D_POSIX_SOURCE is necessary])
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_TRY_COMPILE([#include <stdio.h>
+extern "C" { void fileno(int); }],,
+AC_MSG_RESULT(yes);AC_DEFINE(_POSIX_SOURCE),
+AC_MSG_RESULT(no))
+AC_LANG_RESTORE])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_GETOPT,
+[AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_MSG_CHECKING([declaration of getopt in stdlib.h])
+AC_TRY_COMPILE([#include <stdlib.h>
+extern "C" { void getopt(int); }],,
+AC_MSG_RESULT(no),
+AC_MSG_RESULT(yes);AC_DEFINE(STDLIB_H_DECLARES_GETOPT))
+AC_MSG_CHECKING([declaration of getopt in unistd.h])
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <unistd.h>
+extern "C" { void getopt(int); }],,
+AC_MSG_RESULT(no),
+AC_MSG_RESULT(yes);AC_DEFINE(UNISTD_H_DECLARES_GETOPT))
+AC_LANG_RESTORE])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_PUTENV,
+[AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_MSG_CHECKING([declaration of putenv])
+AC_TRY_COMPILE([#include <stdlib.h>
+extern "C" { void putenv(int); }],,
+AC_MSG_RESULT(no),
+AC_MSG_RESULT(yes);AC_DEFINE(STDLIB_H_DECLARES_PUTENV))
+AC_LANG_RESTORE])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_POPEN,
+[AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_MSG_CHECKING([declaration of popen])
+AC_TRY_COMPILE([#include <stdio.h>
+extern "C" { void popen(int); }],,
+AC_MSG_RESULT(no),
+AC_MSG_RESULT(yes);AC_DEFINE(STDIO_H_DECLARES_POPEN))
+AC_LANG_RESTORE])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_PCLOSE,
+[AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_MSG_CHECKING([declaration of pclose])
+AC_TRY_COMPILE([#include <stdio.h>
+extern "C" { void pclose(int); }],,
+AC_MSG_RESULT(no),
+AC_MSG_RESULT(yes);AC_DEFINE(STDIO_H_DECLARES_PCLOSE))
+AC_LANG_RESTORE])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_SYS_NERR,
+[AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_MSG_CHECKING([for sys_nerr in <errno.h> or <stdio.h>])
+AC_TRY_COMPILE([#include <errno.h>
+#include <stdio.h>],
+[int k; k = sys_nerr;],
+AC_MSG_RESULT(yes);AC_DEFINE(HAVE_SYS_NERR),
+AC_MSG_RESULT(no))
+AC_LANG_RESTORE])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_SYS_ERRLIST,
+[AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_MSG_CHECKING([for sys_errlist[] in <errno.h> or <stdio.h>])
+AC_TRY_COMPILE([#include <errno.h>
+#include <stdio.h>],
+[int k; k = (int)sys_errlist[0];],
+AC_MSG_RESULT(yes);AC_DEFINE(HAVE_SYS_ERRLIST),
+AC_MSG_RESULT(no))
+AC_LANG_RESTORE])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_HYPOT,
+[AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_MSG_CHECKING([declaration of hypot])
+AC_TRY_COMPILE([#include <math.h>
+extern "C" { double hypot(double,double); }],,
+AC_MSG_RESULT(no),
+AC_MSG_RESULT(yes);AC_DEFINE(MATH_H_DECLARES_HYPOT))
+AC_LANG_RESTORE])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_OSFCN_H,
+[AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_MSG_CHECKING([C++ <osfcn.h>])
+AC_TRY_COMPILE([#include <osfcn.h>],
+[read(0, 0, 0); open(0, 0);],
+AC_MSG_RESULT(yes);AC_DEFINE(HAVE_CC_OSFCN_H),
+AC_MSG_RESULT(no))
+AC_LANG_RESTORE])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_LIMITS_H,
+[AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_MSG_CHECKING([C++ <limits.h>])
+AC_TRY_COMPILE([#include <limits.h>],
+[int x = INT_MIN; int y = INT_MAX; int z = UCHAR_MAX;],
+AC_MSG_RESULT(yes);AC_DEFINE(HAVE_CC_LIMITS_H),
+AC_MSG_RESULT(no))
+AC_LANG_RESTORE])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_TIME_T,
+[AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_MSG_CHECKING([for declaration of time_t])
+AC_TRY_COMPILE([#include <time.h>],
+[time_t t = time(0); struct tm *p = localtime(&t);],
+AC_MSG_RESULT(yes),
+AC_MSG_RESULT(no);AC_DEFINE(LONG_FOR_TIME_T))
+AC_LANG_RESTORE])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_STRUCT_EXCEPTION,
+[AC_MSG_CHECKING([struct exception])
+AC_TRY_COMPILE([#include <math.h>],
+[struct exception e;],
+AC_MSG_RESULT(yes);AC_DEFINE(HAVE_STRUCT_EXCEPTION),
+AC_MSG_RESULT(no))])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_ARRAY_DELETE,
+[AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_MSG_CHECKING([whether ANSI array delete syntax supported])
+AC_TRY_COMPILE(,
+changequote(,)dnl
+char *p = new char[5]; delete [] p;changequote([,]),
+AC_MSG_RESULT(yes),
+AC_MSG_RESULT(no);AC_DEFINE(ARRAY_DELETE_NEEDS_SIZE))
+AC_LANG_RESTORE])dnl
+dnl
+dnl
+dnl
+AC_DEFUN(GROFF_TRADITIONAL_CPP,
+[AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_MSG_CHECKING([traditional preprocessor])
+AC_TRY_COMPILE([#define name2(a,b) a/**/b],[int name2(foo,bar);],
+AC_MSG_RESULT(yes);AC_DEFINE(TRADITIONAL_CPP),
+AC_MSG_RESULT(no))
+AC_LANG_RESTORE])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_WCOREFLAG,
+[AC_MSG_CHECKING([w_coredump])
+AC_TRY_RUN([#include <sys/types.h>
+#include <sys/wait.h>
+main()
+{
+#ifdef WCOREFLAG
+ exit(1);
+#else
+ int i = 0;
+ ((union wait *)&i)->w_coredump = 1;
+ exit(i != 0200);
+#endif
+}],
+AC_MSG_RESULT(yes);AC_DEFINE(WCOREFLAG,0200),
+AC_MSG_RESULT(no),
+AC_MSG_RESULT(no))])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_BROKEN_SPOOLER_FLAGS,
+[AC_MSG_CHECKING([default value for grops -b option])
+test -n "${BROKEN_SPOOLER_FLAGS}" || BROKEN_SPOOLER_FLAGS=7
+AC_MSG_RESULT($BROKEN_SPOOLER_FLAGS)
+AC_SUBST(BROKEN_SPOOLER_FLAGS)])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_PAGE,
+[AC_MSG_CHECKING([default paper size])
+if test -z "$PAGE"; then
+ descfile=
+ if test -r $prefix/share/groff/font/devps/DESC; then
+ descfile=$prefix/share/groff/font/devps/DESC
+ elif test -r $prefix/lib/groff/font/devps/DESC; then
+ descfile=$prefix/lib/groff/font/devps/DESC
+ fi
+ if test -n "$descfile" \
+ && grep "^paperlength 841890" $descfile >/dev/null 2>&1; then
+ PAGE=A4
+ else
+ PAGE=letter
+ fi
+fi
+if test -z "$PAGE"; then
+ dom=`awk '([$]1 == "dom" || [$]1 == "search") { print [$]2; exit}' \
+ /etc/resolv.conf 2>/dev/null`
+ if test -z "$dom"; then
+ dom=`(domainname) 2>/dev/null | tr -d '+'`
+ if test -z "$dom"; then
+ dom=`(hostname) 2>/dev/null | grep '\.'`
+ fi
+ fi
+changequote(,)dnl
+ # If the top-level domain is two letters and it's not `us' or `ca'
+ # then they probably use A4 paper.
+ case "$dom" in
+ *.[Uu][Ss]|*.[Cc][Aa]) ;;
+ *.[A-Za-z][A-Za-z]) PAGE=A4 ;;
+ esac
+changequote([,])dnl
+fi
+test -n "$PAGE" || PAGE=letter
+AC_MSG_RESULT($PAGE)
+AC_SUBST(PAGE)])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_CXX_CHECK,
+[AC_REQUIRE([AC_C_CROSS])
+AC_REQUIRE([AC_PROG_CXX])
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+if test "$cross_compiling" = no; then
+ AC_MSG_CHECKING([that C++ compiler can compile simple program])
+fi
+AC_TRY_RUN([int main() { return 0; }],
+AC_MSG_RESULT(yes),
+AC_MSG_RESULT(no);AC_MSG_ERROR([a working C++ compiler is required]),
+:)
+if test "$cross_compiling" = no; then
+ AC_MSG_CHECKING([that C++ static constructors and destructors are called])
+fi
+AC_TRY_RUN([
+extern "C" {
+ void _exit(int);
+}
+int i;
+struct A {
+ char dummy;
+ A() { i = 1; }
+ ~A() { if (i == 1) _exit(0); }
+};
+A a;
+int main() { return 1; }
+],
+AC_MSG_RESULT(yes),
+AC_MSG_RESULT(no);AC_MSG_ERROR([a working C++ compiler is required]),
+:)
+AC_MSG_CHECKING([that header files support C++])
+AC_TRY_LINK([#include <stdio.h>],
+[fopen(0, 0);],
+AC_MSG_RESULT(yes),
+AC_MSG_RESULT(no);AC_MSG_ERROR([header files do not support C++ (if you are using a version of gcc/g++ earlier than 2.5, you should install libg++)]))
+AC_LANG_RESTORE
+])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_TMAC,
+[AC_MSG_CHECKING([for prefix of system macro packages])
+sys_tmac_prefix=
+sys_tmac_file_prefix=
+for d in /usr/share/lib/tmac /usr/lib/tmac; do
+ for t in "" tmac.; do
+ for m in an s m; do
+ f=$d/$t$m
+ if test -z "$sys_tmac_prefix" \
+ && test -f $f \
+ && grep '^\.if' $f >/dev/null 2>&1; then
+ sys_tmac_prefix=$d/$t
+ sys_tmac_file_prefix=$t
+ fi
+ done
+ done
+done
+AC_MSG_RESULT($sys_tmac_prefix)
+AC_SUBST(sys_tmac_prefix)
+tmac_wrap=
+AC_MSG_CHECKING([which system macro packages should be made available])
+if test "x$sys_tmac_file_prefix" = "xtmac."; then
+ for f in $sys_tmac_prefix*; do
+ suff=`echo $f | sed -e "s;$sys_tmac_prefix;;"`
+ case "$suff" in
+ e) ;;
+ *)
+ grep "Copyright.*Free Software Foundation" $f >/dev/null \
+ || tmac_wrap="$tmac_wrap $suff" ;;
+ esac
+ done
+elif test -n "$sys_tmac_prefix"; then
+ files=`echo $sys_tmac_prefix*`
+ grep "\\.so" $files >conftest.sol
+ for f in $files; do
+ case "$f" in
+ ${sys_tmac_prefix}e) ;;
+ *.me) ;;
+ */ms.*) ;;
+ *)
+ b=`basename $f`
+ if grep "\\.so.*/$b\$" conftest.sol >/dev/null \
+ || grep -l "Copyright.*Free Software Foundation" $f >/dev/null; then
+ :
+ else
+ suff=`echo $f | sed -e "s;$sys_tmac_prefix;;"`
+ case "$suff" in
+ tmac.*) ;;
+ *) tmac_wrap="$tmac_wrap $suff" ;;
+ esac
+ fi
+ esac
+ done
+ rm -f conftest.sol
+fi
+AC_MSG_RESULT([$tmac_wrap])
+AC_SUBST(tmac_wrap)
+])dnl
+dnl
+dnl
+AC_DEFUN(GROFF_G,
+[AC_MSG_CHECKING([for existing troff installation])
+if test "x`(echo .tm '|n(.g' | tr '|' '\\\\' | troff -z -i 2>&1) 2>/dev/null`" = x0; then
+ AC_MSG_RESULT(yes)
+ g=g
+else
+ AC_MSG_RESULT(no)
+ g=
+fi
+AC_SUBST(g)
+])dnl
+dnl
+dnl
+dnl We need the path to install-sh to be absolute.
+dnl
+AC_DEFUN(GROFF_INSTALL_SH,
+[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+ac_dir=`cd $ac_aux_dir; pwd`
+ac_install_sh="$ac_dir/install-sh -c"
+])dnl
+dnl
+dnl
+dnl At least one UNIX system, Apple Macintosh Rhapsody 5.5,
+dnl does not have -lm.
+dnl
+AC_DEFUN(GROFF_LIBM,
+[AC_CHECK_LIB(m,sin,LIBM=-lm)
+AC_SUBST(LIBM)
+])dnl
+dnl
+dnl
+dnl We need top_srcdir to be absolute.
+dnl
+AC_DEFUN(GROFF_SRCDIR,
+[ac_srcdir_defaulted=no
+srcdir=`cd $srcdir; pwd`
+])dnl
+dnl
+dnl
+dnl This simplifies Makefile rules.
+dnl
+AC_DEFUN(GROFF_BUILDDIR,
+[top_builddir=`pwd`
+AC_SUBST(top_builddir)
+])
diff --git a/configure b/configure
new file mode 100755
index 00000000..ee511476
--- /dev/null
+++ b/configure
@@ -0,0 +1,2965 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+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'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+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
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # 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 ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$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" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) 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)
+ # 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 << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --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
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$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)
+ 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 ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ 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 "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# 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
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=src/roff/groff/groff.cc
+
+# 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_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ 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 "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# 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 "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+ac_srcdir_defaulted=no
+srcdir=`cd $srcdir; pwd`
+
+top_builddir=`pwd`
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:534: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+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 $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:564: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+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 $# -gt 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
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:615: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:647: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 658 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:663: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:689: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:694: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:703: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:722: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&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
+
+for ac_prog in $CCC c++ g++ gcc CC cxx cc++ 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 $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:758: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CXX="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CXX="$ac_cv_prog_CXX"
+if test -n "$CXX"; then
+ echo "$ac_t""$CXX" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$CXX" && break
+done
+test -n "$CXX" || CXX="gcc"
+
+
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:790: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 801 "configure"
+#include "confdefs.h"
+
+int main(){return(0);}
+EOF
+if { (eval echo configure:806: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cxx_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cxx_cross=no
+ else
+ ac_cv_prog_cxx_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cxx_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6
+if test $ac_cv_prog_cxx_works = no; then
+ { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:832: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6
+echo "configure:837: checking whether we are using GNU C++" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.C <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:846: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gxx=yes
+else
+ ac_cv_prog_gxx=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gxx" 1>&6
+
+if test $ac_cv_prog_gxx = yes; then
+ GXX=yes
+else
+ GXX=
+fi
+
+ac_test_CXXFLAGS="${CXXFLAGS+set}"
+ac_save_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS=
+echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6
+echo "configure:865: checking whether ${CXX-g++} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.cc
+if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then
+ ac_cv_prog_cxx_g=yes
+else
+ ac_cv_prog_cxx_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cxx_g" 1>&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
+
+
+
+
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+if test "$cross_compiling" = no; then
+ echo $ac_n "checking that C++ compiler can compile simple program""... $ac_c" 1>&6
+echo "configure:909: checking that C++ compiler can compile simple program" >&5
+fi
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 915 "configure"
+#include "confdefs.h"
+#ifdef __cplusplus
+extern "C" void exit(int);
+#endif
+int main() { return 0; }
+EOF
+if { (eval echo configure:922: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ echo "$ac_t""yes" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ echo "$ac_t""no" 1>&6;{ echo "configure: error: a working C++ compiler is required" 1>&2; exit 1; }
+fi
+rm -fr conftest*
+fi
+
+if test "$cross_compiling" = no; then
+ echo $ac_n "checking that C++ static constructors and destructors are called""... $ac_c" 1>&6
+echo "configure:936: checking that C++ static constructors and destructors are called" >&5
+fi
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 942 "configure"
+#include "confdefs.h"
+#ifdef __cplusplus
+extern "C" void exit(int);
+#endif
+
+extern "C" {
+ void _exit(int);
+}
+int i;
+struct A {
+ char dummy;
+ A() { i = 1; }
+ ~A() { if (i == 1) _exit(0); }
+};
+A a;
+int main() { return 1; }
+
+EOF
+if { (eval echo configure:961: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ echo "$ac_t""yes" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ echo "$ac_t""no" 1>&6;{ echo "configure: error: a working C++ compiler is required" 1>&2; exit 1; }
+fi
+rm -fr conftest*
+fi
+
+echo $ac_n "checking that header files support C++""... $ac_c" 1>&6
+echo "configure:974: checking that header files support C++" >&5
+cat > conftest.$ac_ext <<EOF
+#line 976 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+int main() {
+fopen(0, 0);
+; return 0; }
+EOF
+if { (eval echo configure:983: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6;{ echo "configure: error: header files do not support C++ (if you are using a version of gcc/g++ earlier than 2.5, you should install libg++)" 1>&2; exit 1; }
+fi
+rm -f conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+
+if test -z "$PSPRINT"; then
+ for ac_prog in lpr
+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 $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1007: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LPR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$LPR"; then
+ ac_cv_prog_LPR="$LPR" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_LPR="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+LPR="$ac_cv_prog_LPR"
+if test -n "$LPR"; then
+ echo "$ac_t""$LPR" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$LPR" && break
+done
+
+ for ac_prog in lp
+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 $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1041: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$LP"; then
+ ac_cv_prog_LP="$LP" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_LP="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+LP="$ac_cv_prog_LP"
+if test -n "$LP"; then
+ echo "$ac_t""$LP" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$LP" && break
+done
+
+ if test -n "$LPR" && test -n "$LP"; then
+ # HP-UX provides an lpr command that emulates lpr using lp,
+ # but it doesn't have lpq; in this case we want to use lp
+ # rather than lpr.
+ for ac_prog in lpq
+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 $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1079: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LPQ'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$LPQ"; then
+ ac_cv_prog_LPQ="$LPQ" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_LPQ="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+LPQ="$ac_cv_prog_LPQ"
+if test -n "$LPQ"; then
+ echo "$ac_t""$LPQ" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$LPQ" && break
+done
+
+ test -n "$LPQ" || LPR=
+ fi
+ if test -n "$LPR"; then
+ PSPRINT="$LPR"
+ elif test -n "$LP"; then
+ PSPRINT="$LP"
+ fi
+fi
+
+echo $ac_n "checking for command to use for printing PostScript files""... $ac_c" 1>&6
+echo "configure:1118: checking for command to use for printing PostScript files" >&5
+echo "$ac_t""$PSPRINT" 1>&6
+# Figure out DVIPRINT from PSPRINT.
+echo $ac_n "checking for command to use for printing dvi files""... $ac_c" 1>&6
+echo "configure:1122: checking for command to use for printing dvi files" >&5
+if test -n "$PSPRINT" && test -z "$DVIPRINT"; then
+ if test "X$PSPRINT" = "Xlpr"; then
+ DVIPRINT="lpr -d"
+ else
+ DVIPRINT="$PSPRINT"
+ fi
+fi
+
+echo "$ac_t""$DVIPRINT" 1>&6
+# Extract the first word of "perl", so it can be a program name with args.
+set dummy perl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1135: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_PERLPATH'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$PERLPATH" in
+ /*)
+ ac_cv_path_PERLPATH="$PERLPATH" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_PERLPATH="$PERLPATH" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_PERLPATH="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_PERLPATH" && ac_cv_path_PERLPATH="/usr/bin/perl"
+ ;;
+esac
+fi
+PERLPATH="$ac_cv_path_PERLPATH"
+if test -n "$PERLPATH"; then
+ echo "$ac_t""$PERLPATH" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+for ac_prog in byacc 'bison -y'
+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 $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1173: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$YACC"; then
+ ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_YACC="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+YACC="$ac_cv_prog_YACC"
+if test -n "$YACC"; then
+ echo "$ac_t""$YACC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1206: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; 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
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+ac_dir=`cd $ac_aux_dir; pwd`
+ac_install_sh="$ac_dir/install-sh -c"
+
+# 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
+# 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"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:1267: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/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
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+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 "$ac_t""$INSTALL" 1>&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_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
+echo "configure:1320: checking whether ln -s works" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ rm -f conftestdata
+if ln -s X conftestdata 2>/dev/null
+then
+ rm -f conftestdata
+ ac_cv_prog_LN_S="ln -s"
+else
+ ac_cv_prog_LN_S=ln
+fi
+fi
+LN_S="$ac_cv_prog_LN_S"
+if test "$ac_cv_prog_LN_S" = "ln -s"; then
+ echo "$ac_t""yes" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for csh hash hack""... $ac_c" 1>&6
+echo "configure:1341: checking for csh hash hack" >&5
+cat <<EOF >conftest.sh
+#!/bin/sh
+true || exit 0
+export PATH || exit 0
+exit 1
+EOF
+chmod +x conftest.sh
+if echo ./conftest.sh | (csh >/dev/null 2>&1) >/dev/null 2>&1; then
+ echo "$ac_t""yes" 1>&6; SH_SCRIPT_SED_CMD='1s/.*/:/'
+else
+ echo "$ac_t""no" 1>&6; SH_SCRIPT_SED_CMD=''
+fi
+rm -f conftest.sh
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:1357: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 1372 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1378: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 1389 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1395: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 1406 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1412: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+for ac_hdr in unistd.h dirent.h limits.h sys/dir.h stdlib.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1440: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1445 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1450: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking for ISC 3.x or 4.x""... $ac_c" 1>&6
+echo "configure:1477: checking for ISC 3.x or 4.x" >&5
+if grep '[34]\.' /usr/options/cb.name >/dev/null 2>&1
+then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define _SYSV3 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+echo $ac_n "checking whether -D_POSIX_SOURCE is necessary""... $ac_c" 1>&6
+echo "configure:1489: checking whether -D_POSIX_SOURCE is necessary" >&5
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+cat > conftest.$ac_ext <<EOF
+#line 1499 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+extern "C" { void fileno(int); }
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1507: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking declaration of getopt in stdlib.h""... $ac_c" 1>&6
+echo "configure:1536: checking declaration of getopt in stdlib.h" >&5
+cat > conftest.$ac_ext <<EOF
+#line 1538 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+extern "C" { void getopt(int); }
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1546: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;cat >> confdefs.h <<\EOF
+#define STDLIB_H_DECLARES_GETOPT 1
+EOF
+
+fi
+rm -f conftest*
+echo $ac_n "checking declaration of getopt in unistd.h""... $ac_c" 1>&6
+echo "configure:1560: checking declaration of getopt in unistd.h" >&5
+cat > conftest.$ac_ext <<EOF
+#line 1562 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <unistd.h>
+extern "C" { void getopt(int); }
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1571: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;cat >> confdefs.h <<\EOF
+#define UNISTD_H_DECLARES_GETOPT 1
+EOF
+
+fi
+rm -f conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking declaration of putenv""... $ac_c" 1>&6
+echo "configure:1600: checking declaration of putenv" >&5
+cat > conftest.$ac_ext <<EOF
+#line 1602 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+extern "C" { void putenv(int); }
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1610: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;cat >> confdefs.h <<\EOF
+#define STDLIB_H_DECLARES_PUTENV 1
+EOF
+
+fi
+rm -f conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking declaration of popen""... $ac_c" 1>&6
+echo "configure:1639: checking declaration of popen" >&5
+cat > conftest.$ac_ext <<EOF
+#line 1641 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+extern "C" { void popen(int); }
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1649: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;cat >> confdefs.h <<\EOF
+#define STDIO_H_DECLARES_POPEN 1
+EOF
+
+fi
+rm -f conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking declaration of pclose""... $ac_c" 1>&6
+echo "configure:1678: checking declaration of pclose" >&5
+cat > conftest.$ac_ext <<EOF
+#line 1680 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+extern "C" { void pclose(int); }
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1688: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;cat >> confdefs.h <<\EOF
+#define STDIO_H_DECLARES_PCLOSE 1
+EOF
+
+fi
+rm -f conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking for sys_nerr in <errno.h> or <stdio.h>""... $ac_c" 1>&6
+echo "configure:1717: checking for sys_nerr in <errno.h> or <stdio.h>" >&5
+cat > conftest.$ac_ext <<EOF
+#line 1719 "configure"
+#include "confdefs.h"
+#include <errno.h>
+#include <stdio.h>
+int main() {
+int k; k = sys_nerr;
+; return 0; }
+EOF
+if { (eval echo configure:1727: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;cat >> confdefs.h <<\EOF
+#define HAVE_SYS_NERR 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking for sys_errlist in <errno.h> or <stdio.h>""... $ac_c" 1>&6
+echo "configure:1756: checking for sys_errlist in <errno.h> or <stdio.h>" >&5
+cat > conftest.$ac_ext <<EOF
+#line 1758 "configure"
+#include "confdefs.h"
+#include <errno.h>
+#include <stdio.h>
+int main() {
+int k; k = (int)sys_errlist[0];
+; return 0; }
+EOF
+if { (eval echo configure:1766: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;cat >> confdefs.h <<\EOF
+#define HAVE_SYS_ERRLIST 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking declaration of hypot""... $ac_c" 1>&6
+echo "configure:1795: checking declaration of hypot" >&5
+cat > conftest.$ac_ext <<EOF
+#line 1797 "configure"
+#include "confdefs.h"
+#include <math.h>
+extern "C" { double hypot(double,double); }
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1805: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;cat >> confdefs.h <<\EOF
+#define MATH_H_DECLARES_HYPOT 1
+EOF
+
+fi
+rm -f conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking C++ <osfcn.h>""... $ac_c" 1>&6
+echo "configure:1834: checking C++ <osfcn.h>" >&5
+cat > conftest.$ac_ext <<EOF
+#line 1836 "configure"
+#include "confdefs.h"
+#include <osfcn.h>
+int main() {
+read(0, 0, 0); open(0, 0);
+; return 0; }
+EOF
+if { (eval echo configure:1843: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;cat >> confdefs.h <<\EOF
+#define HAVE_CC_OSFCN_H 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking C++ <limits.h>""... $ac_c" 1>&6
+echo "configure:1872: checking C++ <limits.h>" >&5
+cat > conftest.$ac_ext <<EOF
+#line 1874 "configure"
+#include "confdefs.h"
+#include <limits.h>
+int main() {
+int x = INT_MIN; int y = INT_MAX; int z = UCHAR_MAX;
+; return 0; }
+EOF
+if { (eval echo configure:1881: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;cat >> confdefs.h <<\EOF
+#define HAVE_CC_LIMITS_H 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking for declaration of time_t""... $ac_c" 1>&6
+echo "configure:1910: checking for declaration of time_t" >&5
+cat > conftest.$ac_ext <<EOF
+#line 1912 "configure"
+#include "confdefs.h"
+#include <time.h>
+int main() {
+time_t t = time(0); struct tm *p = localtime(&t);
+; return 0; }
+EOF
+if { (eval echo configure:1919: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6;cat >> confdefs.h <<\EOF
+#define LONG_FOR_TIME_T 1
+EOF
+
+fi
+rm -f conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
+echo "configure:1940: checking return type of signal handlers" >&5
+if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1945 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int main() {
+int i;
+; return 0; }
+EOF
+if { (eval echo configure:1962: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_type_signal=void
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_type_signal=int
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_type_signal" 1>&6
+cat >> confdefs.h <<EOF
+#define RETSIGTYPE $ac_cv_type_signal
+EOF
+
+
+echo $ac_n "checking struct exception""... $ac_c" 1>&6
+echo "configure:1981: checking struct exception" >&5
+cat > conftest.$ac_ext <<EOF
+#line 1983 "configure"
+#include "confdefs.h"
+#include <math.h>
+int main() {
+struct exception e;
+; return 0; }
+EOF
+if { (eval echo configure:1990: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;cat >> confdefs.h <<\EOF
+#define HAVE_STRUCT_EXCEPTION 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+echo $ac_n "checking for sin in -lm""... $ac_c" 1>&6
+echo "configure:2004: checking for sin in -lm" >&5
+ac_lib_var=`echo m'_'sin | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lm $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2012 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char sin();
+
+int main() {
+sin()
+; return 0; }
+EOF
+if { (eval echo configure:2023: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBM=-lm
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+
+for ac_hdr in unistd.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2049: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2054 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2059: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in getpagesize
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2088: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2093 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* 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();
+
+int main() {
+
+/* 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
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2116: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking for working mmap""... $ac_c" 1>&6
+echo "configure:2141: checking for working mmap" >&5
+if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_mmap_fixed_mapped=no
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2149 "configure"
+#include "confdefs.h"
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+ Here is a matrix of mmap possibilities:
+ mmap private not fixed
+ mmap private fixed at somewhere currently unmapped
+ mmap private fixed at somewhere already mapped
+ mmap shared not fixed
+ mmap shared fixed at somewhere currently unmapped
+ mmap shared fixed at somewhere already mapped
+ For private mappings, we should verify that changes cannot be read()
+ back from the file, nor mmap's back from the file at a different
+ address. (There have been systems where private was not correctly
+ implemented like the infamous i386 svr4.0, and systems where the
+ VM page cache was not coherent with the filesystem buffer cache
+ like early versions of FreeBSD and possibly contemporary NetBSD.)
+ For shared mappings, we should conversely verify that changes get
+ propogated back to all the places they're supposed to be.
+
+ Grep wants private fixed already mapped.
+ The main things grep needs to know about mmap are:
+ * does it exist and is it safe to write into the mmap'd area
+ * how to use it (BSD variants) */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+/* This mess was copied from the GNU getpagesize.h. */
+#ifndef HAVE_GETPAGESIZE
+# ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# endif
+
+/* Assume that all systems that can run configure have sys/param.h. */
+# ifndef HAVE_SYS_PARAM_H
+# define HAVE_SYS_PARAM_H 1
+# endif
+
+# ifdef _SC_PAGESIZE
+# define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+# ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+# ifdef EXEC_PAGESIZE
+# define getpagesize() EXEC_PAGESIZE
+# else /* no EXEC_PAGESIZE */
+# ifdef NBPG
+# define getpagesize() NBPG * CLSIZE
+# ifndef CLSIZE
+# define CLSIZE 1
+# endif /* no CLSIZE */
+# else /* no NBPG */
+# ifdef NBPC
+# define getpagesize() NBPC
+# else /* no NBPC */
+# ifdef PAGESIZE
+# define getpagesize() PAGESIZE
+# endif /* PAGESIZE */
+# endif /* no NBPC */
+# endif /* no NBPG */
+# endif /* no EXEC_PAGESIZE */
+# else /* no HAVE_SYS_PARAM_H */
+# define getpagesize() 8192 /* punt totally */
+# endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+#ifdef __cplusplus
+extern "C" { void *malloc(unsigned); }
+#else
+char *malloc();
+#endif
+
+int
+main()
+{
+ char *data, *data2, *data3;
+ int i, pagesize;
+ int fd;
+
+ pagesize = getpagesize();
+
+ /*
+ * First, make a file with some known garbage in it.
+ */
+ data = malloc(pagesize);
+ if (!data)
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ *(data + i) = rand();
+ umask(0);
+ fd = creat("conftestmmap", 0600);
+ if (fd < 0)
+ exit(1);
+ if (write(fd, data, pagesize) != pagesize)
+ exit(1);
+ close(fd);
+
+ /*
+ * Next, try to mmap the file at a fixed address which
+ * already has something else allocated at it. If we can,
+ * also make sure that we see the same garbage.
+ */
+ fd = open("conftestmmap", O_RDWR);
+ if (fd < 0)
+ exit(1);
+ data2 = malloc(2 * pagesize);
+ if (!data2)
+ exit(1);
+ data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1);
+ if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED, fd, 0L))
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data2 + i))
+ exit(1);
+
+ /*
+ * Finally, make sure that changes to the mapped area
+ * do not percolate back to the file as seen by read().
+ * (This is a bug on some variants of i386 svr4.0.)
+ */
+ for (i = 0; i < pagesize; ++i)
+ *(data2 + i) = *(data2 + i) + 1;
+ data3 = malloc(pagesize);
+ if (!data3)
+ exit(1);
+ if (read(fd, data3, pagesize) != pagesize)
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data3 + i))
+ exit(1);
+ close(fd);
+ unlink("conftestmmap");
+ exit(0);
+}
+
+EOF
+if { (eval echo configure:2289: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_mmap_fixed_mapped=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_mmap_fixed_mapped=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_MMAP 1
+EOF
+
+fi
+
+saved_libs="$LIBS"
+LIBS="$LIBS -lc $LIBM"
+for ac_func in fmod strtol getcwd strerror putenv
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2316: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2321 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* 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();
+
+int main() {
+
+/* 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
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2344: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+LIBOBJS="$LIBOBJS ${ac_func}.${ac_objext}"
+fi
+done
+
+
+LIBS="$saved_libs"
+for ac_func in rename mkstemp strcasecmp
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2374: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2379 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* 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();
+
+int main() {
+
+/* 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
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2402: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking for sys_siglist declaration in signal.h or unistd.h""... $ac_c" 1>&6
+echo "configure:2427: checking for sys_siglist declaration in signal.h or unistd.h" >&5
+if eval "test \"`echo '$''{'ac_cv_decl_sys_siglist'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2432 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <signal.h>
+/* NetBSD declares sys_siglist in unistd.h. */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+int main() {
+char *msg = *(sys_siglist + 1);
+; return 0; }
+EOF
+if { (eval echo configure:2444: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_decl_sys_siglist=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_decl_sys_siglist=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_decl_sys_siglist" 1>&6
+if test $ac_cv_decl_sys_siglist = yes; then
+ cat >> confdefs.h <<\EOF
+#define SYS_SIGLIST_DECLARED 1
+EOF
+
+fi
+
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking whether ANSI array delete syntax supported""... $ac_c" 1>&6
+echo "configure:2473: checking whether ANSI array delete syntax supported" >&5
+cat > conftest.$ac_ext <<EOF
+#line 2475 "configure"
+#include "confdefs.h"
+
+int main() {
+char *p = new char[5]; delete [] p;
+; return 0; }
+EOF
+if { (eval echo configure:2482: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6;cat >> confdefs.h <<\EOF
+#define ARRAY_DELETE_NEEDS_SIZE 1
+EOF
+
+fi
+rm -f conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking traditional preprocessor""... $ac_c" 1>&6
+echo "configure:2511: checking traditional preprocessor" >&5
+cat > conftest.$ac_ext <<EOF
+#line 2513 "configure"
+#include "confdefs.h"
+#define name2(a,b) a/**/b
+int main() {
+int name2(foo,bar);
+; return 0; }
+EOF
+if { (eval echo configure:2520: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6;cat >> confdefs.h <<\EOF
+#define TRADITIONAL_CPP 1
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking w_coredump""... $ac_c" 1>&6
+echo "configure:2541: checking w_coredump" >&5
+if test "$cross_compiling" = yes; then
+ echo "$ac_t""no" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2546 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+main()
+{
+#ifdef WCOREFLAG
+ exit(1);
+#else
+ int i = 0;
+ ((union wait *)&i)->w_coredump = 1;
+ exit(i != 0200);
+#endif
+}
+EOF
+if { (eval echo configure:2561: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ echo "$ac_t""yes" 1>&6;cat >> confdefs.h <<\EOF
+#define WCOREFLAG 0200
+EOF
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -fr conftest*
+fi
+
+echo $ac_n "checking default value for grops -b option""... $ac_c" 1>&6
+echo "configure:2577: checking default value for grops -b option" >&5
+test -n "${BROKEN_SPOOLER_FLAGS}" || BROKEN_SPOOLER_FLAGS=7
+echo "$ac_t""$BROKEN_SPOOLER_FLAGS" 1>&6
+
+echo $ac_n "checking default paper size""... $ac_c" 1>&6
+echo "configure:2582: checking default paper size" >&5
+if test -z "$PAGE"; then
+ descfile=
+ if test -r $prefix/share/groff/font/devps/DESC; then
+ descfile=$prefix/share/groff/font/devps/DESC
+ elif test -r $prefix/lib/groff/font/devps/DESC; then
+ descfile=$prefix/lib/groff/font/devps/DESC
+ fi
+ if test -n "$descfile" \
+ && grep "^paperlength 841890" $descfile >/dev/null 2>&1; then
+ PAGE=A4
+ else
+ PAGE=letter
+ fi
+fi
+if test -z "$PAGE"; then
+ dom=`awk '($1 == "dom" || $1 == "search") { print $2; exit}' \
+ /etc/resolv.conf 2>/dev/null`
+ if test -z "$dom"; then
+ dom=`(domainname) 2>/dev/null | tr -d '+'`
+ if test -z "$dom"; then
+ dom=`(hostname) 2>/dev/null | grep '\.'`
+ fi
+ fi
+ # If the top-level domain is two letters and it's not `us' or `ca'
+ # then they probably use A4 paper.
+ case "$dom" in
+ *.[Uu][Ss]|*.[Cc][Aa]) ;;
+ *.[A-Za-z][A-Za-z]) PAGE=A4 ;;
+ esac
+fi
+test -n "$PAGE" || PAGE=letter
+echo "$ac_t""$PAGE" 1>&6
+
+echo $ac_n "checking for existing troff installation""... $ac_c" 1>&6
+echo "configure:2617: checking for existing troff installation" >&5
+if test "x`(echo .tm '|n(.g' | tr '|' '\\\\' | troff -z -i 2>&1) 2>/dev/null`" = x0; then
+ echo "$ac_t""yes" 1>&6
+ g=g
+else
+ echo "$ac_t""no" 1>&6
+ g=
+fi
+
+
+echo $ac_n "checking for prefix of system macro packages""... $ac_c" 1>&6
+echo "configure:2628: checking for prefix of system macro packages" >&5
+sys_tmac_prefix=
+sys_tmac_file_prefix=
+for d in /usr/share/lib/tmac /usr/lib/tmac; do
+ for t in "" tmac.; do
+ for m in an s m; do
+ f=$d/$t$m
+ if test -z "$sys_tmac_prefix" \
+ && test -f $f \
+ && grep '^\.if' $f >/dev/null 2>&1; then
+ sys_tmac_prefix=$d/$t
+ sys_tmac_file_prefix=$t
+ fi
+ done
+ done
+done
+echo "$ac_t""$sys_tmac_prefix" 1>&6
+
+tmac_wrap=
+echo $ac_n "checking which system macro packages should be made available""... $ac_c" 1>&6
+echo "configure:2648: checking which system macro packages should be made available" >&5
+if test "x$sys_tmac_file_prefix" = "xtmac."; then
+ for f in $sys_tmac_prefix*; do
+ suff=`echo $f | sed -e "s;$sys_tmac_prefix;;"`
+ case "$suff" in
+ e) ;;
+ *)
+ grep "Copyright.*Free Software Foundation" $f >/dev/null \
+ || tmac_wrap="$tmac_wrap $suff" ;;
+ esac
+ done
+elif test -n "$sys_tmac_prefix"; then
+ files=`echo $sys_tmac_prefix*`
+ grep "\\.so" $files >conftest.sol
+ for f in $files; do
+ case "$f" in
+ ${sys_tmac_prefix}e) ;;
+ *.me) ;;
+ */ms.*) ;;
+ *)
+ b=`basename $f`
+ if grep "\\.so.*/$b\$" conftest.sol >/dev/null \
+ || grep -l "Copyright.*Free Software Foundation" $f >/dev/null; then
+ :
+ else
+ suff=`echo $f | sed -e "s;$sys_tmac_prefix;;"`
+ case "$suff" in
+ tmac.*) ;;
+ *) tmac_wrap="$tmac_wrap $suff" ;;
+ esac
+ fi
+ esac
+ done
+ rm -f conftest.sol
+fi
+echo "$ac_t""$tmac_wrap" 1>&6
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# 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. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# 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 \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@top_builddir@%$top_builddir%g
+s%@CC@%$CC%g
+s%@CXX@%$CXX%g
+s%@LPR@%$LPR%g
+s%@LP@%$LP%g
+s%@LPQ@%$LPQ%g
+s%@PSPRINT@%$PSPRINT%g
+s%@DVIPRINT@%$DVIPRINT%g
+s%@PERLPATH@%$PERLPATH%g
+s%@YACC@%$YACC%g
+s%@RANLIB@%$RANLIB%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@LN_S@%$LN_S%g
+s%@SH_SCRIPT_SED_CMD@%$SH_SCRIPT_SED_CMD%g
+s%@CPP@%$CPP%g
+s%@LIBM@%$LIBM%g
+s%@LIBOBJS@%$LIBOBJS%g
+s%@BROKEN_SPOOLER_FLAGS@%$BROKEN_SPOOLER_FLAGS%g
+s%@PAGE@%$PAGE%g
+s%@g@%$g%g
+s%@sys_tmac_prefix@%$sys_tmac_prefix%g
+s%@tmac_wrap@%$tmac_wrap%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# 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_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # 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" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/configure.in b/configure.in
new file mode 100755
index 00000000..bf9a3f0f
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,55 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(src/roff/groff/groff.cc)
+dnl checks for programs
+GROFF_SRCDIR
+GROFF_BUILDDIR
+AC_PROG_CC
+AC_PROG_CXX
+GROFF_CXX_CHECK
+GROFF_PRINT
+AC_PATH_PROG(PERLPATH, perl, /usr/bin/perl)
+GROFF_PROG_YACC
+AC_PROG_RANLIB
+GROFF_INSTALL_SH
+AC_PROG_INSTALL
+AC_PROG_LN_S
+GROFF_CSH_HACK(SH_SCRIPT_SED_CMD='1s/.*/:/', SH_SCRIPT_SED_CMD='')
+AC_SUBST(SH_SCRIPT_SED_CMD)
+dnl checks for headers
+AC_CHECK_HEADERS(unistd.h dirent.h limits.h sys/dir.h stdlib.h)
+GROFF_ISC_SYSV3
+GROFF_POSIX
+GROFF_GETOPT
+GROFF_PUTENV
+GROFF_POPEN
+GROFF_PCLOSE
+GROFF_SYS_NERR
+GROFF_SYS_ERRLIST
+GROFF_HYPOT
+GROFF_OSFCN_H
+GROFF_LIMITS_H
+dnl checks for typedefs
+GROFF_TIME_T
+AC_TYPE_SIGNAL
+GROFF_STRUCT_EXCEPTION
+dnl checks for libraries
+GROFF_LIBM
+dnl checks for functions
+AC_FUNC_MMAP
+saved_libs="$LIBS"
+LIBS="$LIBS -lc $LIBM"
+AC_REPLACE_FUNCS(fmod strtol getcwd strerror putenv)
+LIBS="$saved_libs"
+AC_CHECK_FUNCS(rename mkstemp strcasecmp)
+AC_DECL_SYS_SIGLIST
+dnl checks for compiler characteristics
+GROFF_ARRAY_DELETE
+GROFF_TRADITIONAL_CPP
+dnl checks for operating system services
+GROFF_WCOREFLAG
+dnl other random stuff
+GROFF_BROKEN_SPOOLER_FLAGS
+GROFF_PAGE
+GROFF_G
+GROFF_TMAC
+AC_OUTPUT(Makefile)
diff --git a/contrib/mm/ChangeLog b/contrib/mm/ChangeLog
new file mode 100644
index 00000000..082a6b55
--- /dev/null
+++ b/contrib/mm/ChangeLog
@@ -0,0 +1,484 @@
+Sun Jan 30 22:52:20 19100 Jörgen Hägg (jh at axis.com)
+
+ * version 1.34
+ *
+
+Fri Sep 3 07:33:14 1999 Jörgen Hägg (jh at axis.com)
+
+ * version 1.33
+ * At last! I finally tracked down the PGFORM bug!
+ It didn't setup the @pl, @ll and @po as it should, now it does.
+ * mgm_ref/mgm_roff renamed to mmroff [-x]
+ * fixed y2k-bug in \*[DT]
+ * \n[cov*year] removed, hope noone used that.
+ * ISODATE added with Iso as command line flag
+ (iso-date suggested by Paul Eggert)
+ * Added ISODATE to tmac.mse and removed local settings
+ of new-date.
+ * INITI syntax changed and enhanced. Index processing is now
+ done with mmroff.
+ * A few examples has been added, new subdirectory 'examples'.
+ * Fixed bug with SETR, header references are now only saved
+ when Ref > 0
+ * Problem with register H1h fixed
+ * Added test for missing abstract in 4.MT
+ * Updated Makefile.sub, using tmac_m_prefix.
+
+Mon Mar 15 22:22:42 1999 Jörgen Hägg (jh at axis.com)
+
+ * OK, let's release this as a beta, 1.33 will be better. :-)
+ * version 1.32
+ * fixed .el-error
+ * Added number variable Hss
+ * Changed Hps1 and Hps2 to units
+ * added hd*h1-text to be used in user defined macro TP.
+ * -U needed for SETR (I really need 'mv', 'echo', 'rm'
+ and 'test' builtin!)
+ * Rewritten the reference system, SETR now prints to stderr
+ if the number register Qrf > 0. Store in the filename
+ that is the argument to .INITR
+ The old behaviour is returned if number register Initr > 0.
+ * Fixed bug with List of XXXX, long lines messed up the result.
+ * added number register H1dot.
+ * added string variable H1txt
+ * added string variable Tcst
+ * added number register Dsp.
+ * added alias APPX for user-defined appendix title.
+ * added string variable Apptxt
+ * added H1h for use in TP in headers
+ * added macro EPIC
+ * added macro PIC (safe replacement for PSPIC)
+ * fixed Hps-bug, should be 1, not 1v.
+ * fixed bug with APPSK, variable not set.
+
+Wed Feb 4 15:46:04 1998 Jörgen Hägg (jh at axis.se)
+
+ * version 1.31
+ * .LI will now honor a space mark.
+ * Another fix for .AU to let it be used without arguments.
+ * uninitialized eq*label fixed
+
+Fri Sep 6 07:13:07 1996 Jörgen Hägg (jh at axis.se)
+
+ * version 1.30
+ * This is more like a beta-release, bugs might pop up. :-)
+ * last line in TOC was not correctly terminated (missing .br)
+ * changed the indentation for displays, it will now
+ indent to the current indent, not the one at the definition
+ of the display.
+ * Equation marks should now work better, indentation also.
+ * included these bug fixes from Larry Jones:
+ * The documentation for the argument to .AS was incorrect for MT 4.
+ * \*(EM should be a double-dash for nroff.
+ * \nS is in points, not units.
+ * If \nO isn't set, the default page offset should be .75i for nroff
+ and .963i for troff.
+ * .S D should set the point size to \nS, not 10.
+ * .S was setting the vertical spacing based on the old point size
+ instead of the new point size.
+ * Got rid of a spurrious .br that prevented run-in headings from
+ working.
+ * Reset the .SP counters in pg@header so that spacing on one page
+ won't affect spacing on subsequent pages.
+ * Allow .AU and .AF with no arguments (real mm does, even though it
+ isn't documented).
+ * Do .init@reset first thing to initialize the default environment.
+ * For MT 4, the title should be 4 points larger than the default size,
+ not 12 point.
+ * The cover environment needs to be initialized.
+ * Printing the abstract on the first page needs to be controlled by
+ the .AS argument.
+ * Heading eject should be suppressed if the heading immediately
+ follows the first page stuff (title, author, etc.).
+ * support for table of contents numbering style (.nr Oc)
+ * changes the troff empty line height from .25v to .5v
+ * fixed section page numbering
+ * fixed a really nasty bug in footnotes that could cause you
+ to lose the page footer completely if the very first
+ footnote on the page occurred at just the wrong place
+
+
+Wed May 15 07:39:32 1996 Jörgen Hägg (jh at axis.se)
+
+ * version 1.29
+ * Syntax and scaling errror fixed, (thanks to Frazer Williams)
+ * DF/DE will now do a line-break before printing the display.
+ * Updated the manual for TB,FG,EX and EC.
+ * Added support for the ms- (and mgs-)macro .IX
+ * Added indexmacro IX, INITI, IND and INDP, support for
+ TXIND, TYIND and TZIND.
+ * PGFORM will now always really reset to the default
+ values for unspecified arguments.
+ * Floating displays tested and repaired, it should
+ now (finanlly) work exactly as the original (I hope :-).
+ * Should now set year correctly even after 2000.
+ * Stupid bug in PGNH fixed.
+ * Corrected line length for figure caption (FG and friends)
+
+
+Mon Apr 24 07:37:52 1995 Jörgen Hägg (jh at axis.se)
+
+ * version 1.28
+ * Added AVL (AV without date)
+ * Fixed nroff scaling for W and L.
+ * Added support for register E and roman/bold
+ for all Subject/Date/From strings.
+ * Added support for register C (1-4), (for DRAFTs and other types)
+ * Will protest if not used with groff.
+ * Change of the internal number registers @ps and @vs, they
+ are now in units, and is set in the new macros .@ps and .@vs.
+ @ps and @vs is now corrected to the real point and vertical size.
+ * Macro EQ has now correct pointsize.
+ * Figures should now get the right page number in the index.
+ * User-defined macros can now be defined for list of
+ figures, tables, equations and exhibits (T{X,Y}{FG,TB,EC,EX}.
+ * Space may be omitted between prefix and mark in automatic lists (.AL)
+ See .LI
+
+Tue Jan 10 07:51:37 1995 Jörgen Hägg (jh at axis.se)
+
+ * version 1.27
+ * Manual updated
+ * More bugs fixed in DS/DF
+ * added alias for :g
+ * LC can now be used without argument (as the manual says. :-)
+ * Register :R now supported (RS/RF)
+ * footnote line was printed even if there was no room for
+ any footnotes. Fixed.
+ * Fixed 1C so that it can be used without page eject
+ * Added support for EOP (TPs twin)
+ * Hyphenation turned off by default. (Hy == 0)
+
+Fri Nov 4 08:14:50 1994 Jörgen Hägg (jh at axis.se)
+
+ * version 1.25
+ * DS/DF separated and several bugs fixed. Watch out for new though. :-)
+ * string DT was emptied by mistake in the previous version.
+ * RD made prettier.
+ * typo in AV and let@print-head fixed.
+
+Mon Oct 31 08:19:24 1994 Jörgen Hägg (jh at axis.se)
+
+ * version 1.24
+ * Bug fixed and format extended in .SG and .FC.
+ * date is always printed unless .ND without argument is used.
+ (I wonder what's the right thing to do, this might change.)
+ * Swedish letter-standards implemented in tmac.mse.
+ * .ND can be used to turn off the date. (Empty argument)
+
+Mon Oct 31 08:14:09 1994 Jörgen Hägg (jh at axis.se)
+
+ * version 1.23
+ * An attempt to get in sync with RCS. This is the distributed
+ version.
+
+Thu Oct 27 08:29:34 1994 Jörgen Hägg (jh at axis.se)
+
+ * version 1.22
+ * (version 1.21 lost... :-)
+ * Letter macros added!!
+ * The following macros are added:
+ * AV, FC, IA ,IE, LT, LO, NE, NS, SG, WA, WE
+ * nP also added.
+
+Tue Dec 14 16:26:36 1993 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.20
+ * spelling-corrections
+ * Makefile.sim updated to the correct version, and a uninstall
+ target added.
+ * @cur-lib removed from tmac.m (obsolete)
+ * fixed check for references i .TC, .RP now resets the flag correctly.
+ * floating display should now be printed if there is space.
+ * first version using RCS. I've been avoiding version control until it
+ became necessary.
+ * WC WD now works in two-column-mode.
+
+Tue Sep 7 08:37:00 1993 Jörgen Hägg (jh at efd.lth.se)
+
+ * version 1.19
+ * .lt is called in the header for .TP also.
+ * Variable Pgps added to control the header and footer point-size.
+ * Error-text printed with .APP removed.
+ * Error with .FG, .TB, .EC and .EX indentation fixed.
+ * header and footer line-length is not changed by MC or 2C.
+ * Default for page-length and page-offset is now taken from
+ \n[.p] and \n[.o].
+ * Argument to .ab (abort) is supplied.
+ * Argument to .1C added.
+ * Argument to .PGFORM added.
+ * RP/RS/RF totally rewritten. Should work with 2C now.
+
+Fri Apr 23 10:37:25 1993 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.18
+ * Height of display is now more exactly calculated.
+ * tabs and blankspaces where wrong in .VERBON.
+ * error in manual for escape-character in VERBON.
+ * Makefile.sub: installed tmac.m as tmac.m and tmac.mse
+ * Installation of tmac.mse now supports TMAC_M.
+ * bug with N fixed.
+
+Mon Apr 5 09:36:01 1993 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.17
+ * MULB preserves size.
+ * bug in VERBON fixed, causing strange errors.
+ * section-page footer fixed.
+ * added support for numberregister S
+ * fixed bug with floating displays wich made floats to
+ generate space on a page, but broke page anyway.
+ * end-of-page trap reinstalled.
+
+Mon Mar 29 10:53:13 1993 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.16
+ * MUL* now use the previous font and family.
+ * extra blank page at end-of-text eliminated.
+
+Mon Mar 8 10:27:47 1993 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.15
+ * Didn't restore pointsize to current size in .H.
+ * B1/B2 did not work with indent. (MULE and friends)
+ * fixed old problem with trailing empty pages.
+
+Fri Mar 5 15:20:49 1993 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.14
+ * Sigh. Amazing what a missing \} can do. If the string
+ HP was set, then all text disappeared...
+
+Fri Mar 5 14:12:43 1993 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.13
+ * Fixed bug with handling ps/vs in .H. (again, sigh... )
+
+Wed Mar 3 09:21:20 1993 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.12
+ * Line-break added to PGFORM.
+ * added more features to VERBON
+ * .S is not used anymore in H, it caused confusion with
+ normal text, but it will still set .vs.
+ * SK was broken, will now produce the requested number of
+ empty pages.
+ * dotted lines added to LIST OF FIGURES adn friends.
+ Also better linespacing.
+
+Mon Feb 22 12:41:06 1993 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.11
+ * missing left-parenthesis gave ") .sp" when N=4.
+ * N=4 removed user-specified header also.
+ * MOVE made linelength pageoffset wider than wanted.
+ * fixed (again) parenthesis in RP.
+
+Thu Jan 21 12:10:39 1993 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.10
+ * changed PROG_PREFIX to g in the manual-pages.
+ * Better check if new page is needed in .H, when Ej>0.
+ * Usage of variable Lsp now more complete.
+ * Space added in TOC when mark is equal to size.
+ * Usermacro HY moved after font-calulations.
+ * .S used instead of .ps, which will use .vs correct.
+ * Now possible to set Hps1/2 inside HX.
+ * .FD "" 1 is now fixed.
+ * section-page numbering bug fixed.
+ * several bugs in VERBON/OFF fixed.
+
+Tue Dec 8 16:43:15 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.09
+ * N==4 gives no default header
+
+Sat Nov 21 14:28:20 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.08
+ * Escape-character disabled between
+ VERBON/VERBOFF (turned on by an argument).
+ Pointsize and fontchange also added as arguments.
+ * MULB, MULN and MULE added to get multicolumn output
+ with different width.
+ * Number register N can now use 1-5.
+ * Register Sectp and Sectf added.
+ * Register P is now updated correctly for "section-page" numbering.
+
+Thu Nov 19 11:19:33 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.07
+ * .OP fixed to eject a blank page if not odd.
+
+Fri Nov 13 09:46:09 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.06
+ * Macro TL rewritten. TL depends now on a following .AU.
+ * NOTES updated.
+ * .lt is now used more frequent when linelength is changed.
+ * macro AST added.
+ * removed PH/EH/OH not needed in ?.MT.
+
+Wed Oct 28 14:35:43 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.05
+ * .VM implemented.
+ * Possible bug in page heading fixed. Changed .sp to 'sp in HEADER.
+
+Thu Aug 20 13:56:31 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.04
+ * page-break in .EQ moved.
+ * changed unit for footer-size and header-size from units to lines.
+ Fixes problems with .S and page-breaks.
+ * \n[%] is now treated as a string, wich makes it possible
+ to assign new formats to it. Unfortunately, it was necessary
+ to change the page-number-variable in GETPN to a string.
+ * Makefile.sub included. (Thank you, James)
+
+Thu May 7 16:14:10 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.03
+ * Typo and centering in DS/DE fixed.
+ Even and odd pageheaders were reversed.
+ * LI: pad and mark-indent was lost in some earlier versions. Now fixed.
+ * fixed bug in reference to .FG, .TB, ...
+ * APP did not clear headercounters.
+ * Pointsize in titles is now only set at the beginning and
+ when PH, PF, OH, OF, EH and EF are used.
+
+Thu May 6 16:01:35 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.02
+ * OP fixed.
+
+Fri Mar 6 09:36:09 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.01
+ * two .LI without text between should not be printed
+ on the same row. Now fixed.
+ * figure titles and friends fixed, now possible with many .FG
+ in a DS/DE. Didn't always position correctly in previous version,
+ but is now always printed as it should.
+ * Makefile fixed for Ultrix.
+ * DS/DF could not handle empty arguments correct
+ * Missing .br i EQ added.
+
+Sat Jan 25 15:47:21 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 1.00
+ * No betaversion anymore!
+ * Fixed headernumbers within appendixes.
+ * DS did not keep the same font as before DS.
+ * mmse did a line break.
+
+Fri Jan 24 14:38:16 1992 Joergen Haegg (jh at efd.lth.se)
+
+ * version 0.16
+ * bug in TC, multiple line headers did not wrap correctly.
+ * added support for mm/locale and mm/language_locale.
+ * cov*default-firm in locale sets name of firm in the MT covers.
+ * cov*location-xxxx in locale sets location xxxx to the contents
+ of cov*location-xxxx. Used in the MT covers.
+ * hanging indent in lists fixed.
+ * use larger empty lines if .nroff is defined.
+ * macros, like .P, can now be used inside abstracts.
+ * .S do not reset indentation anymore.
+ * .RS aA now sets a string, not an integer.
+ * appendix with .APP or .APPSK added.
+
+Thu Nov 28 22:00:59 1991 Joergen Haegg (jh at efd.lth.se)
+
+ * version 0.15
+ * Fixed .AU in MT 0-3, added support for variable Au.
+ * Bug in the positioning of the foot-notes.
+ * lists not indented properly.
+ * Hps1 and Hps2 added.
+ * COVER had to have an argument.
+ * table of contents can now have multiline header.
+ * .HU now increments headingvariable H?
+ * added the inclusion of a locale file.
+
+Sat Nov 23 14:40:17 1991 Joergen Haegg (jh at efd.lth.se)
+
+ * version 0.14
+ * bug when using -rO fixed.
+ * MT 1-4 added.
+ * default is now MT 1
+ * .EQ/.EN can be used outside of .DS/.DE without complaints. But
+ I don't recommend it. Neither does the DWB books.
+ * LI don't break lines now if arg too big.
+ * PGFORM did not reset indent.
+ * Added the numbervariable Hps.
+ * Rewritten and added MT 0-5 + "string".
+ * Added TM.
+ * Indent to AS added
+
+Wed Nov 6 15:18:40 1991 Joergen Haegg (jh at efd.lth.se)
+
+ * version 0.13
+ * ds*format nod defined if PS/PE is used without DS/DE.
+ * GETST added, fourth argument to EX, FG, TB and EC added.
+
+Mon Nov 4 13:38:01 1991 Joergen Haegg (jh at efd.lth.se)
+
+ * version 0.12
+ * Fixed C,D,P,+-size in .S
+
+Sun Jan 1 00:00:00 1991 Joergen Haegg (jh at efd.lth.se)
+ * Next version will have ChangeLog entries...
+ * Bug in INITR fixed.
+ * VERBON/VERBOFF added to include programlistings
+ * Bug in .DE fixed, addition overflow
+Sun Jan 1 00:00:00 1991 Joergen Haegg (jh at efd.lth.se)
+ * spelling error in month-names.
+ * WC should work now (no warranty :-)
+ * FD almost finished, some details missing.
+ * incorrect calculation of foot-notes fixed.
+ * DS/DE did not break page when the size was smaller than the paper
+ * Forward/backward referencesystem added. Se .INITR in README.
+ * mgmsw changed name to mgmse.
+Sun Jan 1 00:00:00 1991 Joergen Haegg (jh at efd.lth.se)
+ * embarrassing bug in .P fixed
+ * .H did always eject page, now fixed.
+ * lost floating displays now found.
+ * accents added (from mgs)
+ * empty line in .EQ/.EN removed
+ * indentation in .TC corrected.
+ * indentation of DS/DE in lists fixed.
+ * .TB and friends now work inside DS/DE and outside.
+ * .WC partially implemented (WF and WD). Still working on it.
+ * .mso used if version>=1.02
+Sun Jan 1 00:00:00 1991 Joergen Haegg (jh at efd.lth.se)
+ * register P was not working.
+ * support for register Fg, Tb, Ec and Ex.
+ * list items was left on the previous page at a page break.
+ * tlevel in .TC now defaults to 2.
+ * string DT, EM and Tm supported.
+ * new macro: PGNH, see comments.
+ * bug in MOVE fixed.
+ * pagenumber in .TC fixed.
+ * a blank page was ejected if Ej==1, now fixed
+ * bug in floating display fixed (did break and SP wrong)
+ * bug in .SP fixed, no lines is now printed at top of page
+ * There are still problems with footnotes and displays in two column mode.
+Sun Jan 1 00:00:00 1991 Joergen Haegg (jh at efd.lth.se)
+ * register P added (same as %)
+ * bug in floating displays fixed
+ * MOVE added
+ * MT added, see comment below
+ * COVER/COVEND added
+ * fixed bug in figure titles
+ * extended S, se comment below
+ * MT 0 added
+ * ms-cover added (COVER ms)
+Sun Jan 1 00:00:00 1991 Joergen Haegg (jh at efd.lth.se)
+ * bugs in RD and comb. fonts fixed
+Sun Jan 1 00:00:00 1991 Joergen Haegg (jh at efd.lth.se)
+ * HC added
+ * Combined fonts (IB,BI...)
+ * HM added
+ * RD added
+ * OP added
+ * TP&PX supported
+ * warnings for unimplemented macros
diff --git a/contrib/mm/Makefile.sim b/contrib/mm/Makefile.sim
new file mode 100644
index 00000000..ea1e0ab7
--- /dev/null
+++ b/contrib/mm/Makefile.sim
@@ -0,0 +1,66 @@
+#
+# $Id: Makefile.sim,v 1.1 2000/02/06 09:34:46 wlemb Exp $
+#
+# To install mgm separately as tmac.gm:
+# make -f Makefile.sub tmacdir=/usr/local/lib/groff/tmac srcdir=. \
+# INSTALL_DATA='install -m 644' tmac_m=gm install
+#
+# or as tmac.m:
+#
+# tmacdir is the destination for your groff/tmac-directory, srcdir is
+# this directory and INSTALL_DATA is the command to install a file with.
+# If you dont have 'install': use 'cp'.
+
+
+# change this to whatever you like
+tmacdir=/usr/local/lib/groff/tmac
+#tmac_m = gm
+tmac_m = m
+indexdir = xx
+install = install -m 644
+
+# Do not change anything below this line
+srcdir = .
+version = 1.32
+mdate = 1999-09-03
+
+.SUFFIXES: .n .man
+
+all:
+
+
+install: groff_mm.n groff_mmse.n
+ $(MAKE) -f Makefile.sub tmacdir=$(tmacdir) srcdir=$(srcdir) \
+ INSTALL_DATA='$(install)' tmac_m=$(tmac_m) install
+
+ uninstall: groff_mm.n groff_mmse.n
+ $(MAKE) -f Makefile.sub tmacdir=$(tmacdir) srcdir=$(srcdir) \
+ INSTALL_DATA='$(install)' tmac_m=$(tmac_m) uninstall_sub
+
+
+.man.n:
+ @echo Making $@ from $<
+ @-rm -f $@
+ @sed -e "s;@HYPHENFILE@;$(hyphenfile);g" \
+ -e "s;@FONTDIR@;$(fontdir);g" \
+ -e "s;@FONTPATH@;$(fontpath);g" \
+ -e "s;@MACRODIR@;$(tmacdir);g" \
+ -e "s;@MACROPATH@;$(tmacpath);g" \
+ -e "s;@DEVICE@;$(DEVICE);g" \
+ -e "s;@DEFAULT_INDEX@;$(indexdir)/$(indexname);g" \
+ -e "s;@DEFAULT_INDEX_NAME@;$(indexname);g" \
+ -e "s;@INDEX_SUFFIX@;$(indexext);g" \
+ -e "s;@COMMON_WORDS_FILE@;$(common_words_file);g" \
+ -e "s;@MAN1EXT@;$(man1ext);g" \
+ -e "s;@MAN5EXT@;$(man5ext);g" \
+ -e "s;@MAN7EXT@;$(man7ext);g" \
+ -e "s;@TMAC_S@;$(tmac_s);g" \
+ -e "s;@TMAC_M@;$(tmac_m);g" \
+ -e "s;@TMAC_MDIR@;$(tmacdir)/mm;g" \
+ -e "s;@BROKEN_SPOOLER_FLAGS@;$(BROKEN_SPOOLER_FLAGS);g" \
+ -e "s;@VERSION@;$(version);g" \
+ -e "s;@MDATE@;$(mdate);g" \
+ -e "s;@g@;$(g);g" \
+ -e "s;@G@;`echo $(g) | tr [a-z] [A-Z]`;g" \
+ $< >$@
+
diff --git a/contrib/mm/Makefile.sub b/contrib/mm/Makefile.sub
new file mode 100644
index 00000000..0257a248
--- /dev/null
+++ b/contrib/mm/Makefile.sub
@@ -0,0 +1,49 @@
+#
+# $Id: Makefile.sub,v 1.1 2000/02/06 09:34:46 wlemb Exp $
+#
+PROG=mmroff
+MAN7=\
+ groff_mm.n \
+ groff_mmse.n \
+ mmroff.n
+FILES=0.MT 5.MT 4.MT ms.cov se_ms.cov
+# Local configuration files with default values.
+LOCALE = locale se_locale
+CLEANADD=temp
+install: install_mm
+
+install_mm: install_mmroff install_m
+ -test -d $(tmacdir)/mm || $(mkinstalldirs) $(tmacdir)/mm
+ -for f in $(FILES); do \
+ rm -f $(tmacdir)/mm/$$f; \
+ $(INSTALL_DATA) $(srcdir)/mm/$$f $(tmacdir)/mm/$$f; \
+ done
+ -for f in $(LOCALE); do \
+ test -f $(tmacdir)/mm/$$f || touch $(tmacdir)/mm/$$f; \
+ done
+
+install_m:
+ -test -d $(tmacdir) || $(mkinstalldirs) $(tmacdir)
+ -rm -f $(tmacdir)/tmac.$(tmac_m_prefix)m
+ $(INSTALL_DATA) $(srcdir)/tmac.m $(tmacdir)/tmac.$(tmac_m_prefix)m
+ @sed -e "s;^.mso tmac.m;.mso tmac.$(tmac_m_prefix)m;g" \
+ $(srcdir)/tmac.mse > $(tmacdir)/tmac.$(tmac_m_prefix)mse
+install_mmroff : mmroff
+ -test -d $(bindir) || $(mkinstalldirs) $(bindir)
+ -rm -f $(bindir)/mmroff
+ $(INSTALL_PROGRAM) mmroff $(bindir)/mmroff
+
+mmroff: mmroff.pl
+ -rm -f $@
+ -sed -e 's;/usr/bin/perl;$(PERLPATH);' $(srcdir)/mmroff.pl >$@
+ -chmod +x $@
+
+uninstall_sub:
+ -for f in $(FILES); do rm -f $(tmacdir)/mm/$$f; done
+ -for f in $(LOCALE); do \
+ test -s $(tmacdir)/mm/$$f || rm -f $(tmacdir)/mm/$$f; \
+ done
+ -rm -f $(tmacdir)/tmac.$(tmac_m_prefix)m
+ -rm -f $(tmacdir)/tmac.$(tmac_m_prefix)mse
+ -rmdir $(tmacdir)/mm
+ -rm -f $(bindir)/mmroff
diff --git a/contrib/mm/NOTES b/contrib/mm/NOTES
new file mode 100644
index 00000000..43794a29
--- /dev/null
+++ b/contrib/mm/NOTES
@@ -0,0 +1,103 @@
+######################################################################
+Beware!
+This may be old information. Trust only the source. :-)
+
+Implementation notes. (Or how to make your own national mm)
+
+Different commands:
+
+COVER [arg]
+MT [arg [addressee]]
+The arg is part of a filename in mm/*.MT or mm/*.cov.
+This file is read when the macro is executed. Therefore it must be
+put before any text output.
+In each file there are definitions of all extra macros needed for the
+cover sheet. MT files is only for compatibility reasons, and has several
+limits due to that it don't know when the cover starts, and cannot
+change sizes. Use COVER for new coversheet macros.
+
+But with MT it is possible to write all of the AT&T covers.
+An example can be found in mm/0.MT.
+
+When writing a new cover using COVER, have in mind that the cover
+should print the page with the COVEND macro. This macro
+should be defined by the new macrofile.
+
+Here is a part of ms.cov:
+> .\"-----------------
+> .de COVEND
+> .sp |4.2c
+> .cov@print-title
+> .cov@print-authors
+> .cov@print-firm
+> .cov@print-abstract
+> .cov@print-date
+This is important, since COVER disables the page header.
+> .pg@enable-top-trap
+Should begin with page one (normally).
+> .bp 1
+And enable the trap at the page footer.
+> .pg@enable-trap
+> ..
+
+#########################
+
+Variables for covers:
+I = integer
+S = string
+D = diversion
+M = macro
+
+Name Type Desc.
+cov*au I The number of authors.
+
+cov*title M Title collected with .TL.
+
+cov*au!x!y S Author(s) given to .AU
+cov*at!x!y S Author(s) title given to .AT
+ x is the author-index [1-cov*au],
+ y is the argument-index [1-9].
+ Look at the table with indexes.
+
+cov*firm I Author(s) firm.
+
+cov*abs-arg I Argument to abstract.
+
+cov*abs-ind I Indent for abstract.
+
+cov*abs-name S The string 'ABSTRACT', changed with .AST
+
+cov*abstract M The abstract.
+
+cov*new-date S The date (todays date if ND is not used)
+
+cov*mt-type S MT type
+cov*mt-addresse S MT addressee
+
+
+##########################
+Argument-index for cov*au:
+
+Index Desc.
+1 name
+2 initials
+3 location
+4 department
+5 extension
+6 room
+7 arg 7
+8 arg 8
+9 arg 9
+
+The location is set to the contents of string cov*location-xxxx
+if location is equal to xxxx and cov*location-xxxx is defined
+in the file locale.
+
+
+Argument-index for cov*at:
+
+Index Desc.
+1 title 1
+. .
+. .
+9 title 9
diff --git a/contrib/mm/README b/contrib/mm/README
new file mode 100644
index 00000000..a720f070
--- /dev/null
+++ b/contrib/mm/README
@@ -0,0 +1,28 @@
+
+This is mgm, a macro package for groff.
+
+It is supposed to be compatible with the DWB mm macros,
+and has several extensions.
+
+Send bug reports to jh@axis.se with a description of the problem
+and a sample of text which reproduces the error.
+
+Don't forget to mention the version of mgm (look in the beginning
+of tmac.m) and the version of groff.
+
+Any new ideas or improvements are welcome.
+
+Newest version is available with anonymous FTP
+at ftp://ftp.efd.lth.se/pub/groff/mm<something>.gz
+or ftp://ftp.axis.se/pub/groff/mm<something>.gz
+
+You can install mgm as a separate package without the configure in groff
+with the following command:
+
+make -f Makefile.sim install
+
+This README should be bigger :-)
+
+Jörgen.
+
+Thanks to everyone who have sent me bug-reports and fixes.
diff --git a/contrib/mm/examples/APP b/contrib/mm/examples/APP
new file mode 100644
index 00000000..82352e58
--- /dev/null
+++ b/contrib/mm/examples/APP
@@ -0,0 +1,352 @@
+.H 1 " granary grand grandchild grandchildren granddaughter grandeur"
+granary
+grapheme
+graphic
+graphite
+grapple
+grasp
+grass
+grassland
+grassy
+grata
+grate
+grateful
+grater
+gratify
+gratis
+gratitude
+gratuitous
+gratuity
+grave
+gravel
+.H 2 "grapefruit grapevine graph grapheme graphic graphite"
+granary
+grand
+graphic
+graphite
+grapple
+grasp
+grass
+grassland
+grassy
+grata
+grate
+grateful
+grater
+gratify
+gratis
+gratitude
+gratuitous
+gratuity
+grave
+gravel
+.H 3 "grapple"
+granary
+grand
+grandchild
+grandchildren
+granddaughter
+grandeur
+grandfather
+grandiloquent
+grandiose
+grandma
+grandmother
+grateful
+grater
+gratify
+gratis
+gratitude
+gratuitous
+gratuity
+grave
+gravel
+.H 1 "Graves gravestone graveyard gravid gravitate gravy gray"
+granary
+grand
+grandchild
+grandchildren
+granddaughter
+grandeur
+grandfather
+grandiloquent
+grandiose
+grata
+grate
+grateful
+grater
+gratify
+gratis
+gratitude
+gratuitous
+gratuity
+grave
+gravel
+.H 1 "Greenfield greengrocer greenhouse greenish Greenland Greensboro"
+granary
+grand
+grandchild
+grandchildren
+granddaughter
+grandeur
+grandfather
+grandiloquent
+grassy
+grata
+grate
+grateful
+grater
+gratify
+gratis
+gratitude
+gratuitous
+gratuity
+grave
+gravel
+.H 1 "greensward greenware Greenwich greenwood Greer greet"
+graven
+Graves
+gravestone
+graveyard
+gravid
+gravitate
+gravy
+gray
+graybeard
+grayish
+Grayson
+graywacke
+graze
+grease
+.APP "" "Graves app a gravestone graveyard gravid gravitate gravy gray"
+granary
+grand
+grandchild
+grandchildren
+granddaughter
+grandeur
+grandfather
+grandiloquent
+grandiose
+grata
+grate
+grateful
+grater
+gratify
+gratis
+gratitude
+gratuitous
+gratuity
+grave
+gravel
+.APP "" "Greenfield app b greengrocer greenhouse greenish Greenland Greensboro"
+granary
+grand
+grandchild
+grandchildren
+granddaughter
+grandeur
+.H 2 "grandfather grandiloquent grandiose grandma grandmother grandnephew"
+.H 2 "grandniece grandpa grandparent grandson grandstand granite granitic"
+.H 2 "granny granola grant grantee grantor granular granulate"
+.H 2 "granule Granville grape"
+.H 2 "grapefruit grapevine graph grapheme graphic graphite"
+.H 3 "grapple"
+grandfather
+grandiloquent
+grassy
+grata
+grate
+grateful
+grater
+gratify
+gratis
+gratitude
+gratuitous
+gratuity
+grave
+gravel
+.APP ABC "greensward app abc greenware Greenwich greenwood Greer greet"
+graven
+Graves
+.APP "" "handstand app f handwrite handwritten handy handyman handymen"
+gravestone
+graveyard
+gravid
+gravitate
+gravy
+gray
+graybeard
+grayish
+Grayson
+graywacke
+graze
+grease
+.APPSK "" 10 "Handel app c 10 handhold handicap handicapped handicapper"
+.APPSK "" 23 "handicapping app d 23 handicraftsmen handiwork"
+.APPSK "" 99 "handmade app e 99 handset handshake handsome handspike"
+.nr Aph 0
+.APP "" "handstand app f handwrite handwritten handy handyman handymen"
+headsmen
+headstand
+headstone
+headstrong
+headwall
+headwater
+headway
+headwind
+.H 2 "graybeard grayish Grayson graywacke graze grease greasy great greatcoat"
+.H 2 "greater grebe Grecian Greece greed greedy Greek green Greenbelt Greenberg"
+.H 2 "Greenblatt Greenbriar Greene greenery"
+.H 3 "Greenfield greengrocer greenhouse greenish Greenland Greensboro"
+.H 3 "greensward greenware Greenwich greenwood Greer greet"
+heady
+heal
+Healey
+health
+healthful
+healthy
+Healy
+heap
+hear
+heard
+hearken
+hearsay
+hearse
+Hearst
+heart
+heartbeat
+heartbreak
+hearten
+heartfelt
+hearth
+hearty
+heat
+heater
+heath
+heathen
+heathenish
+Heathkit
+heave
+heaven
+heavenward
+heavy
+heavyweight
+Hebe
+hebephrenic
+Hebraic
+Hebrew
+Hecate
+hecatomb
+heck
+heckle
+Heckman
+hectic
+hector
+.APP "" "hang hangable app f hangar hangman hangmen hangout hangover hank"
+Hecuba
+he'd
+hedge
+.H 2 "graybeard grayish Grayson graywacke graze grease greasy great greatcoat"
+hedgehog
+hedonism
+hedonist
+heed
+heel
+.H 2 "greater grebe Grecian Greece greed greedy Greek green Greenbelt Greenberg"
+heft
+hefty
+Hegelian
+hegemony
+Heidelberg
+heigh
+height
+heighten
+Heine
+Heinrich
+Heinz
+heir
+heiress
+Heisenberg
+held
+Helen
+Helena
+Helene
+Helga
+helical
+helicopter
+heliocentric
+heliotrope
+helium
+helix
+he'll
+hell
+hellbender
+hellebore
+Hellenic
+hellfire
+hellgrammite
+hellish
+hello
+helm
+helmet
+Helmholtz
+helmsman
+helmsmen
+Helmut
+help
+helpful
+helpmate
+.APP "" "Hankel app g Hanley Hanlon Hanna Hannah Hannibal Hanoi Hanover"
+Helsinki
+Helvetica
+hem
+hematite
+Hemingway
+hemisphere
+hemispheric
+hemlock
+hemoglobin
+hemolytic
+hemorrhage
+hemorrhoid
+hemosiderin
+hemp
+Hempstead
+hen
+henbane
+hence
+henceforth
+henchman
+henchmen
+.H 2 "greater grebe Grecian Greece greed greedy Greek green Greenbelt Greenberg"
+Henderson
+Hendrick
+Hendricks
+Hendrickson
+henequen
+Henley
+henpeck
+Henri
+Henrietta
+henry
+hepatica
+hepatitis
+Hepburn
+heptane
+her
+Hera
+Heraclitus
+herald
+herb
+Herbert
+Herculean
+Hercules
+herd
+herdsman
+here
+hereabout
+hereafter
+hereby
+hereditary
+.TC
diff --git a/contrib/mm/examples/B1B2 b/contrib/mm/examples/B1B2
new file mode 100644
index 00000000..a2bb3add
--- /dev/null
+++ b/contrib/mm/examples/B1B2
@@ -0,0 +1,91 @@
+abetting
+abeyance
+abeyant
+abhorred
+abhorrent
+abide
+Abidjan
+Abigail
+abject
+ablate
+ablaze
+able
+ablution
+Abner
+abnormal
+Abo
+aboard
+abode
+abolish
+.B1
+abolition
+abominable
+abominate
+aboriginal
+AAA
+ABORIGINE
+ABORNING
+ABORT
+ABOUND
+ABOUT
+ABOVE
+ABOVEBOARD
+ABOVEGROUND
+abovementioned
+abrade
+Abraham
+Abram
+Abramson
+abrasion
+abrasive
+abreact
+.B2
+abreast
+abrogate
+abrupt
+abscess
+abscissa
+abscissae
+absence
+absent
+absentee
+absenteeism
+absentia
+absentminded
+absinthe
+absolute
+absolution
+absolve
+absorb
+absorbent
+absorption
+absorptive
+abstain
+abstention
+abstract
+abstracter
+abstractor
+ABSURD
+ABUILDING
+ABUNDANT
+ABUSABLE
+ABUSE
+ABUSIVE
+ABUT
+ABUTTED
+ABUTTING
+ABYSMAL
+ABYSS
+ABYSSINIA
+AC
+ACADEME
+ACADEMIA
+ACADEMIC
+ACADEMICIAN
+ACADEMY
+ACADIA
+ACANTHUS
+ACAPULCO
+ACCEDE
+ACCELERATE
+ACCELEROMETER
diff --git a/contrib/mm/examples/COVER b/contrib/mm/examples/COVER
new file mode 100644
index 00000000..d23597f0
--- /dev/null
+++ b/contrib/mm/examples/COVER
@@ -0,0 +1,235 @@
+.COVER
+.ND 911123
+.TL "charge" "filing"
+This is a test
+granary
+grand
+grandchild
+grandchildren
+granddaughter
+grandeur
+grandfather
+grandiloquent
+grandiose
+grandma
+grandmother
+grandnephew
+grandniece
+grandpa
+grandparent
+grandson
+.AU "Nisse Svensson" "DGY" "BF" "Computer Center" "5488" "5-2115" "nisse@vira.sture.elm"
+.AF "MT GRANDSTAND GRANITE GRANITIC"
+.AS 1 10
+grant
+grantee
+grantor
+granular
+granulate
+granule
+Granville
+grape
+grapefruit
+grapevine
+graph
+grapheme
+graphic
+graphite
+grapple
+grasp
+grass
+grassland
+grassy
+grata
+grate
+grateful
+grater
+gratify
+gratis
+gratitude
+gratuitous
+gratuity
+grave
+gravel
+graven
+Graves
+gravestone
+graveyard
+gravid
+gravitate
+gravy
+gray
+graybeard
+grayish
+Grayson
+graywacke
+graze
+grease
+greasy
+great
+greatcoat
+greater
+grebe
+Grecian
+.AE
+.COVEND
+Greece
+greed
+greedy
+Greek
+green
+Greenbelt
+Greenberg
+Greenblatt
+Greenbriar
+Greene
+greenery
+Greenfield
+greengrocer
+greenhouse
+greenish
+Greenland
+Greensboro
+greensward
+greenware
+Greenwich
+greenwood
+Greer
+greet
+Greg
+gregarious
+Gregg
+Gregory
+gremlin
+grenade
+Grendel
+Grenoble
+Gresham
+Greta
+Gretchen
+grew
+grey
+greyhound
+greylag
+grid
+griddle
+gridiron
+grief
+grievance
+grieve
+grievous
+griffin
+Griffith
+grill
+grille
+grilled
+grillwork
+grim
+grimace
+Grimaldi
+grime
+Grimes
+Grimm
+grin
+grind
+grindstone
+grip
+gripe
+grippe
+grisly
+grist
+gristmill
+Griswold
+grit
+gritty
+grizzle
+granary
+grand
+grandchild
+grandchildren
+granddaughter
+grandeur
+grandfather
+grandiloquent
+grandiose
+grandma
+grandmother
+grandnephew
+grandniece
+grandpa
+grandparent
+grandson
+grandstand
+granite
+granitic
+granny
+granola
+grant
+grantee
+grantor
+granular
+granulate
+granule
+Granville
+grape
+grapefruit
+grapevine
+graph
+grapheme
+graphic
+graphite
+grapple
+grasp
+grass
+grassland
+grassy
+grata
+grate
+grateful
+grater
+gratify
+gratis
+gratitude
+gratuitous
+gratuity
+grave
+gravel
+graven
+Graves
+gravestone
+graveyard
+gravid
+gravitate
+gravy
+gray
+graybeard
+grayish
+Grayson
+graywacke
+graze
+grease
+greasy
+great
+greatcoat
+greater
+grebe
+Grecian
+Greece
+greed
+greedy
+Greek
+green
+Greenbelt
+Greenberg
+Greenblatt
+Greenbriar
+Greene
+greenery
+Greenfield
+greengrocer
+greenhouse
+greenish
+Greenland
+Greensboro
+greensward
+greenware
diff --git a/contrib/mm/examples/IND b/contrib/mm/examples/IND
new file mode 100644
index 00000000..fbf6c43a
--- /dev/null
+++ b/contrib/mm/examples/IND
@@ -0,0 +1,4191 @@
+.de foo
+a=\\$1, b=\\$2
+.br
+..
+.INITI N ind-data
+.H 1 "halve"
+.IND granary
+grand
+grandchild
+grandchildren
+granddaughter
+grandeur
+grandfather
+grandiloquent
+grandiose
+grandma
+grandmother
+.IND grandnephew
+grandniece
+grandpa
+grandparent
+grandson
+grandstand
+granite
+granitic
+granny
+granola
+grant
+grantee
+grantor
+granular
+.IND granulate
+granule
+Granville
+grape
+.H 2 "grandfather grandiloquent grandiose grandma grandmother grandnephew"
+grapefruit
+grapevine
+graph
+grapheme
+graphic
+.H 1 "halo halocarbon halogen Halpern Halsey Halstead halt halvah"
+graphite
+grapple
+grasp
+grass
+grassland
+grassy
+grata
+grate
+grateful
+grater
+gratify
+gratis
+gratitude
+gratuitous
+gratuity
+.IND grave
+gravel
+graven
+Graves
+gravestone
+graveyard
+gravid
+gravitate
+gravy
+gray
+graybeard
+grayish
+Grayson
+graywacke
+graze
+grease
+greasy
+great
+greatcoat
+greater
+.H 1 "Han Hancock hand handbag handbook handclasp handcuff Handel handful"
+grebe
+Grecian
+Greece
+greed
+greedy
+.IND Greek
+green
+Greenbelt
+Greenberg
+.H 1 " granary grand grandchild grandchildren granddaughter grandeur"
+Greenblatt
+Greenbriar
+Greene
+greenery
+Greenfield
+greengrocer
+greenhouse
+greenish
+Greenland
+Greensboro
+greensward
+.H 1 "handgun"
+greenware
+Greenwich
+greenwood
+Greer
+greet
+Greg
+gregarious
+Gregg
+Gregory
+.IND gremlin
+grenade
+Grendel
+Grenoble
+Gresham
+Greta
+Gretchen
+grew
+grey
+greyhound
+greylag
+grid
+griddle
+gridiron
+grief
+grievance
+grieve
+grievous
+griffin
+Griffith
+grill
+grille
+grilled
+grillwork
+grim
+.IND grimace
+Grimaldi
+grime
+Grimes
+Grimm
+grin
+grind
+grindstone
+grip
+gripe
+grippe
+grisly
+grist
+gristmill
+Griswold
+grit
+gritty
+grizzle
+grizzly
+groan
+groat
+grocer
+grocery
+groggy
+.IND groin
+grommet
+groom
+groove
+grope
+grosbeak
+gross
+.H 1 "handicapped handicapper handicapping handicraft handicraftsman"
+Grosset
+Grossman
+Grosvenor
+grotesque
+Groton
+ground
+groundsel
+groundskeep
+groundwork
+group
+groupoid
+grout
+grove
+grovel
+Grover
+grow
+growl
+grown
+grownup
+.IND growth
+grub
+grubby
+grudge
+gruesome
+gruff
+grumble
+Grumman
+grunt
+gryphon
+g's
+GSA
+GU
+Guam
+guanidine
+guanine
+guano
+guarantee
+guaranteeing
+guarantor
+guaranty
+guard
+guardhouse
+.IND Guardia
+guardian
+Guatemala
+.IND gubernatorial
+Guelph
+Guenther
+guerdon
+guernsey
+guerrilla
+guess
+guesswork
+guest
+guffaw
+Guggenheim
+Guiana
+guidance
+guide
+guidebook
+guideline
+guidepost
+guiding
+guignol
+guild
+.H 1 "handicraftsmen handiwork handkerchief handle"
+guildhall
+guile
+Guilford
+guillemot
+guillotine
+guilt
+.IND guilty
+guinea
+guise
+guitar
+gules
+gulf
+.H 1 "handleable handlebar handline handmade handmaiden handout"
+gull
+Gullah
+gullet
+gullible
+gully
+gulp
+gum
+gumbo
+gumdrop
+gummy
+gumption
+gumshoe
+gun
+Gunderson
+.IND gunfight
+gunfire
+gunflint
+gunk
+gunky
+gunman
+.IND gunmen
+gunnery
+gunny
+gunplay
+gunpowder
+gunshot
+gunsling
+Gunther
+gurgle
+Gurkha
+guru
+Gus
+gush
+gusset
+gust
+Gustafson
+Gustav
+Gustave
+Gustavus
+gusto
+gusty
+gut
+.H 1 "handset"
+Gutenberg
+Guthrie
+gutsy
+guttural
+.IND guy
+Guyana
+guzzle
+Gwen
+Gwyn
+gym
+gymnasium
+gymnast
+gymnastic
+gymnosperm
+gyp
+gypsite
+gypsum
+gypsy
+gyrate
+gyrfalcon
+gyro
+.IND gyrocompass
+gyroscope
+h
+ha
+Haag
+Haas
+habeas
+haberdashery
+Haberman
+.IND Habib
+habit
+habitant
+habitat
+habitation
+habitual
+habituate
+hacienda
+hack
+hackberry
+Hackett
+hackle
+hackmatack
+.H 1 "handshake handsome handspike handstand handwaving handwrite handwritten"
+hackney
+hackneyed
+hacksaw
+had
+Hadamard
+Haddad
+haddock
+Hades
+Hadley
+hadn't
+Hadrian
+hadron
+hafnium
+.IND Hagen
+Hager
+haggard
+haggle
+Hagstrom
+Hague
+Hahn
+Haifa
+haiku
+hail
+hailstone
+hailstorm
+Haines
+hair
+.IND haircut
+hairdo
+hairpin
+hairy
+Haiti
+Haitian
+Hal
+halcyon
+hale
+Haley
+half
+halfback
+.IND halfhearted
+halfway
+halibut
+halide
+.H 1 "handy handyman handymen Haney Hanford hang hangable hangar"
+Halifax
+halite
+hall
+hallelujah
+Halley
+hallmark
+hallow
+Halloween
+hallucinate
+hallway
+halma
+halo
+halocarbon
+halogen
+Halpern
+Halsey
+Halstead
+halt
+halvah
+halve
+Halverson
+ham
+.IND Hamal
+Hamburg
+hamburger
+Hamilton
+hamlet
+Hamlin
+hammerhead
+hammock
+Hammond
+hamper
+Hampshire
+.IND Hampton
+hamster
+Han
+.H 1 "hangman hangmen hangout hangover hank Hankel Hanley"
+Hancock
+hand
+handbag
+handbook
+handclasp
+handcuff
+Handel
+handful
+handgun
+handhold
+handicap
+handicapped
+.IND handicapper
+handicapping
+handicraft
+handicraftsman
+handicraftsmen
+handiwork
+handkerchief
+handle
+handleable
+handlebar
+handline
+handmade
+handmaiden
+handout
+handset
+handshake
+handsome
+handspike
+handstand
+handwaving
+.H 1 "Hanlon Hanna Hannah Hannibal Hanoi Hanover Hanoverian Hans"
+handwrite
+handwritten
+handy
+handyman
+handymen
+Haney
+.IND Hanford
+hang
+hangable
+hangar
+hangman
+hangmen
+hangout
+hangover
+.IND hank
+Hankel
+Hanley
+Hanlon
+Hanna
+Hannah
+Hannibal
+Hanoi
+Hanover
+Hanoverian
+Hans
+Hansel
+Hansen
+hansom
+Hanson
+Hanukkah
+hap
+.H 1 "Hansel"
+haphazard
+.IND haploid
+haploidy
+haplology
+happen
+happenstance
+happy
+Hapsburg
+harangue
+harass
+Harbin
+harbinger
+Harcourt
+hard
+hardbake
+hardboard
+hardboiled
+hardcopy
+harden
+hardhat
+Hardin
+.H 1 "Hansen hansom Hanson Hanukkah hap haphazard haploid haploidy"
+Harding
+hardscrabble
+hardtack
+hardtop
+hardware
+hardwood
+.IND hardworking
+hardy
+hare
+harelip
+harem
+.IND hark
+Harlan
+Harlem
+Harley
+harm
+harmful
+Harmon
+harmonic
+harmonica
+harmonious
+.H 1 "haplology happen happenstance happy Hapsburg harangue harass Harbin"
+harmony
+harness
+Harold
+harp
+harpoon
+harpsichord
+Harpy
+Harriet
+Harriman
+Harrington
+Harris
+.IND Harrisburg
+Harrison
+harrow
+harry
+harsh
+harshen
+hart
+Hartford
+Hartley
+Hartman
+Harvard
+harvest
+harvestman
+Harvey
+hash
+hashish
+hasn't
+hasp
+hassle
+hast
+haste
+hasten
+Hastings
+hasty
+hat
+hatch
+.IND hatchet
+hatchway
+.IND hate
+hateful
+hater
+Hatfield
+hath
+Hathaway
+hatred
+Hatteras
+Hattie
+Hattiesburg
+Haugen
+haughty
+haul
+haulage
+haunch
+haunt
+Hausdorff
+Havana
+have
+haven
+haven't
+Havilland
+havoc
+haw
+.IND Hawaii
+Hawaiian
+hawk
+Hawkins
+Hawley
+hawthorn
+.H 2 "hammock Hammond hamper Hampshire Hampton hamster"
+Hawthorne
+hay
+Hayden
+Haydn
+Hayes
+hayfield
+Haynes
+Hays
+haystack
+Hayward
+hayward
+hazard
+hazardous
+haze
+hazel
+hazelnut
+hazy
+he
+head
+.IND headache
+.IND headboard
+headdress
+headland
+headlight
+headline
+headmaster
+headphone
+headquarter
+headquarters
+headroom
+headset
+headsman
+headsmen
+headstand
+headstone
+headstrong
+headwall
+headwater
+headway
+headwind
+heady
+heal
+Healey
+health
+healthful
+healthy
+.IND Healy
+heap
+hear
+heard
+hearken
+hearsay
+hearse
+Hearst
+heart
+heartbeat
+heartbreak
+hearten
+heartfelt
+hearth
+hearty
+heat
+heater
+heath
+heathen
+heathenish
+Heathkit
+heave
+.IND heaven
+heavenward
+heavy
+heavyweight
+.IND Hebe
+hebephrenic
+Hebraic
+Hebrew
+Hecate
+hecatomb
+heck
+heckle
+Heckman
+hectic
+hector
+Hecuba
+he'd
+hedge
+hedgehog
+hedonism
+hedonist
+heed
+heel
+heft
+hefty
+Hegelian
+hegemony
+Heidelberg
+heigh
+height
+.IND heighten
+Heine
+Heinrich
+Heinz
+heir
+heiress
+Heisenberg
+held
+Helen
+Helena
+Helene
+Helga
+helical
+helicopter
+heliocentric
+heliotrope
+helium
+helix
+he'll
+.IND hell
+hellbender
+hellebore
+Hellenic
+hellfire
+hellgrammite
+hellish
+.IND hello
+helm
+helmet
+.H 1 "Halverson ham Hamal Hamburg hamburger Hamilton hamlet Hamlin hammerhead"
+Helmholtz
+helmsman
+helmsmen
+Helmut
+help
+helpful
+helpmate
+Helsinki
+Helvetica
+hem
+hematite
+Hemingway
+hemisphere
+hemispheric
+hemlock
+hemoglobin
+hemolytic
+hemorrhage
+hemorrhoid
+hemosiderin
+hemp
+Hempstead
+hen
+.IND henbane
+hence
+henceforth
+henchman
+henchmen
+Henderson
+Hendrick
+Hendricks
+Hendrickson
+henequen
+Henley
+henpeck
+Henri
+Henrietta
+henry
+hepatica
+.IND hepatitis
+Hepburn
+heptane
+her
+Hera
+Heraclitus
+herald
+herb
+Herbert
+Herculean
+.IND Hercules
+herd
+herdsman
+here
+hereabout
+hereafter
+hereby
+hereditary
+heredity
+Hereford
+herein
+hereinabove
+hereinafter
+hereinbelow
+hereof
+heresy
+heretic
+hereto
+heretofore
+hereunder
+hereunto
+herewith
+heritable
+heritage
+Herkimer
+Herman
+.IND Hermann
+hermeneutic
+Hermes
+hermetic
+Hermite
+hermitian
+Hermosa
+Hernandez
+hero
+Herodotus
+heroes
+heroic
+heroin
+.IND heroine
+heroism
+heron
+herpes
+herpetology
+Herr
+herringbone
+Herschel
+herself
+Hershel
+Hershey
+hertz
+Hertzog
+.IND hesitant
+hesitate
+hesitater
+Hesperus
+Hess
+Hesse
+Hessian
+Hester
+heterocyclic
+heterodyne
+heterogamous
+heterogeneity
+heterogeneous
+heterosexual
+heterostructure
+heterozygous
+Hetman
+Hettie
+Hetty
+Heublein
+heuristic
+Heusen
+Heuser
+hew
+Hewett
+Hewitt
+.IND Hewlett
+hewn
+hex
+hexachloride
+hexadecimal
+hexafluoride
+hexagon
+hexagonal
+hexameter
+hexane
+.IND hey
+heyday
+hi
+Hiatt
+hiatus
+Hiawatha
+hibachi
+Hibbard
+hibernate
+Hibernia
+hick
+Hickey
+Hickman
+hickory
+Hicks
+hid
+.IND hidalgo
+hidden
+hide
+hideaway
+hideous
+hideout
+hierarchal
+hierarchic
+hierarchy
+hieratic
+hieroglyphic
+Hieronymus
+hifalutin
+Higgins
+high
+highball
+highboy
+highest
+highfalutin
+highhanded
+highland
+highlight
+highroad
+hightail
+highway
+highwayman
+.IND highwaymen
+hijack
+hijinks
+hike
+hilarious
+hilarity
+Hilbert
+.IND Hildebrand
+hill
+hillbilly
+Hillcrest
+Hillel
+hillman
+hillmen
+hillock
+hillside
+hilltop
+hilly
+hilt
+Hilton
+hilum
+him
+Himalaya
+himself
+hind
+hindmost
+.IND hindrance
+hindsight
+Hindu
+Hinduism
+Hines
+hinge
+Hinman
+hint
+hinterland
+hip
+hippo
+Hippocrates
+Hippocratic
+hippodrome
+hippopotamus
+hippy
+hipster
+Hiram
+hire
+hireling
+Hiroshi
+Hiroshima
+Hirsch
+hirsute
+his
+Hispanic
+.IND hiss
+histamine
+histidine
+histochemic
+.IND histochemistry
+histogram
+histology
+historian
+historic
+historiography
+history
+histrionic
+hit
+Hitachi
+hitch
+Hitchcock
+.H 1 "harbinger"
+hither
+hitherto
+Hitler
+hive
+ho
+hoagie
+Hoagland
+hoagy
+hoar
+hoard
+.IND hoarfrost
+hoarse
+hob
+Hobart
+Hobbes
+hobble
+Hobbs
+hobby
+hobbyhorse
+hobgoblin
+hobo
+Hoboken
+hoc
+hock
+hockey
+hocus
+hodge
+hodgepodge
+Hodges
+Hodgkin
+hoe
+Hoff
+Hoffman
+hog
+hogan
+hogging
+.IND hoi
+.IND Hokan
+Holbrook
+Holcomb
+hold
+holden
+holdout
+holdover
+holdup
+hole
+holeable
+holiday
+Holland
+Hollandaise
+holler
+Hollerith
+Hollingsworth
+Hollister
+hollow
+Holloway
+hollowware
+holly
+hollyhock
+Hollywood
+Holm
+Holman
+.IND Holmdel
+Holmes
+holmium
+holocaust
+Holocene
+hologram
+holography
+Holst
+Holstein
+holster
+holt
+Holyoke
+.IND holystone
+.INDP
+inject injudicious Injun injunct injunction injure injurious injury
+injustice ink inkling inlaid inland inlay inlet Inman inmate inn innards
+innate inner innermost innkeeper innocent innocuous innovate innuendo
+innumerable inoculate inoffensive inoperable inoperative inopportune
+inordinate inorganic input inputting inquest inquire inquiry inquisition
+inquisitive inquisitor inroad insane insatiable inscribe inscription
+inscrutable insect insecticide insecure inseminate insensible insensitive
+inseparable insert inset inshore inside insidious insight insightful
+insignia insignificant insincere insinuate insipid insist insistent
+insofar insolent insoluble insolvable insolvent insomnia insomniac
+insouciant inspect inspector inspiration inspire instable install
+installation instalment instance instant instantaneous instantiate
+.INITI H ind-data2
+.H 1 "halve"
+.IND granary
+grand
+grandchild
+grandchildren
+granddaughter
+grandeur
+grandfather
+grandiloquent
+grandiose
+grandma
+grandmother
+.IND grandnephew
+grandniece
+grandpa
+grandparent
+grandson
+grandstand
+granite
+granitic
+granny
+granola
+grant
+grantee
+grantor
+granular
+.IND granulate
+granule
+Granville
+grape
+.H 2 "grandfather grandiloquent grandiose grandma grandmother grandnephew"
+grapefruit
+grapevine
+graph
+grapheme
+graphic
+.H 1 "halo halocarbon halogen Halpern Halsey Halstead halt halvah"
+graphite
+grapple
+grasp
+grass
+grassland
+grassy
+grata
+grate
+grateful
+grater
+gratify
+gratis
+gratitude
+gratuitous
+gratuity
+.IND grave
+gravel
+graven
+Graves
+gravestone
+graveyard
+gravid
+gravitate
+gravy
+gray
+graybeard
+grayish
+Grayson
+graywacke
+graze
+grease
+greasy
+great
+greatcoat
+greater
+.H 1 "Han Hancock hand handbag handbook handclasp handcuff Handel handful"
+grebe
+Grecian
+Greece
+greed
+greedy
+.IND Greek
+green
+Greenbelt
+Greenberg
+.H 1 " granary grand grandchild grandchildren granddaughter grandeur"
+Greenblatt
+Greenbriar
+Greene
+greenery
+Greenfield
+greengrocer
+greenhouse
+greenish
+Greenland
+Greensboro
+greensward
+.H 1 "handgun"
+greenware
+Greenwich
+greenwood
+Greer
+greet
+Greg
+gregarious
+Gregg
+Gregory
+.IND gremlin
+grenade
+Grendel
+Grenoble
+Gresham
+Greta
+Gretchen
+grew
+grey
+greyhound
+greylag
+grid
+griddle
+gridiron
+grief
+grievance
+grieve
+grievous
+griffin
+Griffith
+grill
+grille
+grilled
+grillwork
+grim
+.IND grimace
+Grimaldi
+grime
+Grimes
+Grimm
+grin
+grind
+grindstone
+grip
+gripe
+grippe
+grisly
+grist
+gristmill
+Griswold
+grit
+gritty
+grizzle
+grizzly
+groan
+groat
+grocer
+grocery
+groggy
+.IND groin
+grommet
+groom
+groove
+grope
+grosbeak
+gross
+.H 1 "handicapped handicapper handicapping handicraft handicraftsman"
+Grosset
+Grossman
+Grosvenor
+grotesque
+Groton
+ground
+groundsel
+groundskeep
+groundwork
+group
+groupoid
+grout
+grove
+grovel
+Grover
+grow
+growl
+grown
+grownup
+.IND growth
+grub
+grubby
+grudge
+gruesome
+gruff
+grumble
+Grumman
+grunt
+gryphon
+g's
+GSA
+GU
+Guam
+guanidine
+guanine
+guano
+guarantee
+guaranteeing
+guarantor
+guaranty
+guard
+guardhouse
+.IND Guardia
+guardian
+Guatemala
+.IND gubernatorial
+Guelph
+Guenther
+guerdon
+guernsey
+guerrilla
+guess
+guesswork
+guest
+guffaw
+Guggenheim
+Guiana
+guidance
+guide
+guidebook
+guideline
+guidepost
+guiding
+guignol
+guild
+.H 1 "handicraftsmen handiwork handkerchief handle"
+guildhall
+guile
+Guilford
+guillemot
+guillotine
+guilt
+.IND guilty
+guinea
+guise
+guitar
+gules
+gulf
+.H 1 "handleable handlebar handline handmade handmaiden handout"
+gull
+Gullah
+gullet
+gullible
+gully
+gulp
+gum
+gumbo
+gumdrop
+gummy
+gumption
+gumshoe
+gun
+Gunderson
+.IND gunfight
+gunfire
+gunflint
+gunk
+gunky
+gunman
+.IND gunmen
+gunnery
+gunny
+gunplay
+gunpowder
+gunshot
+gunsling
+Gunther
+gurgle
+Gurkha
+guru
+Gus
+gush
+gusset
+gust
+Gustafson
+Gustav
+Gustave
+Gustavus
+gusto
+gusty
+gut
+.H 1 "handset"
+Gutenberg
+Guthrie
+gutsy
+guttural
+.IND guy
+Guyana
+guzzle
+Gwen
+Gwyn
+gym
+gymnasium
+gymnast
+gymnastic
+gymnosperm
+gyp
+gypsite
+gypsum
+gypsy
+gyrate
+gyrfalcon
+gyro
+.IND gyrocompass
+gyroscope
+h
+ha
+Haag
+Haas
+habeas
+haberdashery
+Haberman
+.IND Habib
+habit
+habitant
+habitat
+habitation
+habitual
+habituate
+hacienda
+hack
+hackberry
+Hackett
+hackle
+hackmatack
+.H 1 "handshake handsome handspike handstand handwaving handwrite handwritten"
+hackney
+hackneyed
+hacksaw
+had
+Hadamard
+Haddad
+haddock
+Hades
+Hadley
+hadn't
+Hadrian
+hadron
+hafnium
+.IND Hagen
+Hager
+haggard
+haggle
+Hagstrom
+Hague
+Hahn
+Haifa
+haiku
+hail
+hailstone
+hailstorm
+Haines
+hair
+.IND haircut
+hairdo
+hairpin
+hairy
+Haiti
+Haitian
+Hal
+halcyon
+hale
+Haley
+half
+halfback
+.IND halfhearted
+halfway
+halibut
+halide
+.H 1 "handy handyman handymen Haney Hanford hang hangable hangar"
+Halifax
+halite
+hall
+hallelujah
+Halley
+hallmark
+hallow
+Halloween
+hallucinate
+hallway
+halma
+halo
+halocarbon
+halogen
+Halpern
+Halsey
+Halstead
+halt
+halvah
+halve
+Halverson
+ham
+.IND Hamal
+Hamburg
+hamburger
+Hamilton
+hamlet
+Hamlin
+hammerhead
+hammock
+Hammond
+hamper
+Hampshire
+.IND Hampton
+hamster
+Han
+.H 1 "hangman hangmen hangout hangover hank Hankel Hanley"
+Hancock
+hand
+handbag
+handbook
+handclasp
+handcuff
+Handel
+handful
+handgun
+handhold
+handicap
+handicapped
+.IND handicapper
+handicapping
+handicraft
+handicraftsman
+handicraftsmen
+handiwork
+handkerchief
+handle
+handleable
+handlebar
+handline
+handmade
+handmaiden
+handout
+handset
+handshake
+handsome
+handspike
+handstand
+handwaving
+.H 1 "Hanlon Hanna Hannah Hannibal Hanoi Hanover Hanoverian Hans"
+handwrite
+handwritten
+handy
+handyman
+handymen
+Haney
+.IND Hanford
+hang
+hangable
+hangar
+hangman
+hangmen
+hangout
+hangover
+.IND hank
+Hankel
+Hanley
+Hanlon
+Hanna
+Hannah
+Hannibal
+Hanoi
+Hanover
+Hanoverian
+Hans
+Hansel
+Hansen
+hansom
+Hanson
+Hanukkah
+hap
+.H 1 "Hansel"
+haphazard
+.IND haploid
+haploidy
+haplology
+happen
+happenstance
+happy
+Hapsburg
+harangue
+harass
+Harbin
+harbinger
+Harcourt
+hard
+hardbake
+hardboard
+hardboiled
+hardcopy
+harden
+hardhat
+Hardin
+.H 1 "Hansen hansom Hanson Hanukkah hap haphazard haploid haploidy"
+Harding
+hardscrabble
+hardtack
+hardtop
+hardware
+hardwood
+.IND hardworking
+hardy
+hare
+harelip
+harem
+.IND hark
+Harlan
+Harlem
+Harley
+harm
+harmful
+Harmon
+harmonic
+harmonica
+harmonious
+.H 1 "haplology happen happenstance happy Hapsburg harangue harass Harbin"
+harmony
+harness
+Harold
+harp
+harpoon
+harpsichord
+Harpy
+Harriet
+Harriman
+Harrington
+Harris
+.IND Harrisburg
+Harrison
+harrow
+harry
+harsh
+harshen
+hart
+Hartford
+Hartley
+Hartman
+Harvard
+harvest
+harvestman
+Harvey
+hash
+hashish
+hasn't
+hasp
+hassle
+hast
+haste
+hasten
+Hastings
+hasty
+hat
+hatch
+.IND hatchet
+hatchway
+.IND hate
+hateful
+hater
+Hatfield
+hath
+Hathaway
+hatred
+Hatteras
+Hattie
+Hattiesburg
+Haugen
+haughty
+haul
+haulage
+haunch
+haunt
+Hausdorff
+Havana
+have
+haven
+haven't
+Havilland
+havoc
+haw
+.IND Hawaii
+Hawaiian
+hawk
+Hawkins
+Hawley
+hawthorn
+.H 2 "hammock Hammond hamper Hampshire Hampton hamster"
+Hawthorne
+hay
+Hayden
+Haydn
+Hayes
+hayfield
+Haynes
+Hays
+haystack
+Hayward
+hayward
+hazard
+hazardous
+haze
+hazel
+hazelnut
+hazy
+he
+head
+.IND headache
+.IND headboard
+headdress
+headland
+headlight
+headline
+headmaster
+headphone
+headquarter
+headquarters
+headroom
+headset
+headsman
+headsmen
+headstand
+headstone
+headstrong
+headwall
+headwater
+headway
+headwind
+heady
+heal
+Healey
+health
+healthful
+healthy
+.IND Healy
+heap
+hear
+heard
+hearken
+hearsay
+hearse
+Hearst
+heart
+heartbeat
+heartbreak
+hearten
+heartfelt
+hearth
+hearty
+heat
+heater
+heath
+heathen
+heathenish
+Heathkit
+heave
+.IND heaven
+heavenward
+heavy
+heavyweight
+.IND Hebe
+hebephrenic
+Hebraic
+Hebrew
+Hecate
+hecatomb
+heck
+heckle
+Heckman
+hectic
+hector
+Hecuba
+he'd
+hedge
+hedgehog
+hedonism
+hedonist
+heed
+heel
+heft
+hefty
+Hegelian
+hegemony
+Heidelberg
+heigh
+height
+.IND heighten
+Heine
+Heinrich
+Heinz
+heir
+heiress
+Heisenberg
+held
+Helen
+Helena
+Helene
+Helga
+helical
+helicopter
+heliocentric
+heliotrope
+helium
+helix
+he'll
+.IND hell
+hellbender
+hellebore
+Hellenic
+hellfire
+hellgrammite
+hellish
+.IND hello
+helm
+helmet
+.H 1 "Halverson ham Hamal Hamburg hamburger Hamilton hamlet Hamlin hammerhead"
+Helmholtz
+helmsman
+helmsmen
+Helmut
+help
+helpful
+helpmate
+Helsinki
+Helvetica
+hem
+hematite
+Hemingway
+hemisphere
+hemispheric
+hemlock
+hemoglobin
+hemolytic
+hemorrhage
+hemorrhoid
+hemosiderin
+hemp
+Hempstead
+hen
+.IND henbane
+hence
+henceforth
+henchman
+henchmen
+Henderson
+Hendrick
+Hendricks
+Hendrickson
+henequen
+Henley
+henpeck
+Henri
+Henrietta
+henry
+hepatica
+.IND hepatitis
+Hepburn
+heptane
+her
+Hera
+Heraclitus
+herald
+herb
+Herbert
+Herculean
+.IND Hercules
+herd
+herdsman
+here
+hereabout
+hereafter
+hereby
+hereditary
+heredity
+Hereford
+herein
+hereinabove
+hereinafter
+hereinbelow
+hereof
+heresy
+heretic
+hereto
+heretofore
+hereunder
+hereunto
+herewith
+heritable
+heritage
+Herkimer
+Herman
+.IND Hermann
+hermeneutic
+Hermes
+hermetic
+Hermite
+hermitian
+Hermosa
+Hernandez
+hero
+Herodotus
+heroes
+heroic
+heroin
+.IND heroine
+heroism
+heron
+herpes
+herpetology
+Herr
+herringbone
+Herschel
+herself
+Hershel
+Hershey
+hertz
+Hertzog
+.IND hesitant
+hesitate
+hesitater
+Hesperus
+Hess
+Hesse
+Hessian
+Hester
+heterocyclic
+heterodyne
+heterogamous
+heterogeneity
+heterogeneous
+heterosexual
+heterostructure
+heterozygous
+Hetman
+Hettie
+Hetty
+Heublein
+heuristic
+Heusen
+Heuser
+hew
+Hewett
+Hewitt
+.IND Hewlett
+hewn
+hex
+hexachloride
+hexadecimal
+hexafluoride
+hexagon
+hexagonal
+hexameter
+hexane
+.IND hey
+heyday
+hi
+Hiatt
+hiatus
+Hiawatha
+hibachi
+Hibbard
+hibernate
+Hibernia
+hick
+Hickey
+Hickman
+hickory
+Hicks
+hid
+.IND hidalgo
+hidden
+hide
+hideaway
+hideous
+hideout
+hierarchal
+hierarchic
+hierarchy
+hieratic
+hieroglyphic
+Hieronymus
+hifalutin
+Higgins
+high
+highball
+highboy
+highest
+highfalutin
+highhanded
+highland
+highlight
+highroad
+hightail
+highway
+highwayman
+.IND highwaymen
+hijack
+hijinks
+hike
+hilarious
+hilarity
+Hilbert
+.IND Hildebrand
+hill
+hillbilly
+Hillcrest
+Hillel
+hillman
+hillmen
+hillock
+hillside
+hilltop
+hilly
+hilt
+Hilton
+hilum
+him
+Himalaya
+himself
+hind
+hindmost
+.IND hindrance
+hindsight
+Hindu
+Hinduism
+Hines
+hinge
+Hinman
+hint
+hinterland
+hip
+hippo
+Hippocrates
+Hippocratic
+hippodrome
+hippopotamus
+hippy
+hipster
+Hiram
+hire
+hireling
+Hiroshi
+Hiroshima
+Hirsch
+hirsute
+his
+Hispanic
+.IND hiss
+histamine
+histidine
+histochemic
+.IND histochemistry
+histogram
+histology
+historian
+historic
+historiography
+history
+histrionic
+hit
+Hitachi
+hitch
+Hitchcock
+.H 1 "harbinger"
+hither
+hitherto
+Hitler
+hive
+ho
+hoagie
+Hoagland
+hoagy
+hoar
+hoard
+.IND hoarfrost
+hoarse
+hob
+Hobart
+Hobbes
+hobble
+Hobbs
+hobby
+hobbyhorse
+hobgoblin
+hobo
+Hoboken
+hoc
+hock
+hockey
+hocus
+hodge
+hodgepodge
+Hodges
+Hodgkin
+hoe
+Hoff
+Hoffman
+hog
+hogan
+hogging
+.IND hoi
+.IND Hokan
+Holbrook
+Holcomb
+hold
+holden
+holdout
+holdover
+holdup
+hole
+holeable
+holiday
+Holland
+Hollandaise
+holler
+Hollerith
+Hollingsworth
+Hollister
+hollow
+Holloway
+hollowware
+holly
+hollyhock
+Hollywood
+Holm
+Holman
+.IND Holmdel
+Holmes
+holmium
+holocaust
+Holocene
+hologram
+holography
+Holst
+Holstein
+holster
+holt
+Holyoke
+.IND holystone
+.INDP
+inject injudicious Injun injunct injunction injure injurious injury
+injustice ink inkling inlaid inland inlay inlet Inman inmate inn innards
+innate inner innermost innkeeper innocent innocuous innovate innuendo
+innumerable inoculate inoffensive inoperable inoperative inopportune
+inordinate inorganic input inputting inquest inquire inquiry inquisition
+.INITI B ind-data3
+.H 1 "halve"
+.IND granary
+grand
+grandchild
+grandchildren
+granddaughter
+grandeur
+grandfather
+grandiloquent
+grandiose
+grandma
+grandmother
+.IND grandnephew
+grandniece
+grandpa
+grandparent
+grandson
+grandstand
+granite
+granitic
+granny
+granola
+grant
+grantee
+grantor
+granular
+.IND granulate
+granule
+Granville
+grape
+.H 2 "grandfather grandiloquent grandiose grandma grandmother grandnephew"
+grapefruit
+grapevine
+graph
+grapheme
+graphic
+.H 1 "halo halocarbon halogen Halpern Halsey Halstead halt halvah"
+graphite
+grapple
+grasp
+grass
+grassland
+grassy
+grata
+grate
+grateful
+grater
+gratify
+gratis
+gratitude
+gratuitous
+gratuity
+.IND grave
+gravel
+graven
+Graves
+gravestone
+graveyard
+gravid
+gravitate
+gravy
+gray
+graybeard
+grayish
+Grayson
+graywacke
+graze
+grease
+greasy
+great
+greatcoat
+greater
+.H 1 "Han Hancock hand handbag handbook handclasp handcuff Handel handful"
+grebe
+Grecian
+Greece
+greed
+greedy
+.IND Greek
+green
+Greenbelt
+Greenberg
+.H 1 " granary grand grandchild grandchildren granddaughter grandeur"
+Greenblatt
+Greenbriar
+Greene
+greenery
+Greenfield
+greengrocer
+greenhouse
+greenish
+Greenland
+Greensboro
+greensward
+.H 1 "handgun"
+greenware
+Greenwich
+greenwood
+Greer
+greet
+Greg
+gregarious
+Gregg
+Gregory
+.IND gremlin
+grenade
+Grendel
+Grenoble
+Gresham
+Greta
+Gretchen
+grew
+grey
+greyhound
+greylag
+grid
+griddle
+gridiron
+grief
+grievance
+grieve
+grievous
+griffin
+Griffith
+grill
+grille
+grilled
+grillwork
+grim
+.IND grimace
+Grimaldi
+grime
+Grimes
+Grimm
+grin
+grind
+grindstone
+grip
+gripe
+grippe
+grisly
+grist
+gristmill
+Griswold
+grit
+gritty
+grizzle
+grizzly
+groan
+groat
+grocer
+grocery
+groggy
+.IND groin
+grommet
+groom
+groove
+grope
+grosbeak
+gross
+.H 1 "handicapped handicapper handicapping handicraft handicraftsman"
+Grosset
+Grossman
+Grosvenor
+grotesque
+Groton
+ground
+groundsel
+groundskeep
+groundwork
+group
+groupoid
+grout
+grove
+grovel
+Grover
+grow
+growl
+grown
+grownup
+.IND growth
+grub
+grubby
+grudge
+gruesome
+gruff
+grumble
+Grumman
+grunt
+gryphon
+g's
+GSA
+GU
+Guam
+guanidine
+guanine
+guano
+guarantee
+guaranteeing
+guarantor
+guaranty
+guard
+guardhouse
+.IND Guardia
+guardian
+Guatemala
+.IND gubernatorial
+Guelph
+Guenther
+guerdon
+guernsey
+guerrilla
+guess
+guesswork
+guest
+guffaw
+Guggenheim
+Guiana
+guidance
+guide
+guidebook
+guideline
+guidepost
+guiding
+guignol
+guild
+.H 1 "handicraftsmen handiwork handkerchief handle"
+guildhall
+guile
+Guilford
+guillemot
+guillotine
+guilt
+.IND guilty
+guinea
+guise
+guitar
+gules
+gulf
+.H 1 "handleable handlebar handline handmade handmaiden handout"
+gull
+Gullah
+gullet
+gullible
+gully
+gulp
+gum
+gumbo
+gumdrop
+gummy
+gumption
+gumshoe
+gun
+Gunderson
+.IND gunfight
+gunfire
+gunflint
+gunk
+gunky
+gunman
+.IND gunmen
+gunnery
+gunny
+gunplay
+gunpowder
+gunshot
+gunsling
+Gunther
+gurgle
+Gurkha
+guru
+Gus
+gush
+gusset
+gust
+Gustafson
+Gustav
+Gustave
+Gustavus
+gusto
+gusty
+gut
+.H 1 "handset"
+Gutenberg
+Guthrie
+gutsy
+guttural
+.IND guy
+Guyana
+guzzle
+Gwen
+Gwyn
+gym
+gymnasium
+gymnast
+gymnastic
+gymnosperm
+gyp
+gypsite
+gypsum
+gypsy
+gyrate
+gyrfalcon
+gyro
+.IND gyrocompass
+gyroscope
+h
+ha
+Haag
+Haas
+habeas
+haberdashery
+Haberman
+.IND Habib
+habit
+habitant
+habitat
+habitation
+habitual
+habituate
+hacienda
+hack
+hackberry
+Hackett
+hackle
+hackmatack
+.H 1 "handshake handsome handspike handstand handwaving handwrite handwritten"
+hackney
+hackneyed
+hacksaw
+had
+Hadamard
+Haddad
+haddock
+Hades
+Hadley
+hadn't
+Hadrian
+hadron
+hafnium
+.IND Hagen
+Hager
+haggard
+haggle
+Hagstrom
+Hague
+Hahn
+Haifa
+haiku
+hail
+hailstone
+hailstorm
+Haines
+hair
+.IND haircut
+hairdo
+hairpin
+hairy
+Haiti
+Haitian
+Hal
+halcyon
+hale
+Haley
+half
+halfback
+.IND halfhearted
+halfway
+halibut
+halide
+.H 1 "handy handyman handymen Haney Hanford hang hangable hangar"
+Halifax
+halite
+hall
+hallelujah
+Halley
+hallmark
+hallow
+Halloween
+hallucinate
+hallway
+halma
+halo
+halocarbon
+halogen
+Halpern
+Halsey
+Halstead
+halt
+halvah
+halve
+Halverson
+ham
+.IND Hamal
+Hamburg
+hamburger
+Hamilton
+hamlet
+Hamlin
+hammerhead
+hammock
+Hammond
+hamper
+Hampshire
+.IND Hampton
+hamster
+Han
+.H 1 "hangman hangmen hangout hangover hank Hankel Hanley"
+Hancock
+hand
+handbag
+handbook
+handclasp
+handcuff
+Handel
+handful
+handgun
+handhold
+handicap
+handicapped
+.IND handicapper
+handicapping
+handicraft
+handicraftsman
+handicraftsmen
+handiwork
+handkerchief
+handle
+handleable
+handlebar
+handline
+handmade
+handmaiden
+handout
+handset
+handshake
+handsome
+handspike
+handstand
+handwaving
+.H 1 "Hanlon Hanna Hannah Hannibal Hanoi Hanover Hanoverian Hans"
+handwrite
+handwritten
+handy
+handyman
+handymen
+Haney
+.IND Hanford
+hang
+hangable
+hangar
+hangman
+hangmen
+hangout
+hangover
+.IND hank
+Hankel
+Hanley
+Hanlon
+Hanna
+Hannah
+Hannibal
+Hanoi
+Hanover
+Hanoverian
+Hans
+Hansel
+Hansen
+hansom
+Hanson
+Hanukkah
+hap
+.H 1 "Hansel"
+haphazard
+.IND haploid
+haploidy
+haplology
+happen
+happenstance
+happy
+Hapsburg
+harangue
+harass
+Harbin
+harbinger
+Harcourt
+hard
+hardbake
+hardboard
+hardboiled
+hardcopy
+harden
+hardhat
+Hardin
+.H 1 "Hansen hansom Hanson Hanukkah hap haphazard haploid haploidy"
+Harding
+hardscrabble
+hardtack
+hardtop
+hardware
+hardwood
+.IND hardworking
+hardy
+hare
+harelip
+harem
+.IND hark
+Harlan
+Harlem
+Harley
+harm
+harmful
+Harmon
+harmonic
+harmonica
+harmonious
+.H 1 "haplology happen happenstance happy Hapsburg harangue harass Harbin"
+harmony
+harness
+Harold
+harp
+harpoon
+harpsichord
+Harpy
+Harriet
+Harriman
+Harrington
+Harris
+.IND Harrisburg
+Harrison
+harrow
+harry
+harsh
+harshen
+hart
+Hartford
+Hartley
+Hartman
+Harvard
+harvest
+harvestman
+Harvey
+hash
+hashish
+hasn't
+hasp
+hassle
+hast
+haste
+hasten
+Hastings
+hasty
+hat
+hatch
+.IND hatchet
+hatchway
+.IND hate
+hateful
+hater
+Hatfield
+hath
+Hathaway
+hatred
+Hatteras
+Hattie
+Hattiesburg
+Haugen
+haughty
+haul
+haulage
+haunch
+haunt
+Hausdorff
+Havana
+have
+haven
+haven't
+Havilland
+havoc
+haw
+.IND Hawaii
+Hawaiian
+hawk
+Hawkins
+Hawley
+hawthorn
+.H 2 "hammock Hammond hamper Hampshire Hampton hamster"
+Hawthorne
+hay
+Hayden
+Haydn
+Hayes
+hayfield
+Haynes
+Hays
+haystack
+Hayward
+hayward
+hazard
+hazardous
+haze
+hazel
+hazelnut
+hazy
+he
+head
+.IND headache
+.IND headboard
+headdress
+headland
+headlight
+headline
+headmaster
+headphone
+headquarter
+headquarters
+headroom
+headset
+headsman
+headsmen
+headstand
+headstone
+headstrong
+headwall
+headwater
+headway
+headwind
+heady
+heal
+Healey
+health
+healthful
+healthy
+.IND Healy
+heap
+hear
+heard
+hearken
+hearsay
+hearse
+Hearst
+heart
+heartbeat
+heartbreak
+hearten
+heartfelt
+hearth
+hearty
+heat
+heater
+heath
+heathen
+heathenish
+Heathkit
+heave
+.IND heaven
+heavenward
+heavy
+heavyweight
+.IND Hebe
+hebephrenic
+Hebraic
+Hebrew
+Hecate
+hecatomb
+heck
+heckle
+Heckman
+hectic
+hector
+Hecuba
+he'd
+hedge
+hedgehog
+hedonism
+hedonist
+heed
+heel
+heft
+hefty
+Hegelian
+hegemony
+Heidelberg
+heigh
+height
+.IND heighten
+Heine
+Heinrich
+Heinz
+heir
+heiress
+Heisenberg
+held
+Helen
+Helena
+Helene
+Helga
+helical
+helicopter
+heliocentric
+heliotrope
+helium
+helix
+he'll
+.IND hell
+hellbender
+hellebore
+Hellenic
+hellfire
+hellgrammite
+hellish
+.IND hello
+helm
+helmet
+.H 1 "Halverson ham Hamal Hamburg hamburger Hamilton hamlet Hamlin hammerhead"
+Helmholtz
+helmsman
+helmsmen
+Helmut
+help
+helpful
+helpmate
+Helsinki
+Helvetica
+hem
+hematite
+Hemingway
+hemisphere
+hemispheric
+hemlock
+hemoglobin
+hemolytic
+hemorrhage
+hemorrhoid
+hemosiderin
+hemp
+Hempstead
+hen
+.IND henbane
+hence
+henceforth
+henchman
+henchmen
+Henderson
+Hendrick
+Hendricks
+Hendrickson
+henequen
+Henley
+henpeck
+Henri
+Henrietta
+henry
+hepatica
+.IND hepatitis
+Hepburn
+heptane
+her
+Hera
+Heraclitus
+herald
+herb
+Herbert
+Herculean
+.IND Hercules
+herd
+herdsman
+here
+hereabout
+hereafter
+hereby
+hereditary
+heredity
+Hereford
+herein
+hereinabove
+hereinafter
+hereinbelow
+hereof
+heresy
+heretic
+hereto
+heretofore
+hereunder
+hereunto
+herewith
+heritable
+heritage
+Herkimer
+Herman
+.IND Hermann
+hermeneutic
+Hermes
+hermetic
+Hermite
+hermitian
+Hermosa
+Hernandez
+hero
+Herodotus
+heroes
+heroic
+heroin
+.IND heroine
+heroism
+heron
+herpes
+herpetology
+Herr
+herringbone
+Herschel
+herself
+Hershel
+Hershey
+hertz
+Hertzog
+.IND hesitant
+hesitate
+hesitater
+Hesperus
+Hess
+Hesse
+Hessian
+Hester
+heterocyclic
+heterodyne
+heterogamous
+heterogeneity
+heterogeneous
+heterosexual
+heterostructure
+heterozygous
+Hetman
+Hettie
+Hetty
+Heublein
+heuristic
+Heusen
+Heuser
+hew
+Hewett
+Hewitt
+.IND Hewlett
+hewn
+hex
+hexachloride
+hexadecimal
+hexafluoride
+hexagon
+hexagonal
+hexameter
+hexane
+.IND hey
+heyday
+hi
+Hiatt
+hiatus
+Hiawatha
+hibachi
+Hibbard
+hibernate
+Hibernia
+hick
+Hickey
+Hickman
+hickory
+Hicks
+hid
+.IND hidalgo
+hidden
+hide
+hideaway
+hideous
+hideout
+hierarchal
+hierarchic
+hierarchy
+hieratic
+hieroglyphic
+Hieronymus
+hifalutin
+Higgins
+high
+highball
+highboy
+highest
+highfalutin
+highhanded
+highland
+highlight
+highroad
+hightail
+highway
+highwayman
+.IND highwaymen
+hijack
+hijinks
+hike
+hilarious
+hilarity
+Hilbert
+.IND Hildebrand
+hill
+hillbilly
+Hillcrest
+Hillel
+hillman
+hillmen
+hillock
+hillside
+hilltop
+hilly
+hilt
+Hilton
+hilum
+him
+Himalaya
+himself
+hind
+hindmost
+.IND hindrance
+hindsight
+Hindu
+Hinduism
+Hines
+hinge
+Hinman
+hint
+hinterland
+hip
+hippo
+Hippocrates
+Hippocratic
+hippodrome
+hippopotamus
+hippy
+hipster
+Hiram
+hire
+hireling
+Hiroshi
+Hiroshima
+Hirsch
+hirsute
+his
+Hispanic
+.IND hiss
+histamine
+histidine
+histochemic
+.IND histochemistry
+histogram
+histology
+historian
+historic
+historiography
+history
+histrionic
+hit
+Hitachi
+hitch
+Hitchcock
+.H 1 "harbinger"
+hither
+hitherto
+Hitler
+hive
+ho
+hoagie
+Hoagland
+hoagy
+hoar
+hoard
+.IND hoarfrost
+hoarse
+hob
+Hobart
+Hobbes
+hobble
+Hobbs
+hobby
+hobbyhorse
+hobgoblin
+hobo
+Hoboken
+hoc
+hock
+hockey
+hocus
+hodge
+hodgepodge
+Hodges
+Hodgkin
+hoe
+Hoff
+Hoffman
+hog
+hogan
+hogging
+.IND hoi
+.IND Hokan
+Holbrook
+Holcomb
+hold
+holden
+holdout
+holdover
+holdup
+hole
+holeable
+holiday
+Holland
+Hollandaise
+holler
+Hollerith
+Hollingsworth
+Hollister
+hollow
+Holloway
+hollowware
+holly
+hollyhock
+Hollywood
+Holm
+Holman
+.IND Holmdel
+Holmes
+holmium
+holocaust
+Holocene
+hologram
+holography
+Holst
+Holstein
+holster
+holt
+Holyoke
+.IND holystone
+.INDP
+inject injudicious Injun injunct injunction injure injurious injury
+injustice ink inkling inlaid inland inlay inlet Inman inmate inn innards
+innate inner innermost innkeeper innocent innocuous innovate innuendo
+innumerable inoculate inoffensive inoperable inoperative inopportune
+inordinate inorganic input inputting inquest inquire inquiry inquisition
+.INITI B ind-data4 foo
+.H 1 "halve"
+.IND granary
+grand
+grandchild
+grandchildren
+granddaughter
+grandeur
+grandfather
+grandiloquent
+grandiose
+grandma
+grandmother
+.IND grandnephew
+grandniece
+grandpa
+grandparent
+grandson
+grandstand
+granite
+granitic
+granny
+granola
+grant
+grantee
+grantor
+granular
+.IND granulate
+granule
+Granville
+grape
+.H 2 "grandfather grandiloquent grandiose grandma grandmother grandnephew"
+grapefruit
+grapevine
+graph
+grapheme
+graphic
+.H 1 "halo halocarbon halogen Halpern Halsey Halstead halt halvah"
+graphite
+grapple
+grasp
+grass
+grassland
+grassy
+grata
+grate
+grateful
+grater
+gratify
+gratis
+gratitude
+gratuitous
+gratuity
+.IND grave
+gravel
+graven
+Graves
+gravestone
+graveyard
+gravid
+gravitate
+gravy
+gray
+graybeard
+grayish
+Grayson
+graywacke
+graze
+grease
+greasy
+great
+greatcoat
+greater
+.H 1 "Han Hancock hand handbag handbook handclasp handcuff Handel handful"
+grebe
+Grecian
+Greece
+greed
+greedy
+.IND Greek
+green
+Greenbelt
+Greenberg
+.H 1 " granary grand grandchild grandchildren granddaughter grandeur"
+Greenblatt
+Greenbriar
+Greene
+greenery
+Greenfield
+greengrocer
+greenhouse
+greenish
+Greenland
+Greensboro
+greensward
+.H 1 "handgun"
+greenware
+Greenwich
+greenwood
+Greer
+greet
+Greg
+gregarious
+Gregg
+Gregory
+.IND gremlin
+grenade
+Grendel
+Grenoble
+Gresham
+Greta
+Gretchen
+grew
+grey
+greyhound
+greylag
+grid
+griddle
+gridiron
+grief
+grievance
+grieve
+grievous
+griffin
+Griffith
+grill
+grille
+grilled
+grillwork
+grim
+.IND grimace
+Grimaldi
+grime
+Grimes
+Grimm
+grin
+grind
+grindstone
+grip
+gripe
+grippe
+grisly
+grist
+gristmill
+Griswold
+grit
+gritty
+grizzle
+grizzly
+groan
+groat
+grocer
+grocery
+groggy
+.IND groin
+grommet
+groom
+groove
+grope
+grosbeak
+gross
+.H 1 "handicapped handicapper handicapping handicraft handicraftsman"
+Grosset
+Grossman
+Grosvenor
+grotesque
+Groton
+ground
+groundsel
+groundskeep
+groundwork
+group
+groupoid
+grout
+grove
+grovel
+Grover
+grow
+growl
+grown
+grownup
+.IND growth
+grub
+grubby
+grudge
+gruesome
+gruff
+grumble
+Grumman
+grunt
+gryphon
+g's
+GSA
+GU
+Guam
+guanidine
+guanine
+guano
+guarantee
+guaranteeing
+guarantor
+guaranty
+guard
+guardhouse
+.IND Guardia
+guardian
+Guatemala
+.IND gubernatorial
+Guelph
+Guenther
+guerdon
+guernsey
+guerrilla
+guess
+guesswork
+guest
+guffaw
+Guggenheim
+Guiana
+guidance
+guide
+guidebook
+guideline
+guidepost
+guiding
+guignol
+guild
+.H 1 "handicraftsmen handiwork handkerchief handle"
+guildhall
+guile
+Guilford
+guillemot
+guillotine
+guilt
+.IND guilty
+guinea
+guise
+guitar
+gules
+gulf
+.H 1 "handleable handlebar handline handmade handmaiden handout"
+gull
+Gullah
+gullet
+gullible
+gully
+gulp
+gum
+gumbo
+gumdrop
+gummy
+gumption
+gumshoe
+gun
+Gunderson
+.IND gunfight
+gunfire
+gunflint
+gunk
+gunky
+gunman
+.IND gunmen
+gunnery
+gunny
+gunplay
+gunpowder
+gunshot
+gunsling
+Gunther
+gurgle
+Gurkha
+guru
+Gus
+gush
+gusset
+gust
+Gustafson
+Gustav
+Gustave
+Gustavus
+gusto
+gusty
+gut
+.H 1 "handset"
+Gutenberg
+Guthrie
+gutsy
+guttural
+.IND guy
+Guyana
+guzzle
+Gwen
+Gwyn
+gym
+gymnasium
+gymnast
+gymnastic
+gymnosperm
+gyp
+gypsite
+gypsum
+gypsy
+gyrate
+gyrfalcon
+gyro
+.IND gyrocompass
+gyroscope
+h
+ha
+Haag
+Haas
+habeas
+haberdashery
+Haberman
+.IND Habib
+habit
+habitant
+habitat
+habitation
+habitual
+habituate
+hacienda
+hack
+hackberry
+Hackett
+hackle
+hackmatack
+.H 1 "handshake handsome handspike handstand handwaving handwrite handwritten"
+hackney
+hackneyed
+hacksaw
+had
+Hadamard
+Haddad
+haddock
+Hades
+Hadley
+hadn't
+Hadrian
+hadron
+hafnium
+.IND Hagen
+Hager
+haggard
+haggle
+Hagstrom
+Hague
+Hahn
+Haifa
+haiku
+hail
+hailstone
+hailstorm
+Haines
+hair
+.IND haircut
+hairdo
+hairpin
+hairy
+Haiti
+Haitian
+Hal
+halcyon
+hale
+Haley
+half
+halfback
+.IND halfhearted
+halfway
+halibut
+halide
+.H 1 "handy handyman handymen Haney Hanford hang hangable hangar"
+Halifax
+halite
+hall
+hallelujah
+Halley
+hallmark
+hallow
+Halloween
+hallucinate
+hallway
+halma
+halo
+halocarbon
+halogen
+Halpern
+Halsey
+Halstead
+halt
+halvah
+halve
+Halverson
+ham
+.IND Hamal
+Hamburg
+hamburger
+Hamilton
+hamlet
+Hamlin
+hammerhead
+hammock
+Hammond
+hamper
+Hampshire
+.IND Hampton
+hamster
+Han
+.H 1 "hangman hangmen hangout hangover hank Hankel Hanley"
+Hancock
+hand
+handbag
+handbook
+handclasp
+handcuff
+Handel
+handful
+handgun
+handhold
+handicap
+handicapped
+.IND handicapper
+handicapping
+handicraft
+handicraftsman
+handicraftsmen
+handiwork
+handkerchief
+handle
+handleable
+handlebar
+handline
+handmade
+handmaiden
+handout
+handset
+handshake
+handsome
+handspike
+handstand
+handwaving
+.H 1 "Hanlon Hanna Hannah Hannibal Hanoi Hanover Hanoverian Hans"
+handwrite
+handwritten
+handy
+handyman
+handymen
+Haney
+.IND Hanford
+hang
+hangable
+hangar
+hangman
+hangmen
+hangout
+hangover
+.IND hank
+Hankel
+Hanley
+Hanlon
+Hanna
+Hannah
+Hannibal
+Hanoi
+Hanover
+Hanoverian
+Hans
+Hansel
+Hansen
+hansom
+Hanson
+Hanukkah
+hap
+.H 1 "Hansel"
+haphazard
+.IND haploid
+haploidy
+haplology
+happen
+happenstance
+happy
+Hapsburg
+harangue
+harass
+Harbin
+harbinger
+Harcourt
+hard
+hardbake
+hardboard
+hardboiled
+hardcopy
+harden
+hardhat
+Hardin
+.H 1 "Hansen hansom Hanson Hanukkah hap haphazard haploid haploidy"
+Harding
+hardscrabble
+hardtack
+hardtop
+hardware
+hardwood
+.IND hardworking
+hardy
+hare
+harelip
+harem
+.IND hark
+Harlan
+Harlem
+Harley
+harm
+harmful
+Harmon
+harmonic
+harmonica
+harmonious
+.H 1 "haplology happen happenstance happy Hapsburg harangue harass Harbin"
+harmony
+harness
+Harold
+harp
+harpoon
+harpsichord
+Harpy
+Harriet
+Harriman
+Harrington
+Harris
+.IND Harrisburg
+Harrison
+harrow
+harry
+harsh
+harshen
+hart
+Hartford
+Hartley
+Hartman
+Harvard
+harvest
+harvestman
+Harvey
+hash
+hashish
+hasn't
+hasp
+hassle
+hast
+haste
+hasten
+Hastings
+hasty
+hat
+hatch
+.IND hatchet
+hatchway
+.IND hate
+hateful
+hater
+Hatfield
+hath
+Hathaway
+hatred
+Hatteras
+Hattie
+Hattiesburg
+Haugen
+haughty
+haul
+haulage
+haunch
+haunt
+Hausdorff
+Havana
+have
+haven
+haven't
+Havilland
+havoc
+haw
+.IND Hawaii
+Hawaiian
+hawk
+Hawkins
+Hawley
+hawthorn
+.H 2 "hammock Hammond hamper Hampshire Hampton hamster"
+Hawthorne
+hay
+Hayden
+Haydn
+Hayes
+hayfield
+Haynes
+Hays
+haystack
+Hayward
+hayward
+hazard
+hazardous
+haze
+hazel
+hazelnut
+hazy
+he
+head
+.IND headache
+.IND headboard
+headdress
+headland
+headlight
+headline
+headmaster
+headphone
+headquarter
+headquarters
+headroom
+headset
+headsman
+headsmen
+headstand
+headstone
+headstrong
+headwall
+headwater
+headway
+headwind
+heady
+heal
+Healey
+health
+healthful
+healthy
+.IND Healy
+heap
+hear
+heard
+hearken
+hearsay
+hearse
+Hearst
+heart
+heartbeat
+heartbreak
+hearten
+heartfelt
+hearth
+hearty
+heat
+heater
+heath
+heathen
+heathenish
+Heathkit
+heave
+.IND heaven
+heavenward
+heavy
+heavyweight
+.IND Hebe
+hebephrenic
+Hebraic
+Hebrew
+Hecate
+hecatomb
+heck
+heckle
+Heckman
+hectic
+hector
+Hecuba
+he'd
+hedge
+hedgehog
+hedonism
+hedonist
+heed
+heel
+heft
+hefty
+Hegelian
+hegemony
+Heidelberg
+heigh
+height
+.IND heighten
+Heine
+Heinrich
+Heinz
+heir
+heiress
+Heisenberg
+held
+Helen
+Helena
+Helene
+Helga
+helical
+helicopter
+heliocentric
+heliotrope
+helium
+helix
+he'll
+.IND hell
+hellbender
+hellebore
+Hellenic
+hellfire
+hellgrammite
+hellish
+.IND hello
+helm
+helmet
+.H 1 "Halverson ham Hamal Hamburg hamburger Hamilton hamlet Hamlin hammerhead"
+Helmholtz
+helmsman
+helmsmen
+Helmut
+help
+helpful
+helpmate
+Helsinki
+Helvetica
+hem
+hematite
+Hemingway
+hemisphere
+hemispheric
+hemlock
+hemoglobin
+hemolytic
+hemorrhage
+hemorrhoid
+hemosiderin
+hemp
+Hempstead
+hen
+.IND henbane
+hence
+henceforth
+henchman
+henchmen
+Henderson
+Hendrick
+Hendricks
+Hendrickson
+henequen
+Henley
+henpeck
+Henri
+Henrietta
+henry
+hepatica
+.IND hepatitis
+Hepburn
+heptane
+her
+Hera
+Heraclitus
+herald
+herb
+Herbert
+Herculean
+.IND Hercules
+herd
+herdsman
+here
+hereabout
+hereafter
+hereby
+hereditary
+heredity
+Hereford
+herein
+hereinabove
+hereinafter
+hereinbelow
+hereof
+heresy
+heretic
+hereto
+heretofore
+hereunder
+hereunto
+herewith
+heritable
+heritage
+Herkimer
+Herman
+.IND Hermann
+hermeneutic
+Hermes
+hermetic
+Hermite
+hermitian
+Hermosa
+Hernandez
+hero
+Herodotus
+heroes
+heroic
+heroin
+.IND heroine
+heroism
+heron
+herpes
+herpetology
+Herr
+herringbone
+Herschel
+herself
+Hershel
+Hershey
+hertz
+Hertzog
+.IND hesitant
+hesitate
+hesitater
+Hesperus
+Hess
+Hesse
+Hessian
+Hester
+heterocyclic
+heterodyne
+heterogamous
+heterogeneity
+heterogeneous
+heterosexual
+heterostructure
+heterozygous
+Hetman
+Hettie
+Hetty
+Heublein
+heuristic
+Heusen
+Heuser
+hew
+Hewett
+Hewitt
+.IND Hewlett
+hewn
+hex
+hexachloride
+hexadecimal
+hexafluoride
+hexagon
+hexagonal
+hexameter
+hexane
+.IND hey
+heyday
+hi
+Hiatt
+hiatus
+Hiawatha
+hibachi
+Hibbard
+hibernate
+Hibernia
+hick
+Hickey
+Hickman
+hickory
+Hicks
+hid
+.IND hidalgo
+hidden
+hide
+hideaway
+hideous
+hideout
+hierarchal
+hierarchic
+hierarchy
+hieratic
+hieroglyphic
+Hieronymus
+hifalutin
+Higgins
+high
+highball
+highboy
+highest
+highfalutin
+highhanded
+highland
+highlight
+highroad
+hightail
+highway
+highwayman
+.IND highwaymen
+hijack
+hijinks
+hike
+hilarious
+hilarity
+Hilbert
+.IND Hildebrand
+hill
+hillbilly
+Hillcrest
+Hillel
+hillman
+hillmen
+hillock
+hillside
+hilltop
+hilly
+hilt
+Hilton
+hilum
+him
+Himalaya
+himself
+hind
+hindmost
+.IND hindrance
+hindsight
+Hindu
+Hinduism
+Hines
+hinge
+Hinman
+hint
+hinterland
+hip
+hippo
+Hippocrates
+Hippocratic
+hippodrome
+hippopotamus
+hippy
+hipster
+Hiram
+hire
+hireling
+Hiroshi
+Hiroshima
+Hirsch
+hirsute
+his
+Hispanic
+.IND hiss
+histamine
+histidine
+histochemic
+.IND histochemistry
+histogram
+histology
+historian
+historic
+historiography
+history
+histrionic
+hit
+Hitachi
+hitch
+Hitchcock
+.H 1 "harbinger"
+hither
+hitherto
+Hitler
+hive
+ho
+hoagie
+Hoagland
+hoagy
+hoar
+hoard
+.IND hoarfrost
+hoarse
+hob
+Hobart
+Hobbes
+hobble
+Hobbs
+hobby
+hobbyhorse
+hobgoblin
+hobo
+Hoboken
+hoc
+hock
+hockey
+hocus
+hodge
+hodgepodge
+Hodges
+Hodgkin
+hoe
+Hoff
+Hoffman
+hog
+hogan
+hogging
+.IND hoi
+.IND Hokan
+Holbrook
+Holcomb
+hold
+holden
+holdout
+holdover
+holdup
+hole
+holeable
+holiday
+Holland
+Hollandaise
+holler
+Hollerith
+Hollingsworth
+Hollister
+hollow
+Holloway
+hollowware
+holly
+hollyhock
+Hollywood
+Holm
+Holman
+.IND Holmdel
+Holmes
+holmium
+holocaust
+Holocene
+hologram
+holography
+Holst
+Holstein
+holster
+holt
+Holyoke
+.IND holystone
+.INDP
+inject injudicious Injun injunct injunction injure injurious injury
+injustice ink inkling inlaid inland inlay inlet Inman inmate inn innards
+innate inner innermost innkeeper innocent innocuous innovate innuendo
+innumerable inoculate inoffensive inoperable inoperative inopportune
+inordinate inorganic input inputting inquest inquire inquiry inquisition
diff --git a/contrib/mm/examples/LT b/contrib/mm/examples/LT
new file mode 100644
index 00000000..cf063897
--- /dev/null
+++ b/contrib/mm/examples/LT
@@ -0,0 +1,1058 @@
+.ND 1994-10-26
+.\" .WA "Nisse Nilsson" notitle
+.\" .WE
+.WA "Sven Olsson" title
+Return address
+Street
+City, State Zip Code
+Text
+.WE
+.IA "Inside address" title
+Addressee name XXXXXXX
+Title XXXXXXXXXXXXXXX
+Company xxxxxxxxxxxx
+Street xxxxxxxxxxxxxx
+City, State Zip Code
+Text xxxxxxxxxxxxxxxxxx
+.IE
+.LO CN
+.LO RN "referens"
+.LO AT Attention
+.LO SA "Hej hopp"
+.LO SJ "Subject line"
+.LT BL
+hepp
+granary
+grand
+grandchild
+grandchildren
+granddaughter
+grandeur
+grandfather
+grandiloquent
+grandiose
+grandma
+grandmother
+grandnephew
+grandniece
+grandpa
+grandparent
+grandson
+grandstand
+granite
+granitic
+granny
+granola
+grant
+grantee
+grantor
+granular
+granulate
+granule
+Granville
+grape
+grapefruit
+grapevine
+graph
+grapheme
+graphic
+graphite
+grapple
+grasp
+grass
+grassland
+grassy
+grata
+grate
+grateful
+grater
+gratify
+gratis
+gratitude
+gratuitous
+gratuity
+grave
+gravel
+graven
+Graves
+gravestone
+graveyard
+gravid
+gravitate
+gravy
+gray
+graybeard
+grayish
+Grayson
+graywacke
+graze
+grease
+greasy
+great
+greatcoat
+greater
+grebe
+Grecian
+Greece
+greed
+greedy
+Greek
+green
+Greenbelt
+Greenberg
+Greenblatt
+Greenbriar
+Greene
+greenery
+Greenfield
+greengrocer
+greenhouse
+greenish
+Greenland
+Greensboro
+greensward
+greenware
+Greenwich
+greenwood
+Greer
+greet
+Greg
+gregarious
+Gregg
+Gregory
+gremlin
+grenade
+Grendel
+Grenoble
+Gresham
+Greta
+Gretchen
+grew
+grey
+greyhound
+greylag
+grid
+griddle
+gridiron
+grief
+grievance
+grieve
+grievous
+griffin
+Griffith
+grill
+grille
+grilled
+grillwork
+grim
+grimace
+Grimaldi
+grime
+Grimes
+Grimm
+grin
+grind
+grindstone
+grip
+.P
+gripe
+grippe
+grisly
+grist
+gristmill
+Griswold
+grit
+gritty
+grizzle
+grizzly
+groan
+groat
+grocer
+grocery
+groggy
+groin
+grommet
+groom
+groove
+grope
+grosbeak
+gross
+Grosset
+Grossman
+Grosvenor
+grotesque
+Groton
+ground
+groundsel
+groundskeep
+groundwork
+group
+groupoid
+grout
+grove
+grovel
+Grover
+grow
+growl
+grown
+grownup
+growth
+grub
+grubby
+grudge
+gruesome
+gruff
+grumble
+Grumman
+grunt
+gryphon
+g's
+GSA
+GU
+Guam
+guanidine
+guanine
+guano
+guarantee
+guaranteeing
+guarantor
+guaranty
+guard
+guardhouse
+Guardia
+guardian
+Guatemala
+gubernatorial
+Guelph
+Guenther
+guerdon
+guernsey
+guerrilla
+guess
+guesswork
+guest
+guffaw
+Guggenheim
+Guiana
+guidance
+guide
+guidebook
+guideline
+guidepost
+guiding
+guignol
+guild
+guildhall
+guile
+Guilford
+guillemot
+guillotine
+guilt
+guilty
+guinea
+guise
+guitar
+gules
+gulf
+gull
+Gullah
+gullet
+gullible
+gully
+gulp
+gum
+gumbo
+gumdrop
+gummy
+gumption
+gumshoe
+gun
+Gunderson
+gunfight
+gunfire
+gunflint
+gunk
+gunky
+gunman
+gunmen
+gunnery
+gunny
+gunplay
+gunpowder
+gunshot
+gunsling
+Gunther
+gurgle
+Gurkha
+guru
+Gus
+gush
+gusset
+gust
+Gustafson
+Gustav
+Gustave
+Gustavus
+gusto
+gusty
+gut
+Gutenberg
+Guthrie
+gutsy
+guttural
+guy
+.P
+Guyana
+guzzle
+Gwen
+Gwyn
+gym
+gymnasium
+gymnast
+gymnastic
+gymnosperm
+gyp
+gypsite
+gypsum
+gypsy
+gyrate
+gyrfalcon
+gyro
+gyrocompass
+gyroscope
+h
+ha
+Haag
+Haas
+habeas
+haberdashery
+Haberman
+Habib
+habit
+habitant
+habitat
+habitation
+habitual
+habituate
+hacienda
+hack
+hackberry
+Hackett
+hackle
+hackmatack
+hackney
+hackneyed
+hacksaw
+had
+Hadamard
+Haddad
+haddock
+Hades
+Hadley
+hadn't
+Hadrian
+hadron
+hafnium
+Hagen
+Hager
+haggard
+haggle
+Hagstrom
+Hague
+Hahn
+Haifa
+haiku
+hail
+hailstone
+hailstorm
+Haines
+hair
+haircut
+hairdo
+hairpin
+hairy
+Haiti
+Haitian
+Hal
+halcyon
+hale
+Haley
+half
+halfback
+halfhearted
+halfway
+halibut
+halide
+Halifax
+halite
+hall
+hallelujah
+Halley
+hallmark
+hallow
+Halloween
+hallucinate
+hallway
+halma
+halo
+halocarbon
+halogen
+Halpern
+Halsey
+Halstead
+halt
+halvah
+halve
+Halverson
+ham
+Hamal
+Hamburg
+hamburger
+Hamilton
+hamlet
+Hamlin
+hammerhead
+hammock
+Hammond
+hamper
+Hampshire
+Hampton
+hamster
+Han
+Hancock
+hand
+handbag
+handbook
+handclasp
+handcuff
+Handel
+handful
+handgun
+handhold
+handicap
+handicapped
+handicapper
+handicapping
+handicraft
+handicraftsman
+handicraftsmen
+handiwork
+handkerchief
+handle
+handleable
+handlebar
+handline
+handmade
+handmaiden
+handout
+handset
+handshake
+handsome
+handspike
+handstand
+handwaving
+handwrite
+handwritten
+handy
+handyman
+handymen
+Haney
+Hanford
+hang
+hangable
+hangar
+hangman
+hangmen
+hangout
+hangover
+hank
+Hankel
+Hanley
+Hanlon
+Hanna
+Hannah
+Hannibal
+Hanoi
+Hanover
+Hanoverian
+Hans
+Hansel
+Hansen
+hansom
+Hanson
+Hanukkah
+hap
+haphazard
+haploid
+haploidy
+haplology
+happen
+happenstance
+happy
+Hapsburg
+harangue
+harass
+Harbin
+harbinger
+Harcourt
+hard
+hardbake
+hardboard
+hardboiled
+hardcopy
+harden
+hardhat
+Hardin
+Harding
+hardscrabble
+hardtack
+hardtop
+hardware
+hardwood
+hardworking
+hardy
+hare
+harelip
+harem
+hark
+Harlan
+Harlem
+Harley
+harm
+harmful
+Harmon
+harmonic
+harmonica
+harmonious
+harmony
+harness
+Harold
+harp
+harpoon
+harpsichord
+Harpy
+Harriet
+Harriman
+Harrington
+Harris
+Harrisburg
+Harrison
+harrow
+harry
+harsh
+harshen
+hart
+Hartford
+Hartley
+Hartman
+Harvard
+.P
+harvest
+harvestman
+Harvey
+hash
+hashish
+hasn't
+hasp
+hassle
+hast
+haste
+hasten
+Hastings
+hasty
+hat
+hatch
+hatchet
+hatchway
+hate
+hateful
+hater
+Hatfield
+hath
+Hathaway
+hatred
+Hatteras
+Hattie
+Hattiesburg
+Haugen
+haughty
+haul
+haulage
+haunch
+haunt
+Hausdorff
+Havana
+have
+haven
+haven't
+Havilland
+havoc
+haw
+Hawaii
+Hawaiian
+hawk
+Hawkins
+Hawley
+hawthorn
+Hawthorne
+hay
+Hayden
+Haydn
+Hayes
+hayfield
+Haynes
+Hays
+haystack
+Hayward
+hayward
+hazard
+hazardous
+haze
+hazel
+hazelnut
+hazy
+he
+head
+headache
+headboard
+headdress
+headland
+headlight
+headline
+headmaster
+headphone
+headquarter
+headquarters
+headroom
+headset
+headsman
+headsmen
+headstand
+headstone
+headstrong
+headwall
+headwater
+headway
+headwind
+heady
+heal
+Healey
+health
+healthful
+healthy
+Healy
+heap
+hear
+heard
+hearken
+hearsay
+hearse
+Hearst
+heart
+heartbeat
+heartbreak
+hearten
+heartfelt
+hearth
+hearty
+heat
+heater
+heath
+heathen
+heathenish
+Heathkit
+heave
+heaven
+heavenward
+heavy
+heavyweight
+Hebe
+hebephrenic
+Hebraic
+Hebrew
+Hecate
+hecatomb
+heck
+heckle
+Heckman
+hectic
+hector
+Hecuba
+he'd
+hedge
+hedgehog
+hedonism
+hedonist
+heed
+heel
+heft
+hefty
+Hegelian
+hegemony
+Heidelberg
+heigh
+height
+heighten
+Heine
+Heinrich
+Heinz
+heir
+heiress
+Heisenberg
+held
+Helen
+Helena
+Helene
+Helga
+helical
+helicopter
+heliocentric
+heliotrope
+helium
+helix
+he'll
+hell
+hellbender
+hellebore
+Hellenic
+hellfire
+hellgrammite
+hellish
+hello
+helm
+helmet
+Helmholtz
+helmsman
+helmsmen
+Helmut
+help
+helpful
+helpmate
+Helsinki
+Helvetica
+hem
+hematite
+Hemingway
+hemisphere
+hemispheric
+hemlock
+hemoglobin
+hemolytic
+hemorrhage
+hemorrhoid
+hemosiderin
+hemp
+Hempstead
+hen
+henbane
+hence
+henceforth
+henchman
+henchmen
+Henderson
+Hendrick
+Hendricks
+Hendrickson
+henequen
+Henley
+henpeck
+Henri
+Henrietta
+henry
+hepatica
+hepatitis
+Hepburn
+heptane
+her
+Hera
+Heraclitus
+herald
+herb
+Herbert
+Herculean
+Hercules
+herd
+herdsman
+here
+hereabout
+hereafter
+hereby
+hereditary
+heredity
+Hereford
+herein
+hereinabove
+hereinafter
+hereinbelow
+hereof
+heresy
+heretic
+hereto
+heretofore
+hereunder
+hereunto
+.P
+herewith
+heritable
+heritage
+Herkimer
+Herman
+Hermann
+hermeneutic
+Hermes
+hermetic
+Hermite
+hermitian
+Hermosa
+Hernandez
+hero
+Herodotus
+heroes
+heroic
+heroin
+heroine
+heroism
+heron
+herpes
+herpetology
+Herr
+herringbone
+Herschel
+herself
+Hershel
+Hershey
+hertz
+Hertzog
+hesitant
+hesitate
+hesitater
+Hesperus
+Hess
+Hesse
+Hessian
+Hester
+heterocyclic
+heterodyne
+heterogamous
+heterogeneity
+heterogeneous
+heterosexual
+heterostructure
+heterozygous
+Hetman
+Hettie
+Hetty
+Heublein
+heuristic
+Heusen
+Heuser
+hew
+Hewett
+Hewitt
+Hewlett
+hewn
+hex
+hexachloride
+hexadecimal
+hexafluoride
+hexagon
+hexagonal
+hexameter
+hexane
+hey
+heyday
+hi
+Hiatt
+hiatus
+Hiawatha
+hibachi
+Hibbard
+hibernate
+Hibernia
+hick
+Hickey
+Hickman
+hickory
+Hicks
+hid
+hidalgo
+hidden
+hide
+hideaway
+hideous
+hideout
+hierarchal
+hierarchic
+hierarchy
+hieratic
+hieroglyphic
+Hieronymus
+hifalutin
+Higgins
+high
+highball
+highboy
+highest
+highfalutin
+highhanded
+highland
+highlight
+highroad
+hightail
+highway
+highwayman
+highwaymen
+hijack
+hijinks
+hike
+hilarious
+hilarity
+Hilbert
+Hildebrand
+hill
+hillbilly
+Hillcrest
+Hillel
+hillman
+hillmen
+hillock
+hillside
+hilltop
+hilly
+hilt
+Hilton
+hilum
+him
+Himalaya
+himself
+hind
+hindmost
+hindrance
+hindsight
+Hindu
+Hinduism
+Hines
+hinge
+Hinman
+hint
+hinterland
+hip
+hippo
+Hippocrates
+Hippocratic
+hippodrome
+hippopotamus
+hippy
+hipster
+Hiram
+hire
+hireling
+Hiroshi
+Hiroshima
+Hirsch
+hirsute
+his
+Hispanic
+hiss
+histamine
+histidine
+histochemic
+histochemistry
+histogram
+histology
+historian
+historic
+historiography
+history
+histrionic
+hit
+Hitachi
+hitch
+Hitchcock
+hither
+hitherto
+Hitler
+hive
+ho
+hoagie
+Hoagland
+hoagy
+hoar
+hoard
+hoarfrost
+hoarse
+hob
+Hobart
+Hobbes
+hobble
+Hobbs
+hobby
+.P
+hobbyhorse
+hobgoblin
+hobo
+Hoboken
+hoc
+hock
+hockey
+hocus
+hodge
+hodgepodge
+Hodges
+Hodgkin
+hoe
+Hoff
+Hoffman
+hog
+hogan
+hogging
+hoi
+Hokan
+Holbrook
+Holcomb
+hold
+holden
+holdout
+holdover
+holdup
+hole
+holeable
+holiday
+Holland
+Hollandaise
+holler
+Hollerith
+Hollingsworth
+Hollister
+hollow
+Holloway
+hollowware
+holly
+hollyhock
+Hollywood
+Holm
+Holman
+Holmdel
+Holmes
+holmium
+holocaust
+Holocene
+hologram
+holography
+Holst
+Holstein
+holster
+holt
+Holyoke
+holystone
+.FC
+.SG
+.NS 7
+text text text
+text text text
+.NS 12
+Holyoke
+holystone
+.NS
+holt
+.NE
diff --git a/contrib/mm/examples/LT.se b/contrib/mm/examples/LT.se
new file mode 100644
index 00000000..bfbd77f5
--- /dev/null
+++ b/contrib/mm/examples/LT.se
@@ -0,0 +1,1062 @@
+.\" groff -mmse LT.se
+.ND 1994-10-26
+.WA "Sven Olsson" title
+Return address
+Street
+City, State Zip Code
+Text
+.WE
+.IA "Inside address" title
+Addressee name XXXXXXX
+Title XXXXXXXXXXXXXXX
+Company xxxxxxxxxxxx
+Street xxxxxxxxxxxxxx
+City, State Zip Code
+Text xxxxxxxxxxxxxxxxxx
+.IE
+.LO DNAMN Dokumentnamn
+.LO MDAT 1994-01-01
+.LO BIL 2
+.LO KOMP Kompletteringsuppgift
+.LO DBET dokumentnummer
+.LO BET ärendebeteckning
+.LO MBET "Mottagarens b"
+.LO SIDOR 22
+.\" vänster eller högerställt brev
+.\" .LT SVH
+.LT SVV
+hepp
+granary
+grand
+grandchild
+grandchildren
+granddaughter
+grandeur
+grandfather
+grandiloquent
+grandiose
+grandma
+grandmother
+grandnephew
+grandniece
+grandpa
+grandparent
+grandson
+grandstand
+granite
+granitic
+granny
+granola
+grant
+grantee
+grantor
+granular
+granulate
+granule
+Granville
+grape
+grapefruit
+grapevine
+graph
+grapheme
+graphic
+graphite
+grapple
+grasp
+grass
+grassland
+grassy
+grata
+grate
+grateful
+grater
+gratify
+gratis
+gratitude
+gratuitous
+gratuity
+grave
+gravel
+graven
+Graves
+gravestone
+graveyard
+gravid
+gravitate
+gravy
+gray
+graybeard
+grayish
+Grayson
+graywacke
+graze
+grease
+greasy
+great
+greatcoat
+greater
+grebe
+Grecian
+Greece
+greed
+greedy
+Greek
+green
+Greenbelt
+Greenberg
+Greenblatt
+Greenbriar
+Greene
+greenery
+Greenfield
+greengrocer
+greenhouse
+greenish
+Greenland
+Greensboro
+greensward
+greenware
+Greenwich
+greenwood
+Greer
+greet
+Greg
+gregarious
+Gregg
+Gregory
+gremlin
+grenade
+Grendel
+Grenoble
+Gresham
+Greta
+Gretchen
+grew
+grey
+greyhound
+greylag
+grid
+griddle
+gridiron
+grief
+grievance
+grieve
+grievous
+griffin
+Griffith
+grill
+grille
+grilled
+grillwork
+grim
+grimace
+Grimaldi
+grime
+Grimes
+Grimm
+grin
+grind
+grindstone
+grip
+.P
+gripe
+grippe
+grisly
+grist
+gristmill
+Griswold
+grit
+gritty
+grizzle
+grizzly
+groan
+groat
+grocer
+grocery
+groggy
+groin
+grommet
+groom
+groove
+grope
+grosbeak
+gross
+Grosset
+Grossman
+Grosvenor
+grotesque
+Groton
+ground
+groundsel
+groundskeep
+groundwork
+group
+groupoid
+grout
+grove
+grovel
+Grover
+grow
+growl
+grown
+grownup
+growth
+grub
+grubby
+grudge
+gruesome
+gruff
+grumble
+Grumman
+grunt
+gryphon
+g's
+GSA
+GU
+Guam
+guanidine
+guanine
+guano
+guarantee
+guaranteeing
+guarantor
+guaranty
+guard
+guardhouse
+Guardia
+guardian
+Guatemala
+gubernatorial
+Guelph
+Guenther
+guerdon
+guernsey
+guerrilla
+guess
+guesswork
+guest
+guffaw
+Guggenheim
+Guiana
+guidance
+guide
+guidebook
+guideline
+guidepost
+guiding
+guignol
+guild
+guildhall
+guile
+Guilford
+guillemot
+guillotine
+guilt
+guilty
+guinea
+guise
+guitar
+gules
+gulf
+gull
+Gullah
+gullet
+gullible
+gully
+gulp
+gum
+gumbo
+gumdrop
+gummy
+gumption
+gumshoe
+gun
+Gunderson
+gunfight
+gunfire
+gunflint
+gunk
+gunky
+gunman
+gunmen
+gunnery
+gunny
+gunplay
+gunpowder
+gunshot
+gunsling
+Gunther
+gurgle
+Gurkha
+guru
+Gus
+gush
+gusset
+gust
+Gustafson
+Gustav
+Gustave
+Gustavus
+gusto
+gusty
+gut
+Gutenberg
+Guthrie
+gutsy
+guttural
+guy
+.P
+Guyana
+guzzle
+Gwen
+Gwyn
+gym
+gymnasium
+gymnast
+gymnastic
+gymnosperm
+gyp
+gypsite
+gypsum
+gypsy
+gyrate
+gyrfalcon
+gyro
+gyrocompass
+gyroscope
+h
+ha
+Haag
+Haas
+habeas
+haberdashery
+Haberman
+Habib
+habit
+habitant
+habitat
+habitation
+habitual
+habituate
+hacienda
+hack
+hackberry
+Hackett
+hackle
+hackmatack
+hackney
+hackneyed
+hacksaw
+had
+Hadamard
+Haddad
+haddock
+Hades
+Hadley
+hadn't
+Hadrian
+hadron
+hafnium
+Hagen
+Hager
+haggard
+haggle
+Hagstrom
+Hague
+Hahn
+Haifa
+haiku
+hail
+hailstone
+hailstorm
+Haines
+hair
+haircut
+hairdo
+hairpin
+hairy
+Haiti
+Haitian
+Hal
+halcyon
+hale
+Haley
+half
+halfback
+halfhearted
+halfway
+halibut
+halide
+Halifax
+halite
+hall
+hallelujah
+Halley
+hallmark
+hallow
+Halloween
+hallucinate
+hallway
+halma
+halo
+halocarbon
+halogen
+Halpern
+Halsey
+Halstead
+halt
+halvah
+halve
+Halverson
+ham
+Hamal
+Hamburg
+hamburger
+Hamilton
+hamlet
+Hamlin
+hammerhead
+hammock
+Hammond
+hamper
+Hampshire
+Hampton
+hamster
+Han
+Hancock
+hand
+handbag
+handbook
+handclasp
+handcuff
+Handel
+handful
+handgun
+handhold
+handicap
+handicapped
+handicapper
+handicapping
+handicraft
+handicraftsman
+handicraftsmen
+handiwork
+handkerchief
+handle
+handleable
+handlebar
+handline
+handmade
+handmaiden
+handout
+handset
+handshake
+handsome
+handspike
+handstand
+handwaving
+handwrite
+handwritten
+handy
+handyman
+handymen
+Haney
+Hanford
+hang
+hangable
+hangar
+hangman
+hangmen
+hangout
+hangover
+hank
+Hankel
+Hanley
+Hanlon
+Hanna
+Hannah
+Hannibal
+Hanoi
+Hanover
+Hanoverian
+Hans
+Hansel
+Hansen
+hansom
+Hanson
+Hanukkah
+hap
+haphazard
+haploid
+haploidy
+haplology
+happen
+happenstance
+happy
+Hapsburg
+harangue
+harass
+Harbin
+harbinger
+Harcourt
+hard
+hardbake
+hardboard
+hardboiled
+hardcopy
+harden
+hardhat
+Hardin
+Harding
+hardscrabble
+hardtack
+hardtop
+hardware
+hardwood
+hardworking
+hardy
+hare
+harelip
+harem
+hark
+Harlan
+Harlem
+Harley
+harm
+harmful
+Harmon
+harmonic
+harmonica
+harmonious
+harmony
+harness
+Harold
+harp
+harpoon
+harpsichord
+Harpy
+Harriet
+Harriman
+Harrington
+Harris
+Harrisburg
+Harrison
+harrow
+harry
+harsh
+harshen
+hart
+Hartford
+Hartley
+Hartman
+Harvard
+.P
+harvest
+harvestman
+Harvey
+hash
+hashish
+hasn't
+hasp
+hassle
+hast
+haste
+hasten
+Hastings
+hasty
+hat
+hatch
+hatchet
+hatchway
+hate
+hateful
+hater
+Hatfield
+hath
+Hathaway
+hatred
+Hatteras
+Hattie
+Hattiesburg
+Haugen
+haughty
+haul
+haulage
+haunch
+haunt
+Hausdorff
+Havana
+have
+haven
+haven't
+Havilland
+havoc
+haw
+Hawaii
+Hawaiian
+hawk
+Hawkins
+Hawley
+hawthorn
+Hawthorne
+hay
+Hayden
+Haydn
+Hayes
+hayfield
+Haynes
+Hays
+haystack
+Hayward
+hayward
+hazard
+hazardous
+haze
+hazel
+hazelnut
+hazy
+he
+head
+headache
+headboard
+headdress
+headland
+headlight
+headline
+headmaster
+headphone
+headquarter
+headquarters
+headroom
+headset
+headsman
+headsmen
+headstand
+headstone
+headstrong
+headwall
+headwater
+headway
+headwind
+heady
+heal
+Healey
+health
+healthful
+healthy
+Healy
+heap
+hear
+heard
+hearken
+hearsay
+hearse
+Hearst
+heart
+heartbeat
+heartbreak
+hearten
+heartfelt
+hearth
+hearty
+heat
+heater
+heath
+heathen
+heathenish
+Heathkit
+heave
+heaven
+heavenward
+heavy
+heavyweight
+Hebe
+hebephrenic
+Hebraic
+Hebrew
+Hecate
+hecatomb
+heck
+heckle
+Heckman
+hectic
+hector
+Hecuba
+he'd
+hedge
+hedgehog
+hedonism
+hedonist
+heed
+heel
+heft
+hefty
+Hegelian
+hegemony
+Heidelberg
+heigh
+height
+heighten
+Heine
+Heinrich
+Heinz
+heir
+heiress
+Heisenberg
+held
+Helen
+Helena
+Helene
+Helga
+helical
+helicopter
+heliocentric
+heliotrope
+helium
+helix
+he'll
+hell
+hellbender
+hellebore
+Hellenic
+hellfire
+hellgrammite
+hellish
+hello
+helm
+helmet
+Helmholtz
+helmsman
+helmsmen
+Helmut
+help
+helpful
+helpmate
+Helsinki
+Helvetica
+hem
+hematite
+Hemingway
+hemisphere
+hemispheric
+hemlock
+hemoglobin
+hemolytic
+hemorrhage
+hemorrhoid
+hemosiderin
+hemp
+Hempstead
+hen
+henbane
+hence
+henceforth
+henchman
+henchmen
+Henderson
+Hendrick
+Hendricks
+Hendrickson
+henequen
+Henley
+henpeck
+Henri
+Henrietta
+henry
+hepatica
+hepatitis
+Hepburn
+heptane
+her
+Hera
+Heraclitus
+herald
+herb
+Herbert
+Herculean
+Hercules
+herd
+herdsman
+here
+hereabout
+hereafter
+hereby
+hereditary
+heredity
+Hereford
+herein
+hereinabove
+hereinafter
+hereinbelow
+hereof
+heresy
+heretic
+hereto
+heretofore
+hereunder
+hereunto
+.P
+herewith
+heritable
+heritage
+Herkimer
+Herman
+Hermann
+hermeneutic
+Hermes
+hermetic
+Hermite
+hermitian
+Hermosa
+Hernandez
+hero
+Herodotus
+heroes
+heroic
+heroin
+heroine
+heroism
+heron
+herpes
+herpetology
+Herr
+herringbone
+Herschel
+herself
+Hershel
+Hershey
+hertz
+Hertzog
+hesitant
+hesitate
+hesitater
+Hesperus
+Hess
+Hesse
+Hessian
+Hester
+heterocyclic
+heterodyne
+heterogamous
+heterogeneity
+heterogeneous
+heterosexual
+heterostructure
+heterozygous
+Hetman
+Hettie
+Hetty
+Heublein
+heuristic
+Heusen
+Heuser
+hew
+Hewett
+Hewitt
+Hewlett
+hewn
+hex
+hexachloride
+hexadecimal
+hexafluoride
+hexagon
+hexagonal
+hexameter
+hexane
+hey
+heyday
+hi
+Hiatt
+hiatus
+Hiawatha
+hibachi
+Hibbard
+hibernate
+Hibernia
+hick
+Hickey
+Hickman
+hickory
+Hicks
+hid
+hidalgo
+hidden
+hide
+hideaway
+hideous
+hideout
+hierarchal
+hierarchic
+hierarchy
+hieratic
+hieroglyphic
+Hieronymus
+hifalutin
+Higgins
+high
+highball
+highboy
+highest
+highfalutin
+highhanded
+highland
+highlight
+highroad
+hightail
+highway
+highwayman
+highwaymen
+hijack
+hijinks
+hike
+hilarious
+hilarity
+Hilbert
+Hildebrand
+hill
+hillbilly
+Hillcrest
+Hillel
+hillman
+hillmen
+hillock
+hillside
+hilltop
+hilly
+hilt
+Hilton
+hilum
+him
+Himalaya
+himself
+hind
+hindmost
+hindrance
+hindsight
+Hindu
+Hinduism
+Hines
+hinge
+Hinman
+hint
+hinterland
+hip
+hippo
+Hippocrates
+Hippocratic
+hippodrome
+hippopotamus
+hippy
+hipster
+Hiram
+hire
+hireling
+Hiroshi
+Hiroshima
+Hirsch
+hirsute
+his
+Hispanic
+hiss
+histamine
+histidine
+histochemic
+histochemistry
+histogram
+histology
+historian
+historic
+historiography
+history
+histrionic
+hit
+Hitachi
+hitch
+Hitchcock
+hither
+hitherto
+Hitler
+hive
+ho
+hoagie
+Hoagland
+hoagy
+hoar
+hoard
+hoarfrost
+hoarse
+hob
+Hobart
+Hobbes
+hobble
+Hobbs
+hobby
+.P
+hobbyhorse
+hobgoblin
+hobo
+Hoboken
+hoc
+hock
+hockey
+hocus
+hodge
+hodgepodge
+Hodges
+Hodgkin
+hoe
+Hoff
+Hoffman
+hog
+hogan
+hogging
+hoi
+Hokan
+Holbrook
+Holcomb
+hold
+holden
+holdout
+holdover
+holdup
+hole
+holeable
+holiday
+Holland
+Hollandaise
+holler
+Hollerith
+Hollingsworth
+Hollister
+hollow
+Holloway
+hollowware
+holly
+hollyhock
+Hollywood
+Holm
+Holman
+Holmdel
+Holmes
+holmium
+holocaust
+Holocene
+hologram
+holography
+Holst
+Holstein
+holster
+holt
+Holyoke
+holystone
+.FC
+.SG
+.NS 7
+text text text
+text text text
+.NS 12
+Holyoke
+holystone
+.NS
+holt
+.NE
diff --git a/contrib/mm/examples/ML b/contrib/mm/examples/ML
new file mode 100644
index 00000000..bbfca3de
--- /dev/null
+++ b/contrib/mm/examples/ML
@@ -0,0 +1,169 @@
+granary
+grand
+grandchild
+grandchildren
+granddaughter
+grandeur
+grandfather
+grandiloquent
+grandiose
+grandma
+grandmother
+grandnephew
+grandniece
+grandpa
+.ML MARK
+.LI "LOCALMARK"
+granola
+grant
+grantee
+grantor
+granular
+granulate
+granule
+Granville
+grape
+grapefruit
+grapevine
+.LI
+.DS
+Where shall we put this.
+Where shall we put this.
+Where shall we put this.
+.DE
+.LI
+granola
+grant
+grantee
+grantor
+granular
+granulate
+granule
+Granville
+grape
+grapefruit
+grapevine
+.LI
+.DS
+Where shall we put this.
+.DE
+.LI
+graphic
+graphite
+grapple
+grasp
+grass
+grassland
+grassy
+.LI
+grata
+grate
+grateful
+grater
+gratify
+gratis
+gratitude
+gratuitous
+.LI
+gratuity
+grave
+gravel
+.LE
+.SP 3
+.ML $ 1c
+.LI
+graven
+Graves
+gravestone
+graveyard
+gravid
+gravitate
+gravy
+gray
+.LI
+graybeard
+grayish
+Grayson
+graywacke
+graze
+grease
+greasy
+great
+greatcoat
+.LI
+greater
+grebe
+Grecian
+Greece
+greed
+greedy
+Greek
+green
+.LI
+Greenbelt
+Greenberg
+Greenblatt
+Greenbriar
+Greene
+greenery
+.LE
+.SP 3
+.ML X 1c 1
+.LI
+Greenfield
+greengrocer
+grandson
+grandstand
+granite
+granitic
+granny
+graph
+.LI
+grapheme
+greenhouse
+greenish
+Greenland
+Greensboro
+granary
+grand
+grandchild
+grandchildren
+granddaughter
+grandeur
+grandfather
+grandiloquent
+grandiose
+.LI
+grandma
+grandmother
+grandnephew
+grandniece
+grandpa
+grandparent
+grandson
+grandstand
+granite
+granitic
+granny
+.LI
+granola
+grant
+grantee
+grantor
+granular
+granulate
+granule
+Granville
+grape
+grapefruit
+.LI
+grapevine
+graph
+grapheme
+graphic
+graphite
+grapple
+grasp
+grass
+grassland
+.LE
diff --git a/contrib/mm/examples/MOVE b/contrib/mm/examples/MOVE
new file mode 100644
index 00000000..0f0399cc
--- /dev/null
+++ b/contrib/mm/examples/MOVE
@@ -0,0 +1,175 @@
+.PH "'hej'hopp'i skogen'"
+.PF "'livet'är'härligt'"
+.OH "'ojämn'%'sida'"
+.EH "'ojämn'%'sida'"
+.OF "'ojämn'%'sida'"
+.EF "'ojämn'%'sida'"
+10th
+1st
+2nd
+3rd
+4th
+5th
+6th
+7th
+8th
+9th
+a
+AAA
+AAAS
+Aarhus
+Aaron
+AAU
+ABA
+Ababa
+aback
+abacus
+abalone
+abandon
+abase
+abash
+abate
+abater
+abbas
+abbe
+abbey
+abbot
+Abbott
+abbreviate
+abc
+abdicate
+abdomen
+abdominal
+abet
+abetted
+abetting
+abeyance
+abeyant
+abhorred
+abhorrent
+abide
+Abidjan
+Abigail
+abject
+ablate
+ablaze
+able
+ablution
+Abner
+.MOVE 50 20
+abnormal
+Abo
+aboard
+abode
+abolish
+abolition
+abominable
+abominate
+aboriginal
+AAA
+ABORIGINE
+ABORNING
+ABORT
+ABOUND
+ABOUT
+ABOVE
+ABOVEBOARD
+ABOVEGROUND
+abovementioned
+abrade
+Abraham
+Abram
+Abramson
+abrasion
+abrasive
+abreact
+abreast
+BBB
+ABRIDGE
+ABRIDGMENT
+ABROAD
+abrogate
+abrupt
+abscess
+abscissa
+abscissae
+absence
+absent
+absentee
+absenteeism
+absentia
+absentminded
+.MOVE 30 10
+absinthe
+absolute
+absolution
+absolve
+absorb
+absorbent
+absorption
+absorptive
+abstain
+abstention
+abstinent
+abstract
+abstracter
+abstractor
+CCC
+ABSTRUSE
+ABSURD
+ABUILDING
+ABUNDANT
+ABUSABLE
+ABUSE
+ABUSIVE
+ABUT
+ABUTTED
+ABUTTING
+ABYSMAL
+ABYSS
+ABYSSINIA
+AC
+ACADEME
+ACADEMIA
+ACADEMIC
+ACADEMICIAN
+ACADEMY
+ACADIA
+ACANTHUS
+ACAPULCO
+ACCEDE
+ACCELERATE
+ACCELEROMETER
+ACCENT
+ACCENTUAL
+ACCENTUATE
+ACCEPT
+ACCEPTANT
+acceptor
+access
+.MOVE 62 0 20
+accessible
+accession
+accessory
+accident
+accidental
+accipiter
+acclaim
+acclamation
+acclimate
+accolade
+accommodate
+accompaniment
+accompanist
+accompany
+accomplice
+accomplish
+accord
+accordant
+DDD
+ACCORDION
+ACCOST
+ACCOUNT
+ACCOUNTANT
+ACCRA
+.PGFORM
diff --git a/contrib/mm/examples/MUL b/contrib/mm/examples/MUL
new file mode 100644
index 00000000..ae91fae0
--- /dev/null
+++ b/contrib/mm/examples/MUL
@@ -0,0 +1,535 @@
+inject
+injudicious
+Injun
+injunct
+injunction
+injure
+injurious
+injury
+injustice
+ink
+inkling
+inlaid
+inland
+inlay
+inlet
+Inman
+inmate
+inn
+innards
+innate
+inner
+innermost
+innkeeper
+innocent
+innocuous
+innovate
+innuendo
+innumerable
+inoculate
+inoffensive
+inoperable
+inoperative
+inopportune
+inordinate
+inorganic
+input
+inputting
+inquest
+inquire
+inquiry
+inquisition
+inquisitive
+inquisitor
+inroad
+insane
+insatiable
+inscribe
+inscription
+inscrutable
+insect
+insecticide
+insecure
+inseminate
+insensible
+insensitive
+inseparable
+insert
+inset
+inshore
+inside
+insidious
+insight
+insightful
+insignia
+insignificant
+insincere
+insinuate
+insipid
+insist
+insistent
+insofar
+insolent
+insoluble
+insolvable
+insolvent
+insomnia
+insomniac
+insouciant
+inspect
+inspector
+inspiration
+inspire
+instable
+install
+installation
+instalment
+instance
+instant
+instantaneous
+instantiate
+instead
+instep
+instigate
+instill
+instillation
+instinct
+instinctual
+institute
+institution
+instruct
+instructor
+instrument
+instrumentation
+insubordinate
+insubstantial
+insufferable
+insufficient
+insular
+insulate
+insulin
+insult
+insuperable
+insupportable
+insuppressible
+insurance
+insure
+insurgent
+insurmountable
+insurrect
+insurrection
+intact
+intake
+intangible
+integer
+integrable
+.MULB 4c 1 5c 1 4c 1 3c
+Grenoble
+Gresham
+Greta
+Gretchen
+grew
+grieve
+grievous
+griffin
+Griffith
+grill
+grille
+grilled
+grillwork
+grim
+grimace
+Grimaldi
+grime
+Grimes
+Grimm
+grin
+grind
+grindstone
+grip
+gripe
+grippe
+grisly
+grist
+gristmill
+Griswold
+grit
+gritty
+grizzle
+grizzly
+groan
+groat
+grocer
+grocery
+groggy
+groin
+grommet
+groom
+groove
+grope
+grosbeak
+gross
+.MULN
+h
+ha
+Haag
+Haas
+habeas
+haberdashery
+Haberman
+Habib
+habit
+habitant
+habitat
+habitation
+habitual
+habituate
+hacienda
+hack
+hackberry
+Hackett
+hackle
+hackmatack
+hackney
+hackneyed
+hacksaw
+had
+Hadamard
+Haddad
+haddock
+Hades
+Hadley
+hadn't
+Hadrian
+hadron
+hafnium
+Hagen
+Hager
+haggard
+haggle
+Hagstrom
+Hague
+Hahn
+Haifa
+haiku
+hail
+hailstone
+hailstorm
+Haines
+hair
+haircut
+hairdo
+hairpin
+hairy
+Haiti
+Haitian
+Hal
+halcyon
+hale
+Haley
+half
+halfback
+halfhearted
+halfway
+halibut
+halide
+Halifax
+halite
+hall
+hallelujah
+Halley
+hallmark
+hallow
+Halloween
+hallucinate
+hallway
+halma
+halo
+halocarbon
+halogen
+Halpern
+Halsey
+Halstead
+halt
+halvah
+halve
+Halverson
+ham
+Hamal
+Hamburg
+hamburger
+Hamilton
+hamlet
+Hamlin
+hammerhead
+hammock
+Hammond
+hamper
+Hampshire
+Hampton
+hamster
+Han
+Hancock
+hand
+handbag
+handbook
+handclasp
+handcuff
+.MULN
+coliform
+coliseum
+collaborate
+collage
+collagen
+collapse
+collapsible
+collar
+collarbone
+collard
+collate
+collateral
+colleague
+collect
+collectible
+collector
+college
+collegial
+collegian
+collegiate
+collet
+collide
+collie
+Collier
+collimate
+collinear
+Collins
+collision
+collocation
+colloidal
+Colloq
+colloquia
+colloquial
+colloquium
+colloquy
+command
+commandant
+commandeer
+commando
+commemorate
+commend
+commendation
+commendatory
+commensurable
+commensurate
+comment
+commentary
+commentator
+commerce
+commercial
+commingle
+commiserate
+commissariat
+commissary
+commission
+commit
+committable
+committal
+committed
+committee
+committeeman
+committeemen
+committeewoman
+committeewomen
+committing
+commodious
+commodity
+commodore
+common
+commonality
+.MULN
+locoweed
+lunch
+luncheon
+lunchroom
+lunchtime
+Lund
+Lundberg
+Lundquist
+lung
+lunge
+lupine
+Lura
+lurch
+lure
+lurid
+lurk
+Lusaka
+luscious
+lush
+lust
+lustful
+lustrous
+lusty
+lutanist
+lute
+lutetium
+Luther
+Lutheran
+Lutz
+lymphocyte
+lymphoma
+lynch
+Lynchburg
+Lynn
+lynx
+Lyon
+Lyons
+Lyra
+lyric
+lyricism
+Lysenko
+lysergic
+lysine
+.MULE
+m
+ma
+Mabel
+Mac
+macabre
+macaque
+MacArthur
+Macassar
+Macbeth
+MacDonald
+MacDougall
+mace
+Macedon
+Macedonia
+MacGregor
+Mach
+Machiavelli
+machination
+machine
+machinelike
+machinery
+machismo
+macho
+macintosh
+mack
+MacKenzie
+mackerel
+Mackey
+Mackinac
+Mackinaw
+mackintosh
+MacMillan
+Macon
+macrame
+macro
+macromolecular
+macromolecule
+macrophage
+macroprocessor
+macroscopic
+macrostructure
+mad
+Madagascar
+madam
+Madame
+madcap
+madden
+Maddox
+made
+Madeira
+Madeleine
+Madeline
+madhouse
+Madison
+madman
+madmen
+Madonna
+Madras
+Madrid
+madrigal
+Madsen
+madstone
+Mae
+Maelstrom
+maestro
+Mafia
+magazine
+Magdalene
+magenta
+Maggie
+maggot
+maggoty
+magi
+magic
+magician
+magisterial
+magistrate
+magma
+magna
+magnanimity
+magnanimous
+magnate
+magnesia
+magnesite
+magnesium
+magnet
+magnetic
+magnetite
+magneto
+magnetron
+magnificent
+magnify
+magnitude
+magnolia
+magnum
+Magnuson
+Magog
+magpie
+Magruder
+Mahayana
+Mahayanist
+mahogany
+Mahoney
+maid
+maiden
+maidenhair
+maidservant
+Maier
+mail
+mailbox
+mailman
+mailmen
+maim
+main
+Maine
+mainland
+mainline
+mainstay
+mainstream
+maintain
+maintenance
+maitre
+majestic
+majesty
+major
+make
+makeshift
+makeup
+Malabar
+maladapt
+maladaptive
+maladjust
+maladroit
+malady
+Malagasy
+malaise
+malaprop
+malaria
+malarial
+Malawi
+Malay
+Malaysia
diff --git a/contrib/mm/examples/NCOL b/contrib/mm/examples/NCOL
new file mode 100644
index 00000000..82c6f8d5
--- /dev/null
+++ b/contrib/mm/examples/NCOL
@@ -0,0 +1,196 @@
+granary
+grand
+grandchild
+grandchildren
+granddaughter
+grandeur
+grandfather
+grandiloquent
+grandiose
+grandma
+grandmother
+grandnephew
+grandniece
+grandpa
+grandparent
+grandson
+grandstand
+granite
+granitic
+granny
+granola
+grant
+grantee
+grantor
+granular
+granulate
+granule
+Granville
+grape
+grapefruit
+grapevine
+graph
+grapheme
+graphic
+graphite
+grapple
+grasp
+grass
+grassland
+grassy
+.MC 3c
+grata
+grate
+grateful
+grater
+gratify
+gratis
+gratitude
+gratuitous
+gratuity
+grave
+gravel
+graven
+Graves
+gravestone
+graveyard
+gravid
+gravitate
+gravy
+gray
+graybeard
+grayish
+Grayson
+graywacke
+graze
+grease
+greasy
+great
+greatcoat
+greater
+grebe
+Grecian
+Greece
+greed
+greedy
+.NCOL
+Greek
+green
+Greenbelt
+Greenberg
+Greenblatt
+Greenbriar
+Greene
+greenery
+Greenfield
+greengrocer
+greenhouse
+greenish
+Greenland
+Greensboro
+greensward
+greenware
+Greenwich
+greenwood
+Greer
+greet
+Greg
+gregarious
+Gregg
+Gregory
+gremlin
+grenade
+Grendel
+Grenoble
+Gresham
+Greta
+Gretchen
+grew
+grey
+greyhound
+greylag
+grid
+griddle
+gridiron
+grief
+grievance
+grieve
+grievous
+griffin
+Griffith
+grill
+grille
+grilled
+grillwork
+.NCOL
+grim
+grimace
+Grimaldi
+grime
+Grimes
+Grimm
+grin
+grind
+grindstone
+grip
+gripe
+grippe
+grisly
+grist
+gristmill
+Griswold
+grit
+gritty
+grizzle
+grizzly
+groan
+groat
+grocer
+grocery
+groggy
+groin
+grommet
+groom
+groove
+grope
+grosbeak
+gross
+Grosset
+Grossman
+Grosvenor
+grotesque
+Groton
+ground
+groundsel
+groundskeep
+groundwork
+group
+groupoid
+grout
+grove
+grovel
+Grover
+grow
+growl
+grown
+grownup
+growth
+grub
+grubby
+grudge
+gruesome
+gruff
+grumble
+Grumman
+grunt
+gryphon
+g's
+GSA
+GU
+Guam
+guanidine
+guanine
+guano
+guarantee
+guaranteeing
+guarantor
diff --git a/contrib/mm/examples/ND b/contrib/mm/examples/ND
new file mode 100644
index 00000000..4b3694a3
--- /dev/null
+++ b/contrib/mm/examples/ND
@@ -0,0 +1,17 @@
+.nf
+----------------------------------------------------------------------
+.ce
+Testing
+----------------------------------------------------------------------
+Date = \*[DT]
+.ISODATE
+Date = \*[DT]
+.ISODATE 0
+
+.ND "13 August 1992"
+Date = \*[DT]
+
+.ISODATE
+.ND "14 August 1992"
+Date = \*[DT]
+----------------------------------------------------------------------
diff --git a/contrib/mm/examples/README b/contrib/mm/examples/README
new file mode 100644
index 00000000..cb6980f8
--- /dev/null
+++ b/contrib/mm/examples/README
@@ -0,0 +1,32 @@
+
+This directory contains examples of my enhancements to MM.
+
+APP The appendix macro
+B1B2 Box macro with text
+COVER My general cover macro, this example is using
+ ms.cov.
+IND A general indexing method, see manual for INITI
+LT The letter macro
+LT.se A swedish example with the extra
+ swedish macros for getting a letter conforming
+ to swedish standard letter, both left and right adjusted.
+ML Marked list, an extended list type
+MOVE The MOVE macro, how to begin to print on an exact position.
+MUL Enhanced multicolumn mode.
+NCOL Start on next column. (Not for MUL*)
+ND New date, with iso date example
+References How to use references
+SETR General reference system, see manual for INITR
+
+
+Examples that I should have:
+
+PIC How to include postscript pictures, see manual for PIC
+VERBON Begin verbatim output
+
+
+And remember, check the manual for all string and number registers,
+I've made shure that mgm will be useful in several languages
+and all english output can be redefined.
+Check the manual for groff_mse (swedish format) and the
+macro file, tmac.mse.
diff --git a/contrib/mm/examples/References b/contrib/mm/examples/References
new file mode 100644
index 00000000..72f64822
--- /dev/null
+++ b/contrib/mm/examples/References
@@ -0,0 +1,975 @@
+.PH "'this'is'a header'"
+.PF "'this'is'a footer'"
+.OH "'odd'%'page'"
+.EH "'even'%'page'"
+.OF "'odd'%'page'"
+.EF "'even'%'page'"
+10th
+1st
+2nd
+3rd
+4th
+5th
+6th
+7th
+8th
+9th
+a
+AAA
+.B
+AAAS
+Aarhus
+Aaron
+.R
+AAU
+ABA
+Ababa
+aback
+abacus
+abalone
+abandon
+abase
+.H 1 "hej hopp"
+abash
+abate
+abater
+abbas
+abbe
+abbey
+abbot
+Abbott
+abbreviate
+abc
+abdicate
+abdomen
+abet
+abetted
+abetting
+abeyance
+abeyant
+.H 2 "hej hopp"
+abhorred
+abhorrent
+abide
+Abidjan
+Abigail
+abject
+ablate
+ablaze
+able
+ablution
+Abner
+abnormal
+.H 2 "hej hopp"
+Abo
+aboard
+abode
+abolish
+.HU "hej hopp"
+.B1
+abolition
+abominable
+abominate\*(Rf
+aboriginal
+.RS
+AAA
+ABORIGINE
+ABORNING
+ABORT
+ABOUND
+ABOUT
+ABOVE
+ABOVEBOARD
+ABOVEGROUND
+.RF
+abovementioned
+abrade
+Abraham\*(Rf
+Abram\*(Rf
+Abramson\*(Rf
+abrasion\*(Rf
+abrasive\*(Rf
+abreact\*(Rf
+.B2
+abreast\*(Rf
+.RS
+BBB
+ABRIDGE
+ABRIDGMENT
+ABROAD
+.RF
+abrogate
+abrupt
+abscess\*(Rf
+abscissa\*(Rf
+abscissae\*(Rf
+absence\*(Rf
+absent
+absentee
+absenteeism
+absentia
+.H 3 "hej hopp"
+absentminded
+absinthe
+absolute
+absolution
+absolve
+absorb
+absorbent
+absorption
+absorptive
+abstain
+abstention
+abstinent\*(Rf
+abstract
+abstracter
+abstractor
+.RS nisse
+CCC
+ABSTRUSE
+ABSURD
+ABUILDING
+ABUNDANT
+ABUSABLE
+ABUSE
+ABUSIVE
+ABUT
+ABUTTED
+ABUTTING
+ABYSMAL
+ABYSS
+ABYSSINIA
+AC
+ACADEME
+ACADEMIA
+ACADEMIC
+ACADEMICIAN
+ACADEMY
+ACADIA
+ACANTHUS
+ACAPULCO
+ACCEDE
+ACCELERATE
+ACCELEROMETER
+ACCENT
+ACCENTUAL
+ACCENTUATE
+ACCEPT
+ACCEPTANT
+.RF
+acceptor
+access
+accessible
+accession
+Ref \*[nisse]
+accessory
+.H 4 "hej hopp"
+accident
+accidental
+accipiter
+acclaim
+acclamation
+acclimate
+accolade
+accommodate
+accompaniment
+accompanist
+accompany
+accomplice
+accomplish\*(Rf
+accord
+accordant
+.RS
+DDD
+ACCORDION
+ACCOST
+ACCOUNT
+ACCOUNTANT
+ACCRA
+ACCREDIT
+ACCREDITATE
+ACCREDITATION
+ACCRETION
+ACCRUAL
+ACCRUE
+.RF
+acculturate
+accumulate
+accuracy
+accurate
+accusation
+accusative
+accusatory
+accuse
+accustom
+ace
+acerbic
+acerbity
+acetate
+acetic
+acetone
+acetylene
+ache
+achieve
+Achilles
+aching
+achromatic
+acid
+acidic
+acidulous
+.H 5 "hej hopp"
+Ackerman
+Ackley
+acknowledge
+acknowledgeable
+ACM
+acme
+acolyte
+acorn
+acoustic
+acquaint
+acquaintance
+acquiesce
+acquiescent
+acquire
+acquisition
+acquisitive
+acquit
+acquittal
+acquitting
+acre
+acreage
+acrid
+acrimonious
+acrimony
+acrobacy
+acrobat
+acrobatic
+acronym
+acropolis
+across
+acrylate
+acrylic
+ACS
+act
+Actaeon
+actinic
+actinide
+actinium
+actinolite
+actinometer
+activate
+activation
+activism
+Acton
+actor
+actress
+Acts
+actual
+actuarial
+actuate
+.H 6 "hej hopp"
+acuity
+acumen
+acute
+acyclic
+ad
+Ada
+adage
+adagio
+Adair
+Adam
+adamant
+Adams
+Adamson
+adapt
+adaptation
+adaptive
+add
+added
+addend
+addenda
+addendum
+addict
+Addis
+Addison
+addition
+additional
+additive
+addle
+address
+addressee
+Addressograph
+adduce
+Adelaide
+Adele
+Adelia
+Aden
+adenine
+adenoma
+adenosine
+adept
+adequacy
+adequate
+adhere
+adherent
+adhesion
+adhesive
+adiabatic
+adieu
+adipic
+Adirondack
+.H 7 "hej hopp"
+adjacent
+adject
+adjectival
+adjective
+adjoin
+adjoint
+adjourn
+adjudge
+adjudicate
+adjunct
+adjust
+adjutant
+Adkins
+Adler
+administer
+administrable
+administrate
+administratrix
+admiral
+admiralty
+admiration
+admire
+admissible
+admission
+admit
+admittance
+admitted
+admitting
+admix
+admixture
+admonish
+admonition
+ado
+adobe
+adolescent
+Adolph
+Adolphus
+Adonis
+adopt
+adoption
+adoptive
+adore
+adorn
+adposition
+adrenal
+adrenaline
+Adrian
+Adriatic
+Adrienne
+adrift
+adroit
+adsorb
+adsorbate
+adsorption
+adsorptive
+adulate
+adult
+adulterate
+adulterous
+adultery
+adulthood
+advance
+advantage
+advantageous
+advent
+adventitious
+adventure
+adventurous
+adverb
+adverbial
+adversary
+adverse
+advert
+advertise
+advice
+advisable
+advise
+advisee
+advisor
+advisory
+advocacy
+advocate
+Aegean
+aegis
+Aeneas
+Aeneid
+aeolian
+Aeolus
+aerate
+aerial
+Aerobacter
+aerobic
+aerodynamic
+aerogene
+aeronautic
+aerosol
+aerospace
+Aeschylus
+aesthete
+aesthetic
+10th
+1st
+2nd
+3rd
+4th
+5th
+6th
+7th
+8th
+9th
+a
+AAA
+AAAS
+Aarhus
+Aaron
+AAU
+ABA
+Ababa
+aback
+abacus
+abalone
+abandon
+abase
+.H 1 "hej hopp"
+abash
+abate
+abater
+abbas
+abbe
+abbey
+abbot
+Abbott
+abbreviate
+abc
+abdicate
+abdomen
+abdominal
+abduct
+Abe
+abed
+Abel
+Abelian
+Abelson
+Aberdeen
+Abernathy
+aberrant
+aberrate
+abet
+abetted
+abetting
+abeyance
+abeyant
+.H 2 "hej hopp"
+abhorred
+abhorrent
+abide
+Abidjan
+Abigail
+abject
+ablate
+ablaze
+able
+ablution
+Abner
+abnormal
+Abo
+aboard
+abode
+abolish
+abolition
+abominable
+abominate
+aboriginal
+aborigine
+aborning
+abort
+abound
+about
+above
+aboveboard
+aboveground
+abovementioned
+abrade
+Abraham
+Abram
+Abramson
+abrasion
+abrasive
+abreact
+abreast
+abridge
+abridgment
+abroad
+abrogate
+abrupt
+abscess
+abscissa
+abscissae
+absence
+absent
+absentee
+absenteeism
+absentia
+.H 3 "hej hopp"
+absentminded
+absinthe
+absolute
+absolution
+absolve
+absorb
+absorbent
+absorption
+absorptive
+abstain
+abstention
+abstinent
+abstract
+abstracter
+abstractor
+abstruse
+absurd
+abuilding
+abundant
+abusable
+abuse
+abusive
+abut
+abutted
+abutting
+abysmal
+abyss
+Abyssinia
+AC
+academe
+academia
+academic
+academician
+academy
+Acadia
+acanthus
+Acapulco
+accede
+accelerate
+accelerometer
+accent
+accentual
+accentuate
+accept
+acceptant
+acceptor
+access
+accessible
+accession
+accessory
+.H 4 "hej hopp"
+accident
+accidental
+accipiter
+acclaim
+acclamation
+acclimate
+accolade
+accommodate
+accompaniment
+accompanist
+accompany
+accomplice
+accomplish
+accord
+accordant
+accordion
+accost
+account
+accountant
+Accra
+accredit
+accreditate
+accreditation
+accretion
+accrual
+accrue
+acculturate
+accumulate
+accuracy
+accurate
+accusation
+accusative
+accusatory
+accuse
+accustom
+ace
+acerbic
+acerbity
+acetate
+acetic
+acetone
+acetylene
+ache
+achieve
+Achilles
+aching
+achromatic
+acid
+acidic
+acidulous
+.H 5 "hej hopp"
+Ackerman
+Ackley
+acknowledge
+acknowledgeable
+ACM
+acme
+acolyte
+acorn
+acoustic
+acquaint
+acquaintance
+acquiesce
+acquiescent
+acquire
+acquisition
+acquisitive
+acquit
+acquittal
+acquitting
+acre
+acreage
+acrid
+acrimonious
+acrimony
+acrobacy
+acrobat
+acrobatic
+acronym
+acropolis
+across
+acrylate
+acrylic
+ACS
+act
+Actaeon
+actinic
+actinide
+actinium
+actinolite
+actinometer
+activate
+activation
+activism
+Acton
+actor
+actress
+Acts
+actual
+actuarial
+actuate
+.H 6 "hej hopp"
+acuity
+acumen
+acute
+acyclic
+ad
+Ada
+adage
+adagio
+Adair
+Adam
+adamant
+Adams
+Adamson
+adapt
+adaptation
+adaptive
+add
+added
+addend
+addenda
+addendum
+addict
+Addis
+Addison
+addition
+additional
+additive
+addle
+address
+addressee
+Addressograph
+adduce
+Adelaide
+Adele
+Adelia
+Aden
+adenine
+adenoma
+adenosine
+adept
+adequacy
+adequate
+adhere
+adherent
+adhesion
+adhesive
+adiabatic
+adieu
+adipic
+Adirondack
+.H 7 "hej hopp"
+adjacent
+adject
+adjectival
+adjective
+adjoin
+adjoint
+adjourn
+adjudge
+adjudicate
+adjunct
+adjust
+adjutant
+Adkins
+Adler
+administer
+administrable
+administrate
+administratrix
+admiral
+admiralty
+admiration
+admire
+admissible
+admission
+admit
+admittance
+admitted
+admitting
+admix
+admixture
+admonish
+admonition
+ado
+adobe
+adolescent
+Adolph
+Adolphus
+Adonis
+adopt
+adoption
+adoptive
+adore
+adorn
+adposition
+adrenal
+adrenaline
+Adrian
+Adriatic
+Adrienne
+adrift
+adroit
+adsorb
+adsorbate
+adsorption
+adsorptive
+adulate
+adult
+adulterate
+adulterous
+adultery
+adulthood
+advance
+advantage
+advantageous
+advent
+adventitious
+adverse
+advert
+advertise
+advice
+advisable
+advise
+advisee
+advisor
+advisory
+advocacy
+advocate
+Aegean
+aegis
+Aeneas
+Aeneid
+aeolian
+Aeolus
+aerate
+aerial
+Aerobacter
+aerobic
+aerodynamic
+aerogene
+aeronautic
+aerosol
+aerospace
+Aeschylus
+aesthete
+aesthetic
+.H 1 "hej hopp"
+acuity
+acumen
+acute
+acyclic
+ad
+Ada
+adage
+adagio
+Adair
+Adam
+adamant
+Adams
+Adamson
+adapt
+adaptation
+adaptive
+add
+added
+addend
+addenda
+addendum
+addict
+Addis
+Addison
+addition
+additional
+additive
+addle
+address
+addressee
+Addressograph
+adduce
+Adelaide
+Adele
+Adelia
+Aden
+adenine
+adenoma
+adenosine
+adept
+adequacy
+adequate
+adhere
+adherent
+adhesion
+adhesive
+adiabatic
+adieu
+adipic
+Adirondack
+.H 2 "hej hopp"
+adjacent
+adject
+adjectival
+adjective
+adjoin
+adjoint
+adjourn
+adjudge
+adjudicate
+.H 2 "hej hopp"
+adjunct
+adjust
+adjutant
+Adkins
+Adler
+administer
+administrable
+administrate
+administratrix
+admiral
+admiralty
+admiration
+admire
+admissible
+admission
+admit
+admittance
+admitted
+admitting
+admix
+admixture
+admonish
+admonition
+ado
+adobe
+adolescent
+Adolph
+Adolphus
+Adonis
+adopt
+adoption
+adoptive
+adore
+adorn
+adposition
+adrenal
+adrenaline
+Adrian
+Adriatic
+Adrienne
+adrift
+adroit
+adsorb
+adsorbate
+adsorption
+adsorptive
+adulate
+adult
+adulterate
+adulterous
+adultery
+adulthood
+advance
+advantage
+advantageous
+advent
+adventitious
+adverse
+advert
+advertise
+advice
+advisable
+advise
+advisee
+advisor
+advisory
+advocacy
+advocate
+Aegean
+aegis
+Aeneas
+Aeneid
+aeolian
+Aeolus
+aerate
+aerial
+Aerobacter
+aerobic
+aerodynamic
+aerogene
+aeronautic
+aerosol
+aerospace
+Aeschylus
+aesthete
+aesthetic
+.RP 0 1
+.TC
diff --git a/contrib/mm/examples/SETR b/contrib/mm/examples/SETR
new file mode 100644
index 00000000..0a922415
--- /dev/null
+++ b/contrib/mm/examples/SETR
@@ -0,0 +1,109 @@
+.nr Cl 6
+.INITR setr
+.H 1 " granary grand grandchild grandchildren granddaughter grandeur"
+.SETR ref1
+.H 2 "grandfather grandiloquent grandiose grandma grandmother grandnephew"
+.H 2 "grandniece grandpa grandparent grandson grandstand granite granitic"
+.H 2 "granny granola grant grantee grantor granular granulate"
+.SETR ref2
+.H 2 "granule Granville grape"
+grant
+grantee
+grantor
+granular
+granulate
+.br
+granule
+.B
+REF 9:
+.GETHN ref9
+, page number
+.GETPN ref9
+.R
+Granville
+grape
+.br
+grapefruit
+grapevine
+graph
+grapheme
+graphic
+graphite
+\fBExhibit\fP
+.GETHN ex1
+
+grapple
+grasp
+grass
+grassland
+grassy
+grata
+grate
+.H 2 "grapefruit grapevine graph grapheme graphic graphite"
+.H 3 "grapple"
+.SETR ref3
+.H 3 "grasp grass grassland grassy grata grate grateful"
+.H 3 "grater gratify gratis gratitude"
+.H 4 "gratuitous gratuity grave"
+.H 4 "gravel graven"
+.SETR ref4
+.H 1 "Graves gravestone graveyard gravid gravitate gravy gray"
+.H 2 "graybeard grayish Grayson graywacke graze grease greasy great greatcoat"
+.H 2 "greater grebe Grecian Greece greed greedy Greek green Greenbelt Greenberg"
+.H 2 "Greenblatt Greenbriar Greene greenery"
+.SETR ref5
+.H 1 "Greenfield greengrocer greenhouse greenish Greenland Greensboro"
+.H 1 "greensward greenware Greenwich greenwood Greer greet"
+grant
+grantee
+.DS
+
+Advertisements contain the only truths to be relied on in a newspaper.
+ -- Thomas Jefferson
+.EX fortune "" "" ex1
+.DE
+grantor
+granular
+.GETR ref1
+granulate
+granule
+.H 2 "Using variables"
+.B
+REF 2:
+.GETHN ref2 c
+.GETPN ref2 bbb
+\*c, page number \*[bbb]
+.R
+Granville
+grape
+grapefruit
+grapevine
+graph
+grapheme
+.H 2 "Greg gregarious Gregg Gregory gremlin grenade Grendel"
+.H 2 "Grenoble Gresham Greta Gretchen"
+.SETR ref6
+.H 2 "grew"
+.H 1 "grey greyhound greylag grid griddle gridiron grief"
+.H 1 "grievance grieve grievous griffin Griffith grill grille grilled grillwork"
+.H 3 "grim grimace Grimaldi grime Grimes Grimm grin grind grindstone"
+.H 3 "grip gripe grippe grisly grist gristmill Griswold grit"
+.SETR ref7
+.H 3 "gritty grizzle grizzly groan groat grocer grocery groggy groin"
+.H 1 "grommet groom groove grope grosbeak gross Grosset Grossman Grosvenor grotesque"
+.H 1 "Groton ground groundsel groundskeep groundwork group groupoid"
+.H 4 "grout grove grovel Grover grow growl grown grownup growth grub grubby"
+.H 4 "grudge gruesome gruff grumble Grumman grunt gryphon g's"
+.SETR ref8
+.H 4 "GSA GU Guam guanidine guanine guano guarantee guaranteeing guarantor"
+.H 4 "guaranty"
+.H 1 "guard guardhouse Guardia guardian Guatemala gubernatorial Guelph Guenther"
+.H 1 "guerdon guernsey guerrilla guess guesswork guest guffaw Guggenheim"
+.SETR ref9
+.H 1 "Guiana guidance guide guidebook guideline guidepost guiding"
+.H 1 "guignol"
+.GETR ref6
+.H 1 "guild guildhall guile Guilford guillemot guillotine guilt"
+.SETR ref10
+.H 1 "guilty guinea guise guitar gules gulf gull Gullah"
+.H 1 "gullet gullible gully gulp gum gumbo gumdrop gummy gumption"
diff --git a/contrib/mm/groff_mm.man b/contrib/mm/groff_mm.man
new file mode 100644
index 00000000..9054a5a5
--- /dev/null
+++ b/contrib/mm/groff_mm.man
@@ -0,0 +1,1894 @@
+.\"
+.\" $Id: groff_mm.man,v 1.1 2000/02/06 09:34:52 wlemb Exp $
+.\"
+.de T2
+.ne 2v
+.ti -.5i
+\\$1
+.sp -1
+..
+.de T3
+.ne 2v
+.ti -.5i
+\fB\\$1\fP
+.br
+..
+.TH GROFF_MM @MAN7EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+groff_mm \- groff mm macros
+.SH SYNOPSIS
+.B groff
+.B \-m@TMAC_M_PREFIX@m
+[
+.IR options .\|.\|.
+]
+[
+.IR files .\|.\|.
+]
+.SH DESCRIPTION
+The groff mm macros are intended to be compatible with the DWB mm macros
+with the following limitations:
+.TP
+.B \(bu
+no Bell Labs localisms implemented.
+.TP
+.B \(bu
+the macros OK and PM is not implemented.
+.TP
+.B \(bu
+groff mm does not support cut marks
+.LP
+\fBm@TMAC_M_PREFIX@m\fP is intended to be international. Therefore it is
+possible to write short national macrofiles which change all
+english text to the preferred language. Use \fBm@TMAC_M_PREFIX@mse\fP as an example.
+.\"########################################################################
+.LP
+A file called \fBlocale\fP or \fIlang\fP\fB_locale\fP is read
+after the initiation of the global variables. It is therefore
+possible to localize the macros with companyname and so on.
+.sp
+In this manual square brackets is used to show optional arguments.
+.sp 3
+\fBNumber registers and strings\fP
+.br
+Many macros can be controlled by number registers and strings.
+A number register is assigned with the \fBnr\fP command:
+.br
+\fB\&.nr\fP \fIXXX\fP \fI[+-]n [i]\fP
+.br
+\fBXXX\fP is the name of the register, \fBn\fP is the value to
+be assigned, and \fBi\fP is increment value for auto-increment.
+\fBn\fP can have a plus or minus sign as prefix if an increment
+or decrement of the current value is wanted. (Auto-increment or decrement
+occurs if the number register is used with a plus or minus sign,
+\fB\en+[XXX]\fP or \fB\en-[XXX]\fP.)
+.sp
+Strings is defined with \fBds\fP.
+.br
+\fB\&.ds\fP \fIYYY string\fP
+.br
+The string is assigned everything to the end of the line, even blanks.
+Initial blanks in \fIstring\fP should be prefixed with
+a double-quote. (Strings are used in the text as \fB\e*[YYY]\fP.)
+.sp
+\fBSpecial formatting of number registers\fP
+A number register is printed with normal digits if no format has been
+given.
+Set the format with \fBaf\fP:
+.br
+\fB\&.af\fP \fIR c\fP
+.br
+\fIR\fP is the name of the register, \fIc\fP is the format.
+.in +.5i
+.T2 \fBForm\fP
+\fBSequence\fP
+.T2 1
+0, 1, 2, 3, ...
+.T2 001
+000, 001, 002, 003, ...
+.T2 i
+0, i, ii, iii, iv, ...
+.T2 I
+0, I, II, III, IV, ...
+.T2 a
+0, a, b, c, ..., z, aa, ab, ...
+.T2 A
+0, A, B, C, ..., Z, AA, AB, ...
+.in
+
+.LP
+\fBMacros:\fP
+.TP
+.B ")E level text"
+Adds \fBtext\fP (heading-text) to the table of contents
+with \fBlevel\fP either 0
+or between 1-7. See also \fB.H\fP. This macro is used for customized
+table of contents.
+.TP
+.B "1C [1]"
+Begin one column processing. An \fB1\fP as argument disables the page-break.
+Use wide footnotes, small footnotes may be overprinted.
+.TP
+.B 2C
+Begin two column processing. Splits the page in two columns. It is
+a special case of \fBMC\fP. See also \fB1C\fP.
+.TP
+.B AE
+Abstract end, see \fBAS\fP.
+.TP
+.B "AF [name of firm]"
+Authors firm, should be called before \fBAU\fP, see also \fBCOVER\fP.
+.TP
+.B "AL [type [text-indent [1]]]]"
+Start autoincrement list. Items are numbered beginning on one.
+The \fItype\fP argument controls the type of numbers.
+.in +.5i
+.T2 Arg
+Description
+.T2 1
+Arabic (the default)
+.T2 A
+Upper-case letters (A-Z)
+.T2 a
+Lower-case letters (a-z)
+.T2 I
+Upper-case roman
+.T2 i
+Lower-case roman
+.in
+\fIText-indent\fP sets the indent and overrides \fBLi\fP.
+A third argument will prohibit printing of a blank line before each
+item.
+.TP
+.B "APP name text"
+Begin an appendix with name \fIname\fP. Automatic naming occurs if
+\fIname\fP is "". The appendixes starts with \fBA\fP if auto is used.
+An new page is ejected, and a header is also produced if the number
+variable \fBAph\fP is non-zero. This is the default.
+The appendix always appear in the 'List of contents' with correct
+pagenumber. The name \fIAPPENDIX\fP can be changed by setting
+the string \fBApp\fP to the desired text.
+The string \fBApptxt\fP contains the current appendix text.
+.TP
+.B "APPSK name pages text"
+Same as \fB.APP\fP, but the pagenr is incremented with \fIpages\fP.
+This is used when diagrams or other non-formatted documents are
+included as appendixes.
+.TP
+.B "AS [arg [indent]]"
+Abstract start. Indent is specified in 'ens', but scaling is allowed.
+Argument \fIarg\fP controls where the abstract is printed.
+.in +.5i
+.T2 Arg
+Placement
+.T2 0
+Abstract will be printed on page 1 and on the cover sheet if
+used in the released-paper style (\fBMT 4\fP), otherwise
+it will be printed on page 1 without a cover sheet.
+.T2 1
+Abstract will only be printed on the cover sheet (\fBMT 4\fP only).
+.T2 2
+Abstract will be printed only on the cover sheet (other than \fBMT 4\fP only).
+The cover sheet is printed without need for \fBCS\fP.
+.in
+Abstract is not printed at all in external letters (\fBMT 5\fP).
+The \fIindent\fP controls the indentation of both margins, otherwise
+will normal text indent be used.
+.TP
+.B "AST [title]"
+Abstract title. Default is \fBABSTRACT\fP.
+Sets the text above the abstract text.
+.TP
+.B "AT title1 [title2 ...]"
+Authors title. \fBAT\fP must appear just after each \fBAU\fP.
+The title will show up after the name in the signature block.
+.TP
+.B "AU [name [initials [loc [dept [ext [room [arg [arg [arg]]]]]]]]]"
+Author information, specifies the author of the memo or paper, and
+will be printed on the cover sheet and on other similar places.
+\fBAU\fP must appear before \fBTL\fP. The author information
+can contain intials, location, department, telephone extension,
+room number or name and up to three extra arguments.
+.TP
+.B "AV [name [1]]"
+Approval signature, generates an approval line with place for
+signature and date. The string \fBAPPROVED:\fP can be changed
+with variable \fBLetapp\fP, and the string \fBDate\fP in \fBLetdate\fP.
+.TP
+.B "AVL [name]"
+Letter signature, generates a line with place for signature.
+.TP
+.B "B [bold-text [prev-font-tex [bold...]]]"
+Begin boldface
+No limit on the number of arguments.
+All arguments will be concatenated to one word, the first, third and so
+on will be printed in boldface.
+.TP
+.B B1
+Begin box (as the ms macro)
+Draws a box around the text. The text will be indented one character,
+and the right margin will be one character shorter.
+.TP
+.B B2
+End box. Finish the box started by \fBB1\fP.
+.TP
+.B BE
+End bottom block, see \fBBS\fP.
+.TP
+.B "BI [bold-text [italic-text [bold-text [...]]]"
+Bold-italic.
+No limit on the number of arguments, see \fBB\fP.
+.TP
+.B "BL [text-indent [1]]"
+Start bullet list, initialize a list with a bullet and a space
+in the beginning of each list item (see \fBLI\fP).
+\fIText-indent\fP
+overrides the default indentation of the list items set by
+number register \fBPi\fP.
+A third argument will prohibit printing of a blank line before each
+item.
+.TP
+.B "BR [bold-text [roman-text [bold-text [...]]]"
+Bold-roman.
+No limit on the number of arguments.
+.TP
+.B BS
+Bottom block start. Begins the definition of a text block wich is
+printed at the bottom of each page. Block ends with \fBBE\fP.
+.TP
+.B BVL
+Start of
+broken variable-item list.
+Broken variable-item list has no fixed mark, it assumes that
+every \fBLI\fP has a mark instead.
+The text will always begin at the next line after the mark.
+\fIText-indent\fP sets the indent to the text, and \fImark-indent\fP
+the distance from the current indent to the mark.
+A third argument will prohibit printing of a blank line before each
+item.
+.TP
+.B "COVER [arg]"
+\&\fBCOVER\fP begins a coversheet definition. It is important
+that \fB.COVER\fP appears before any normal text.
+\&\fB.COVER\fP uses \fIarg\fP to build the filename
+@TMAC_MDIR@/\fIarg\fP.cov. Therefore it is possible to create unlimited
+types of coversheets.
+\fIms.cov\fP is supposed to look like the \fBms\fP coversheet.
+\&\fB.COVER\fP requires a \fB.COVEND\fP at the end of the coverdefinition.
+Always use this order of the covermacros:
+.nf
+\&.COVER
+\&.TL
+\&.AF
+\&.AU
+\&.AT
+\&.AS
+\&.AE
+\&.COVEND
+.fi
+However, only \fB.TL\fP and \fB.AU\fP are required.
+.TP
+.B COVEND
+This finish the cover description and prints the cover-page.
+It is defined in the cover file.
+.TP
+.B DE
+Display end. Ends a block of text, display, that begins
+with \fBDS\fP or \fBDF\fP.
+.TP
+.B "DF [format [fill [rindent]]]"
+Begin floating display (no nesting allowed).
+A floating display is saved in a queue and is printed in the
+order entered. \fIFormat\fP, \fIfill\fP and \fIrindent\fP is the same
+as in \fBDS\fP.
+Floating displays are controlled by the two number registers \fBDe\fP
+and \fBDf\fP.
+.sp
+\fBDe register\fP
+.in +.5i
+.T2 0
+Nothing special, this is the default.
+.T2 1
+A page eject will occur after each printed display, giving only
+one display per page and no text following it.
+.in
+.sp
+\fBDf register\fP
+.in +.5i
+.T2 0
+Displays are printed at the end of each section (when section-page
+numbering is active) or at the end of the document.
+.T2 1
+A new display will be printed on the current page is there is enough
+space, otherwise it will be printed at the end of the document.
+.T2 2
+One display will be printed at the top of each page or column
+(in multi-column mode).
+.T2 3
+Print one display if there is enough space for it, otherwise it will
+be printed at the top of the next page or column.
+.T2 4
+Print as many displays that will fit in a new page or column.
+A page break will occur between each display if \fBDe\fP is not zero.
+.T2 5
+Fill the current page with displays and the rest beginning at a new page
+or column. (This is the default.)
+A page break will occur between each display
+if \fBDe\fP is not zero.
+.in
+.TP
+.B "DL [text-indent [1]]"
+Dash list start. Begins a list where each item is printed
+after a dash. \fIText-indent\fP changes the default indentation
+of the list items set by
+number register \fBPi\fP.
+A third argument will prohibit printing of a blank line before each
+item.
+A second argument prevents the empty line between each list item
+to be printed. See \fBLI\fP.
+.TP
+.B "DS [format [fill [rindent]]]"
+Static display start.
+Begins collection of text until \fBDE\fP.
+The text is printed together on the same page, unless it is longer
+than the height of the page.
+\fBDS\fP can be nested to a unlimited depth (reasonably :-).
+.sp
+\fBformat\fP
+.in +.5i
+.ds x "
+.T2 """"""
+No indentation.
+.T2 none
+No indentation.
+.T2 L
+No indentation.
+.T2 I
+Indent text with the value of number register \fBSi\fP.
+.T2 C
+Center each line
+.T2 CB
+Center the whole display as a block.
+.T2 R
+Right adjust the lines.
+.T2 RB
+Right adjust the whole display as a block
+.in
+.sp
+L, I, C and CB can also be specified as 0, 1, 2 or 3 for compatibility
+reasons. (Don't use it. :-)
+.sp
+\fBfill\fP
+.in +.5i
+.T2 """"""
+Line-filling turned off.
+.T2 none
+Line-filling turned off.
+.T2 N
+Line-filling turned off.
+.T2 F
+Line-filling turned on.
+.in
+.sp
+N and F can also be specified as 0 or 1.
+An empty line will normally be printed before and after the
+display. Setting number register \fBDs\fP to 0 will prevent this.
+\fIRindent\fP shortens the line length by that amount.
+.TP
+.B "EC [title [override [flag [refname]]]]"
+Equation title.
+Sets a title for an equation. The \fIoverride\fP argument
+change the numbering.
+.sp
+\fBflag\fP
+.in +.5i
+.T2 none
+\fIoverride\fP is a prefix to the number.
+.T2 0
+\fIoverride\fP is a prefix to the number.
+.T2 1
+\fIoverride\fP is a suffix to the number.
+.T2 2
+\fIoverride\fP replaces the number.
+.in
+\fBEC\fP uses the number register \fBEc\fP as counter.
+It is possible to use \fB.af\fP to change the format of the number.
+If number register \fBOf\fP is 1, then the format of title
+will use a dash instead of a dot after the number.
+.br
+The string \fBLe\fP controls the title of the
+List of Equations, default is \fILIST OF EQUATIONS\fP.
+The List of Equations will only be printed if number register \fBLe\fP
+is 1, default 0.
+The string \fBLiec\fP contains the word \fIEquation\fP, wich
+is printed before the number.
+If \fIrefname\fP is used, then the equation number is saved with
+\&\fB.SETR\fP, and can be retrieved with \fB.GETST\fP \fIrefname\fP.
+.br
+Special handling of the title will occur if
+\fBEC\fP is used inside \fBDS\fP/\fBDE\fP, it will not be
+affected by the format of \fBDS\fP.
+.TP
+.B "EF [arg]"
+Even-page footer, printed just above the normal page footer
+on even pages, see \fBPF\fP.
+.TP
+.B "EH [arg]"
+Even-page header, printed just below the normal page header
+on even pages, see \fBPH\fP.
+.TP
+.B EN
+Equation end, see \fBEQ\fP.
+.TP
+.B EOP
+End of page user-defined macro. This macro will be called
+instead of the normal printing of the footer. The macro
+will be executed in a separate environment, without any
+trap active. See \fBTP\fP.
+.sp
+\fBStrings available to EOP\fP
+.in +.5i
+.T2 EOPf
+Argument from \fBPF\fP.
+.T2 EOPef
+Argument from \fBEF\fP.
+.T2 EOPof
+Argument from \fBOF\fP.
+.in
+.TP
+.B "EPIC width height [name]"
+\fBEPIC\fP draws a box with the given \fIwidth\fP and \fIheight\fP, it will
+also print the text \fIname\fP or a default string if
+\fIname\fP is not specified..
+This is used to include external pictures, just give the size
+of the picture.
+See \fBPIC\fP
+.TP
+.B "EQ [label]"
+Equation start.
+\fBEQ\fP/\fBEN\fP are the delimiters for equations written for \fBeqn\fP.
+\fBEQ\fP/\fBEN\fP must be inside a \fBDS\fP/\fBDE\fP-pair, except
+when \fBEQ\fP is only used to set options in \fBeqn\fP.
+The \fIlabel\fP will appear at the right margin of the equation, unless
+number register \fBEq\fP is 1. Then the label will appear at the
+left margin.
+.TP
+.B "EX [title [override [flag [refname]]]]"
+Exhibit title, arguments are the same as for \fBEC\fP.
+\fBEX\fP uses the number register \fBEx\fP as counter.
+The string \fBLx\fP controls the title of the
+List of Exhibits, default is \fILIST OF EXHIBITS\fP.
+The List of Exhibits will only be printed if number register \fBLx\fP
+is 1, default 1.
+The string \fBLiex\fP contains the word \fIExhibit\fP, wich
+is printed before the number.
+If \fIrefname\fP is used, then the exhibit number is saved with
+\&\fB.SETR\fP, and can be retrieved with \fB.GETST\fP \fIrefname\fP.
+.br
+Special handling of the title will occur if
+\fBEX\fP is used inside \fBDS\fP/\fBDE\fP, it will not be
+affected by the format of \fBDS\fP.
+.TP
+.B "FC [closing]"
+Prints \fIYours\ very\ truly,\fP as a formal closing of a letter or
+memorandum. The argument replaces the defualt string.
+The default is stored in string variable \fBLetfc\fP.
+.TP
+.B "FD [arg [1]]"
+Footnote default format.
+Controls the hyphenation (hyphen), right margin justification (adjust),
+indentation of footnote text (indent). It can also change the label
+justification (ljust).
+.sp
+.ne 14v
+.nf
+.ta .5i +.8i +.8i +.8i +.8i
+\fBarg hyphen adjust indent ljust\fP
+0 no yes yes left
+1 yes yes yes left
+2 no no yes left
+3 yes no yes left
+4 no yes no left
+5 yes yes no left
+6 no no no left
+7 yes no no left
+8 no yes yes right
+9 yes yes yes right
+10 no no yes right
+11 yes no yes right
+.sp
+.fi
+.DT
+Argument greater than or equal to 11 is considered as arg 0.
+Default for m@TMAC_M_PREFIX@m is 10.
+.TP
+.B FE
+Footnote end.
+.TP
+.B "FG [title [override [flag [refname]]]]"
+Figure title, arguments are the same as for \fBEC\fP.
+\fBFG\fP uses the number register \fBFg\fP as counter.
+The string \fBLf\fP controls the title of the
+List of Figures, default is \fILIST OF FIGURES\fP.
+The List of Figures will only be printed if number register \fBLf\fP
+is 1, default 1.
+The string \fBLifg\fP contains the word \fIFigure\fP, wich
+is printed before the number.
+If \fIrefname\fP is used, then the figure number is saved with
+\&\fB.SETR\fP, and can be retrieved with \fB.GETST\fP \fIrefname\fP.
+.br
+Special handling of the title will occur if
+\fBFG\fP is used inside \fBDS\fP/\fBDE\fP, it will not be
+affected by the format of \fBDS\fP.
+.TP
+.B "FS [label]"
+Footnote start.
+The footnote is ended by \fBFE\fP. Footnotes is normally automatically
+numbered, the number is available in string \fBF\fP.
+Just add \fB\e*F\fP in the text. By adding \fIlabel\fP, it is possible
+to have other number or names on the footnotes.
+Footnotes in displays is now possible.
+An empty line separates footnotes, the height of the line
+is controlled by number register \fBFs\fP, default value is 1.
+.TP
+.B "GETHN refname [varname]"
+Includes the headernumber where the corresponding \fBSETR\fP \fIrefname\fP
+was placed. Will be X.X.X. in pass 1. See \fBINITR\fP.
+If varname is used, \fBGETHN\fP sets the stringvariable \fIvarname\fP to the
+headernumber.
+.TP
+.B "GETPN refname [varname]"
+Includes the pagenumber where the corresponding \fBSETR\fP \fIrefname\fP
+was placed. Will be 9999 in pass 1. See \fBINITR\fP.
+If varname is used, \fBGETPN\fP sets the stringvariable \fIvarname\fP
+to the pagenumber.
+.TP
+.B "GETR refname"
+Combines \fBGETHN\fP and \fBGETPN\fP with the text 'chapter' and ', page'.
+The string \fIQrf\fP contains the text for reference:
+.ti +.5i
+\&.ds Qrf See chapter \e\e*[Qrfh], page \e\e*[Qrfp].
+.br
+\fIQrf\fP may be changed to support other languages.
+Strings \fIQrfh\fP and \fIQrfp\fP are set by \fBGETR\fP
+and contains the page and headernumber.
+.TP
+.B "GETST refname [varname]"
+Includes the string saved with the second argument to \fB.SETR\fP.
+Will be dummystring in pass 1.
+If varname is used, \fBGETST\fP sets the stringvariable \fIvarname\fP to the
+saved string. See \fBINITR\fP.
+.TP
+.B "H level [heading-text [heading-suffix]]"
+Numbered section heading.
+Section headers can have a level between 1 and 7, level 1 is the
+top level. The text is given in \fIheading-text\fP, and must be
+surrounded by double quotes if it contains spaces.
+\fBHeading-suffix\fP is added to the header in the text but not in
+the table of contents. This is normally used for footnote marks
+and similar things. Don't use \fB\e*F\fP in \fIheading-suffix\fP, it won't
+work. A manual label must be used, see \fBFS\fP.
+.sp
+An eventual paragraph, \fBP\fP, directly after \fBH\fP will be
+ignored, \fBH\fP is taking care of spacing and indentation.
+.sp
+\fBPage ejection before heading\fP
+.br
+Number register \fBEj\fP controls page ejection before the heading.
+Normally, a level one heading gets two blank lines before it, higher levels
+gets only one. A new page is ejected before each
+first-level heading if number register \fBEj\fP is 1.
+All levels below or equal the value of \fBEj\fP gets a new page.
+Default value for \fBEj\fP is 0.
+.sp
+\fBHeading break level\fP
+.br
+A line break occurs after the heading if the heading level is less
+or equal to number register \fBHb\fP.
+Default value 2.
+.sp
+\fBHeading space level\fP
+.br
+A blank line is inserted after the heading if the heading level is less
+or equal to number register \fBHs\fP.
+Default value 2.
+.sp
+Text will follow the heading on the same line if the level is greater
+than both \fBHb\fP and \fBHs\fP.
+.sp
+\fBPost-heading indent\fP
+.br
+Indentation of the text after the heading is controlled by number
+register \fBHi\fP, default value 0.
+\fBHi\fP
+.in +.5i
+.T2 0
+The text will be left-justified.
+.T2 1
+Indentation of the text will follow the value of number register \fBPt\fP,
+see \fBP\fP.
+.T2 2
+The text will be lined up with the first word of the heading.
+.in
+.sp
+\fBCentered section headings\fP
+.br
+All headings whose level is equal or below number register \fBHc\fP
+and also less than or equal to \fBHb\fP or \fBHs\fP
+is centerered.
+.sp
+\fBFont control of the heading\fP
+.br
+The font of each heading level is controlled by string \fBHF\fP.
+It contains a fontnumber or fontnam for each level. Default
+is \fB2\ 2\ 2\ 2\ 2\ 2\ 2\fP (all headings in italic).
+Could also be written as \fBI\ I\ I\ I\ I\ I\ I\fP.
+All omitted values are presumed to be a 1.
+.sp
+\fBPoint size control\fP.
+.br
+String \fBHP\fP controls the pointsize of each heading, in the
+same way as \fBHF\fP controls the font.
+A value of 0 selects the default point size.
+Default value is \fB0\ 0\ 0\ 0\ 0\ 0\ 0\fP. Beware that only the
+point size changes, not the vertical size.
+That can be controlled by the user specified macro \fBHX\fP and/or
+\fBHZ\fP.
+.sp
+\fBHeading counters\fP
+.br
+Seven number registers, named \fBH1\fP thru \fBH7\fP contains
+the counter for each heading level.
+The values are printed using arabic numerals, this can be changed
+with the macro \fBHM\fP (see below).
+All marks ar concatenated before printing. To avoid this, set
+number register \fBHt\fP to 1. That will only print the current
+heading counter at each heading.
+.sp
+\fBAutomatic table of contents\fP
+.br
+All headings whose level is equal or below number register \fBCl\fP
+is saved to be printed in the table of contents. Default value is 2.
+.sp
+\fBSpecial control of the heading, user-defined macros\fP.
+.br
+These macros can be defined by the user to get a finer control
+of vertical spacing, fonts or other features.
+Argument \fIlevel\fP is the level-argument to \fBH\fP, but
+0 for unnumbered headings (see \fBHU\fP).
+Argument \fIrlevel\fP is the real level, it is
+set to number register \fBHu\fP for unnumbered headings.
+Argument \fIheading-text\fP is the text argument to \fBH\fP and \fBHU\fP.
+.sp
+\fBHX\ \fP\fIlevel\ rlevel\ heading-text\fP
+.br
+\fBHX\fP is called just before the printing of the heading.
+The following register is available for \fBHX\fP.
+\fBHX\fP may alter \fB}0\fP, \fB}2\fP and \fB;3\fP.
+.in +.5i
+.T3 "string }0"
+Contains the heading mark plus two spaces if \fIrlevel\fP is non-zero,
+otherwise empty.
+.T3 "register ;0"
+Contains the position of the text after the heading.
+0 means that the text should follow the heading on the same line, 1
+means that a line break should occur before the text and
+2 means that a blank line should separate the heading and the text.
+.T3 "string }2"
+Contains two spaces if register \fB;0\fP is 0. It is used to
+separate the heading from the text. The string
+is empty if \fB;0\fP is non-zero.
+.T3 "register ;3"
+Contains the needed space in units after the heading.
+Default is 2v.
+
+Can be used to change things like numbering (\fB}0\fP),
+vertical spacing (\fB}2\fP)
+and the needed space after the heading.
+.in
+.sp
+\fBHY\ \fP\fIdlevel\ rlevel\ heading-text\fP
+.br
+\fBHY\fP is called after size and font calculations and
+might be used to change indentation.
+.sp
+\fBHZ\ \fP\fIdlevel\ rlevel\ heading-text\fP
+\fBHZ\fP is called after the printing of the heading, just before
+\fBH\fP or \fBHU\fP exits.
+Could be used to change the page header according to the section heading.
+.TP
+.B "HC [hyphenation-character]"
+Set hyphenation character.
+Default value is \e%.
+Resets to the default if called without argument.
+Hyphenation can be turned by setting number
+register \fBHy\fP to 0 in the beginning of the file.
+.TP
+.B "HM [arg1 [arg2 [... [arg7]]]]"
+Heading mark style.
+Controls the type of marking for printing of the heading counters.
+Default is 1 for all levels.
+.sp
+\fBArgument\fP
+.in +.5i
+.T2 1
+Arabic numerals.
+.T2 0001
+Arabic numerals with leading zeroes, one or more.
+.T2 A
+Upper-case alphabetic
+.T2 a
+Lower-case alphabetic
+.T2 I
+Upper-case roman numerals
+.T2 i
+lower-case roman numerals
+.T2 \fIempty\fP
+Arabic numerals.
+.in
+.TP
+.B "HU heading-text"
+Unnumbered section header.
+\fBHU\fP behavies like \fBH\fP at the level in number register \fBHu\fP.
+See \fBH\fP.
+.TP
+.B "HX dlevel rlevel heading-text"
+Userdefined heading exit.
+Called just before printing the header.
+See \fBH\fP.
+.TP
+.B "HY dlevel rlevel heading-text"
+Userdefined heading exit.
+Called just before printing the header.
+See \fBH\fP.
+.TP
+.B "HZ dlevel rlevel heading-text"
+Userdefined heading exit.
+Called just after printing the header.
+See \fBH\fP.
+.TP
+.B "I [italic-text [prev-font-text [italic-text [...]]]"
+Italic.
+Changes the font to italic if called without arguments.
+With one argument it will set the word in italic.
+With two argument it will concatenate them and set the first
+word in italic and the second in the previous font.
+There is no limit on the number of argument, all will be concatenated.
+.TP
+.B "IA [addressee-name [title]]
+Begins specification of the addressee and addressee's address in
+letter style.
+Several names can be specified with empty \fBIA\fP/\fBIE\fP-pairs, but
+only one address.
+See \fBLT\fP.
+.TP
+.B "IB [italic-text [bold-text [italic-text [...]]]"
+Italic-bold
+Even arguments is printed in italic, odd in boldface.
+See \fBI\fP.
+.TP
+.B IE
+Ends the address-specification after \fPIA\fP.
+.TP
+.B "INITI type filename [macro]"
+Initialize the new index system, sets the filename to collect
+index lines in with \fBIND\fP. Argument \fItype\fP selects
+the type of index, page number, header marks or both.
+The default is \fIN\fP.
+
+It is also possible to create a macro that is responsible
+for formatting each row. Add the name of the macro as argument 3.
+The macro will be called with the index as argument(s).
+.sp
+\fBtype\fP
+.in +.5i
+.T2 N
+Page numbers
+.T2 H
+Header marks
+.T2 B
+Both page numbers and header marks, tab separated
+.in
+.TP
+.B "INITR filename"
+Initialize the refencemacros. References will be written to
+\fIfilename.tmp\fP and \fIfilename.qrf\fP. Requires two passes with groff.
+The first looks for references and the second includes them.
+\fBINITR\fP can be used several times, but it is only the first
+occurrence of \fBINITR\fP that is active.
+Option \fB-U\fP might be needed if \fBunsafe\fP-errors occur.
+See also \fBSETR\fP, \fBGETPN\fP and \fBGETHN\fP.
+.TP
+.B "IND arg1 [arg2 [...]]"
+\fBIND\fP writes a line in the index file selected by \fBINITI\fP
+with all arguments and the page number or header mark separated by tabs.
+.in +.5i
+\fBExamples\fP
+.br
+arg1\etpage number
+.br
+arg1\etarg2\etpage number
+.br
+arg1\etheader mark
+.br
+arg1\etpage number\etheader mark
+.in
+.TP
+.B "INDP"
+\fBINDP\fP prints the index by running the command specified
+by string variable \fBIndcmd\fP, normally \fIsort\ -t\et\fP.
+\fBINDP\fP reads the output from the command to form
+the index, normally in two columns (can be changed by defining \fBTYIND\fP).
+The index is printed with string variable \fBIndex\fP as header,
+default is \fBINDEX\fP. One-column processing is
+returned after the list. \fBINDP\fP will call the
+user-defined macros \fBTXIND\fP, \fBTYIND\fP and \fBTZIND\fP if defined.
+\fBTXIND\fP is called before printing \fBINDEX\fP, \fBTYIND\fP
+is called instead of printing \fBINDEX\fP. \fBTZIND\fP is called
+after the printing and should take care of restoring to normal
+operation again.
+.TP
+.B "ISODATE [0]"
+\fBISODATE\fP changes the predefined date string in \fBDT\fP to
+ISO-format, ie YYYY-MM-DD. This can also be done by
+adding \fB-rIso=1\fP on the command line.
+Reverts to old date format if argument is \fB0\fP.
+.TP
+.B "IR [italic-text [roman-text [italic-text [...]]]"
+Italic-roman
+Even arguments is printed in italic, odd in roman.
+See \fBI\fP.
+.TP
+.B "LB text-indent mark-indent pad type [mark [LI-space [LB-space]]]"
+List begin macro.
+This is the common macro used for all lists.
+\fIText-indent\fP is the number of spaces to indent the text from the
+current indent.
+.sp
+\fIPad\fP and \fImark-indent\fP controls where to put the mark.
+The mark is placed within the mark area, and \fImark-indent\fP
+sets the number of spaces before this area. It is normally 0.
+The mark area ends where the text begins. The start of the text
+is still controlled by \fItext-indent\fP.
+.sp
+The mark is left justified whitin the mark area if \fIpad\fP is 0.
+If \fIpad\fP is greater than 0, then \fImark-indent\fP is ignored, and
+the mark is placed \fIpad\fP spaces before the text.
+This will right justify the mark.
+.sp
+If \fItype\fP is 0 the list will have either a hanging indent or, if
+argument \fImark\fP is given, the string \fImark\fP as mark.
+.sp
+If \fItype\fP is greater than 0 automatic numbering will occur, arabic
+if \fImark\fP is empty. \fIMark\fP can then be any of \fB1\fP, \fBA\fP,
+\fBa\fP, \fBI\fP or \fBi\fP.
+.sp
+\fIType\fP selects one of six possible ways to display the mark.
+.br
+\fBtype\fP
+.in +.6i
+.T2 1
+x.
+.T2 2
+x)
+.T2 3
+(x)
+.T2 4
+[x]
+.T2 5
+<x>
+.T2 6
+{x}
+.in
+.sp
+Every item in the list will get \fILI-space\fP number of blank lines
+before them. Default is 1.
+.sp
+\fBLB\fP itself will print \fILB-space\fP blank lines. Default is 0.
+.TP
+.B "LC [list-level]"
+List-status clear
+Terminates all current active lists down to \fIlist-level\fP, or 0
+if no argmuent is given. This is used by \fBH\fP to clear any
+active list.
+.TP
+.B "LE [1]"
+List end.
+Terminate the current list. \fBLE\fP outputs a blank line
+if an argument is given.
+.TP
+.B "LI [mark [1]]"
+List item precedes every item in a list. Without argument \fBLS\fP
+will print the mark determined by the current list type. By giving
+\fBLI\fP one argument, it will use that as the mark instead.
+Two arguments to \fBLI\fP will make \fImark\fP a prefix to
+the current mark.
+There will be no separating space between the prefix
+and the mark if the second argument is \fB2\fP instead of \fB1\fP.
+This behaviour can also be achieved by setting number register
+\fBLimsp\fP to zero.
+A zero length \fImark\fP will make a hanging
+indent instead.
+.sp
+A blank line is normally printed before the list item. This behaviour
+can be controlled by number register \fBLs\fP. Pre-spacing
+will occur for each list-level less than or equal to \fBLs\fP.
+Default value is 99. (Nesting of lists is unlimited. :-)
+.sp
+The indentation can be changed thru number register \fBLi\fP.
+Default is 6.
+.sp
+All lists begins with a list initialization macro, \fBLB\fP.
+There are, however, seven predefined listtypes to
+make lists easier to use. They all call \fBLB\fP with different
+default values.
+.in +.5i
+.T2 \fBAL\fP
+Automatically Incremented List
+.T2 \fBML\fP
+Marked List
+.T2 \fBVL\fP
+Variable-Item List
+.T2 \fBBL\fP
+Bullet List
+.T2 \fBDL\fP
+Dash List
+.T2 \fBRL\fP
+Reference List
+.T2 \fBBVL\fP
+Broken Varable List.
+.in
+These lists are described at other places in this manual. See also \fBLB\fP.
+.TP
+.B "LT [arg]"
+Formats a letter in one of four different styles depending
+on the argument.
+See also \fBINTERNALS\fP.
+.in +.5i
+.T2 \fBArg
+Style\fP
+.T2 BL
+Blocked. Date line, return address, writer's address and closing
+begins at the center of the line. All other lines begins at the left margin.
+.T2 SB
+Semi-blocked. Same as blocked, except that the first line in every
+paragraph is indented five spaces.
+.T2 FB
+Full-blocked. All lines begin at the left margin.
+.T2 SP
+Simplified. Almost the same as the full-blocked style. Subject and
+the writer'sidentification is printed in all-capital.
+.in
+.TP
+.B "LO type [arg]"
+Specify options in letter (see \fB.LT\fP).
+This is a list of the standard options:
+.in +.5i
+.T2 CN
+Confidential notation. Prints \fBRESTRICTED\fP on the second line
+below the date line. Any argument replaces \fBRESTRICTED\fP.
+See also string variable \fBLetCN\fP.
+.T2 RN
+Reference notation. Prints \fBIn reference to:\fP and the argument
+two lines below the date line.
+See also string variable \fBLetRN\fP.
+.T2 AT
+Attention. Prints \fBATTENTION:\fP and the argument below the inside address.
+See also string variable \fBLetAT\fP.
+.T2 SA
+Salutation. Prints \fBTo Whom It May Concern:\fP or the argument if
+it was present. The salutation is printed two lines below the inside address.
+See also string variable \fBLetSA\fP.
+.T2 SJ
+Subject line. Prints the argument as subject prefixed with \fBSUBJECT:\fP
+two lines below the inside address, except in letter type \fBSP\fP.
+Then the subject is printed in all-captial without any prefix.
+See also string variable \fBLetSJ\fP.
+.in
+.TP
+.B "MC column-size [column-separation] "
+Begin multiple columns. Return to normal with \fB1C\fP.
+\fBMC\fP will create as many columns as the current line length permits.
+\fIColumn-size\fP is the width of each column, and \fIcolumn-separation\fP
+is the space between two columns. Default separation is the
+column-size/15.
+See also \fB1C\fP.
+.TP
+.B "ML mark [text-indent [1]]"
+Marked list start. The \fImark\fP argument will be printed before
+each list item.
+\fIText-indent\fP sets the indent and overrides \fBLi\fP.
+A third argument will prohibit printing of a blank line before each
+item.
+.TP
+.B "MT [arg [addressee]]"
+Memorandum type.
+The \fIarg\fP is part of a filename in \fI@TMAC_MDIR@/*.MT\fP.
+Memorandum type 0 thru 5 are supported, including \fI"string"\fP.
+\fIAddresse\fP just sets a variable, used in the AT&T macros.
+.br
+\fBarg\fP
+.in +.5i
+.T2 0
+Normal memorandum, no type printed
+.T2 1
+Memorandum with \fIMEMORANDUM FOR FILE\fP printed
+.T2 2
+Memorandum with \fIPROGRAMMER'S NOTES\fP printed
+.T2 3
+Memorandum with \fIENGINEER'S NOTES\fP printed
+.T2 4
+Released paper style
+.T2 5
+External letter style
+.in
+See also \fBCOVER\fP/\fBCOVEND\fP, a more flexible type of front page.
+.TP
+.B "MOVE y-pos [x-pos [line-length]]"
+Move to a position, pageoffset set to \fIx-pos\fP.
+If \fIline-length\fP is not given, the difference between
+current and new pageoffset is used.
+Use \fBPGFORM\fP without arguments to return to normal.
+.TP
+.B "MULB cw1 space1 [cw2 space2 [cw3 ...]]"
+Begin a special multi-column mode. Every columns width must be specified.
+Also the space between the columns must be specified. The last column
+does not need any space-definition. MULB starts a diversion and MULE
+ends the diversion and prints the columns.
+The unit for width and space is 'n', but MULB accepts all
+normal unitspecifications like 'c' and 'i'.
+MULB operates in a separate environment.
+.TP
+.B "MULN"
+Begin the next column. This is the only way to switch column.
+.TP
+.B "MULE"
+End the multi-column mode and print the columns.
+.TP
+.B "nP [type]"
+Print numbered paragraph with header level two. Se \fB.P\fP.
+.TP
+.B "NCOL"
+Force printing to the next column, don't use this together with
+the \fBMUL*\fP macros, see \fB2C\fP.
+.TP
+.B "NS [arg [1]]"
+Prints different types of notations. The argument selects between
+the predefined type of notations. If the second argument is available,
+then the argument becomes the entire notation.
+If the argument doesn't exist in the predefined, it will be
+printed as \fBCopy (\fP\fIarg\fP\fB) to\fP.
+It is possible to add more standard notations, see the string variable
+\fBLetns\fP and \fBLetnsdef\fP.
+.nf
+.in +.5i
+.T2 \fBArg
+Notation\fP
+.T2 \fInone\fP
+Copy To
+.T2 """""
+Copy To
+.T2 1
+Copy To (with att.) to
+.T2 2
+Copy To (without att.) to
+.T2 3
+Att.
+.T2 4
+Atts.
+.T2 5
+Enc.
+.T2 6
+Encs.
+.T2 7
+Under separate cover
+.T2 8
+Letter to
+.T2 9
+Memorandum to
+.T2 10
+Copy (with atts.) to
+.T2 11
+Copy (without atts.) to
+.T2 12
+Abstract Only to
+.T2 13
+Complete Memorandum to
+.T2 14
+CC
+.in
+.fi
+.TP
+.B "ND new-date"
+New date. Override the current date. Date is not
+printed if \fInew-date\fP is an empty string.
+.TP
+.B "OF [arg]"
+Odd-page footer, a line printed just above the normal footer.
+See \fBEF\fP and \fBPF\fP.
+.TP
+.B "OH [arg]"
+Odd-page header, a line printed just below the normal header.
+See \fBEH\fP and \fBPH\fP.
+.TP
+.B OP
+Make sure that the following text is printed at the top
+of an odd-numbered page. Will not output an empty page
+if currently at the top of an odd page.
+.TP
+.B "P [type]"
+Begin new paragraph.
+\fBP\fP without argument will produce left justified text, even
+the first line of the paragraph. This is the same as setting
+\fItype\fP to 0. If the argument is 1, then the first line
+of text following \fBP\fP will be indented by the number of
+spaces in number register \fBPi\fP, normally 5.
+.sp
+Instead of giving 1 as argument to \fBP\fP it is possible to set the
+paragraph type in number register \fBPt\fP. Using 0 and 1
+will be the same as adding that value to \fBP\fP.
+A value of 2 will indent all paragraphs, except after
+headings, lists and displays.
+.sp
+The space between two paragraphs is controlled by number register \fBPs\fP,
+and is 1 by default (one blank line).
+.TP
+.B "PGFORM [linelength [pagelength [pageoffset [1]]]]"
+Sets linelength, pagelength and/or pageoffset.
+This macro can be used for special formatting, like letterheads
+and other.
+It is normally the first command in a file, though it's not necessary.
+\fBPGFORM\fP can be used without arguments
+to reset everything after a \fBMOVE\fP.
+A line-break is done unless the fourth argument is given.
+This can be used to avoid the pagenumber on the first page while setting
+new width and length.
+(It seems as if this macro sometimes doesn't work too well.
+Use the command line arguments
+to change linelength, pagelength and pageoffset instead. Sorry.)
+.TP
+.B PGNH
+No header is printed on the next page. Used to get rid off
+the header in letters or other special texts
+This macro must be used before any text to inhibit the pageheader
+on the first page.
+.TP
+.B PIC [-L] [-C] [-R] [-I n] filename [width [height]]
+\fBPIC\fP includes a Postscript file in the document.
+The macro depends on \fBmmroff\fP and \fBINITR\fP.
+\fB-L\fP, \fB-C\fP, \fB-R\fP and \fB-I n\fP adjusts the picture
+or indents it. The optionally \fIwidth\fP and \fIheight\fP
+can also be given to resize the picture.
+.TP
+.B PE
+Picture end.
+Ends a picture for \fB@TMAC_M_PREFIX@pic\fP, see the manual for \fB@TMAC_M_PREFIX@pic\fP.
+.TP
+.B "PF [arg]"
+Page footer.
+\fBPF\fP sets the line to be printed at the bottom of each page.
+Normally empty. See \fBPH\fP for the argument specification.
+.TP
+.B "PH [arg]"
+Page header, a line printed at the top of each page.
+The argument should be specified as "'left-part'center-part'right-part'",
+where left-, center- and right-part is printed left-justified, centered
+and right justified. The character \fB%\fP is changed to the current
+page number. The default page-header is "''- % -''", the page
+number between two dashes.
+.TP
+.B PS
+Picture start (from pic). Begins a picture for \fB@TMAC@pic\fP, see
+the manual.
+.TP
+.B PX
+Page-header user-defined exit.
+\fBPX\fP is called just after the printing of the page header
+in \fIno-space\fP mode.
+.TP
+.B R
+Roman.
+Return to roman font, see also \fBI\fP.
+.TP
+.B "RB [roman-text [bold-text [roman-text [...]]]"
+Roman-bold.
+Even arguments is printed in roman, odd in boldface.
+See \fBI\fP.
+.TP
+.B "RD [prompt [diversion [string]]]"
+Read from standard input to diversion and/or string.
+The text will be saved in a diversion named \fIdiversion\fP.
+Recall the text by writing the name of the diversion after a dot
+on an empty line. A string will also be defined if
+\fIstring\fP is given. \fIDiversion\fP and/or \fIprompt\fP can
+be empty ("").
+.TP
+.B RF
+Reference end. Ends a reference definition and returns to normal
+processing. See \fBRS\fP.
+.TP
+.B "RI [roman-text [italic-text [roman-text [...]]]"
+Even arguments is printed in roman, odd in italic.
+See \fBI\fP.
+.TP
+.B "RL [text-indent [1]]"
+Reference list start
+Begins a list where each item is preceded with a automatically
+incremented number between
+square brackets.
+\fIText-indent\fP changes the default indentation
+.TP
+.B "RP [arg1 [arg2]]"
+Produce reference page.
+\fBRP\fP can be used if a reference page is wanted somewhere in the
+document. It is not needed if \fBTC\fP is used to produce
+a table of content. The reference page will then be printed automatically.
+.sp
+The reference counter will not be resetted if \fIarg1\fP is 1.
+.sp
+\fIArg2\fP tells \fBRP\fP whether to eject a page or not.
+.br
+\fBArg2\fP
+.in +.5i
+.T2 0
+The reference page will be printed on a separate page.
+This is
+the default.
+.T2 1
+Do not eject page after the list.
+.T2 2
+Do not eject page before the list.
+.T2 3
+Do not eject page before and after the list.
+.in
+The reference items will be separated by a blank line.
+Setting number register \fBLs\fP to 0 will suppress the line.
+.sp
+The string \fBRp\fP contains the reference page title and
+is normally set to \fIREFERENCES\fP.
+.TP
+.B "RS [string-name]"
+\fBRS\fP begins an automatically numbered reference definition.
+Put the string \fB\e*(Rf\fP where the reference mark
+should be and write the reference between \fBRS\fP/\fBRF\fP
+at next new line after the reference mark. The reference number
+is stored in number register \fB:R\fP.
+If \fIstring-name\fP is given, a string with that name
+will be defined and contain the current reference mark.
+The string can be referenced as \fB\e*[\fIstring-name\fP]\fP later in
+the text.
+.TP
+.B "S [size [spacing]]"
+Set point size and vertical spacing. If any argument is equal 'P', then
+the previous value is used. A 'C' means current value, and 'D' default value.
+If '+' or '-' is used before the value, then increment or decrement of
+the current value will be done.
+.TP
+.B "SA [arg]"
+Set right-margin justification.
+Justification is normally turned on.
+No argumenent or \fB0\fP turns off justification, a \fB1\fP turns on
+justification.
+.TP
+.B "SETR refname [string]"
+Remember the current header and page-number as refname.
+Saves \fIstring\fP if \fIstring\fP is defined. \fIstring\fP is retrieved
+with \fB.GETST\fP.
+See \fBINITR\fP.
+.TP
+.B "SG [arg [1]]"
+Signature line. Prints the authors name(s) after the formal closing.
+The argument will be appended to the reference data, printed
+at either the first or last author. The reference data is the location,
+department and initials specified with \fB.AU\fP.
+It will be printed at the first author, otherwise at the last.
+No reference data will be printed if the author(s) is specifed
+thru \fB.WA\fP/\fB.WE\fP.
+See \fBLetter internals\fP.
+.TP
+.B "SK [pages]"
+Skip pages.
+If \fIpages\fP is \fB0\fP or omitted, a skip to the next page
+will occur unless it is already at the top of a page.
+Otherwise it will skip \fIpages\fP pages.
+.TP
+.B "SM string1 [string2 [string3]]"
+Make a string smaller.
+If \fIstring2\fP is given, \fIstring1\fP will be smaller and \fIstring2\fP
+normal, concatenated with \fIstring1\fP. With three argument, all is
+concatenated, but only \fIstring2\fP is made smaller.
+.TP
+.B "SP [lines]"
+Space vertically. \fIlines\fP can have any scalingfactor, like \fI3i\fP or
+\fI8v\fP. Several \fBSP\fP in a line will only produce the
+maximum number of lines, not the sum. \fBSP\fP will also be ignored
+until the first textline in a page. Add a \fB\e&\fP before \fBSP\fP
+to avoid this.
+.TP
+.B TAB
+reset tabs to every 5n. Normally used to reset any previous tabpositions.
+.TP
+.B "TB [title [override [flag [refname]]]]"
+Table title, arguments are the same as for \fBEC\fP.
+\fBTB\fP uses the number register \fBTb\fP as counter.
+The string \fBLt\fP controls the title of the
+List of Tables, default is \fILIST OF TABLES\fP.
+The List of Tables will only be printed if number register \fBLt\fP
+is 1, default 1.
+The string \fBLitb\fP contains the word \fITABLE\fP, wich
+is printed before the number.
+.br
+Special handling of the title will occur if
+\fBTB\fP is used inside \fBDS\fP/\fBDE\fP, it will not be
+affected by the format of \fBDS\fP.
+.TP
+.B "TC [slevel [spacing [tlevel [tab [h1 [h2 [h3 [h4 [h5]]]]]]]]]"
+Table of contents.
+This macro is normally used at the last line of the document.
+It generates a table of contents with headings up to the level
+controlled by number register \fBCl\fP. Note that \fBCl\fP controls
+the saving of headings, it has nothing to do with \fBTC\fP.
+Headings with level less than or equal to \fIslevel\fP will get
+\fIspacing\fP number of lines before them.
+Headings with level less than or equal to \fItlevel\fP will have
+their page numbers right justified with dots or spaces separating
+the text and the page number. Spaces is used if \fItab\fP
+is greater than zero, otherwise dots.
+Other headings will have the
+page number directly at the end of the heading text (\fIragged right\fP).
+.sp
+The rest of the arguments will be printed, centered, before the
+table of contents.
+.sp
+The user-defined macros \fBTX\fP and \fBTY\fP are used if \fBTC\fP is called
+with at most four arguments. \fBTX\fP is called before the printing
+of \fICONTENTS\fP, and \fBTY\fP is called instead of printing \fICONTENTS\fP.
+.sp
+Equivalent macros can be defined for list of figures, tables, equations
+and excibits by defining \fBTXxx\fP or \fBTYxx\fP, where \fBxx\fP
+is \fBFg\fP, \fBTB\fP, \fBEC\fP or \fBEX\fP.
+.sp
+String \fBCi\fP can be set to control the indentations for each heading-level.
+It must be scaled, like \fB.ds\ Ci\ .25i\ .5i\ .75i\ 1i\ 1i\fP.
+The indentation is normally controlled by the maxlength of headings
+in each level.
+.sp
+All texts can be redefined, new stringvariables
+\fILifg\fP, \fILitb\fP, \fILiex\fP, \fILiec\fP and \fILicon\fP contains
+"Figure", "TABLE", "Exhibit", "Equation" and "CONTENTS".
+These can be redefined to other languages.
+.TP
+.B TE
+Table end. See \fBTS\fP.
+.TP
+.B "TH [N]"
+Table header. See \fBTS\fP.
+\fBTH\fP ends the header of the table. This header will
+be printed again if a page-break occurs.
+Argument \fIN\fP isn't implemented yet.
+.TP
+.B TL [charging-case number(s) [filing-case number(s)]
+Begin title of memorandum.
+All text up to the next \fBAU\fP is included in the title.
+\fICharging-case number\fP and \fIfiling-case\fP is saved
+for use in the front page processing.
+.TP
+.B TM [num1 [num2 [...]]]
+Technical memorandumnumbers used in \fB.MT\fP. Unlimited number
+of arguments may be given.
+.TP
+.B TP
+Top of page user-defined macro.
+This macro is called instead of the normal page header. It is
+possible to get complete control over the header.
+Note that header and footer is printed in a separate environment.
+Linelength is preserved though.
+.TP
+.B "TS [H]"
+Table start. This is the start of a table specification
+to \fB@TMAC@tbl\fP. See separate manual for \fB@TMAC@tbl\fP.
+\fBTS\fP ends with \fBTE\fP.
+Argument \fIH\fP tells \fBm@TMAC@m\fP that the table
+has a header. See \fBTH\fP.
+.TP
+.B TX
+Userdefined table of contents exit.
+This macro is called just before \fBTC\fP prints the word \fICONTENTS\fP.
+See \fBTC\fP.
+.TP
+.B TY
+Userdefined table of contents exit (no "CONTENTS").
+This macro is called instead of printing \fICONTENTS\fP.
+See \fBTC\fP.
+.TP
+.B VERBON [flag [pointsize [font]]]
+Begin verbatim output using courier font.
+Usually for printing programs.
+All character has equal width.
+The pointsize can be changed with
+the second argument. By specifying the font-argument
+it is possible to use another font instead of courier.
+\fIflag\fP control several special features.
+It contains the sum of all wanted features.
+.in +.5i
+.T2 Value
+Description
+.T2 1
+Disable the escape-character (\e). This is normally turned on during
+verbose output.
+.T2 2
+Add en empty line before the verbose text.
+.T2 4
+Add en empty line after the verbose text.
+.T2 8
+Print the verbose text with numbered lines. This adds four digitsized
+spaces in the beginning of each line. Finer control is available with
+the string-variable \fBVerbnm\fP. It contains all arguments to the
+\fBtroff\fP-command \fB.nm\fP, normally '1'.
+.T2 16
+Indent the verbose text with five 'n':s. This is controlled by the
+number-variable \fBVerbin\fP (in units).
+.in
+.TP
+.B VERBOFF
+End verbatim output.
+.TP
+.B "VL text-indent [mark-indent [1]]"
+Variable-item list has no fixed mark, it assumes that
+every \fBLI\fP have a mark instead.
+\fIText-indent\fP sets the indent to the text, and \fImark-indent\fP
+the distance from the current indent to the mark.
+A third argument will prohibit printing of a blank line before each
+item.
+.TP
+.B "VM [top [bottom]]"
+Vertical margin.
+.TP
+.B "WA [writer-name [title]]
+Begins specification of the writer and writer's address.
+Several names can be specified with empty \fBWA\fP/\fBWE\fP-pairs, but
+only one address.
+.TP
+.B WE
+Ends the address-specification after \fP.WA\fP.
+.TP
+.B "WC [format]"
+Footnote and display width control.
+.in +.5i
+.T2 N
+Set default mode, \fB-WF\fP, \fB-FF\fP, \fB-WD\fP and \fBFB\fP.
+.T2 WF
+Wide footnotes, wide also in two-column mode.
+.T2 -WF
+Normal footnote width, follow column mode.
+.T2 FF
+All footnotes gets the same width as the first footnote encountered.
+.T2 -FF
+Normal footnotes, width follows \fBWF\fP and \fB-WF\fP.
+.T2 WD
+Wide displays, wide also in two-column mode.
+.T2 -WD
+Normal display width, follow column mode.
+.T2 FB
+Floating displays generates a line break when printed on the current page.
+.T2 -FB
+Floating displays does not generate line break.
+.in
+.sp 3
+.LP
+.\"########################################################################
+.LP
+.B "Strings used in m@TMAC_M_PREFIX@m:"
+.TP
+.B App
+A string containing the word "APPENDIX".
+.TP
+.B Apptxt
+.TP
+The current appendix text.
+.B "EM"
+Em dash string
+.TP
+.B H1txt
+Will be updated by \fB.H\fP and \fB.HU\fP to the current heading text.
+Also updated in table of contents & friends.
+.TP
+.B HF
+Fontlist for headings, normally "2 2 2 2 2 2 2".
+Nonnumeric fontnames may also be used.
+.TP
+.B HP
+Pointsize list for headings. Normally "0 0 0 0 0 0 0" which is the same as
+"10 10 10 10 10 10 10".
+.TP
+.B Index
+.TP
+Contains \fIINDEX\fP.
+.B Indcmd
+.TP
+Contains the index command, \fIsort\ -t\et\fP.
+.B Lifg
+String containing \fIFigure\fP.
+.TP
+.B Litb
+String containing \fITABLE\fP.
+.TP
+.B Liex
+String containing \fIExhibit\fP.
+.TP
+.B Liec
+String containing \fIEquation\fP.
+.TP
+.B Licon
+String containing \fICONTENTS\fP.
+.TP
+.B Lf
+Contains "LIST OF FIGURES".
+.TP
+.B Lt
+Contains "LIST OF TABLES".
+.TP
+.B Lx
+Contains "LIST OF EXHIBITS".
+.TP
+.B Le
+Contains "LIST OF EQUATIONS".
+.TP
+.B Letfc
+Contains "Yours very truly,", used in \fB.FC\fP.
+.TP
+.B Letapp
+Contains "APPROVED:", used in \fB.AV.\fP.
+.TP
+.B Letdate
+Contains "Date", used in \fB.AV.\fP.
+.TP
+.B LetCN
+Contains "CONFIDENTIAL", used in \fB.LO CN\fP.
+.TP
+.B LetSA
+Contains "To Whom It May Concern:", used in \fB.LO SA\fP.
+.TP
+.B LetAT
+Contains "ATTENTION:", used in \fB.LO AT\fP.
+.TP
+.B LetSJ
+Contains "SUBJECT:", used in \fB.LO SJ\fP.
+.TP
+.B LetRN
+Contains "In reference to:", used in \fB.LO RN\fP.
+.TP
+.B Letns
+is an array containing the different strings used in \fB.NS\fP.
+It is really a number of stringvariables prefixed with \fBLetns!\fP.
+If the argument doesn't exist, it will be included
+between \fB()\fP with \fBLetns!copy\fP as prefix and \fBLetns!to\fP as suffix.
+Observe the space after \fBcopy\fP and before \fBto\fP.
+.nf
+.ta 1.5i
+\fBName Value\fP
+Letns!0 Copy to
+Letns!1 Copy (with att.) to
+Letns!2 Copy (without att.) to
+Letns!3 Att.
+Letns!4 Atts.
+Letns!5 Enc.
+Letns!6 Encs.
+Letns!7 Under separate cover
+Letns!8 Letter to
+Letns!9 Memorandum to
+Letns!10 Copy (with atts.) to
+Letns!11 Copy (without atts.) to
+Letns!12 Abstract Only to
+Letns!13 Complete Memorandum to
+Letns!14 CC
+Letns!copy Copy "
+Letns!to " to
+.fi
+.TP
+.B Letnsdef
+Defines the standard-notation used when no argument is given
+to \fB.NS\fP. Default is \fB0\fP.
+.TP
+.B "MO1 - MO12"
+Strings containing \fIJanuary\fP thru \fIDecember\fP.
+.TP
+.B Qrf
+String containing "See chapter \e\e*[Qrfh], page \e\en[Qrfp].".
+.TP
+.B Rp
+Contains "REFERENCES".
+.TP
+.B Tcst
+Contains current status of table of contents and list of XXXX.
+Empty outside \fB.TC\fP.
+Useful in user-defined macros like \fB.TP\fP.
+.nf
+.ta 1.5i
+\fBValue Meaning\fP
+co Table of contents
+fg List of figures
+tb List of tables
+ec List of equations
+ex List of exhibits
+ap Appendix
+.fi
+.ta
+.TP
+.B Tm
+Contains \e(tm, trade mark.
+.TP
+.B Verbnm
+Argument to \fB.nm\fP in \fB.VERBON\fP, default: \fB1\fP.
+.\"-----------------------------------
+.LP
+.B "Number variables used in m@TMAC_M_PREFIX@m:"
+.TP
+.B Aph
+Print an appendix-page for every new appendix
+if this numbervariable is non-zero.
+No output will occur if \fBAph\fP is zero, but there will always
+be an appendix-entry in the 'List of contents'.
+.TP
+.B Cl
+Contents level [0:7], contents saved if heading level <= Cl, default 2.
+.TP
+.B Cp
+Eject page between LIST OF XXXX if Cp == 0, default 0.
+.TP
+.B D
+Debugflag, values >0 produces varying degree of debug. A value of 1
+gives information about the progress of formatting, default 0.
+.TP
+.B De
+Eject after floating display is output [0:1], default 0.
+.TP
+.B Dsp
+Controls the space output before and after static displays
+if defined. Otherwise is the value of Lsp used.
+.TP
+.B Df
+Floating keep output [0:5], default 5.
+.TP
+.B Ds
+\fBLsp\fP space before and after display if == 1 [0:1], default 1.
+.TP
+.B Ej
+Eject page, default 0.
+.TP
+.B Eq
+Equation lable adjust 0=left, 1=right. Default 0.
+.TP
+.B Fs
+Footnote spacing, default 1.
+.TP
+.B "H1-H7"
+Heading counters
+.TP
+.B H1dot
+Append a dot after the level one heading number if > 0. Default is 1.
+.TP
+.B H1h
+.TP
+Copy of number register \fBH1\fP, but it is incremented
+just before the page break. Useful in user defined header macros.
+.B Hb
+Heading break level [0:7], default 2.
+.TP
+.B Hc
+Heading centering level, [0:7]. Default 0.
+.TP
+.B Hi
+Heading temporary indent [0:2], default 1.
+.br
+0\ ->\ 0 indent, left margin
+.br
+1\ ->\ indent to right , like .P 1
+.br
+2\ ->\ indent to line up with text part of preceding heading
+.TP
+.B Hps
+Numbervariable with the heading pre-space level. If the heading-level
+is less than or equal to \fBHps\fP, then two lines will precede the
+section heading instead of one. Default is first level only.
+The real amount of lines is controlled by the variables \fBHps1\fP and
+\fBHps2\fP.
+.TP
+.B Hps1
+This is the number of lines preceding \fB.H\fP when the heading-level
+is greater than \fBHps\fP. Value is in units, normally 0.5.
+.TP
+.B Hps2
+This is the number of lines preceding \fB.H\fP when the heading-level
+is less than or equal to \fBHps\fP. Value is in units, normally 1.
+.TP
+.B Hs
+Heading space level [0:7], default 2.
+.TP
+.B Hss
+This is the number of lines that follows \fB.H\fP when the heading-level
+is less than or equal to \fBHs\fP. Value is in units, normally 1.
+.TP
+.B Ht
+Heading numbering type, default 0.
+0 -> multiple (1.1.1 ...)
+.br
+1 -> single
+.TP
+.B Hu
+Unnumbered heading level, default 2.
+.TP
+.B Hy
+Hyphenation in body, default 1.
+.br
+0\ ->\ no hyphenation
+.br
+1\ ->\ hyphenation 14 on
+.TP
+.B Iso
+Set this variable to 1 on the command line to get ISO-formatted date string.
+(\fB-rIso=1\fP)
+Useless inside a document.
+.TP
+.B Letwam
+Max lines in return-address, used in \fB.WA\fP/\fB.WE\fP. Default 14.
+.TP
+.B "Lf, Lt, Lx, Le"
+Enables (1) or disables (0) the printing of List of figures,
+List of tables, List of exhibits and List of equations.
+Default: Lf=1, Lt=1, Lx=1, Le=0.
+.TP
+.B Li
+List indent, used by .AL, default 6.
+.TP
+.B Limsp
+Flag for space between prefix and mark in automatic lists (.AL).
+.br
+0\ ==\ no space
+.br
+1\ ==\ space
+.TP
+.B Ls
+List space, if current listlevel > Ls then no spacing will occur around lists.
+Default 99.
+.TP
+.B Lsp
+.TP
+The size of an empty line. Normally 0.5v, but it is 1v
+if \fBn\fP is set (\fB.nroff\fP).
+.TP
+.B N
+Numbering style [0:5], default 0.
+.br
+0\ ==\ (default) normal header for all pages.
+.br
+1\ ==\ header replaces footer on first page, header is empty.
+.br
+2\ ==\ page header is removed on the first page.
+.br
+3\ ==\ "section-page" numbering enabled.
+.br
+4\ ==\ page header is removed on the first page.
+.br
+5\ ==\ "section-page" and "section-figure" numbering enabled.
+Se also the number-register Sectf and Sectp.
+.TP
+.B Np
+Numbered paragraphs, default 0.
+.br
+0\ ==\ not numbered
+.br
+1\ ==\ numbered in first level headings.
+.TP
+.B Of
+Format of figure,table,exhibit,equation titles, default 0.
+.br
+0\ =\ ". "
+.br
+1\ =\ " - "
+.TP
+.B P
+Current page-number, normally the same as % unless "section-page" numbering
+is enabled.
+.TP
+.B Pi
+paragraph indent, default 5.
+.TP
+.B Pgps
+Controls whether header and footer pointsize should follow the current
+setting or just change when the header and footer is defined.
+.in +.5i
+.ti -.5i
+.T2 Value
+Description
+.T2 0
+Pointsize will only change to the current setting when \fB.PH\fP, \fB.PF\fP,
+\&\fB.OH\fP, \fP.EH\fP, \fB.OF\fP or \fB.OE\fP is executed.
+.T2 1
+Pointsize will change after every \fB.S\fP. This is the default.
+.in
+.TP
+.B Ps
+paragraph spacing, default 1.
+.TP
+.B Pt
+Paragraph type, default 0.
+.br
+0\ ==\ left-justified
+.br
+1\ ==\ indented .P
+.br
+2\ ==\ indented .P except after .H, .DE or .LE.
+.TP
+.B Sectf
+Flag controlling "section-figures". A non-zero value enables this.
+Se also register N.
+.TP
+.B Sectp
+Flag controlling "section-page-numbers". A non-zero value enables this.
+Se also register N.
+.TP
+.B Si
+Display indent, default 5.
+.TP
+.B Verbin
+Indent for \fB.VERBON\fP, default 5n.
+.TP
+.B .mgm
+Always 1.
+.LP
+.SH INTERNALS
+The letter macros is using different submacros depending on
+the letter type. The name of the submacro has the letter type
+as suffix. It is therefore possible to define other letter types, either
+in the national macro-file, or as local additions.
+\&\fB.LT\fP will set the number variables \fBPt\fP and \fBPi\fP to 5 and 0.
+The following strings and macros must be defined for a new letter type:
+.TP
+\fBlet@init_\fP\fItype\fP
+This macro is called directly by \fB.LT\fP. It is supposed to initialize
+variables and other stuff.
+.TP
+\fBlet@head_\fP\fItype\fP
+This macro prints the letter head, and is called instead of the
+normal page header. It is supposed to remove the alias \fBlet@header\fP,
+otherwise it will be called for all pages.
+.TP
+\fBlet@sg_\fP\fItype\ name\ title\ n\ flag\ [arg1\ [arg2\ [...]]]\fP
+\&\fB.SG\fP is calling this macro only for letters, memorandums has
+its own processing. \fIname\fP and \fItitle\fP is specified
+thru \fB.WA\fP/\fB.WB\fP. \fIn\fP is the counter, 1-max, and
+\fIflag\fP is true for the last name. Any other argument to \fB.SG\fP
+is appended.
+.TP
+\fBlet@fc_\fP\fItype\ closing\fP
+This macro is called by \fB.FC\fP, and has the
+formal closing as argument.
+.LP
+\&\fB.LO\fP is implemented as a general option-macro. \fB.LO\fP demands
+that a string named \fBLet\fP\fItype\fP is defined, where \fItype\fP
+is the letter type.
+\&\fB.LO\fP will then assign the argument to the string
+variable \fBlet*lo-\fP\fItype\fP.
+.LP
+.\".SH BUGS
+.SH AUTHOR
+Jörgen Hägg, Lund, Sweden <jh@axis.se>.
+.SH FILES
+.TP
+.B @MACRODIR@/tmac.@TMAC_M_PREFIX@m
+.TP
+.B @TMAC_MDIR@/*.cov
+.TP
+.B @TMAC_MDIR@/*.MT
+.TP
+.B @TMAC_MDIR@/locale
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@),
+.BR @g@tbl (@MAN1EXT@),
+.BR @g@pic (@MAN1EXT@),
+.BR @g@eqn (@MAN1EXT@)
+.br
+.BR mm (@MAN7EXT@)
+.BR m@TMAC_M_PREFIX@mse (@MAN7EXT@)
diff --git a/contrib/mm/groff_mmse.man b/contrib/mm/groff_mmse.man
new file mode 100644
index 00000000..58e47ea9
--- /dev/null
+++ b/contrib/mm/groff_mmse.man
@@ -0,0 +1,82 @@
+.\"
+.\" $Id: groff_mmse.man,v 1.1 2000/02/06 09:34:52 wlemb Exp $
+.\" Skrivet av Jörgen Hägg, Lund, Sverige
+.\"
+.TH GROFF_MMSE @MAN7EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAMN
+groff_mmse \- svenska mm makro för groff
+.SH SYNTAX
+.B groff
+.B \-m@TMAC_M_PREFIX@mse
+[
+.IR flaggor .\|.\|.
+]
+[
+.IR filer .\|.\|.
+]
+.SH BESKRIVNING
+\fBm@TMAC_M_PREFIX@mse\fP är en svensk variant av \fBm@TMAC_M_PREFIX@m\fP. Alla texter
+är översatta. En A4 sida får text som är 13 cm bred, 3.5 cm indragning
+samt är 28.5 cm hög.
+Det finns stöd för brevuppställning enligt svensk standard
+för vänster och högerjusterad text.
+.LP
+\fBCOVER\fP kan använda \fIse_ms\fP som argument. Detta ger ett
+svenskt försättsblad.
+Se \fBgroff_mm(@MAN7EXT@)\fP för övriga detaljer.
+.SH BREV
+Tillgängliga brevtyper:
+.TP
+.B ".LT SVV"
+Vänsterställd löptext med adressat i position T0 (vänsterställt).
+.TP
+.B ".LT SVH"
+Högerställd löptext med adressat i position T4 (passar
+fönsterkuvert).
+.LP
+Följande extra LO-variabler används.
+.TP
+.B ".LO DNAMN\fI namn\fP"
+Anger dokumentets namn.
+.TP
+.br
+.B ".LO MDAT\fI datum\fP"
+Mottagarens datum, anges under \fBErt datum:\fP (\fBLetMDAT\fP).
+.TP
+.br
+.B ".LO BIL\fI sträng\fP"
+Anger bilaga, nummer eller sträng med \fBBilaga\fP (\fBLetBIL\fP)
+som prefix.
+.TP
+.br
+.B ".LO KOMP\fI text\fP"
+Anger kompletteringsuppgift.
+.TP
+.br
+.B ".LO DBET\fI beteckning\fP"
+Anger dokumentbeteckning eller dokumentnummer.
+.TP
+.br
+.B ".LO BET\fI beteckning\fP"
+Anger beteckning (ärendebeteckning i form av diarienummer eller liknande).
+.TP
+.br
+.B ".LO SIDOR\fI antal\fP"
+Anger totala antalet sidor och skrivs ut efter sidnumret inom
+parenteser.
+.LP
+Om makrot \fB.TP\fP är definierat anropas det efter utskrift av brevhuvudet.
+Där lägger man lämpligen in postadress och annat som brevfot.
+.SH "SKRIVET AV"
+Jörgen Hägg, Lund, Sweden <Jorgen.Hagg@axis.se>
+.SH FILER
+.B @MACRODIR@/tmac.@TMAC_M_PREFIX@mse
+.B @TMAC_MDIR@/se_*.cov
+.SH "SE OCKSÅ"
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@),
+.BR @g@tbl (@MAN1EXT@),
+.BR @g@pic (@MAN1EXT@),
+.BR @g@eqn (@MAN1EXT@)
+.br
+.BR m@TMAC_M_PREFIX@m (@MAN7EXT@)
diff --git a/contrib/mm/mm/0.MT b/contrib/mm/mm/0.MT
new file mode 100644
index 00000000..58a524a5
--- /dev/null
+++ b/contrib/mm/mm/0.MT
@@ -0,0 +1,146 @@
+.\"------------
+.\" $Id: 0.MT,v 1.1 2000/02/06 09:35:00 wlemb Exp $
+.\" Cover sheet. Memorandum type 0-3 and "string".
+.\"------------
+.if !r Au .nr Au 1
+.nr cov*mt0-ind 1.1c
+.de cov@print-title
+.MOVE 4.8c 1.5c
+.S 8
+subject:
+.sp -1.1
+.S
+.PGFORM
+.ft \\*[@sdf_font]
+.ll 9c
+.fi
+.cov*title
+.ft
+.ll
+.nf
+.if d cov*title-charge-case \fBCharge Case \\*[cov*title-charge-case]\fP
+.if d cov*title-file-case \fBFile Case \\*[cov*title-file-case]\fP
+.fi
+..
+.\"------------
+.de cov@print-authors
+.MOVE 5.7c 13.3c
+.nf
+.S 8
+\\$1:
+.br
+.S
+.sp -1
+.in 0.8c
+.ft \\*[@sdf_font]
+.nr cov*i 0 1
+.while \\n+[cov*i]<=\\n[cov*au] \{\
+. cov@print-au1 \\n[cov*i] 1
+. if \\n[Au] \{\
+. cov@print-au2 \\n[cov*i] 3 4
+. cov@print-au2 \\n[cov*i] 6 5
+. cov@print-au1 \\n[cov*i] 7
+. cov@print-au1 \\n[cov*i] 8
+. cov@print-au1 \\n[cov*i] 9
+. \}
+. if \\n[cov*i]<\\n[cov*au] .SP 1
+.\}
+.ft
+.if r cov*mt-tm-max \{\
+. SP 1
+. nr cov*i 0 1
+. ft \\*[@sdf_font]
+TM
+. in 1.5c
+. sp -1
+. while \\n+[cov*i]<\\n[cov*mt-tm-max] \\*[cov*mt-tm!\\n[cov*i]]
+. in
+. ft
+.\}
+.fi
+.PGFORM
+..
+.\"------------
+.\" index arg1
+.de cov@print-au1
+.if d cov*au!\\$1!\\$2 \\*[cov*au!\\$1!\\$2]
+..
+.\"------------
+.de cov@print-au2
+.\" index arg1 arg2
+.if d cov*au!\\$1!\\$2 \\*[cov*au!\\$1!\\$2] \c
+.if \\$3=5 .if d cov*au!\\$1!\\$3 x\c
+.if d cov*au!\\$1!\\$3 \\*[cov*au!\\$1!\\$3]\c
+.br
+..
+.\"------------
+.de cov@print-date
+.MOVE 4.8c 13.3c
+.S 8
+.nf
+\\$1:
+.br
+.S
+.sp -1
+.in 0.8c
+\f[\\*[@sdf_font]]\\*[cov*new-date]\fP
+.br
+.fi
+.PGFORM
+..
+.\"------------
+.de cov@print-firm
+.if d cov*firm \{\
+. MOVE 2.8c 0 17.7c
+. S 18
+. rj 1
+\fB\\*[cov*firm]\fP
+. S
+. PGFORM
+.\}
+..
+.\"------------
+.de cov@print-abstract
+.SP 3
+.if d cov*abstract \{\
+. misc@ev-keep cov*ev
+. if \\n[cov*abs-ind]>0 \{\
+. in +\\n[cov*abs-ind]u
+. ll -\\n[cov*abs-ind]u
+. \}
+. ce
+\fI\\$1\fP
+. SP 1.5
+. fi
+. cov*abstract
+. br
+. ev
+.\}
+..
+.\"-----------------
+.ds cov*mt0-txt!1 MEMORANDUM FOR FILE
+.ds cov*mt0-txt!2 PROGRAMMER'S NOTES
+.ds cov*mt0-txt!3 ENGINEER'S NOTES
+.if d cov*default-firm .if !d cov*firm .ds cov*firm \\*[cov*default-firm]
+.\"
+.if !d cov*mt-printed \{\
+. cov@print-firm
+. cov@print-title subject
+. cov@print-date date
+. cov@print-authors from
+. cov@print-abstract \\*[cov*abs-name]
+. SP 3
+. if (\*[cov*mt-type]>=1)&(\*[cov*mt-type]<=3) \{\
+. ce
+\fI\*[cov*mt0-txt!\*[cov*mt-type]]\fP
+. SP 1.5
+. \}
+. if \*[cov*mt-type]=6 \{\
+. ce
+\fI\*[cov*mt-type-text]\fP
+. SP 1.5
+. \}
+. pg@enable-top-trap
+. pg@enable-trap
+. ds cov*mt-printed
+.\}
diff --git a/contrib/mm/mm/4.MT b/contrib/mm/mm/4.MT
new file mode 100644
index 00000000..c0dd9fec
--- /dev/null
+++ b/contrib/mm/mm/4.MT
@@ -0,0 +1,81 @@
+.\"------------
+.\" $Id: 4.MT,v 1.1 2000/02/06 09:35:00 wlemb Exp $
+.\" Cover sheet. Memorandum type 4
+.\"------------
+.de cov@print-title
+.if !d cov*title .@error title (.TL) not defined!
+.MOVE 2.4c
+.S +4
+.ad c
+.fi
+.B
+.cov*title
+.br
+.S
+.R
+.ad b
+.PGFORM
+..
+.\"------------
+.de cov@print-authors
+.SP 0.5
+.I
+.nr cov*i 0 1
+.while \\n+[cov*i]<=\\n[cov*au] \{\
+.ce
+\\*[cov*au!\\n[cov*i]!1]
+.br
+.\}
+.R
+.PGFORM
+..
+.\"------------
+.de cov@print-firm
+.if !d cov*firm .@error firm (.AF) not defined!
+.SP 0.5
+.ce
+\\*[cov*firm]
+..
+.\"------------
+.de cov@print-abstract
+.SP 2
+.if d cov*abstract \{\
+. misc@ev-keep cov*ev
+. init@reset
+. if \\n[cov*abs-ind]>0 \{\
+. in +\\n[cov*abs-ind]u
+. ll -\\n[cov*abs-ind]u
+. \}
+. ce
+\fI\\*[cov*abs-name]\fP
+. SP 2
+. fi
+. cov*abstract
+. br
+. ev
+.\}
+..
+.\"-----------------
+.if d cov*default-firm .if !d cov*firm .ds cov*firm \\*[cov*default-firm]
+.if !d cov*mt-printed \{\
+. cov@print-title
+. cov@print-authors
+. cov@print-firm
+. if d cov*abstract \{\
+. if !\n[cov*abs-arg] .cov@print-abstract
+. \}
+. SP 3
+. nr hd*cur-bline \n[nl]
+. ds cov*mt-printed
+. pg@enable-top-trap
+. pg@enable-trap
+.\}
+.de CS
+.pg@disable-top-trap
+.SK
+.cov@print-title
+.cov@print-authors
+.cov@print-firm
+.cov@print-abstract
+..
+
diff --git a/contrib/mm/mm/5.MT b/contrib/mm/mm/5.MT
new file mode 100644
index 00000000..e6a0f861
--- /dev/null
+++ b/contrib/mm/mm/5.MT
@@ -0,0 +1,34 @@
+.\"------------
+.\" $Id: 5.MT,v 1.1 2000/02/06 09:35:00 wlemb Exp $
+.\" Cover sheet. Memorandum type 5
+.\"------------
+.nr cov*mt0-ind 1.1c
+.de cov@print-title
+.B
+.ll 9c
+.fi
+.cov*title
+.R
+.ll
+.nf
+.if d cov*title-charge-case \fBCharge Case \\*[cov*title-charge-case]\fP
+.if d cov*title-file-case \fBFile Case \\*[cov*title-file-case]\fP
+.fi
+..
+.\"------------
+.de cov@print-date
+.rj 1
+\f[\\*[@sdf_font]]\\*[cov*new-date]\fP
+.br
+..
+.\"------------
+.if !d cov*mt-printed \{\
+. SP 1.9c
+. cov@print-title
+. SP 1.2c
+. cov@print-date
+. SP 3
+. pg@enable-top-trap
+. pg@enable-trap
+. ds cov*mt-printed
+.\}
diff --git a/contrib/mm/mm/ms.cov b/contrib/mm/mm/ms.cov
new file mode 100644
index 00000000..6a834e5e
--- /dev/null
+++ b/contrib/mm/mm/ms.cov
@@ -0,0 +1,84 @@
+.\"------------
+.\" $Id: ms.cov,v 1.1 2000/02/06 09:35:00 wlemb Exp $
+.\" Cover sheet. Mostly like ms cover.
+.\"------------
+.de cov@print-title
+.in 0
+.misc@ev-keep cov*ev
+.init@reset
+.ad c
+.hy 0
+.fi
+.B
+.cov*title
+.br
+.ad b
+.R
+.ev
+..
+.\"------------
+.de cov@print-authors
+.SP
+.nr cov*i 0 1
+.while \\n+[cov*i]<=\\n[cov*au] \{\
+. ce
+\fI\\*[cov*au!\\n[cov*i]!1]\fP
+. nr cov*j 0 1
+. while \\n+[cov*j]<=9 \{\
+. if d cov*at!\\n[cov*i]!\\n[cov*j] \{\
+. if \w'\\*[cov*at!\\n[cov*i]!\\n[cov*j]]' \{\
+. ce
+\s-1\\*[cov*at!\\n[cov*i]!\\n[cov*j]]\s0
+. .\}
+. \}
+. \}
+.\}
+..
+.\"------------
+.de cov@print-firm
+.SP .5
+.ce
+\\*[cov*firm]
+..
+.\"------------
+.de cov@print-abstract
+.SP 2
+.if d cov*abstract \{\
+. misc@ev-keep cov*ev
+. init@reset
+. if \\n[cov*abs-ind]>0 \{\
+. in +\\n[cov*abs-ind]u
+. ll -\\n[cov*abs-ind]u
+. \}
+. ce
+\fI\\$1\fP
+. SP 1.5
+. fi
+. cov*abstract
+. br
+. ev
+.\}
+..
+.\"------------
+.de cov@print-date
+.SP 2
+\f[\\*[@sdf_font]]\\*[cov*new-date]\fP
+..
+.\"-----------------
+.de COVEND
+.br
+.if d cov*default-firm .if !d cov*firm .ds cov*firm \\*[cov*default-firm]
+.sp |4.2c
+.cov@print-title
+.cov@print-authors
+.cov@print-firm
+.cov@print-abstract \\*[cov*abs-name]
+.cov@print-date
+.pg@enable-top-trap
+.bp 1
+.pg@enable-trap
+.if d cov*abs-arg .if \\n[cov*abs-arg] \{\
+. cov@print-abstract ABSTRACT
+. SP 2
+.\}
+..
diff --git a/contrib/mm/mm/se_ms.cov b/contrib/mm/mm/se_ms.cov
new file mode 100644
index 00000000..cb786350
--- /dev/null
+++ b/contrib/mm/mm/se_ms.cov
@@ -0,0 +1,3 @@
+.\" $Id: se_ms.cov,v 1.1 2000/02/06 09:35:00 wlemb Exp $
+.mso mm/ms.cov
+.nr cur*abstract-ll 11c
diff --git a/contrib/mm/mmroff.man b/contrib/mm/mmroff.man
new file mode 100644
index 00000000..71534b15
--- /dev/null
+++ b/contrib/mm/mmroff.man
@@ -0,0 +1,48 @@
+.\"
+.\" $Id: mmroff.man,v 1.1 2000/02/06 09:35:00 wlemb Exp $
+.\"
+.TH MMROFF @MAN7EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+mmroff \- reference preprocessor
+.SH SYNOPSIS
+.B mmroff
+[
+.I -x
+]
+.I groff_arguments
+.SH DESCRIPTION
+\fBmmroff\fP is a simple preprocessor for \fBgroff\fP, it is
+used for expanding references in \fBm@TMAC_M_PREFIX@m\fP, see
+\fBgroff_mm(@MAN7EXT@)\fP.
+\fBgroff\fP is executed twice, first with \fB-z\fP and \fB-rRef=1\fR
+to collect all references and then to do the real processing
+when the reference file is up to date.
+.TP
+\fB\-x\fR
+Just create the reference file. This can be used to refresh
+the reference file, it isn't always needed to have accurate
+references and by using this option \fBgroff\fP will only
+be run once.
+.\".SH BUGS
+.SH AUTHOR
+Jörgen Hägg, Lund, Sweden <jh@axis.se>.
+.SH FILES
+.TP
+.B @MACRODIR@/tmac.@TMAC_M_PREFIX@m
+.TP
+.B @TMAC_MDIR@/*.cov
+.TP
+.B @TMAC_MDIR@/*.MT
+.TP
+.B @TMAC_MDIR@/locale
+.SH "SEE ALSO"
+.BR groff_mm(@MAN7EXT@),
+.BR groff_mmse(@MAN7EXT@),
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@),
+.BR @g@tbl (@MAN1EXT@),
+.BR @g@pic (@MAN1EXT@),
+.BR @g@eqn (@MAN1EXT@)
+.br
+.BR mm (@MAN7EXT@)
+.BR m@TMAC_M_PREFIX@mse (@MAN7EXT@)
diff --git a/contrib/mm/mmroff.pl b/contrib/mm/mmroff.pl
new file mode 100644
index 00000000..69b6105b
--- /dev/null
+++ b/contrib/mm/mmroff.pl
@@ -0,0 +1,134 @@
+#!/usr/bin/perl
+
+use strict;
+# runs groff in safe mode, that seems to be the default
+# installation now. That means that I have to fix all nice
+# features outside groff. Sigh.
+# I do agree however that the previous way opened a whole bunch
+# of security holes.
+
+my $no_exec;
+# check for -x and remove it
+if (grep(/^-x$/, @ARGV)) {
+ $no_exec++;
+ @ARGV = grep(!/^-x$/, @ARGV);
+}
+
+my $check_macro = "groff -rRef=1 -z @ARGV";
+my $run_macro = "groff @ARGV";
+
+my (%cur, $rfilename, $max_height, $imacro, $max_width, @out, @indi);
+open(MACRO, "$check_macro 2>&1 |") || die "run $check_macro:$!";
+while(<MACRO>) {
+ if (m#^\.\\" Rfilename: (\S+)#) {
+ # remove all directories just to be more secure
+ ($rfilename = $1) =~ s#.*/##;
+ next;
+ }
+ if (m#^\.\\" Imacro: (\S+)#) {
+ # remove all directories just to be more secure
+ ($imacro = $1) =~ s#.*/##;
+ next;
+ }
+ if (m#^\.\\" Index: (\S+)#) {
+ # remove all directories just to be more secure
+ my $f;
+ ($f = $1) =~ s#.*/##;
+ &print_index($f, \@indi, $imacro);
+ @indi = ();
+ $imacro = '';
+ next;
+ }
+ my $x;
+ if (($x) = m#^\.\\" IND (.+)#) {
+ $x =~ s#\\##g;
+ my @x = split(/\t/, $x);
+ grep(s/\s+$//, @x);
+ push(@indi, join("\t", @x));
+ next;
+ }
+ if (m#^\.\\" PIC id (\d+)#) {
+ %cur = ('id', $1);
+ next;
+ }
+ if (m#^\.\\" PIC file (\S+)#) {
+ &psbb($1);
+ &ps_calc($1);
+ next;
+ }
+ if (m#^\.\\" PIC (\w+)\s+(\S+)#) {
+ eval "\$cur{'$1'} = '$2'";
+ next;
+ }
+ s#\\ \\ $##;
+ push(@out, $_);
+}
+close(MACRO);
+
+
+if ($rfilename && @out) {
+ push(@out, ".nr pict*max-height $max_height\n") if defined $max_height;
+ push(@out, ".nr pict*max-width $max_width\n") if defined $max_width;
+
+ open(OUT, ">$rfilename") || "create $rfilename:$!";
+ my $i;
+ for $i (@out) {
+ print OUT $i;
+ }
+ close(OUT);
+}
+
+exit 0 if $no_exec;
+exit system($run_macro);
+
+sub print_index {
+ my ($f, $ind, $macro) = @_;
+
+ open(OUT, ">$f") || "create $f:$!";
+ my $i;
+ for $i (sort @$ind) {
+ if ($macro) {
+ $i = '.'.$macro.' "'.join('" "', split(/\t/, $i)).'"';
+ }
+ print OUT "$i\n";
+ }
+ close(OUT);
+}
+
+sub ps_calc {
+ my ($f) = @_;
+
+ my $w = abs($cur{'llx'}-$cur{'urx'});
+ my $h = abs($cur{'lly'}-$cur{'ury'});
+ $max_width = $w if $w > $max_width;
+ $max_height = $h if $h > $max_height;
+
+ my $id = $cur{'id'};
+ push(@out, ".ds pict*file!$id $f\n");
+ push(@out, ".ds pict*id!$f $id\n");
+ push(@out, ".nr pict*llx!$id $cur{'llx'}\n");
+ push(@out, ".nr pict*lly!$id $cur{'lly'}\n");
+ push(@out, ".nr pict*urx!$id $cur{'urx'}\n");
+ push(@out, ".nr pict*ury!$id $cur{'ury'}\n");
+ push(@out, ".nr pict*w!$id $w\n");
+ push(@out, ".nr pict*h!$id $h\n");
+}
+
+
+sub psbb {
+ my ($f) = @_;
+
+ unless (open(IN, $f)) {
+ print STDERR "Warning: Postscript file $f:$!";
+ next;
+ }
+ while(<IN>) {
+ if (/^%%BoundingBox:\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/) {
+ $cur{'llx'} = $1;
+ $cur{'lly'} = $2;
+ $cur{'urx'} = $3;
+ $cur{'ury'} = $4;
+ }
+ }
+ close(IN);
+}
diff --git a/contrib/mm/tmac.m b/contrib/mm/tmac.m
new file mode 100755
index 00000000..71fcce6a
--- /dev/null
+++ b/contrib/mm/tmac.m
@@ -0,0 +1,3471 @@
+.\"
+.de @revision
+.ds RE \\$2
+..
+.\"
+.\" $Id: tmac.m,v 1.1 2000/02/06 09:34:59 wlemb Exp $
+.@revision $Revision: 1.1 $
+.ig
+
+Copyright (C) 1991-2000 Free Software Foundation, Inc.
+mgm is written by Jörgen Hägg <jh@axis.se>
+
+mgm 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.
+
+mgm 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Please send bugreports with examples to jh@axis.com.
+
+Naming convention stolen from mgs.
+Local names module*name
+Extern names module@name
+Env.var environ:name
+Index array!index
+..
+.if !\n(.g .ab These mm macros require groff.
+.if \n(.C .ab The groff mm macros do not work in compatibility mode.
+.warn
+.\" ######## init #######
+.\" Contents level [0:7], contents saved if heading level <= Cl
+.nr Cl 2
+.\" Eject page between LIST OF XXXX if Cp == 0
+.nr Cp 0
+.\" Debugflag
+.if !r D .nr D 0
+.\" Eject after floating display is output [0:1]
+.nr De 0
+.\" Floating keep output [0;5]
+.nr Df 5
+.\" space before and after display if == 1 [0:1]
+.nr Ds 1
+.\" Eject page
+.nr Ej 0
+.\" Equation label adjust 0=left, 1=right
+.nr Eq 0
+.\" Em dash string
+.ie n .ds EM " --
+.el .ds EM \(em
+.\" Footnote spacing
+.nr Fs 1
+.\" H1-H7 heading counters
+.nr H1 0 1
+.nr H2 0 1
+.nr H3 0 1
+.nr H4 0 1
+.nr H5 0 1
+.nr H6 0 1
+.nr H7 0 1
+.\" Heading break level [0:7]
+.nr Hb 2
+.\" heading centering level, [0:7]
+.nr Hc 0
+.\" header format
+.ds HF 2 2 2 2 2 2 2
+.\" heading temp. indent [0:2]
+.\" 0 -> 0 indent, left margin
+.\" 1 -> indent to right , like .P 1
+.\" 2 -> indent to line up with text part of preceding heading
+.nr Hi 1
+.\" header pointsize
+.ds HP 0 0 0 0 0 0 0
+.\" heading space level [0:7]
+.nr Hs 2
+.\" heading numbering type
+.\" 0 -> multiple (1.1.1 ...)
+.\" 1 -> single
+.nr Ht 0
+.\" Unnumbered heading level
+.nr Hu 2
+.\" hyphenation in body
+.\" 0 -> no hyphenation
+.\" 1 -> hyphenation 14 on
+.nr Hy 0
+.\" text for toc, selfexplanatory. Look in the new variable section
+.ds Lf LIST OF FIGURES
+.nr Lf 1
+.ds Lt LIST OF TABLES
+.nr Lt 1
+.ds Lx LIST OF EXHIBITS
+.nr Lx 1
+.ds Le LIST OF EQUATIONS
+.nr Le 0
+.\" List indent, used by .AL
+.nr Li 6
+.\" List space, if listlevel > Ls then no spacing will occur around lists.
+.nr Ls 99
+.\" Numbering style [0:5]
+.if !r N .nr N 0
+.\" numbered paragraphs
+.\" 0 == not numbered
+.\" 1 == numbered in first level headings.
+.nr Np 0
+.\" Format of figure,table,exhibit,equation titles.
+.\" 0= ". ", 1=" - "
+.nr Of 0
+.\" Table of contents page numbering style
+.nr Oc 0
+.\" Page-number, normally same as %.
+.nr P 0
+.\" paragraph indent
+.nr Pi 5
+.\" paragraph spacing
+.nr Ps 1
+.\" paragraph type
+.\" 0 == left-justified
+.\" 1 == indented .P
+.\" 2 == indented .P except after .H, .DE or .LE.
+.nr Pt 0
+.\" Reference title
+.ds Rp REFERENCES
+.\" Display indent
+.nr Si 5
+.\"
+.\" Current state of TOC, empty outside TC, inside
+.\" it will be set to co,fg,tb,ec,ex or ap.
+.ds Tcst
+.\"
+.ds Tm \(tm
+.\"
+.\"---------------------------------------------
+.\" Internal global variables
+.\"
+.\" This is for cover macro .MT
+.\" .ds @language
+.\"
+.nr @copy_type 0
+.if r C .nr @copy_type \n[C]
+.\" >0 if Subject/Date/From should be bold, roman otherwise
+.ie n .ds @sdf_font R
+.el .ds @sdf_font B
+.if \n[@copy_type]=4 \{\
+. ls 2
+. nr Pi 10
+. nr Pt 1
+.\}
+.\"
+.\"
+.if r E \{\
+. ie \n[E] .ds @sdf_font B
+. el .ds @sdf_font R
+.\}
+.\"
+.\" Current pointsize and vertical space, always in points.
+.if !r S .nr S 10
+.ps \n[S]
+.vs \n[S]+2
+.\"
+.nr @ps \n[.ps]
+.nr @vs \n[.v]
+.if \n[D]>1 .tm @ps=\n[@ps], @vs=\n[@vs]
+.if \n[D]>3 .tm INIT: l:\n[.l] p:\n[.p] o:\n[.o]
+.\"
+.\" Page length
+.if r L \{\
+. ie n .pl \n[L]u
+. el .pl \n[L]u
+.\}
+.nr @pl \n[.p]
+.\"
+.\" page width
+.ie r W \{\
+. ie n .ll \n[W]u
+. el .ll \n[W]u
+.\}
+.el .ll 6i
+.nr @ll \n[.l]
+.nr @cur-ll \n[@ll]
+.lt \n[@ll]u
+.\"
+.\" page offset
+.ie r O .po \n[O]
+.el \{\
+. ie n .po .75i
+. el .po .963i
+.\}
+.\"
+.nr @po \n[.o]
+.\"
+.\" non-zero if escape mechanism is turned off. Used by VERBON/OFF
+.nr @verbose-flag 0
+.\"---------------------------------------------
+.\" New variables
+.\"
+.\" Appendix name
+.ds App APPENDIX
+.\" print appendixheader, 0 == don't
+.nr Aph 1
+.\"
+.\" Current appendix text
+.ds Apptext
+.\" Controls the space before and after static displays if defined.
+.\" Lsp is used otherwise
+.\" .nr Dsp 1v
+.\"
+.\" Add a dot after level one heading number if >0
+.nr H1dot 1
+.\"
+.\" header prespace level. If level <= Hps, then two lines will be printed
+.\" before the header instead of one.
+.nr Hps 1
+.\"
+.\" These variables controls the number of lines preceding .H.
+.\" Hps1 is the number of lines when level > Hps
+.nr Hps1 0.5
+.if n .nr Hps1 1
+.\"
+.\" Hps2 is the number of lines when level <= Hps
+.nr Hps2 1
+.if n .nr Hps2 2
+.\"
+.\" Hss is the number of lines (Lsp) after the header.
+.nr Hss 1
+.\"
+.\" H1txt will be updated by .H and .HU, containing the heading text.
+.\" Will also be updated in table of contents & friends
+.\"
+.ds H1txt
+.\"
+.\" header text for the index
+.ds Index INDEX
+.\" command to sort the index
+.ds Indcmd sort
+.\"
+.\" flag for mkindex
+.if !r Idxf .nr Idxf 0
+.\" Change these in the national configuration file
+.ds Lifg Figure
+.ds Litb TABLE
+.ds Liex Exhibit
+.ds Liec Equation
+.ds Licon CONTENTS
+.\" Flag for space between mark and prefix 1==space, 0==no space
+.\" Can also be controlled by using '.LI mark 2'
+.nr Limsp 1
+.\"
+.\" Lsp controls the height of an empty line. Normally 0.5v
+.\" Normally used for nroff compatibility.
+.nr Lsp 0.5v
+.if n .nr Lsp 1v
+.ds MO1 January
+.ds MO2 February
+.ds MO3 March
+.ds MO4 April
+.ds MO5 May
+.ds MO6 June
+.ds MO7 July
+.ds MO8 August
+.ds MO9 September
+.ds MO10 October
+.ds MO11 November
+.ds MO12 December
+.\" for GETR
+.ds Qrf See chapter \\*[Qrfh], page \\*[Qrfp].
+.\"
+.\" header- and footer-size will only change to the current
+.\" if Pgps is > 0.
+.nr Pgps 1
+.\"
+.\" section-page if Sectp > 0
+.nr Sectp 0
+.if (\n[N]=3):(\n[N]=5) \{\
+. nr Sectp 1
+. nr Ej 1
+.\}
+.\" section-figure if Sectf > 0
+.nr Sectf 0
+.if \n[N]=5 .nr Sectf 1
+.\"
+.\" argument to .nm in .VERBON.
+.ds Verbnm "1
+.\" indent for VERBON
+.nr Verbin 5n
+.\"
+.\" Letter section
+.\" Formal closing (.FC)
+.ds Letfc Yours very truly,
+.\"
+.\" Approval line
+.ds Letapp APPROVED:
+.\" Approval date-string
+.ds Letdate Date
+.\"
+.ds LetCN CONFIDENTIAL\" Confidential default
+.ds LetSA To Whom It May Concern:\" Salutation default
+.ds LetAT ATTENTION:\" Attention string
+.ds LetSJ SUBJECT:\" Subject string
+.ds LetRN In reference to:\" Reference string
+.\"
+.\" Copy to (.NS)
+.ds Letnsdef 0
+.ds Letns!copy Copy \" space!
+.ds Letns!to " to
+.ds Letns!0 Copy to
+.ds Letns!1 Copy (with att.) to
+.ds Letns!2 Copy (without att.) to
+.ds Letns!3 Att.
+.ds Letns!4 Atts.
+.ds Letns!5 Enc.
+.ds Letns!6 Encs.
+.ds Letns!7 Under separate cover
+.ds Letns!8 Letter to
+.ds Letns!9 Memorandum to
+.ds Letns!10 Copy (with atts.) to
+.ds Letns!11 Copy (without atts.) to
+.ds Letns!12 Abstract Only to
+.ds Letns!13 Complete Memorandum to
+.ds Letns!14 CC:
+.\"
+.\" Text printed below the footer. Controlled by @copy_type (C).
+.ds Pg_type!0
+.ds Pg_type!1 OFFICIAL FILE COPY
+.ds Pg_type!2 DATE FILE COPY
+.ds Pg_type!3 D\ R\ A\ F\ T
+.ds Pg_type!4 D\ R\ A\ F\ T
+.\" Max lines in return address
+.nr Letwam 14
+.\"--------------------------
+.\" test for mgm macro. This can be used if the text must test
+.\" what macros is used.
+.nr .mgm 1
+.\"
+.\" Due to security problems with groff I had to rewrite
+.\" the reference system. It's not as elegant as before, you
+.\" have to run groff with '-z -rRef=1' and put stderr into the filename
+.\" for .INITR
+.\"
+.\" Output references to stderr if non-zero
+.ie !r Ref \{\
+. nr Ref 0
+.\}
+.el .warn 0
+.\"
+.\"---------------------------------------------
+.\" set local variables.
+.ie d @language .mso mm/\*[@language]_locale
+.el .mso mm/locale
+.\"---------------------------------------------
+.if \n[D] .tm Groff mm, version \*[RE].
+.\" ####### module init ######
+.\" reset all things
+.de init@reset
+.ie \\n[misc@adjust] 'ad
+.el 'na
+.ie \\n[Hy] 'hy 14
+.el 'nh
+'in 0
+'ti 0
+.ps \\n[@ps]u
+.vs \\n[@vs]u
+..
+.de @warning
+'tm WARNING:(\\n[.F]) input line \\n[.c]:\\$*
+.if \\n[D] .backtrace
+..
+.de @error
+'tm ******************
+'tm ERROR:(\\n[.F]) input line \\n[.c]:\\$*
+.if \\n[D] .backtrace
+'tm ******************
+.ab "Input aborted, syntax error"
+..
+.de misc@toupper
+.tr aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ
+.br
+\\$1
+.tr aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz
+.br
+..
+.\" ####### module debug #################################
+.de debug
+'tm \\$1:\\n[.F]:\\n[c.] ll=\\n[.l] vs=\\n[.v] ps=\\n[.s],\\n[.ps] \
+in=\\n[.i] fi=\\n[.u] .d=\\n[.d] nl=\\n[nl] pg=\\n[%]
+..
+.de debug-all
+.nr debug*n 1n
+.nr debug*m 1m
+'tm \\$1:\\n[.F]:\\n[c.] ll=\\n[.l] vs=\\n[.v] ps=\\n[.s] in=\\n[.i]\
+ ad=\\n[.j] fi=\\n[.u] pl=\\n[.p] page=\\n[%] .o=\\n[.o]
+'tm _______ .d=\\n[.d] .f=\\n[.f] .h=\\n[.h] .k=\\n[.k] .n=\\n[.n]\
+ .p=\\n[.p] .t=\\n[.t] .z=\\n[.z] nl=\\n[nl] dn=\\n[dn] n=\\n[debug*n]
+..
+.\" ####### module par #################################
+.nr par@ind-flag 1 \" indent on following P if Pt=2
+.nr hd*last-pos -1
+.nr hd*last-hpos -1
+.nr par*number 0 1
+.af par*number 01
+.nr par*number2 0 1
+.af par*number2 01
+.nr par*num-count 0 1
+.af par*num-count 01
+.\" reset numbered paragraphs, arg1 = headerlevel
+.de par@reset-num
+.if \\$1<3 .nr par*num-count 0
+.if (\\$1=1)&(\\n[Np]=1) .nr par*number 0
+..
+.\"------------
+.\" paragraph
+.de P
+.\" skip P if previous heading
+.ie !((\\n[nl]=\\n[hd*last-pos]):(\\n[nl]=(\\n[hd*last-pos]-.5v))) \{\
+. if \\n[D]>2 .tm Paragraph nl=\\n[nl]
+. par@doit \\$*
+. if \\n[Np] \\n[H1].\\n+[par*number]\ \ \c
+.\}
+.el .if !(\\n[hd*last-hpos]=\\n[.k]) \{\
+. if \\n[D]>2 .tm Paragraph nl=\\n[nl]
+. par@doit \\$*
+. if \\n[Np] \\n[H1].\\n+[par*number]\ \ \c
+.\}
+.nr par@ind-flag 1
+..
+.\"------------
+.de nP
+.\" skip P if previous heading
+.ie !((\\n[nl]=\\n[hd*last-pos]):(\\n[nl]=(\\n[hd*last-pos]-.5v))) \{\
+. if \\n[D]>2 .tm Paragraph nl=\\n[nl]
+. par@doit \\$*
+\\n[H2].\\n+[par*number2]\ \ \c
+.\}
+.el .if !(\\n[hd*last-hpos]=\\n[.k]) \{\
+. if \\n[D]>2 .tm Paragraph nl=\\n[nl]
+. par@doit \\$*
+\\n[H2].\\n+[par*number2]\ \ \c
+.\}
+.nr par@ind-flag 1
+..
+.\"------------
+.de par@doit
+.SP (u;\\n[Ps]*\\n[Lsp])
+.ie \\n[.$] \{\
+. if \\$1=1 .ti +\\n[Pi]n
+.\}
+.el \{\
+. if \\n[Pt]=1 .ti +\\n[Pi]n
+. if (\\n[Pt]=2)&\\n[par@ind-flag] .ti +\\n[Pi]n
+.\}
+..
+.\" ####### module line #######################################
+.de SP
+.br
+.if !r line*lp\\n[.z] .nr line*lp\\n[.z] 0
+.if !r line*ac\\n[.z] .nr line*ac\\n[.z] 0
+.ie \\n[.$] .nr line*temp (v;\\$1)
+.el .nr line*temp 1v
+.\"
+.ie \\n[line*lp\\n[.z]]=\\n[.d] \{\
+. \" go here if no output since the last .SP
+. nr line*output \\n[line*temp]-\\n[line*ac\\n[.z]]
+. if \\n[line*output]<0 .nr line*output 0
+. nr line*ac\\n[.z] +\\n[line*output]
+.\}
+.el \{\
+. nr line*ac\\n[.z] \\n[line*temp]
+. nr line*output \\n[line*temp]
+. \" no extra space in the beginning of a page
+. if (\\n[.d]<0):(\\n[pg*head-mark]=\\n[.d]) .nr line*output 0
+.\}
+.if \\n[line*output] .sp \\n[line*output]u
+.nr line*lp\\n[.z] \\n[.d]
+..
+.\" ######## module misc ###############
+.nr misc@adjust 14
+.de SA
+.if \\n[.$] \{\
+. if \\$1-1 .@error "SA: bad arg: \\$1"
+. nr misc@adjust 0\\$1
+.\}
+.ie \\n[misc@adjust] 'ad
+.el 'na
+..
+.\"-------------
+.\" switch environment, keep all important settings.
+.de misc@ev-keep
+.nr misc*ll \\n[.l]
+.ev \\$1
+.ll \\n[misc*ll]u
+.lt \\n[misc*ll]u
+..
+.\"-------------
+.\" .misc@push stackname value
+.de misc@push
+.ie d misc*st-\\$1 .ds misc*st-\\$1 \\$2 \\*[misc*st-\\$1]
+.el .ds misc*st-\\$1 \\$2
+..
+.\"-------------
+.\" .misc@pop stackname
+.\" value returned in the string misc*pop
+.de misc@pop
+.misc@pop-set misc*st-\\$1 \\*[misc*st-\\$1]
+..
+.\"-------------
+.de misc@pop-set
+.ds misc*st-name \\$1
+.shift
+.if \\n[.$]<1 .@error "stack \\*[misc*st-name] empty"
+.ds misc*pop \\$1
+.shift
+.ds \\*[misc*st-name] \\$*
+..
+.\"-------------
+.\" .misc@pop-nr stackname varname
+.de misc@pop-nr
+.misc@pop \\$1
+.nr \\$2 \\*[misc*pop]
+..
+.\"-------------
+.\" .misc@pop-ds stackname varname
+.de misc@pop-ds
+.misc@pop \\$1
+.ds \\$2 \\*[misc*pop]
+..
+.\"-----------
+.\" reset tabs
+.de TAB
+.ta T 5n
+..
+.\"-------------
+.\" .PGFORM linelength [ pagelength [ pageoffset [1]]]
+.de PGFORM
+.\" Break here to avoid problems with new linesetting of the previous line.
+.\" Hope this doesn't break anything else :-)
+.\" Don't break if arg_4 is a '1'.
+.if \\n[D]>2 .tm PGFORM: \\$*
+.if ''\\$4' .br
+.if \\n[D]>3 .tm PGFORM: IN l:\\n[.l] p:\\n[.p] o:\\n[.o]
+.ie !''\\$1' \{\
+. ll \\$1
+. nr @ll \\n[.l]
+. nr @cur-ll \\n[@ll]
+. lt \\n[@ll]u
+.\}
+.el \{\
+. ll \\n[@ll]u
+. lt \\n[@ll]u
+.\}
+.\"
+.ie !''\\$2' \{\
+. pl \\$2
+. nr @pl \\n[.p]
+.\}
+.el .pl \\n[@pl]u
+.\"
+.ie !''\\$3' \{\
+. po \\$3
+. nr @po \\n[.o]
+.\}
+.el .po \\n[@po]u
+.if \\n[D]>3 .tm PGFORM: OUT l:\\n[.l] p:\\n[.p] o:\\n[.o]
+.if \\n[D]>2 .tm PGFORM: ll=\\n[@ll], pl=\\n[@pl], po=\\n[@po]
+'in 0
+.pg@move-trap
+.if \\n[D]>2 \{\
+. tm Traps:
+. ptr
+.\}
+..
+.\"-------------
+.\" .MOVE y [[x] linelength]
+.\" move to line y, indent to x
+.de MOVE
+.if !\\n[.$] .@error "MOVE y [x]: no arguments"
+.if \\n[nl]<0 \c
+.\" move to Y-pos
+.sp |(v;\\$1)
+.\" calc linelength
+.ie \\n[.$]>2 .nr pg*i (n;\\$3)
+.el \{\
+. ie \\n[.$]>1 .nr pg*i (n;\\n[@ll]u-\\$2)
+. el .nr pg*i \\n[@ll]u
+.\}
+.\" move to X-pos, if any
+.if !''\\$2' .po \\$2
+.\" set linelength
+.ll \\n[pg*i]u
+..
+.\"-------------
+.de SM
+.if !\\n[.$] .@error "SM: no arguments"
+.if \\n[.$]=1 \s-1\\$1\s0
+.if \\n[.$]=2 \s-1\\$1\s0\\$2
+.if \\n[.$]=3 \\$1\s-1\\$2\s0\\$3
+..
+.\"-------------
+.nr misc*S-ps \n[@ps]
+.nr misc*S-vs \n[@vs]
+.nr misc*S-ps1 \n[@ps]
+.nr misc*S-vs1 \n[@vs]
+.ds misc*a
+.ds misc*b
+.de S
+.ie !\\n[.$] \{\
+. ds misc*a P
+. ds misc*b P
+.\}
+.el \{\
+. ie \\n[.$]=1 .ds misc*b D
+. el \{\
+. ie \w@\\$2@=0 .ds misc*b C
+. el .ds misc*b \\$2
+. \}
+. ie \w@\\$1@=0 .ds misc*a C
+. el .ds misc*a \\$1
+.\}
+.\"
+.\" set point size
+.if !'\\*[misc*a]'C' \{\
+. ie '\\*[misc*a]'P' .ps \\n[misc*S-ps]u
+. el \{\
+. ie '\\*[misc*a]'D' .ps \\n[@ps]u
+. el .ps \\*[misc*a]
+. if \\n[D]>2 .tm S: .ps \\*[misc*a]
+. \}
+.\}
+.\"
+.\" set vertical spacing
+.if !'\\*[misc*b]'C' \{\
+. ie '\\*[misc*b]'P' .vs \\n[misc*S-vs]u
+. el \{\
+. ie '\\*[misc*b]'D' .vs \\n[.ps]u+2p
+. el .vs \\*[misc*b]
+. if \\n[D]>2 .tm S: .vs \\*[misc*b]
+. \}
+.\}
+.nr @ps \\n[.ps]
+.nr @vs \\n[.v]
+.\"
+.if \\n[D]>1 .tm S(\\$*): ma:\\*[misc*a], mb:\\*[misc*b] => ps:\\n[@ps]u, vs:\\n[@vs]u
+.nr misc*S-ps \\n[misc*S-ps1]
+.nr misc*S-vs \\n[misc*S-vs1]
+.nr misc*S-ps1 \\n[@ps]
+.nr misc*S-vs1 \\n[@vs]
+.pg@move-trap
+..
+.\"------------
+.de HC
+.ev 0
+.hc \\$1
+.ev
+.ev 1
+.hc \\$1
+.ev
+.ev 2
+.hc \\$1
+.ev
+..
+.\"------------
+.de RD
+.di misc*rd
+'fl
+.rd \\$1\t
+.br
+.di
+.ie !''\\$3' \{\
+. di misc*rd2
+. ds \\$3 "\\*[misc*rd]
+. br
+. di
+.\}
+.if !''\\$2' .rn misc*rd \\$2
+.rm misc*rd misc*rd2
+..
+.\"------------
+.\" VERBON [flag [pointsize [font]]]
+.\" flag
+.\" bit function
+.\" 0 escape on
+.\" 1 add an empty line before verbose text
+.\" 2 add an empty line after verbose text
+.\" 3 numbered lines (controlled by the string Verbnm)
+.\" 4 indent text by the numbervariable Verbin.
+.de VERBON
+.br
+.nr misc*verb 0\\$1
+.if (0\\n[misc*verb]%4)/2 .SP \\n[Lsp]u
+.misc@ev-keep misc*verb-ev
+.nf
+.if (0\\n[misc*verb]%16)/8 .nm \\*[Verbnm]
+.ie !'\\$3'' .ft \\$3
+.el .ft CR
+.ie 0\\$2 \{\
+. ss \\$2
+. ps \\$2
+. vs \\$2
+.\}
+.el .ss 12
+.ta T 8u*\w@n@u
+.if (0\\n[misc*verb]%32)/16 .in +\\n[Verbin]u
+.if 0\\n[misc*verb]%2 \{\
+. eo
+. nr @verbose-flag 1 \" tell pageheader to set ec/eo
+.\}
+..
+.de VERBOFF
+.ec
+.br
+.if (0\\n[misc*verb]%8)/4 .SP \\n[Lsp]u
+.if (0\\n[misc*verb]%16)/8 .nm
+.if (0\\n[misc*verb]%32)/16 .in
+.ev
+.nr @verbose-flag 0
+..
+.\" ######## module pict #################
+.nr pict*width 0
+.nr pict*height 0
+.nr pict*mode 0
+.nr pict*ind 0
+.nr pict*id 0 1
+.\" I assume that the number variable pict*id is the same
+.\" between two runs.
+.de PIC
+.br
+.nr pict*ind 0
+.nr pict*box 0
+.while \\n[.$]>0 \{\
+. if '-B'\\$1' \{\
+. nr pict*box 1
+. shift
+. continue
+. \}
+. if '-L'\\$1' \{\
+. nr pict*mode 0
+. shift
+. continue
+. \}
+. if '-R'\\$1' \{\
+. nr pict*mode 1
+. shift
+. continue
+. \}
+. if '-I'\\$1' \{\
+. nr pict*ind (m;\\$2)
+. nr pict*mode 2
+. shift 2
+. continue
+. \}
+. if '-C'\\$1' \{\
+. nr pict*mode 3
+. shift
+. continue
+. \}
+. ds pict*f \\$1
+. nr pict*id +1
+. shift
+. if \\n[.$]>0 \{\
+. nr pict*width (i;\\$1)
+. shift
+. \}
+. if \\n[.$]>0 \{\
+. nr pict*height (i;\\$1)
+. shift
+. \}
+.\}
+.if \\n[Ref]>0 \{\
+. tm .\\\\" PIC id \\n[pict*id]
+. tm .\\\\" PIC file \\*[pict*f]
+.\}
+.if d pict*file!\\n[pict*id] \{\
+. ds pict*f \\*[pict*file!\\n[pict*id]]
+. nr pict*llx \\n[pict*llx!\\n[pict*id]]
+. nr pict*lly \\n[pict*lly!\\n[pict*id]]
+. nr pict*urx \\n[pict*urx!\\n[pict*id]]
+. nr pict*ury \\n[pict*ury!\\n[pict*id]]
+. \"
+. nr pict*w (p;\\n[pict*urx]-\\n[pict*llx])
+. if \\n[pict*w]<0 .nr pict*w 0-\\n[pict*w]
+. nr pict*h (p;\\n[pict*ury]-\\n[pict*lly])
+. if \\n[pict*h]<0 .nr pict*h 0-\\n[pict*h]
+. if \\n[pict*width]>0 \{\
+. nr pict*rs (u;1000*\\n[pict*width]/\\n[pict*w])
+. nr pict*w (u;\\n[pict*w]*\\n[pict*rs]/1000)
+. nr pict*h (u;\\n[pict*h]*\\n[pict*rs]/1000)
+. \}
+. if \\n[pict*height]>0 \{\
+. nr pict*rs (u;1000*\\n[pict*height]/\\n[pict*h])
+. nr pict*h (u;\\n[pict*h]*\\n[pict*rs]/1000)
+. \}
+. if '0'\\n[pict*mode]' \{\
+. nr pict*in \\n[.i]u
+. \}
+. if '1'\\n[pict*mode]' \{\
+. nr pict*in (u;\\n[.l]-\\n[.i]-\\n[pict*w])
+. \}
+. if '2'\\n[pict*mode]' \{\
+. nr pict*in \\n[pict*ind]u
+. \}
+. if '3'\\n[pict*mode]' \{\
+. nr pict*in (u;(\\n[.l]-\\n[.i]-\\n[pict*w])/2)
+. \}
+. ds pict*h "
+. if \\n[pict*h]>0 .ds pict*h \\n[pict*h]
+. \"
+. ne \\n[pict*h]u
+. \"
+. \" these lines are copied and modified from tmac.pspic.
+. \" Originally written by James Clark
+. br
+. ie \\n[pict*box]>0 \{\
+\h'\\n[pict*in]u'\
+\Z'\D'p 0 \\n[pict*h]u \\n[pict*w]u 0 0 -\\n[pict*h]u''\
+\v'\\n[pict*h]u'\X'ps: import \\*[pict*f] \
+\\n[pict*llx] \\n[pict*lly] \\n[pict*urx] \\n[pict*ury] \\n[pict*w] \\n[pict*h]'
+.\}
+. el \{\
+\h'\\n[pict*in]u'\
+\X'ps: invis'\
+\Z'\D'p 0 \\n[pict*h]u \\n[pict*w]u 0 0 -\\n[pict*h]u''\
+\X'ps: endinvis'\
+\v'\\n[pict*h]u'\X'ps: import \\*[pict*f] \
+\\n[pict*llx] \\n[pict*lly] \\n[pict*urx] \\n[pict*ury] \\n[pict*w] \\n[pict*h]'
+. \}
+. br
+. sp \\n[pict*h]u
+.\}
+..
+.\" external picture
+.de EPIC
+.if \\n[.$]< 2 .@error "EPIC: Not enough arguments"
+.nr pict*w \\$1
+.nr pict*h \\$2
+.ds pict*name "External picture
+.if !''$3' .ds pict*name \\$3
+\&
+.br
+.ne \\n[pict*h]u
+.sp \\n[pict*h]u
+.nr pict*ind (u;(\\n[.l]-\\n[.i]-\\n[pict*w])/2)
+.in +\\n[pict*ind]u
+\D'l \\n[pict*w]u 0'\
+\D'l 0 -\\n[pict*h]u'\
+\D'l -\\n[pict*w]u 0'\
+\D'l 0 \\n[pict*h]u'\
+\v'-(u;\\n[pict*h]/2)'\
+\h'(u;(\\n[pict*w]-\w'\\*[pict*name]'/2))'\\*[pict*name]
+.in
+..
+.\" ######## module acc #################
+.\"-----------
+.\" accents. These are copied from mgs, written by James Clark.
+.de acc@over-def
+.ds \\$1 \Z'\v'(u;\w'x'*0+\En[rst]-\En[.cht])'\
+\h'(u;-\En[skw]+(-\En[.w]-\w'\\$2'/2)+\En[.csk])'\\$2'
+..
+.de acc@under-def
+.ds \\$1 \Z'\v'\En[.cdp]u'\h'(u;-\En[.w]-\w'\\$2'/2)'\\$2'
+..
+.acc@over-def ` \`
+.acc@over-def ' \'
+.acc@over-def ^ ^
+.acc@over-def ~ ~
+.acc@over-def : \(ad
+.acc@over-def ; \(ad
+.acc@under-def , \(ac
+.\" ######## module uni #################
+.\" unimplemented macros
+.de OK
+'tm "OK: not implemented"
+..
+.de PM
+'tm "PM: not implemented"
+..
+.\" ######## module hd #################
+.\" support for usermacro
+.nr hd*h1-page 1 \" last page-number for level 1 header.
+.nr hd*htype 0
+.ds hd*sect-pg
+.ds hd*mark
+.ds hd*suf-space
+.nr hd*need 0
+.aln ;0 hd*htype
+.als }0 hd*mark
+.als }2 hd*suf-space
+.aln ;3 hd*need
+.\"-------------
+.\" .hd@split varable index name val1 val2 ...
+.de hd@split
+.if \\$2>(\\n[.$]-3) .@error "\\$3 must have at least \\$2 values (\\*[\\$3]).
+.nr hd*sp-tmp \\$2+3
+.ds \\$1 \\$[\\n[hd*sp-tmp]]
+..
+.de HU
+.H 0 "\\$1"
+..
+.\"-------------
+.de H
+.if !r hd*cur-bline .nr hd*cur-bline \\n[nl]
+.br
+.df@print-float 2\" $$$ could be wrong...
+.\" terminate all lists
+.LC
+.init@reset
+.nr hd*level 0\\$1
+.nr hd*arg1 0\\$1
+.if !\\n[hd*level] .nr hd*level \\n[Hu]
+.\"
+.\" clear lower counters
+.nr hd*i 1 1
+.while \\n+[hd*i]<8 .if \\n[hd*level]<\\n[hd*i] .nr H\\n[hd*i] 0 1
+.\"
+.\" save last text for use in TP
+.if \\n[hd*level]=1 .ds H1txt \\$2\\$3
+.\"
+.\" This is a little fix to be able to get correct H1 heading number
+.\" in page headers. Special attention was needed when other formats are used.
+.ie !''\\g[H1]' \{\
+. ds hd*format \\g[H1]
+. af H1 0
+. nr H1h \\n[H1] 1
+. af H1 \\*[hd*format]
+.\}
+.el .nr H1h \\n[H1] 1
+.if \\n[hd*level]=1 .nr H1h +1
+.\"
+.\" Check if it's time for new page. Only if text has
+.\" appeared before.
+.if \\n[Ej]&(\\n[Ej]>=\\n[hd*level])&(\\n[nl]>\\n[hd*cur-bline]) .pg@next-page
+.\"
+.\" increment current counter
+.nr H\\n[hd*level] +1
+.\"
+.\" update pagenumber if section-page is used
+.if (\\n[hd*level]=1)&(\\n[Sectp]>0) .hd@set-page 1
+.\"
+.\" hd*mark is the text written to the left of the header.
+.ds hd*mark \\n[H1].
+.\"
+.if \\n[hd*level]>1 .as hd*mark \\n[H2]
+.\"
+.nr hd*i 2 1
+.while \\n+[hd*i]<8 .if \\n[hd*level]>(\\n[hd*i]-1) .as hd*mark .\\n[H\\n[hd*i]]
+.if \\n[Ht] .ds hd*mark \\n[H\\n[hd*level]].
+.\"
+.\" special case, no dot after level one heading if not H1dot true
+.if (\\n[hd*level]=1)&(\\n[H1dot]=0) .ds hd*mark \\n[H1]
+.\"
+.as hd*mark \ \ \" add spaces between mark and heading
+.if !\\n[hd*arg1] .ds hd*mark\" no mark for unnumbered
+.\"
+.if \\n[D]>1 .tm At header \\*[hd*mark] "\\$2"
+.nr hd*htype 0 \" hd*htype = check break and space
+. \" 0 = run-in, 1 = break only, 2 = space
+.if \\n[hd*level]<=\\n[Hb] .nr hd*htype 1
+.if \\n[hd*level]<=\\n[Hs] .nr hd*htype 2
+. \" two spaces if hd*htype == 0
+.ie (\\n[hd*htype]=0)&(\w@\\$2@) .ds hd*suf-space " \"
+.el .ds hd*suf-space
+.nr hd*need 2v \" hd*need = header need space
+.\"---------- user macro HX ------------
+.\" User exit macro to override numbering.
+.\" May change hd*mark (}0), hd*suf-space (}2) and hd*need (;3)
+.\" Can also change Hps1/2.
+.if d HX .HX \\n[hd*level] \\n[hd*arg1] "\\$2\\$3"
+.\"--------------------------------------
+.\" pre-space
+.ie \\n[hd*level]<=\\n[Hps] .SP (u;\\n[Hps2])
+.el .SP (u;\\n[Hps1])
+.\"
+.par@reset-num \\n[hd*level]\" reset numbered paragraph
+.\" start diversion to measure size of header
+.di hd*div
+\\*[hd*mark]\\$2\\$3\\*[hd*suf-space]
+.br
+.di
+.rm hd*div
+.if \\n[hd*htype] .na \" no adjust if run-in
+.if \\n[hd*htype]<2 .nr hd*need +\\n[Lsp]u \" add some extra space
+.ne \\n[hd*need]u+\\n[dn]u+.5p-1v \" this is the needed space for a header
+.\"
+.\" size and font calculations
+.hd@split hd*font \\n[hd*level] HF \\*[HF]\" get font for this level
+.ft \\*[hd*font]\" set new font
+.hd@split hd*new-ps \\n[hd*level] HP \\*[HP]\" get point size
+.ie (\\*[hd*new-ps]=0):(\w@\\*[hd*new-ps]@=0) \{\
+. if \\n[hd*htype] \{\
+. if '\\*[hd*font]'3' \{\
+. ps -1
+. vs -1
+. \}
+. if '\\*[hd*font]'B' \{\
+. ps -1
+. vs -1
+. \}
+. \}
+.\}
+.el \{\
+. ps \\*[hd*new-ps]
+. vs \\*[hd*new-ps]+2
+.\}
+.\"
+.\"---------- user macro HY -------------
+.\" user macro to reset indents
+.if d HY .HY \\n[hd*level] \\n[hd*arg1] "\\$2\\$3"
+.\"--------------------------------------
+.nr hd*mark-size \w@\\*[hd*mark]@
+.if (\\n[hd*level]<=\\n[Hc])&\\n[hd*htype] .ce\" center if level<=Hc
+.\"
+.\" finally, output the header
+\\*[hd*mark]\&\c
+.\" and the rest of the header
+.ie \\n[hd*htype] \{\
+\\$2\\$3
+. br
+.\}
+.el \\$2\\$3\\*[hd*suf-space]\&\c
+.ft 1
+.\" restore pointsize and vertical size.
+.ps \\n[@ps]u
+.vs \\n[@vs]u
+.\"
+.\" table of contents
+.if (\\n[hd*level]<=\\n[Cl])&\w@\\$2@ .toc@entry \\n[hd*level] "\\$2"
+.\" set adjust to previous value
+.SA
+.\" do break or space
+.if \\n[hd*htype] .br
+.if \\n[hd*htype]>1 .SP (u;\\n[Lsp]*\\n[Hss])
+.if \\n[hd*htype] \{\
+. \" indent if Hi=1 and Pt=1
+. if (\\n[Hi]=1)&(\\n[Pt]=1) .ti +\\n[Pi]n
+. \" indent size of mark if Hi=2
+. if \\n[hd*htype]&(\\n[Hi]>1) .ti +\\n[hd*mark-size]u
+.\}
+.nr par@ind-flag 0 \" no indent on .P if Pt=2
+.\"
+.\" check if it is time to reset footnotes
+.if (\\n[hd*level]=1)&\\n[ft*clear-at-header] .nr ft*nr 0 1
+.\"
+.\" check if it is time to reset indexes
+.if (\\n[hd*level]=1)&\\n[Sectf] \{\
+. nr lix*fg-nr 0 1
+. nr lix*tb-nr 0 1
+. nr lix*ec-nr 0 1
+. nr lix*ex-nr 0 1
+.\}
+.\"---------- user macro HZ ----------
+.if d HZ .HZ \\n[hd*level] \\n[hd*arg1] "\\$2\\$3"
+.nr hd*last-pos \\n[nl]
+.nr hd*last-hpos \\n[.k]
+.nr par@ind-flag 0
+..
+.\"--------
+.de HM
+.nr hd*i 0 1
+.while \\n+[hd*i]<8 .af H\\n[hd*i] \\$[\\n[hd*i]] 1
+..
+.\"----------------------
+.\" set page-nr, called from header
+.\"
+.de hd@set-page
+.\"
+.ie \\n[.$]>0 .nr P \\$1
+.el .nr P +1
+.\" Set section-page-string
+.ds hd*sect-pg \\n[H1]-\\n[P]
+.if \\n[Sectp]>1 .if '\\n[H1]'0' .ds hd*sect-pg "
+..
+.\"########### module pg ####################
+.\" set end of text trap
+.wh 0 pg@header
+.em pg@end-of-text
+.\"
+.ds pg*header ''- \\nP -''
+.ds pg*footer
+.if \n[N]=4 .ds pg*header ''''
+.if (\n[N]=3):(\n[N]=5) \{\
+. ds pg*header ''''
+. ds pg*footer ''\\*[hd*sect-pg]''
+.\}
+.ds pg*even-footer
+.ds pg*odd-footer
+.ds pg*even-header
+.ds pg*odd-header
+.\"
+.nr pg*top-margin 0
+.nr pg*foot-margin 0
+.nr pg*block-size 0
+.nr pg*footer-size 5\" 1v+footer+even/odd footer+2v
+.nr pg*header-size 7\" 3v+header+even/odd header+2v
+.nr pg*extra-footer-size 0
+.nr pg*extra-header-size 0
+.nr ft*note-size 0
+.nr pg*cur-column 0
+.nr pg*cols-per-page 1
+.nr pg*cur-po \n[@po]
+.nr pg*head-mark 0
+.\"
+.nr pg*ps \n[@ps]
+.nr pg*vs \n[@vs]
+.\"-------------------------
+.\" footer TRAPS: set, enable and disable
+.de pg@set-new-trap
+.nr pg*foot-trap \\n[@pl]u-(\\n[pg*block-size]u+\\n[ft*note-size]u+\\n[pg*foot-margin]u+\\n[pg*footer-size]v+\\n[pg*extra-footer-size]u)
+.\"
+.if \\n[D]>2 .tm pg*foot-trap \\n[@pl]u-(\\n[pg*block-size]u+\\n[ft*note-size]u+\\n[pg*foot-margin]u+\\n[pg*footer-size]v+\\n[pg*extra-footer-size]u) = \\n[pg*foot-trap]
+.\"
+.\" last-pos points to the position of the footer and bottom
+.\" block below foot-notes.
+.nr pg*last-pos \\n[@pl]u-(\\n[pg*block-size]u+\\n[pg*foot-margin]u+\\n[pg*footer-size]v)
+.if \\n[D]>2 .tm pg*last-pos \\n[@pl]u-(\\n[pg*block-size]u+\\n[pg*foot-margin]u+\\n[pg*footer-size]v) = \\n[pg*last-pos]
+..
+.de pg@enable-trap
+.wh \\n[pg*foot-trap]u pg@footer
+.if \\n[D]>2 .tm pg@enable-trap .t=\\n[.t] nl=\\n[nl]
+.if \\n[D]>2 .ptr
+..
+.de pg@disable-trap
+.ch pg@footer
+..
+.\" move to new trap (if changed).
+.de pg@move-trap
+.pg@disable-trap
+.pg@set-new-trap
+.pg@enable-trap
+..
+.de pg@enable-top-trap
+.\" set trap for pageheader.
+.nr pg*top-enabled 1
+..
+.de pg@disable-top-trap
+.\" remove trap for pageheader.
+.nr pg*top-enabled 0
+..
+.\" no header on the next page
+.de PGNH
+.nr pg*top-enabled (-1)
+..
+.\" set first trap for pagefooter
+.pg@enable-top-trap
+.pg@set-new-trap
+.pg@enable-trap
+.\"-------------------------
+.\" stop output and begin on next page. Fix footnotes and all that.
+.de pg@next-page
+.\".debug next-page
+.ne 999i \" activate trap
+.\" .pg@footer
+..
+.\"-------------------------
+.\" support for PX, TP and EOP.
+.als }t pg*header
+.als }e pg*even-header
+.als }o pg*odd-header
+.als TPh pg*header
+.als TPeh pg*even-header
+.als TPoh pg*odd-header
+.\"
+.als EOPf pg*footer
+.als EOPef pg*even-footer
+.als EOPof pg*odd-footer
+.\"------------------------------------------------------------
+.\" HEADER
+.de pg@header
+.if \\n[D]>1 .tm Page# \\n[%] (\\n[.F]:\\n[c.])
+.if \\n[Idxf] \{\
+.tl '<pagenr\ \\n[%]>'''
+.\}
+.\" assign current page-number to P
+.hd@set-page
+.\" reset spacing
+.nr line*lp\\n[.z] 0
+.nr line*ac\\n[.z] 0
+.\"
+.\" suppress pageheader if pagenumber == 1 and N == [124]
+.if \\n[pg*top-enabled] \{\
+.\" must be fixed!!
+.\". pg@disable-top-trap
+. if \\n[pg*extra-header-size] 'sp \\n[pg*extra-header-size]u
+. if \\n[pg*top-margin] 'sp \\n[pg*top-margin]u
+. ev pg*tl-ev
+. pg@set-env
+. ie d let@header .let@header
+. el \{\
+. ie d TP .TP
+. el \{\
+' sp 3
+. ie ((\\n[%]=1)&((\\n[N]=1):(\\n[N]=2))) .sp
+. el .tl \\*[pg*header]
+. ie o .tl \\*[pg*odd-header]
+. el .tl \\*[pg*even-header]
+' sp 2
+. \}
+. \}
+. ev
+. \" why no-space??
+. if d PX \{\
+. ns
+. PX
+. rs
+. \}
+. \" check for pending footnotes
+. ft@check-old
+. \"
+. \" back to normal text processing
+. pg@enable-trap
+. \" mark for multicolumn
+. nr pg*head-mark \\n[nl]u
+. \" reset NCOL pointer at each new page.
+. nr pg*last-ncol 0
+. \" set multicolumn
+. \"
+. pg@set-po
+. \" print floating displays
+. df@print-float 4
+. tbl@top-hook
+. ns
+.\}
+.if \\n[pg*top-enabled]<0 .nr pg*top-enabled 1
+.nr hd*cur-bline \\n[nl] \" .H needs to know if output has occured
+..
+.\"---------------------------------------------------------
+.\" FOOTER
+.de pg@footer
+.ec
+.if \\n[D]>2 .tm Footer# \\n[%] (\\n[.F]:\\n[c.])
+.pg@disable-trap
+.\".debug footer
+.tbl@bottom-hook
+.\" increment pageoffset for MC
+.\" move to the exact start of footer.
+'sp |\\n[pg*foot-trap]u+1v
+.\"
+.if \\n[D]>3 .tm FOOTER after .sp
+.\" print footnotes
+.if d ft*div .ft@print
+.\"
+.pg@inc-po
+.if !\\n[pg*cur-column] .pg@print-footer
+.\" next column
+.pg@set-po
+.pg@enable-trap
+.if \\n[@verbose-flag] .eo \" to help VERBON/VERBOFF
+..
+.\"-------------------------
+.de pg@print-footer
+.\" jump to the position just below the foot-notes.
+'sp |\\n[pg*last-pos]u+1v
+.\" check if there are any bottom block
+.if d pg*block-div .pg@block
+.\"
+.\" print the footer and eject new page
+.ev pg*tl-ev
+.pg@set-env
+.\" user defined end-of-page macro
+.ie d EOP .EOP
+.el \{\
+. ie o .tl \\*[pg*odd-footer]
+. el .tl \\*[pg*even-footer]
+. ie (\\n[%]=1)&(\\n[N]=1) .tl \\*[pg*header]
+. el .tl \\*[pg*footer]
+. tl ''\\*[Pg_type!\\n[@copy_type]]''
+.\}
+.ev
+.\" be sure that floating displays and footnotes will be
+.\" printed at the end of the document.
+.ie (\\n[df*fnr]>=\\n[df*o-fnr]):\\n[ft*exist] \{\
+. ev ne
+' bp
+. ev
+.\}
+.el 'bp
+..
+.\"-------------------------
+.\"
+.\" Initialize the title environment
+.de pg@set-env
+'na
+'nh
+'in 0
+'ti 0
+.ie \\n[Pgps] \{\
+. ps \\n[@ps]u
+. vs \\n[@vs]u
+.\}
+.el \{\
+. ps \\n[pg*ps]u
+. vs \\n[pg*vs]u
+.\}
+.lt \\n[@ll]u
+..
+.\"-------------------------
+.de PH
+.ds pg*header "\\$1
+.pg@set-new-size
+..
+.de PF
+.ds pg*footer "\\$1
+.pg@set-new-size
+..
+.de OH
+.ds pg*odd-header "\\$1
+.pg@set-new-size
+..
+.de EH
+.ds pg*even-header "\\$1
+.pg@set-new-size
+..
+.de OF
+.ds pg*odd-footer "\\$1
+.pg@set-new-size
+..
+.de EF
+.ds pg*even-footer "\\$1
+.pg@set-new-size
+..
+.de pg@clear-hd
+.ds pg*even-header
+.ds pg*odd-header
+.ds pg*header
+..
+.de pg@clear-ft
+.ds pg*even-footer
+.ds pg*odd-footer
+.ds pg*footer
+..
+.de pg@set-new-size
+.nr pg*ps \\n[@ps]
+.nr pg*vs \\n[@vs]
+.pg@move-trap
+..
+.\"-------------------------
+.\" end of page processing
+.de pg@footnotes
+.\".debug footnotes
+.\" output footnotes. set trap for block
+.\"
+..
+.\"-------------------------
+.\" print bottom block
+.de pg@block
+.ev pg*block-ev
+'nf
+'in 0
+.ll 100i
+.pg*block-div
+.br
+.ev
+..
+.\"-------------------------
+.\" define bottom block
+.de BS
+.misc@ev-keep pg*block-ev
+.init@reset
+.br
+.di pg*block-div
+..
+.\"-------------------------
+.de BE
+.br
+.di
+.nr pg*block-size \\n[dn]u
+.ev
+.pg@move-trap
+..
+.\"-------------------------
+.\" print out all pending text
+.de pg@end-of-text
+.if \\n[D]>2 .tm ---------- End of text processing ----------------
+.df@eot-print
+.ref@eot-print
+..
+.\"-------------------------
+.\" set top and bottom margins
+.de VM
+.if \\n[.$]=0 \{\
+. nr pg*extra-footer-size 0
+. nr pg*extra-header-size 0
+.\}
+.if \\n[.$]>0 .nr pg*extra-header-size (v;\\$1)
+.if \\n[.$]>1 .nr pg*extra-footer-size (v;\\$2)
+.if \\n[D]>2 \{\
+. tm extra top \\n[pg*extra-footer-size]
+. tm extra bottom \\n[pg*extra-header-size]
+.\}
+.pg@move-trap
+..
+.\"---------------------
+.\" multicolumn output.
+.de pg@set-po
+.if \\n[pg*cols-per-page]>1 \{\
+. ll \\n[pg*column-size]u
+.\}
+..
+.de pg@inc-po
+.if \\n[pg*cols-per-page]>1 \{\
+. ie \\n+[pg*cur-column]>=\\n[pg*cols-per-page] \{\
+. nr pg*cur-column 0 1
+. nr pg*cur-po \\n[@po]u
+. po \\n[@po]u
+. ll \\n[@ll]u
+. \}
+. el \{\
+. nr pg*cur-po +(\\n[pg*column-size]u+\\n[pg*column-sep]u)
+. po \\n[pg*cur-po]u
+' sp |\\n[pg*head-mark]u
+. tbl@top-hook
+. \}
+.\}
+..
+.\" An argument disables the page-break.
+.de 1C
+.br
+.if \\n[pg*cols-per-page]<=1 .@error "1C: multicolumn mode not active"
+.nr pg*cols-per-page 1
+.nr pg*column-sep 0
+.nr pg*column-size \\n[@ll]
+.nr pg*ncol-i \\n[pg*cur-column]\" temp variable
+.nr pg*cur-column 0 1
+.nr pg*cur-po \\n[@po]u
+.PGFORM
+.ie !'\\$1'1' .SK
+.el \{\
+. if d ft*div \{\
+. if \\n[pg*ncol-i]>0 \{\
+. @warning 1C: footnotes will be messy
+. \}
+. \}
+. if \\n[pg*last-ncol]>0 \{\
+. sp |\\n[pg*last-ncol]u
+. nr pg*last-ncol 0
+. \}
+.\}
+..
+.de 2C
+.br
+.nr pg*head-mark \\n[nl]u
+.if \\n[pg*cols-per-page]>1 .@error "2C: multicolumn mode already active"
+.nr pg*cols-per-page 2
+.nr pg*column-sep \\n[@ll]/15
+.nr pg*column-size (\\n[@ll]u*7)/15
+.nr pg*cur-column 0 1
+.nr pg*cur-po \\n[@po]u
+.ll \\n[pg*column-size]u
+.\" .lt \\n[pg*column-size]u
+..
+.\" MC column-size [ column-separation ]
+.de MC
+.br
+.nr pg*head-mark \\n[nl]u
+.if \\n[pg*cols-per-page]>1 .@error "MC: multicolumn mode already active"
+.ie ''\\$1' .nr pg*column-size \\n[.l]
+.el .nr pg*column-size (n;\\$1)
+.ie ''\\$2' .nr pg*column-sep \\n[pg*column-size]/15
+.el .nr pg*column-sep (n;\\$2)
+.\"
+.nr pg*cols-per-page (u;\\n[.l]/(\\n[pg*column-size]+\\n[pg*column-sep]+1))
+.nr pg*cur-column 0 1
+.nr pg*cur-po \\n[@po]u
+.ll \\n[pg*column-size]u
+.\" .lt \\n[pg*column-size]u
+..
+.\" begin a new column
+.de NCOL
+.br
+.if \\n[nl]>\\n[pg*last-ncol] .nr pg*last-ncol \\n[nl]
+.pg@footer
+..
+.\" skip pages
+.de SK
+.br
+.bp
+.nr pg*i 0 1
+.\" force new page by writing something invisible.
+.while \\n+[pg*i]<=(0\\$1) \{\
+\&
+. bp
+.\}
+..
+.\"-------------------------------
+.\" MULB width1 space1 width2 space2 width3 space3 ...
+.de MULB
+.br
+.nr pg*i 0 1
+.nr pg*mul-x 0 1
+.nr pg*mul-ind 0
+.nr pg*mul-last 0
+.while \\n[.$] \{\
+. nr pg*mul!\\n+[pg*i] (n;0\\$1)
+. nr pg*muls!\\n[pg*i] (n;0\\$2)
+. shift 2
+.\}
+.nr pg*mul-max-col \\n[pg*i]
+.ds pg*mul-fam \\n[.fam]
+.nr pg*mul-font \\n[.f]
+.ev pg*mul-ev
+.ps \\n[@ps]u
+.vs \\n[@vs]u
+.fam \\*[pg*mul-fam]
+.ft \\n[pg*mul-font]
+.fi
+.hy 14
+.di pg*mul-div
+.MULN
+..
+.\"-----------
+.de MULN
+.if \\n[pg*mul-x]>=\\n[pg*mul-max-col] .@error "MULN: Undefined columnwidth"
+.br
+.if \\n[.d]>\\n[pg*mul-last] .nr pg*mul-last \\n[.d]
+.rt +0
+.in \\n[pg*mul-ind]u
+.ll (u;\\n[.i]+\\n[pg*mul!\\n+[pg*mul-x]])u
+.nr pg*mul-ind +(u;\\n[pg*mul!\\n[pg*mul-x]]+\\n[pg*muls!\\n[pg*mul-x]])
+..
+.\"-----------
+.\" MULE
+.de MULE
+.br
+.if \\n[.d]>\\n[pg*mul-last] .nr pg*mul-last \\n[.d]
+.di
+.ev
+.ne \\n[pg*mul-last]u
+.nf
+.mk
+.pg*mul-div
+.rt
+.sp \\n[pg*mul-last]u
+.fi
+..
+.\"-----------
+.de OP
+.br
+.ie o .if !\\n[pg*head-mark]=\\n[nl] \{\
+. bp +1
+. bp +1
+.\}
+.el .bp
+..
+.\"########### module footnotes ###################
+.nr ft*note-size 0
+.nr ft*busy 0
+.nr ft*nr 0 1
+.nr ft*wide 0
+.nr ft*hyphen 0\" hyphenation value
+.nr ft*adjust 1\" >0 if adjust true
+.nr ft*indent 1\" >0 if text indent true (not imp. $$$)
+.nr ft*just 0\" 0=left justification, 1=right (not imp. $$$)
+.nr ft*exist 0\" not zero if there are any footnotes to be printed
+.nr ft*clear-at-header 0\" >0 if footnotes should be reset at first level head.
+.\"
+.ds F \v'-.4m'\s-3\\n+[ft*nr]\s0\v'.4m'
+.\"
+.\"-----------------
+.\" init footnote environment
+.de ft@init
+.\" indentcontrol not implemented $$$
+.\" label justification not implemented $$$
+'in 0
+'fi
+.ie \\n[ft*adjust] 'ad
+.el 'na
+.ie \\n[ft*hyphen] 'hy 14
+.el 'hy 0
+.ll \\n[@cur-ll]u
+.lt \\n[@cur-ll]u
+.ps (p;\\n[@ps]u-2)
+.vs (p;\\n[@vs]u-1)
+..
+.\"-----------------
+.\" set footnote format
+.\" no support for two column processing (yet). $$$
+.de FD
+.if \\n[.$]=0 .@error "FD: bad arg \\$1"
+.ie \\n[.$]=2 .nr ft*clear-at-header 1
+.el .nr ft*clear-at-header 0
+.\"
+.if !'\\$1'' \{\
+. ie \\$1>11 .nr ft*format 0
+. el .nr ft*format \\$1
+. \"
+. nr ft*hyphen (\\n[ft*format]%2)*14
+. nr ft*format \\n[ft*format]/2
+. \"
+. nr ft*adjust 1-(\\n[ft*format]%2)
+. nr ft*format \\n[ft*format]/2
+. \"
+. nr ft*indent 1-(\\n[ft*format]%2)
+. nr ft*format \\n[ft*format]/2
+. \"
+. nr ft*just \\n[ft*format]%2
+.\}
+..
+.\"---------------
+.\" Footnote and display width control $$$
+.de WC
+.nr ft*i 0 1
+.while \\n+[ft*i]<=\\n[.$] \{\
+. ds ft*x \\$[\\n[ft*i]]
+. if '\\*[ft*x]'N' \{\
+. nr ft*wide 0
+. nr ft*first-fn 0
+. nr ds*wide 0
+. nr ds*float-break 1
+. \}
+. if '\\*[ft*x]'-WF' .nr ft*wide 0
+. if '\\*[ft*x]'WF' .nr ft*wide 1
+. if '\\*[ft*x]'-FF' .nr ft*first-fn 0
+. if '\\*[ft*x]'FF' .nr ft*first-fn 1
+. if '\\*[ft*x]'-WD' \{\
+. nr ds*wide 0
+. if r ft*df-save \{\
+. nr Df \\n[ft*df-save]
+. rm ft*df-save
+. \}
+. \}
+. if '\\*[ft*x]'WD' \{\
+. nr ds*wide 1
+. nr ft*df-save \\n[Df]
+. nr Df 4
+. \}
+. if '\\*[ft*x]'-FB' .nr ds*float-break 0
+. if '\\*[ft*x]'FB' .nr ds*float-break 1
+. if \\n[D]>1 .tm WC WF=\\n[ft*wide] WD=\\n[ds*wide]
+.\}
+..
+.\"-----------------
+.\" begin footnote
+.\" Change environment, switch to diversion and print the foot-note mark.
+.de FS
+.if \\n[ft*busy] .@error "FS: missing FE"
+.nr ft*busy 1
+.ev ft*ev
+.ft@init
+.if !\\n[ft*wide] .pg@set-po
+.di ft*tmp-div
+.nr ft*space (u;\\n[Fs]*\\n[Lsp])
+.sp \\n[ft*space]u
+.\" print mark
+.ie \\n[.$] .ds ft*mark \\$1
+.el .ds ft*mark \\n[ft*nr].
+\\*[ft*mark]
+.in +.75c
+.sp -1
+.nr ft*exist 1
+..
+.\"-----------------
+.\" init footnote diversion
+.de ft@init-footnote
+.di ft*div
+\l'20n'
+.br
+.di
+.nr ft*note-size \\n[dn]
+..
+.\"-----------------
+.\" end footnote
+.\" End the diversion, back to previous environment, and adjust
+.\" the trap to the new foot-note size.
+.de FE
+.nr ft*busy 0
+.br
+.di
+'in 0
+'nf
+.if \\n[@pl]u<\\n[dn]u .@error "FE: too big footnote"
+.if !d ft*div .nr dn +1v
+.if \\n[D]>3 .tm FE: foot-trap=\\n[pg*foot-trap] .d=\\n[.d] dn=\\n[dn]
+.ie (\\n[pg*foot-trap]u-\\n[.d]u)<\\n[dn]u \{\
+. da ft*next-div
+. ft*tmp-div
+. br
+. di
+.\}
+.el \{\
+. if !d ft*div .ft@init-footnote
+. da ft*div
+. ft*tmp-div
+. di
+. nr ft*note-size +\\n[dn]
+.\}
+.rm ft*tmp-div
+.ev
+.pg@move-trap
+..
+.\"-----------------
+.\" print footnotes, see pg@footer
+.de ft@print
+.ev ft*print-ev
+'nf
+'in 0
+.ll 100i
+.ft*div
+.br
+.ev
+.rm ft*div
+.nr ft*note-size 0
+.pg@move-trap
+..
+.\"-----------------
+.\" check if any pending footnotes, see pg@header
+.de ft@check-old
+.if d ft*next-div \{\
+. ev ft*ev
+. ft@init
+. ft@init-footnote
+. nf
+. in 0
+. da ft*div
+. ft*next-div
+. di
+. nr ft*note-size +\\n[dn]
+. rm ft*next-div
+. ev
+. nr ft*exist 0
+. pg@move-trap
+.\}
+..
+.\"########### module display ###################
+.nr ds*wide 0\" >0 if wide displays wanted
+.nr df*fnr 0 1\" floating display counter
+.nr df*o-fnr 1\" floating display counter, already printed
+.nr ds*snr 0 1\" static display counter
+.nr ds*lvl 0 1\" display level
+.nr ds*float-busy 0\" >0 if printing float
+.nr df*float 0 >0 if previous display was floating
+.\"--------------------------------------------
+.de DE
+.ie \\n[df*float] .df@end \\$@
+.el .ds@end \\$@
+..
+.\"--------------------------------------------
+.\" floating display start
+.\" nested DF/DE is not allowed.
+.de DF
+.if \\n[df*float] .@error "DF:nested floating is not allowed. Use DS."
+.ds@set-format \\$@
+.\"
+.nr df*old-ll \\n[.l]
+.nr ds*ftmp \\n[.f]
+.misc@ev-keep df*ev
+.ft \\n[ds*ftmp]
+.\"
+.init@reset
+.di df*div
+'in 0
+.\"
+.ds@set-new-ev \\n[df*old-ll]
+.SP \\n[Lsp]u
+.nr df*float 1
+..
+.\"--------------------------------------------
+.de df@end
+.br
+.SP \\n[Lsp]u
+.di
+.nr df*width!\\n+[df*fnr] \\n[dl]
+.nr df*height!\\n[df*fnr] \\n[dn]
+.nr df*wide!\\n[df*fnr] \\n[ds*wide]
+.nr df*format!\\n[df*fnr] \\n[ds*format]
+.ev
+.if \\n[D]>2 .tm DF:fnr=\\n[df*fnr] w=\\n[dl] h=\\n[dn] wide=\\n[ds*wide] \
+ form=\\n[ds*format]
+.\" move div to the floating display list
+.rn df*div df*fdiv!\\n[df*fnr]
+.\"
+.nr par@ind-flag 0
+.\" print float if queue is empty and the display fits into
+.\" the current page
+.if ((\\n[df*fnr]>=\\n[df*o-fnr])&(\\n[dn]<\\n[.t])) .df@print-float 1
+.nr df*float 0
+..
+.\"-------------
+.\" called by end-of-text
+.de df@eot-print
+.br
+.if \\n[df*o-fnr]<=\\n[df*fnr] \{\
+. if \\n[D]>2 .tm Print remaining displays.
+.\" still some floats left, make non-empty environment
+. misc@ev-keep ne
+. init@reset
+\c
+. df@print-float 3
+. ev
+.\}
+..
+.\"---------------
+.\" print according to Df and De.
+.\" .df@print-float type
+.\" type called from
+.\" 1 .DE
+.\" 2 end of section
+.\" 3 end of document
+.\" 4 beginning of new page
+.\"
+.de df@print-float
+.if \\n[Df]>5 .@error "Df=\\n[Df], max value is 5"
+.if !\\n[ds*float-busy] \{\
+. nr ds*float-busy 1
+.\" at .DE
+. if \\n[D]>3 .tm print-float: .t=\\n[.t], h=\\n[df*height!\\n[df*o-fnr]]
+. \" Df = 1 or 5
+. if (\\$1=1)&((\\n[Df]=1):(\\n[Df]=5)) \{\
+. if \\n[.t]>\\n[df*height!\\n[df*o-fnr]] \{\
+. \" Print only new displays.
+. if \\n[df*o-fnr]=\\n[df*fnr] \{\
+. br
+. ds@print-one-float
+. \}
+. \}
+. \}
+. \" Df = 3
+. if (\\$1=1)&(\\n[Df]=3) \{\
+. if \\n[.t]>\\n[df*height!\\n[df*o-fnr]] \{\
+. br
+. ds@print-one-float
+. \}
+. \}
+.\" print all if Df<2 and end of section
+. if (\\$1=2)&(\\n[Sectp]>0)&(\\n[Df]<2) \{\
+. br
+. ds@print-all-floats
+. \}
+.\" print all if end of document. Where should they go instead?
+. if \\$1=3 \{\
+. br
+. ds@print-all-floats
+.\}
+.\" new page
+. if (\\$1=4)&(\\n[Df]>1) \{\
+. if \\n[Df]=2 .ds@print-one-float
+. if \\n[Df]=3 .ds@print-one-float
+. if \\n[Df]>3 \{\
+. ie \\n[De] .ds@print-all-floats
+. el .ds@print-this-page
+. \}
+. \}
+. nr ds*float-busy 0
+.\}
+..
+.\"---------------
+.\" DF out
+.\" print a floating diversion
+.de ds@output-float
+.nr df*old-ll \\n[.l]
+.nr df*old-in \\n[.i]
+.ev ds*fev
+.nf
+.nr df*i \\n[df*o-fnr]
+.nr df*f \\n[df*format!\\n[df*i]]
+.\"
+.in \\n[df*old-in]u
+.if \\n[df*f]=1 'in +\\n[Si]n
+.if \\n[df*f]>=2 'in 0
+.if \\n[df*f]=2 'ce 9999
+.if \\n[df*f]=3 'in (u;(\\n[.l]-\\n[df*width!\\n[df*i]])/2)
+.if \\n[df*f]=4 'rj 9999
+.if \\n[df*f]=5 'in (u;\\n[.l]-\\n[df*width!\\n[df*i]])
+.\"
+.\"
+.df*fdiv!\\n[df*o-fnr]
+.\"
+.if \\n[df*f]=2 'ce 0
+.if \\n[df*f]=4 'rj 0
+.ev
+.rm df*fdiv!\\n[df*i]
+.rm df*height!\\n[df*i]
+.rm df*format!\\n[df*i]
+.if \\n[df*wide!\\n[df*i]] .nr pg*head-mark \\n[nl]u
+.nr df*o-fnr +1
+..
+.\"---------------
+.\" print one floating display if there is one.
+.de ds@print-one-float
+.if \\n[df*o-fnr]<=\\n[df*fnr] \{\
+. if \\n[D]>3 .tm print-one-float: .t=\\n[.t], h=\\n[df*height!\\n[df*o-fnr]]
+. if \\n[.t]<\\n[df*height!\\n[df*o-fnr]] .pg@next-page
+. ds@output-float
+. if \\n[De] .pg@next-page
+.\}
+..
+.\"---------------
+.\" print all queued floats.
+.\" if De>0 do a page eject between the floats.
+.de ds@print-all-floats
+.while \\n[df*o-fnr]<=\\n[df*fnr] \{\
+. if \\n[D]>3 .tm print-all-floats: .t=\\n[.t], h=\\n[df*height!\\n[df*o-fnr]]
+. if \\n[.t]<\\n[df*height!\\n[df*o-fnr]] .pg@next-page
+. br
+\c
+. ds@output-float
+. if \\n[De] .pg@next-page
+.\}
+..
+.\"---------------
+.\" print as many floats as will fit on the current page
+.de ds@print-this-page
+.while \\n[df*o-fnr]<=\\n[df*fnr] \{\
+. if \\n[D]>3 .tm print-this-page: .t=\\n[.t], h=\\n[df*height!\\n[df*o-fnr]]
+. if \\n[.t]<\\n[df*height!\\n[df*o-fnr]] .break
+. ds@output-float
+.\}
+..
+.\"---------------------------------------------------
+.\" get format of the display
+.de ds@set-format
+.ie \\n[.$] \{\
+. ie r ds*format!\\$1 .nr ds*format \\n[ds*format!\\$1]
+. el .@error "DS/DF:wrong format:\\$1"
+.\}
+.el .nr ds*format 0
+.if \\n[D]>2 .tm set format=\\n[ds*format]
+.\" fill or not to fill, that is the...
+.nr ds*fill 0
+.ie \\n[.$]>1 \{\
+. ie r ds*fill!\\$2 .nr ds*fill \\n[ds*fill!\\$2]
+. el .@error "\\*[ds*type]:wrong fill:\\$2"
+.\}
+.if \\n[D]>2 .tm set fill=\\n[ds*fill]
+.nr ds*rindent 0
+.if \\n[.$]>2 .nr ds*rindent \\$3
+.if \\n[D]>2 .tm set indent=\\n[ds*rindent]
+..
+.\"-----------------------------
+.\" .ds@set-new-ev previous-line-length
+.de ds@set-new-ev
+.ll \\$1u
+.lt \\$1u
+.if \\n[ds*rindent] \{\
+. ll -\\n[ds*rindent]n
+. lt -\\n[ds*rindent]n
+.\}
+.if \\n[ds*wide] \{\
+. ll \\n[@ll]u
+. lt \\n[@ll]u
+.\}
+.\"
+.ie \\n[ds*fill] 'fi
+.el 'nf
+..
+.\"--------------------------------------------------------
+.nr ds*format 0\" dummy value for .En/.EQ
+.nr ds*format! 0\" no indent
+.nr ds*format!0 0\" no indent
+.nr ds*format!L 0\" no indent
+.nr ds*format!I 1\" indent
+.nr ds*format!1 1\" indent
+.nr ds*format!C 2\" center each line
+.nr ds*format!2 2\" center each line
+.nr ds*format!CB 3\" center as block
+.nr ds*format!3 3\" center as block
+.nr ds*format!R 4\" right justify each line
+.nr ds*format!4 4\" right justify each line
+.nr ds*format!RB 5\" right justify as block
+.nr ds*format!5 5\" right justify as block
+.\"---------------
+.nr ds*fill! 0\" no fill
+.nr ds*fill!N 0\" no fill
+.nr ds*fill!0 0\" no fill
+.nr ds*fill!F 1\" fill on
+.nr ds*fill!1 1\" fill on
+.\"--------------------------------------------
+.\" static display start
+.\" nested DS/DE is allowed. No limit on depth.
+.de DS
+.br
+.nr ds*lvl +1
+.ds@set-format \\$@
+.\"
+.nr ds*old-ll \\n[.l]
+.nr ds*old-in \\n[.i]
+.misc@push ds-ll \\n[.l]
+.misc@push ds-form \\n[ds*format]
+.nr ds*i \\n[.i]
+.nr ds*ftmp \\n[.f]
+.misc@ev-keep ds*ev!\\n+[ds*snr]
+.ft \\n[ds*ftmp]
+.\"
+.init@reset
+.\" indent in a diversion doesn't seem like a good idea.
+'in 0
+.di ds*div!\\n[ds*snr]
+.\"
+.ds@set-new-ev \\n[ds*old-ll]
+.nr df*float 0
+..
+.\"--------------------------------------------
+.de ds@end
+.if \\n-[ds*lvl]<0 .@error "DE: no corresponding DS"
+.br
+.di
+.\" **********
+.nr ds*width \\n[dl]
+.nr ds*height \\n[dn]
+.misc@pop-nr ds-ll ds*old-ll
+.misc@pop-nr ds-form ds*format
+.\"
+.\" **********
+'nf
+.\" calculate needed space
+.nr ds*need \\n[ds*height]
+.nr ds*i \\n[pg*foot-trap]-\\n[pg*header-size]v-\\n[pg*extra-header-size]v
+.if (\\n[ds*height]>\\n[ds*i])&(\\n[.t]<(\\n[ds*i]/2)) .nr ds*need \\n[.t]u+1v
+.if (\\n[ds*height]<\\n[ds*i])&(\\n[.t]<(\\n[ds*height])) .nr ds*need \\n[.t]u+1v
+.\" Eject page if display will fit one page and
+.\" there are less than half of the page left.
+.if \\n[ds*need] .ne \\n[ds*need]u
+.\"
+.\" check if pending equation label
+.eq@check \\n[ds*need]
+'in \\n[ds*old-in]u
+.if \\n[ds*format]=1 'in \\n[ds*old-in]u+\\n[Si]n
+.if \\n[ds*format]>=2 'in 0
+.if \\n[ds*format]=2 'ce 9999
+.if \\n[ds*format]=3 'in (u;(\\n[.l]-\\n[ds*width])/2)
+.if \\n[ds*format]=4 'rj 9999
+.if \\n[ds*format]=5 'in (u;\\n[.l]-\\n[ds*width])
+.\" **********
+.\"
+.\" Print static display
+.nr ds*i \\n[Lsp]
+.if r Dsp .nr ds*i \\n[Dsp]
+.\"
+.if \\n[Ds] .SP \\n[ds*i]u
+.ds*div!\\n[ds*snr]
+.if \\n[Ds] .SP \\n[ds*i]u
+.\"
+.if \\n[ds*format]=2 'ce 0
+.if \\n[ds*format]=4 'rj 0
+.rm ds*div!\\n[ds*snr]
+.nr ds*snr -1
+.nr par@ind-flag 0
+.ev
+..
+.\"########### module list ###################
+.\" .LI text-indent mark-indent pad type [mark [LI-space [LB-space] ] ]
+.\"
+.nr li*tind 0
+.nr li*mind 0
+.nr li*pad 0
+.nr li*type 0
+.ds li*mark 0
+.nr li*li-spc 0
+.nr li*lvl 0 1
+.aln :g li*lvl
+.nr li*cur-vpos 0
+.\"--------------------------
+.\" the major list-begin macro.
+.\" If type == -1 a 'break' will occur.
+.de LB
+.if \\n[.$]<4 .@error "LB: not enough arguments, min 4"
+.misc@push cind \\n[.i]
+.misc@push tind \\n[li*tind]
+.misc@push mind \\n[li*mind]
+.misc@push pad \\n[li*pad]
+.misc@push type \\n[li*type]
+.misc@push li-spc \\n[li*li-spc]
+.ds li*mark-list!\\n[li*lvl] \\*[li*mark]
+.nr li*lvl +1
+.\"
+.nr li*tind (n;0\\$1)\" text-indent
+.nr li*mind (n;0\\$2)\" mark-indent
+.nr li*pad (n;0\\$3)\" pad
+.nr li*type 0\\$4\" type
+.ds li*mark \\$5\" mark
+.ie !'\\$6'' .nr li*li-spc \\$6\" LI-space
+.el .nr li*li-spc 1
+.ie !'\\$7'' .nr li*lb-spc \\$6\" LB-space
+.el .nr li*lb-spc 0
+.\" init listcounter
+.nr li*cnt!\\n[li*lvl] 0 1
+.\" assign format
+.af li*cnt!\\n[li*lvl] 1
+.if \\n[li*type] .if !'\\*[li*mark]'' .af li*cnt!\\n[li*lvl] \\*[li*mark]
+.\"
+.if \\n[li*lb-spc] .SP (u;\\n[li*lb-spc]*\\n[Lsp])
+.in +\\n[li*tind]u
+..
+.\"---------------
+.de LI
+.if \\n[li*lvl]<1 .@error "LI:no lists active"
+.if \\n[li*li-spc]&(\\n[Ls]>=\\n[li*lvl]) .SP (u;\\n[li*li-spc]*\\n[Lsp])
+.ne 2v
+.\"
+.ds li*c-mark \\*[li*mark]
+.nr li*cnt!\\n[li*lvl] +1
+.if \\n[li*type]=1 .ds li*c-mark \\n[li*cnt!\\n[li*lvl]].
+.if \\n[li*type]=2 .ds li*c-mark \\n[li*cnt!\\n[li*lvl]])
+.if \\n[li*type]=3 .ds li*c-mark (\\n[li*cnt!\\n[li*lvl]])
+.if \\n[li*type]=4 .ds li*c-mark [\\n[li*cnt!\\n[li*lvl]]]
+.if \\n[li*type]=5 .ds li*c-mark <\\n[li*cnt!\\n[li*lvl]]>
+.if \\n[li*type]=6 .ds li*c-mark {\\n[li*cnt!\\n[li*lvl]]}
+.if \\n[.$]=1 .ds li*c-mark \\$1
+.ie \\n[.$]=2 \{\
+. ie (\\$2=2):(\\n[Limsp]=0) .ds li*c-mark \\$1\\*[li*c-mark]
+. el .ds li*c-mark \\$1\ \\*[li*c-mark]
+.\}
+.\"
+.\" determine where the text begins
+.nr li*text-begin \\n[li*tind]>?\w@\\*[li*c-mark]\ @
+.nr x \w@\\*[li*c-mark]\ @
+.\"
+.\" determine where the mark begin
+.ie !\\n[li*pad] .nr li*in \\n[li*mind]
+.el .nr li*in \\n[li*text-begin]-\\n[li*pad]-\w@\\*[li*c-mark]@
+.if !\\n[li*in] .nr li*in 0
+.\"
+.ti -\\n[li*tind]u
+.\" no indentation if hanging indent
+.if (\w@\\*[li*c-mark]@=0)&((\\n[.$]=0):(\w@\\$1@=0)) .nr li*text-begin 0
+\Z'\&\h'\\n[li*in]u'\\*[li*c-mark]'\h'\\n[li*text-begin]u'\&\c
+.if \\n[li*type]=-1 .br
+..
+.\"
+.\"-------------
+.de li@pop
+.nr li*lvl -1
+.misc@pop-nr cind li*tmp
+.in \\n[li*tmp]u
+.misc@pop-nr tind li*tind
+.misc@pop-nr mind li*mind
+.misc@pop-nr pad li*pad
+.misc@pop-nr type li*type
+.misc@pop-nr li-spc li*li-spc
+.ds li*mark \\*[li*mark-list!\\n[li*lvl]]
+..
+.de LE
+.if \\n[li*lvl]<1 .@error "LE:mismatched"
+.li@pop
+.if '\\$1'1' .SP \\n[Lsp]u
+..
+.\"-------------
+.\" list status clear.
+.\" terminate all lists to level i
+.de LC
+.ie \\n[.$]<1 .nr li*i 0
+.el .nr li*i \\$1
+.if \\n[li*i]>\\n[li*lvl] .@error "LC: incorrect argument: \\n[li*i] (too big)"
+.while \\n[li*lvl]>\\n[li*i] .li@pop
+.nr par@ind-flag 0
+..
+.\"-------------
+.de AL
+.if \\n[.$]>3 .@error "AL: too many arguments"
+.if \\n[D]>2 .tm AL $*
+.ie \\n[.$]<=1 .LB \\n[Li] 0 2 1 "\\$1"
+.el \{\
+. ie \\n[.$]=2 .LB 0\\$2 0 2 1 "\\$1"
+. el \{\
+. ie !'\\$2'' .LB \\$2 0 2 1 "\\$1" 0 1
+. el .LB \\n[Li] 0 2 1 "\\$1" 0 1
+. \}
+.\}
+..
+.de ML
+.if \\n[.$]>3 .@error "ML: too many arguments"
+.if \\n[D]>2 .tm ML $*
+.nr li*ml-width \w@\\$1@u+1n
+.if \\n[.$]<2 .LB \\n[li*ml-width]u 0 1 0 "\\$1"
+.if \\n[.$]=2 .LB 0\\$2 0 1 0 "\\$1"
+.if \\n[.$]=3 \{\
+. ie '\\$2'' .LB \\n[li*ml-width]u 0 1 0 "\\$1" 0 1
+. el .LB \\n[Li] 0 1 0 "\\$1" 0 1
+.\}
+..
+.de VL
+.if \\n[D]>2 .tm VL $*
+.if \\n[.$]>3 .@error "VL: too many arguments"
+.if \\n[.$]<1 .@error "VL: missing text-indent"
+.ie \\n[.$]<3 .LB 0\\$1 0\\$2 0 0
+.el .LB 0\\$1 0\\$2 0 0 \& 0 1
+..
+.\" Bullet (for .BL)
+.de BL
+.if \\n[D]>2 .tm BL $*
+.ds BU \s-2\(bu\s0
+.if \\n[.$]>2 .@error "BL: too many arguments"
+.if \\n[.$]<1 .LB \\n[Pi] 0 1 0 \\*[BU]
+.if \\n[.$]=1 .LB 0\\$1 0 1 0 \\*[BU]
+.if \\n[.$]=2 \{\
+. ie '\\$1'' .LB \\n[Pi] 0 1 0 \\*[BU] 0 1
+. el .LB 0\\$1 0 1 0 \\*[BU] 0 1
+.\}
+..
+.de DL
+.if \\n[D]>2 .tm DL $*
+.if \\n[.$]>2 .@error "DL: too many arguments"
+.if \\n[.$]<1 .LB \\n[Pi] 0 1 0 \(em
+.if \\n[.$]=1 .LB 0\\$1 0 1 0 \(em
+.if \\n[.$]=2 \{\
+. ie '\\$1'' .LB \\n[Pi] 0 1 0 \(em 0 1
+. el .LB 0\\$1 0 1 0 \(em 0 1
+.\}
+..
+.de RL
+.if \\n[D]>2 .tm RL $*
+.if \\n[.$]>2 .@error "RL: too many arguments"
+.if \\n[.$]<1 .LB 6 0 2 4
+.if \\n[.$]=1 .LB 0\\$1 0 2 4
+.if \\n[.$]=2 \{\
+. ie '\\$1'' .LB 6 0 2 4 1 0 1
+. el .LB 0\\$1 0 2 4 1 0 1
+.\}
+..
+.\" Broken Variable List. As .VL but text begin on the next line
+.de BVL
+.if \\n[D]>2 .tm BVL $*
+.if \\n[.$]>3 .@error "BVL: too many arguments"
+.if \\n[.$]<1 .@error "BVL: missing text-indent"
+.ie \\n[.$]<3 .LB 0\\$1 0\\$2 0 -1
+.el .LB 0\\$1 0\\$2 0 -1 \& 0 1
+..
+.\" ####### module tbl #######################################
+.\" This module is copied from groff_ms and modified for mgm.
+.\" Yes, it does not resemble the original anymore :-).
+.\" Don't know if I missed something important.
+.\" Groff_ms is written by James Clark.
+.nr tbl*have-header 0
+.nr tbl*header-written 0
+.de TS
+.br
+.if ''\\n[.z]' .SP
+.if '\\$1'H' .di tbl*header-div
+..
+.de tbl@top-hook
+.if \\n[tbl*have-header] \{\
+. ie \\n[.t]-\\n[tbl*header-ht]-1v .tbl@print-header
+. el .sp \\n[.t]u
+.\}
+..
+.de tbl@bottom-hook
+.if \\n[tbl*have-header] \{\
+. nr T. 1
+.\" draw bottom and side lines of boxed tables.
+. T#
+.\}
+.nr tbl*header-written 0
+..
+.de tbl@print-header
+.ev tbl*ev
+'nf
+.tbl*header-div
+.ev
+.mk #T
+.nr tbl*header-written 1
+..
+.de TH
+.if '\\$1'N' @error TH: N not implemented yet. Sorry.
+.ie '\\n[.z]'tbl*header-div' \{\
+. nr T. 0
+. T#
+. br
+. di
+. nr tbl*header-ht \\n[dn]
+. ne \\n[dn]u+1v
+. nr tbl*have-header 1
+. ie '\\$1'N' .if !\\n[tbl*header-written] .tbl@print-header
+. el .tbl@print-header
+.\}
+.el .@error ".TH without .TS H"
+..
+.de TE
+.ie '\\n(.z'tbl*header-div' .@error ".TS H but no .TH before .TE"
+.el \{\
+. nr tbl*have-header 0
+.\}
+.\" reset tabs
+.TAB
+..
+.de T&
+..
+.\" ####### module pic #######################################
+.de PS
+.nr pic*in 0
+.br
+.SP .5
+.ie \\n[.$]<2 .@error "PS: bad arguments. Probably not processed with pic."
+.el \{\
+. if !\\n[ds*lvl] .ne (u;\\$1)+1v
+.\" should be contained between .DS/.DE
+.if r ds*format \{\
+. if \\n[ds*lvl]&((\\n[ds*format]=2):(\\n[ds*format]=3)) \{\
+. nr pic*in \\n[.i]
+.\" . in +(u;\\n[.l]-\\n[.i]-\\$2/2)
+. \}
+. \}
+.\}
+..
+.de PE
+.init@reset
+.SP .5
+..
+.\" ####### module eq #######################################
+.\"
+.nr eq*number 0 1
+.ds eq*label
+.de EQ
+.ds eq*label "\\$1
+..
+.de eq@check
+.if !'\\*[eq*label]'' \{\
+. mk
+' sp (u;\\$1/2-.45v)
+. ie (\\n[Eq]%2) \{\
+. \" label to the left
+\h'|0'\\*[eq*label]\c
+. \}
+. el \{\
+. \" label to the right
+\h'|\\n[.l]u'\\*[eq*label]
+. \}
+. rt
+.\}
+.ds eq*label
+..
+.de EN
+..
+.\"########### module toc ###################
+.\" table of contents
+.nr toc*slevel 1
+.nr toc*spacing \n[Lsp]u
+.nr toc*tlevel 2
+.nr toc*tab 0
+.\"-----------
+.\" Table of contents with friends (module lix)
+.de TC
+.br
+.\" print any pending displays and references
+.df@print-float 3
+.if \\n[ref*flag] .RP 0 1
+.\"
+.if \w@\\$1@>0 .nr toc*slevel \\$1
+.if \w@\\$2@>0 .nr toc*spacing (u;\\$2*\\n[Lsp])
+.if \w@\\$3@>0 .nr toc*tlevel \\$3
+.if \w@\\$4@>0 .nr toc*tab \\$4
+.if \\n[pg*cols-per-page]>1 .1C
+.ds H1txt \\*[Licon]
+.ds Tcst co
+.pg@clear-hd
+.EF ""
+.OF ""
+.pg@next-page
+.\"-------------
+.if d Ci .toc@read-Ci \\*[Ci]
+.nf
+.in 0
+.ie \\n[Oc] .hd@set-page 1
+.el \{\
+. nr toc*pn 1 1
+. af toc*pn i
+. aln ;g toc*pn
+. PF "''\\\\\\\\n[toc*pn]''"
+. am pg@header
+. nr toc*pn +1
+\\..
+.\}
+.nr toc*i 4 1
+.while \\n+[toc*i]<10 \{\
+. if !'\\$\\n[toc*i]'' \{\
+. ce
+\\$\\n[toc*i]
+. br
+. \}
+.\}
+.if \\n[.$]<=4 .if d TX .TX
+.ie d TY .if \\n[.$]<=4 .TY
+.el \{\
+. ce
+\\*[Licon]
+. br
+. SP 3
+.\}
+.if d toc*list .toc*list
+.br
+.\" print LIST OF XXX
+.if d lix*dsfg .lix@print-ds fg FG "\\*[Lf]" \\n[.$]
+.if d lix*dstb .lix@print-ds tb TB "\\*[Lt]" \\n[.$]
+.if d lix*dsec .lix@print-ds ec EC "\\*[Le]" \\n[.$]
+.if d lix*dsex .lix@print-ds ex EX "\\*[Lx]" \\n[.$]
+..
+.\"-----------
+.\" .toc@read-Ci lev1 lev2 lev3 lev4 ... lev7
+.de toc@read-Ci
+.nr toc*i 0 1
+.while \\n+[toc*i]<8 \{\
+. nr toc*hl!\\n[toc*i] \\$\\n[toc*i]
+.\}
+..
+.\"-----------
+.de toc@entry
+.ie \\n[Sectp] \{\
+. toc@save \\$1 "\\*[hd*mark]" "\\$2" \\*[hd*sect-pg]
+.\}
+.el .toc@save \\$1 "\\*[hd*mark]" "\\$2" \\n[%]
+..
+.als )E toc@entry
+.\"-----------
+.de toc@save
+.\" collect maxsize of mark if string Ci don't exist.
+.if !d Ci \{\
+. if !r toc*hl!\\$1 .nr toc*hl!\\$1 0
+. if \\n[toc*hl!\\$1]<=\w@\\$2@ \{\
+. nr toc*hl!\\$1 \w@\\$2@u
+. \}
+.\}
+.am toc*list
+.\" .toc@set level headernumber text pagenr
+.toc@set \\$1 "\\$2" "\\$3" \\$4
+\\..
+..
+.\"-----------
+.\" level mark text pagenumber
+.de toc@set
+.if \\$1<=\\n[toc*slevel] .SP \\n[toc*spacing]u
+.na
+.fi
+.nr toc*ind 0
+.nr toc*i 0 1
+.ie d Ci \{\
+. nr toc*ind +\\n[toc*hl!\\$1]u
+.\}
+.el \{\
+. while \\n+[toc*i]<\\$1 \{\
+. nr toc*ind +\\n[toc*hl!\\n[toc*i]]u
+. \}
+.\}
+.nr toc*text \\n[toc*ind]u+\\n[toc*hl!\\$1]u
+.in \\n[toc*text]u
+.ti -\\n[toc*hl!\\$1]u
+.\"
+.\" length of headernum space
+.nr toc*i \\n[toc*hl!\\$1]-\w@\\$2@
+.\"
+.ll \\n[@ll]u-\w@\\$4@u-2m
+.ne 2v
+.\" ragged right ---------------------------------
+.ie \\$1>\\n[toc*tlevel] \{\
+\\$2
+. sp -1
+\\$3\ \ \ \\$4
+. br
+.\}
+.el \{\
+. \" unnumbered heading --------------------
+. ie '\\$2'' \{\
+. in \\n[toc*ind]u
+\\$3\h'1m'
+. \}
+. \" normal heading ------------------------
+. el \{\
+\\$2
+. sp -1
+\\$3\h'1m'
+. \}
+. ll \\n[@ll]u
+. sp -1
+. nr toc*sep (u;\\n[.l]-\\n[.n]-\\n[.i]-\w@\\$4@)-1m
+\h'|\\n[.n]u'\l'\\n[toc*sep]u.'\h'1m'\\$4
+.\}
+.ll \\n[@ll]u
+..
+.\"########################### module lix ############################
+.\" LIST OF figures, tables, exhibits and equations
+.nr lix*fg-nr 0 1
+.nr lix*tb-nr 0 1
+.nr lix*ec-nr 0 1
+.nr lix*ex-nr 0 1
+.aln Fg lix*fg-nr
+.aln Tb lix*tb-nr
+.aln Ec lix*ec-nr
+.aln Ex lix*ex-nr
+.\"------------
+.de FG
+.lix@print-line fg Lf \\n+[lix*fg-nr] "\\$1" "\\$2" "\\$3" "\\$4"
+..
+.de TB
+.lix@print-line tb Lt \\n+[lix*tb-nr] "\\$1" "\\$2" "\\$3" "\\$4"
+..
+.de EC
+.lix@print-line ec Le \\n+[lix*ec-nr] "\\$1" "\\$2" "\\$3" "\\$4"
+..
+.de EX
+.lix@print-line ex Lx \\n+[lix*ex-nr] "\\$1" "\\$2" "\\$3" "\\$4"
+..
+.\"------------
+.\" print line with 'figure' in the text
+.\" type stringvar number text override flag refname
+.de lix@print-line
+.ds lix*text "\\$4
+.\"
+.ie \\n[Sectf] .ds lix*numb \\n[H1]-\\$3
+.el .ds lix*numb \\$3
+.\"
+.ie !\\n[Of] .ds lix*ds-form .\ \ \"
+.el .ds lix*ds-form "\ \(em\ \"
+.nr lix*in \\n[.i]
+.ds lix*label \\*[Li\\$1]\ \\*[lix*numb]\\*[lix*ds-form]
+.if !'\\$5'' \{\
+. if !0\\$6 .ds lix*label \\*[Li\\$1]\ \\$5\\*[lix*numb]\\*[lix*ds-form]
+. if 0\\$6=1 .ds lix*label \\*[Li\\$1]\ \\*[lix*numb]\\$5\\*[lix*ds-form]
+. if 0\\$6=2 .ds lix*label \\*[Li\\$1]\ \\$5\\*[lix*ds-form]
+.\}
+.\" print line if not between DS/DE
+.ie \\n[ds*lvl]<1&\\n[df*float]=0 \{\
+. lix@print-text "\\*[lix*label]" "\\*[lix*text]" \\$1 \\$2 \\$7
+.\}
+.el \{\
+. lix@embedded-text "\\*[lix*label]" "\\*[lix*text]" \\$1 \\$2 \\$7
+.\}
+.\"
+..
+.\"-----------
+.\" label text type stringvar refname
+.de lix@print-text
+.ie \\n[Sectp] .ds lix*pgnr \\*[hd*sect-pg]
+.el .ds lix*pgnr \\n[%]
+.SP \\n[Lsp]u
+.misc@ev-keep lix
+.init@reset
+.br
+.ie (\w@\\$1\\$2@)>(\\n[.l]-\\n[.i]) \{\
+. in +\w@\\$1@u
+. ti 0
+.\}
+.el .ce 1
+\fB\\$1\fP\\$2
+.br
+.ev
+.\" save line for LIST OF XXX, wth is the width of the label
+.if !r lix*wth\\$3 .nr lix*wth\\$3 0
+.\" find the maximum width
+.if \w@\\*[lix*label]@>\\n[lix*wth\\$3] .nr lix*wth\\$3 \w@\\*[lix*label]@
+.if \\n[\\$4] .lix@ds-save \\$3 \\*[lix*pgnr] "\\*[lix*text]" "\\*[lix*label]"
+.\" save reference to the figure
+.if !'\\$5'' .SETR \\$5 \\*[lix*numb]
+..
+.\" hide printout until diversion is evaluated
+.de lix@embedded-text
+\!.ie \\\\n[Sectp] .ds lix*pgnr \\\\*[hd*sect-pg]
+\!.el .ds lix*pgnr \\\\n[%]
+\!.SP \\\\n[Lsp]u
+\!.misc@ev-keep lix
+\!.ll \\n[.l]u
+\!.init@reset
+\!.fi
+\!.ie (\w@\\$1\\$2@)>(\\\\n[.l]-\\\\n[.i]) \{\
+. in +\w@\\$1@u
+\!. ti 0
+\!\fB\\$1\fP\\$2
+\!.\}
+\!.el \{\
+. ce 1
+\!\fB\\$1\fP\\$2
+\!.\}
+\!.br
+\!.ev
+.\" save line for LIST OF XXX, wth is the width of the label
+\!.if !r lix*wth\\$3 .nr lix*wth\\$3 0
+.\" find the maximum width
+\!.if \w@\\*[lix*label]@>\\\\n[lix*wth\\$3] .nr lix*wth\\$3 \w@\\*[lix*label]@
+\!.if \\\\n[\\$4] .lix@ds-save \\$3 \\\\*[lix*pgnr] "\\*[lix*text]" "\\*[lix*label]"
+.\" save reference to the figure
+\!.if !'\\$5'' .SETR \\$5 \\*[lix*numb]
+..
+.\"------------
+.\" print complete list of XXXX
+.de lix@print-ds
+.\" arg: fg,tb,ec,ex text
+.ds H1txt \\$3
+.ds Tcst \\$1
+.if !\\n[Cp] .pg@next-page
+.\" print LIST OF XXXX
+.\" execute user-defined macros
+.if \\$4<=4 .if d TX\\$2 .TX\\$2
+.ie d TY\\$2 .if \\$4<=4 .TY\\$2
+.el \{\
+. ce
+\\$3
+. SP 3
+.\}
+.in \\n[lix*wth\\$1]u
+.fi
+.lix*ds\\$1
+..
+.\"------------
+.\" save line of list in macro
+.de lix@ds-save
+.\" type pagenumber text
+.am lix*ds\\$1
+.lix@dsln \\$1 \\$2 "\\$3" "\\$4" \\$5
+\\..
+..
+.\"------------
+.\" print appended macro
+.\" lix@dsln type pagenumber text headernr
+.de lix@dsln
+.nr lix*i \\n[lix*wth\\$1]-\w@\\$4@
+.ne 4v
+.ll \\n[@ll]u-\w@\\$4@u-\w@\\$2@u-2m
+.ti -\\n[lix*wth\\$1]u
+\\$4
+.sp -1
+\\$3\h'1m'
+.sp -1
+.ll
+.nr lix*sep (u;\\n[.l]-\\n[.n]-\\n[.i]-\w@\\$2@)-1m
+\h'|\\n[.n]u'\l'\\n[lix*sep]u.'\h'1m'\\$2
+.SP \\n[toc*spacing]u
+..
+.\"########################### module fnt ############################
+.\" some font macros.
+.de R
+.ft R
+.ul 0
+..
+.\"-----------
+.de fnt@switch
+.ul 0
+.ds fnt*tmp
+.nr fnt*prev \\n[.f]
+.nr fnt*i 2 1
+.while \\n+[fnt*i]<=\\n[.$] \{\
+. if \\n[fnt*i]>3 .as fnt*tmp \,
+. ie (\\n[fnt*i]%2)=1 .as fnt*tmp \\$1\\$[\\n[fnt*i]]
+. el .as fnt*tmp \\$2\\$[\\n[fnt*i]]
+. if \\n[fnt*i]<\\n[.$] .as fnt*tmp \/
+.\}
+\&\\*[fnt*tmp]\f[\\n[fnt*prev]]
+..
+.\"-----------
+.de B
+.ie \\n[.$] .fnt@switch \fB \f[\\n[.f]] \\$@
+.el .ft B
+..
+.de I
+.ie \\n[.$] .fnt@switch \fI \f[\\n[.f]] \\$@
+.el .ft I
+..
+.de IB
+.if \\n[.$] .fnt@switch \fI \fB \\$@
+..
+.de BI
+.if \\n[.$] .fnt@switch \fB \fI \\$@
+..
+.de IR
+.if \\n[.$] .fnt@switch \fI \fR \\$@
+..
+.de RI
+.if \\n[.$] .fnt@switch \fR \fI \\$@
+..
+.de RB
+.if \\n[.$] .fnt@switch \fR \fB \\$@
+..
+.de BR
+.if \\n[.$] .fnt@switch \fB \fR \\$@
+..
+.\"########################### module box ############################
+.\" draw a box around some text. Text will be kept on the same page.
+.\"
+.nr box*ll 0
+.\" .B1 and .B2 works like .DS
+.de B1
+.if \\n[box*ll] .@error "B1: missing B2"
+.nr box*ll \\n[.l]
+.nr box*ind \\n[.i]
+.nr box*hyp \\n[.hy]
+.nr box*wid \\n[.l]-\\n[.i]
+.\"
+.\" jump to new environment.
+.ev box*ev
+.di box*div
+.ps \\n[@ps]u
+.vs \\n[@vs]u
+.in 1n
+.ll (u;\\n[box*wid]-1n)
+.hy \\n[.hy]
+..
+.de B2
+.if !\\n[box*ll] .@error "B2: missing B1"
+.br
+.di
+.nr box*height \\n[dn]
+.ne \\n[dn]u+1v
+.ll \\n[box*ll]u
+.in \\n[box*ind]u
+.nr box*y-pos \\n[.d]u
+.nf
+.box*div
+.fi
+\v'-1v+.25m'\
+\D'l \\n[box*wid]u 0'\
+\D'l 0 -\\n[box*height]u'\
+\D'l -\\n[box*wid]u 0'\
+\D'l 0 \\n[box*height]u'
+.br
+.sp -1
+.ev
+.sp .20v
+.in \\n[box*ind]u
+.ll \\n[box*ll]u
+.rm box*div
+.nr box*ll 0
+..
+.\"########################### module ref ############################
+.nr ref*nr 0 1
+.aln :R ref*nr
+.nr ref*nr-width 5n
+.nr ref*flag 0 \" for end-of-text
+.ds Rf \v'-.4m'\s-3[\\n+[ref*nr]]\s0\v'.4m'
+.\"
+.\" start reference
+.\"------------
+.de RS
+.if !''\\$1' .ds \\$1 \v'-.4m'\s-3[\\n[ref*nr]]\s0\v'.4m'
+.nr ref*flag 1
+.am ref*mac
+.ref@start-print \\n[ref*nr]
+\\..
+.eo
+.am ref*mac RF
+..
+.\"------------
+.de RF
+.ec
+.am ref*mac
+.ref@stop-print
+\\..
+..
+.\"------------
+.de ref@start-print
+.di ref*div
+.in \\n[ref*nr-width]u
+.ti -(\w@\\$1.@u+1n)
+\\$1.
+.sp -1
+..
+.de ref@stop-print
+.br
+.di
+.ne \\n[dn]u
+.ev ref*ev2
+.nf
+.ref*div
+.ev
+.rm ref*div
+.if \\n[Ls] .SP \\n[Lsp]u
+..
+.\"-----------
+.de RP
+.if !d ref*mac .@error "RP: No references!"
+.nr ref*i 0\\$2
+.if \\n[ref*i]<2 .SK
+.SP 2
+.ref@print-refs
+.if 0\\$1<1 .nr ref*nr 0 1
+.if ((\\n[ref*i]=0):(\\n[ref*i]=2)) .SK
+..
+.\"-----------
+.\" called by end-of-text!
+.de ref@eot-print
+.\".if \\n[ref*flag] \{
+.if d ref*mac \{\
+. if \\n[D]>2 .tm Print references, called by eot
+. nr ref*flag 0
+. br
+. misc@ev-keep ne
+. init@reset
+\c
+' bp
+. ev
+. ref@print-refs
+.\}
+..
+.\"-----------
+.\" prints the references
+.de ref@print-refs
+.toc@save 1 "" "\\*[Rp]" \\n[%]
+.ce
+\fI\\*[Rp]\fP
+.sp
+.nr ref*ll \\n[.l]
+.misc@ev-keep ref*ev
+.ll \\n[ref*ll]u
+.in 0
+.ref*mac
+.in
+.rm ref*mac
+.ev
+.nr ref*flag 0 1
+..
+.\"########################### module app ############################
+.\"
+.nr app*nr 0 1
+.af app*nr A
+.nr app*dnr 0 1
+.nr app*flag 0
+.\"------------
+.\" .APP name text
+.\" name == "" -> autonumber
+.de APP
+.\" .if \\n[.$]<2 .@error "APP: too few arguments"
+.app@set-ind "\\$1"
+.\"
+.ds Tcst ap
+.ds Apptxt \\$2
+.\"
+.ie \\n[Aph] .app@header \\*[app*ind] "\\$2"
+.el .bp
+.app@index "\\*[app*ind]" "\\$2"
+..
+.\"------------
+.\" .APPSK name pages text
+.\" name == "" -> autonumber
+.de APPSK
+.if \\n[.$]<2 .@error "APPSK: too few arguments"
+.app@set-ind "\\$1"
+.\"
+.ds Tcst ap
+.ds Apptxt \\$3
+.\"
+.ie \\n[Aph] .app@header \\*[app*ind] "\\$3"
+.el .bp
+.app@index "\\*[app*ind]" "\\$3"
+.pn +\\$2
+..
+.\"------------
+.de app@set-ind
+.ie \w@\\$1@ .ds app*ind \\$1
+.el \{\
+. if !\\n[app*flag] \{\
+. nr H1 0 1
+. af H1 A
+. af H1h A
+. nr app*flag 1
+. \}
+. ds app*ind \\n+[app*nr]
+. nr H1 \\n+[app*dnr]
+. nr H1h \\n[app*dnr]
+.\}
+.\" clear lower counters
+.nr app*i 1 1
+.while \\n+[app*i]<8 .nr H\\n[app*i] 0 1
+..
+.\"------------
+.de app@index
+.toc@save 1 "" "\\*[App] \\$1: \\$2" \\n[%]
+..
+.\"------------
+.\" app@heaer name text
+.de app@header
+.bp
+.SP (u;\\n[Lsp]*4)
+.ce 1
+\s+4\fB\\*[App]\ \\$1\fP\s0
+.SP (u;\\n[Lsp]*2)
+.if \w@\\$2@<\\n[.l] .ce 1
+\fB\s+2\\$2\s0\fP
+.SP (u;\\n[Lsp]*4)
+..
+.als APPX app@header
+.\"########################### module cov ############################
+.\" title stored in diversion cov*title
+.\" abstract stored in diversion cov*abstract
+.\" arg to abstract stored in cov*abs-arg
+.\" indent stored in cov*abs-ind
+.\" number of authors stored in cov*au
+.\" author(s) stored in cov*au!x!y
+.\" author(s) title stored in cov*at!x!y
+.\" x is the author-index [1-cov*au], y is the argument-index [1-9].
+.\" author(s) firm stored in cov*firm
+.\" new date (if .ND exists) is stored in cov*new-date
+.\"
+.\"
+.ds cov*abs-name ABSTRACT
+.\"
+.nr cov*au 0
+.de TL
+.rm IA IE WA WE LO LT
+.if \\n[.$]>0 .ds cov*title-charge-case \\$1
+.if \\n[.$]>1 .ds cov*title-file-case \\$2
+.pg@disable-top-trap
+.eo
+.de cov*title AU
+..
+.\"-------------------
+.de cov@title-end
+.ec
+..
+.\"-------------------
+.\" .AU name [initials [loc [dept [ext [room [arg [arg [arg]]]]]]]]
+.de AU
+.cov@title-end
+.pg@disable-top-trap
+.nr cov*au +1
+.nr cov*i 0 1
+.ds cov*au!\\n[cov*au]!1
+.while \\n[.$]>=\\n+[cov*i] \{\
+. ds cov*au!\\n[cov*au]!\\n[cov*i] "\\$[\\n[cov*i]]
+.\}
+.if (\\n[.$]>=3)&(\w@\\$3@) \{\
+. if d cov*location-\\$3] \{\
+. ds cov*au!3!\\n[cov*au] \\*[cov*location-\\$3]
+. \}
+.\}
+..
+.\"-------------------
+.\" .AT title1 [title2 [... [title9] ]]]]
+.\" Well, thats all that COVEND look for.
+.\" Must appear directly after .AU
+.de AT
+.if \\n[.$]<1 .@error "AT: no arguments"
+.nr cov*i 0 1
+.while \\n[.$]>=\\n+[cov*i] \{\
+. ds cov*at!\\n[cov*au]!\\n[cov*i] "\\$[\\n[cov*i]]
+.\}
+..
+.\"-------------------
+.de AF
+.cov@title-end
+.ds cov*firm \\$1
+..
+.de AST
+.ds cov*abs-name \\$1
+..
+.de AS
+.pg@disable-top-trap
+.if d cov*abstract .@error "AS: only one abstract allowed"
+.if !''\\n[.z]' .@error "AS: no diversion allowed (previous .AS?)"
+.nr cov*abs-arg 0\\$1
+.nr cov*abs-ind (n;0\\$2)
+.de cov*abstract AE
+..
+.de AE
+..
+.\" fixed for 2000, now uses \n[year].
+.de ISODATE
+. \" support for ISO-date
+. nr cov*mm \\n[mo]
+. nr cov*dd \\n[dy]
+. af cov*mm 01
+. af cov*dd 01
+. ie '0'\\$1' \{\
+. ds cov*new-date \\*[MO\\n[mo]] \\n[dy], \\n[year]
+. \}
+. el \{\
+. ds cov*new-date \\n[year]-\\n[cov*mm]-\\n[cov*dd]
+. \}
+..
+.ISODATE 0
+.als DT cov*new-date
+.de ND
+.ds cov*new-date \\$1
+..
+.\" switch to ISO-date if register Iso exist: YYYY-MM-DD
+.if r Iso .ISODATE 1
+.\"-------------------
+.\" save technical numbers.
+.de TM
+.nr cov*i 0 1
+.while \\n[.$]>=\\n+[cov*i] .ds cov*mt-tm!\\n[cov*i] \\$[\\n[cov*i]]
+.nr cov*mt-tm-max \\n[.$]
+..
+.\"-----------------------
+.\" cover sheet
+.\" the file must have the following last lines (somewhere):
+.\" .pg@enable-top-trap
+.\" .bp 1
+.\" .pg@enable-trap
+.ds cov*mt-file!0 0.MT
+.ds cov*mt-file!1 0.MT
+.ds cov*mt-file!2 0.MT
+.ds cov*mt-file!3 0.MT
+.ds cov*mt-file!4 4.MT
+.ds cov*mt-file!5 5.MT
+.ds cov*mt-file!6 0.MT
+.\"------------
+.de MT
+.ie \\n[.$] \{\
+. ie d cov*mt-file!\\$1 .ds cov*mt-type \\$1
+. el .ds cov*mt-type 6
+.\}
+.el .ds cov*mt-type 1
+.ds cov*mt-addresse "\\$2
+.ds cov*mt-type-text "\\$1
+.ie d @language .ds cov*str mm/\\*[@language]_
+.el .ds cov*str mm/
+.mso \\*[cov*str]\\*[cov*mt-file!\\*[cov*mt-type]]
+..
+.de COVER
+.ie !\\n[.$] .ds cov*cov-type ms
+.el .ds cov*cov-type \\$1
+.pg@disable-top-trap
+.ie d @language .ds cov*str mm/\\*[@language]_\\*[cov*cov-type].cov
+.el .ds cov*str mm/\\*[cov*cov-type].cov
+.mso \\*[cov*str]
+..
+.\"########################### module qrf ############################
+.\" forward and backward reference thru special files.
+.\"
+.\" check if stderr-method is wanted
+.\" This was needed when I discovered that groff was considered unsafe
+.\" and groff -U didn't work. It's a workaround like the original
+.\" index method, but not in my view elegant enough.
+.\"
+.\" init reference system
+.de INITR
+.ds qrf*file \\$1.qrf
+.nr qrf*pass 2
+.if \\n[D]>1 .tm INITR: source \\*[qrf*file]
+.ie \\n[Ref] \{\
+. tm .\\\\" Rfilename: \\*[qrf*file]
+.\}
+.el 'so \\*[qrf*file]
+..
+.\"---------------
+.\" set a reference.
+.de SETR
+.if \\n[.$]<1 .@error "SETR:reference name missing"
+.if !r qrf*pass .tm "SETR: No .INITR in this file"
+.if \\n[Ref] \{\
+. ds qrf*name qrf*ref-\\$1
+. if \\n[D]>2 .tm SETR: ref \\*[qrf*name]=\\*[hd*mark],\\n[%]
+. \" heading-number
+. ds \\*[qrf*name]-hn \\*[hd*mark]
+. \" page-number
+. ds \\*[qrf*name]-pn \\n[%]
+. \"
+. if \\n[Ref] \{\
+. tm .ds \\*[qrf*name]-hn \\*[hd*mark]
+. tm .ds \\*[qrf*name]-pn \\n[%]
+. if !'\\$2'' .tm .ds \\*[qrf*name]-xx \\$2
+. \}
+.\}
+..
+.\"---------------
+.\" get misc-string
+.\" If two arg -> set var. arg to misc-string.
+.de GETST
+.if \\n[.$]<1 .@error "GETST:reference name missing"
+.if !r qrf*pass .tm "GETST: No .INITR in this file"
+.ds qrf*name qrf*ref-\\$1
+. if d \\*[qrf*name]-xx \{\
+. ie \\n[.$]>1 .ds \\$2 \\*[\\*[qrf*name]-xx]
+. el \\*[\\*[qrf*name]-xx]\c
+. \}
+.\}
+..
+.\"---------------
+.\" get header-number
+.\" If two arg -> set var. arg to header-number.
+.de GETHN
+.if \\n[.$]<1 .@error "GETHN:reference name missing"
+.if !r qrf*pass .tm "GETHN: No .INITR in this file"
+.ds qrf*name qrf*ref-\\$1
+.if d \\*[qrf*name]-hn \{\
+. ie \\n[.$]>1 .ds \\$2 \\*[\\*[qrf*name]-hn]
+. el \\*[\\*[qrf*name]-hn]\c
+.\}
+..
+.\"---------------
+.\" get page-number
+.\" If two arg -> set var. arg to page-number.
+.de GETPN
+.if \\n[.$]<1 .@error "GETPN:reference name missing"
+.if !r qrf*pass .tm "GETPN: No .INITR in this file"
+.ds qrf*name qrf*ref-\\$1
+.if d \\*[qrf*name]-pn \{\
+. ie \\n[.$]>1 .ds \\$2 \\*[\\*[qrf*name]-pn]
+. el \\*[\\*[qrf*name]-pn]\c
+.\}
+..
+.\"----------
+.de GETR
+.if \\n[.$]<1 .@error "GETR:reference name missing"
+.ie !r qrf*pass \{\
+. tm "GETR: No .INITR in this file"
+.\}
+.el \{\
+. GETHN \\$1 Qrfh
+. GETPN \\$1 Qrfp
+\\*[Qrf]
+.\}
+..
+.\"########################### module ind ############################
+.\" Support for mgs-style indexing, borrowed from mgs.
+.de IX
+.tm \\$1\t\\$2\t\\$3\t\\$4 ... \\n[%]
+..
+.\"--------------------
+.\" Another type of index system
+.\" INITI type filename [macro]
+.de INITI
+.if \\n[.$]<1 .@error "INITI:type missing"
+.\" ignore if INITI has already been used
+.if \\n[.$]>1 \{\
+. if d ind*file .@error "INITI:file already set"
+. ds ind*file \\$2.ind
+. if \\n[D]>1 .tm INITI: source \\*[ind*file]
+.\}
+.if !d ind*file .@error "INITI:file not specified"
+.ds ind*type \\$1
+.if \\n[Ref] \{\
+. if \\n[.$]>2 .tm .\\\\" Imacro: \\$3
+.\}
+..
+.\"---------------
+.de IND
+.if !d ind*file .@error "IND: No active INITI"
+.if \\n[D]>1 .tm IND: type=\\*[ind*type]
+.ds ind*ref
+.if '\\*[ind*type]'N' .ds ind*ref \\n[%]
+.if '\\*[ind*type]'H' .ds ind*ref \\*[hd*mark]
+.if '\\*[ind*type]'B' .ds ind*ref \\*[hd*mark]\t\\n[%]
+.if '\\*[ind*ref]'' .@error "IND:wrong index type: \\*[ind*ref]"
+.\"
+.ds ind*line \\$1
+.while \\n[.$]>0 \{\
+. shift
+. as ind*line \t\\$1
+.\}
+.as ind*line \\*[ind*ref]
+.if \\n[Ref] .tm .\\\\" IND \\*[ind*line]
+..
+.\" print index
+.de INDP
+.ie \\n[Ref] .tm .\\\\" Index: \\*[ind*file]
+.el \{\
+. if !\\n[Cp] .pg@next-page
+. \" print INDEX
+. \" execute user-defined macros
+. if d TXIND .TXIND
+. ie d TYIND .TYIND
+. el \{\
+. SK
+. ce
+\\*[Index]
+. SP 3
+. 2C
+. nf
+. \}
+' so \\*[ind*file]
+. ie d TZIND .TZIND
+. el \{\
+. fi
+. 1C
+. \}
+.\}
+.rm ind*file
+..
+.\"########################### module let ############################
+.\" Letter macros
+.\"------------------------
+.\" Formal closing
+.de FC
+.df@print-float 3
+.ie \\n[.$] .ds let*i \\$1
+.el .ds let*i \\*[Letfc]
+.ie d let*type .let@fc_\\*[let*type] "\\*[let*i]" \\$@
+.el .let@mt-closing "\\*[let*i]" \\$@
+..
+.\"-------
+.de let@mt-closing
+.ne 5v
+.in (u;\\n[.l]/2)
+.sp
+\\$1
+.in
+..
+.\"------------------------
+.\" Signature line
+.de SG
+.ie d let*type .let*lt-sign \\$@
+.el .let*mt-sign \\$@
+..
+.\"------------------------
+.de let*lt-sign
+.if !d let@sg_\\*[let*type] .@error "SG: letter type \\*[let*type] undefined"
+.df@print-float 3
+.nr let*i 0 1
+.nr let*j 0
+.while \\n+[let*i]<=\\n[let*wa-n] \{\
+.if \\n[let*i]=\\n[let*wa-n] .nr let*j 1
+.let@sg_\\*[let*type] "\\*[let*wa-name!\\n[let*i]]" "\\*[let*wa-title!\\n[let*i]]" \\n[let*i] \\n[let*j] \\$@
+.\}
+..
+.\"------------------------
+.\" Memorandum signature
+.de let*mt-sign
+.df@print-float 3
+.ne \\n[cov*au]u*4v
+.ie \\n[.$]>1 .nr let*k 1
+.el .nr let*k \\n[cov*au]
+.ds let*tmp \\*[cov*au!\\n[let*k]!3]-\\*[cov*au!\\n[let*k]!4]-
+.nr let*i 0 1
+.while \\n+[let*i]<=\\n[cov*au] \{\
+. if \\n[let*i]>1 .as let*tmp /
+. as let*tmp \\*[cov*au!\\n[let*k]!2]
+.\}
+.if !''\\$1' .as let*tmp -\\$1
+.in (u;\\n[.l]/2)
+.nf
+.nr let*i 0 1
+.while \\n+[let*i]<=\\n[cov*au] \{\
+. SP 3v
+. if \\n[let*i]=\\n[let*k] \{\
+\Z'\h'-(u;\\n[.l]/2)'\\*[let*tmp]'\c
+. \}
+\\*[cov*au!\\n[let*i]!1]
+.\}
+.fi
+.in
+..
+.\"------------------------
+.\" Approval signature
+.de AV
+.ne 6v
+.nf
+.sp
+.ie \\n[.$]<2 \\*[Letapp]
+.el .sp
+.sp 2
+.ie n ______________________________ ______________
+.el \D'l 25m 0'\h'4m'\D'l 12m 0'
+\Z'\\$1'\h'29m'\f[\\*[@sdf_font]]\\*[Letdate]\fP
+.fi
+..
+.\"------------------------
+.\" Letter signature
+.de AVL
+.ne 6v
+.nf
+.sp 3
+.ie n ______________________________
+.el \D'l 25m 0'
+\Z'\\$1'
+.fi
+..
+.\"------------------------
+.\" Letter type
+.\" let@header is called from the header. It is supposed
+.\" to remove the alias itself.
+.de LT
+.rm AF AS AE AT AU CS OK TL MT
+.ds let*type BL
+.nr Pi 5
+.nr Pt 0
+.if !''\\$1' .ds let*type \\$1
+.if !d let@head_\\*[let*type] .@error "LT: unknown letter type \\$1"
+.shift
+.als let@header let@head_\\*[let*type]
+.let@init_\\*[let*type] \\$@
+.if \n[D]>1 .tm Letter type \\*[let*type]
+..
+.\"-----------
+.\" Blocked letter
+.de let@init_BL
+..
+.de let@head_BL
+.rm let@header
+.let@print-head 1
+..
+.de let@sg_BL
+.ne 5v
+.nf
+.in (u;\\n[.l]/2)
+.sp 3v
+\\$1
+\\$2
+.in
+.if \\$4 .sp
+.if \w'\\$5'&\\$4 \\$5
+.fi
+..
+.als let@fc_BL let@mt-closing
+.\"-----------
+.\" Semiblocked letter
+.de let@init_SB
+.nr Pt 1
+..
+.de let@head_SB
+.rm let@header
+.let@print-head 1
+..
+.als let@sg_SB let@sg_BL
+.als let@fc_SB let@mt-closing
+.\"-----------
+.\" Full-blocked letter
+.de let@init_FB
+..
+.de let@head_FB
+.rm let@header
+.let@print-head
+..
+.de let@sg_FB
+.ne 5v
+.nf
+.sp 3v
+\\$1
+\\$2
+.if \\$4 .sp
+.if \w'\\$5'&\\$4 \\$5
+.fi
+..
+.de let@fc_FB
+.ne 5v
+.sp
+\\$1
+..
+.\"-----------
+.\" Simplified letter
+.de let@init_SP
+..
+.de let@head_SP
+.rm let@header
+.let@print-head
+..
+.de let@sg_SP
+.nf
+.if \\$3=1 .sp
+.sp
+.misc@toupper "\\$1, \\$2"
+.if \\$4 .sp
+.if \w'\\$5'&\\$4 \\$5
+.fi
+..
+.de let@fc_SP
+.sp 2
+..
+.\"--------------------------------------
+.\" Print the letter-head
+.de let@print-head
+.nf
+.sp |11
+.if '1'\\$1' .in (u;\\n[.l]/2)
+.\" ---- WA
+.ie d let@wa-div .let@wa-div
+.el .sp 3
+.\" ---- datum
+\\*[cov*new-date]
+.sp
+.if '1'\\$1' .if !d let*lo-CN .if !d let*lo-RN .sp 2
+.\" ---- Confidential
+.if d let*lo-CN \{\
+. ti 0
+. ie !''\\*[let*lo-CN]' \\*[let*lo-CN]
+. el \\*[LetCN]
+. sp
+.\}
+.\" ---- Reference
+.if d let*lo-RN \{\
+\\*[LetRN] \\*[let*lo-RN]
+. sp
+.\}
+.\" ---- IA
+.sp
+.in 0
+.nr let*i 0 1
+.while \\n+[let*i]<=\\n[let*ia-n] \{\
+\\*[let*ia-name!\\n[let*i]]
+\\*[let*ia-title!\\n[let*i]]
+.\}
+.if d let@ia-div .let@ia-div
+.\" ---- Attention
+.if d let*lo-AT \{\
+. sp
+\\*[LetAT] \\*[let*lo-AT]
+.\}
+.\" ---- Salutation
+.if !'\\*[let*type]'SP' .if d let*lo-SA \{\
+. sp
+. ti 0
+. ie !''\\*[let*lo-SA]' \\*[let*lo-SA]
+. el \\*[LetSA]
+.\}
+.\" ---- Subject
+.if d let*lo-SJ \{\
+. ie '\\*[let*type]'SP' \{\
+. sp 2
+. misc@toupper \\*[let*lo-SJ]
+. sp
+. \}
+. el \{\
+. sp
+. if '\\*[let*type]'SB' .ti +5m
+\\*[LetSJ] \f[\\*[@sdf_font]]\\*[let*lo-SJ]\fP
+. \}
+.\}
+..
+.\"-------------------
+.\" .IA [name [title]]
+.nr let*ia-n 0 1
+.de IA
+.if \\n[.$] .ds let*ia-name!\\n+[let*ia-n] \\$1
+.if \\n[.$]>1 .ds let*ia-title!\\n[let*ia-n] \\$2
+.ev let@ev
+'nf
+.di let@ia-div
+.eo
+..
+.de IE
+.di
+.ec
+.ev
+..
+.\"-------------------
+.\" .WA [name [title]]
+.nr let*wa-n 0 1
+.de WA
+.if \\n[.$] .ds let*wa-name!\\n+[let*wa-n] \\$1
+.if \\n[.$]>1 .ds let*wa-title!\\n[let*wa-n] \\$2
+.ev let@ev
+'nf
+.di let@wa-div
+.it \\n[Letwam] let@wa-drain
+.eo
+..
+.\"------
+.de let@wa-drain
+.it
+.di
+.di let@wa-junk
+..
+.\"------
+.de WE
+.it
+.ec
+.di
+.ev
+.if d let@wa-junk .rm let@wa-junk
+..
+.\"-------------------
+.\" Copy to
+.de NS
+.sp
+.ie !''\\$2' .ds let*str \\$1
+.el \{\
+. ie \\n[.$]>0 \{\
+. ie !\w'\\$1' .ds let*str \\*[Letns!\\*[Letnsdef]]
+. el \{\
+. ie d Letns!\\$1 .ds let*str \\*[Letns!\\$1]
+. el .ds let*str \\*[Letns!copy](\\$1)\\*[Letns!to]
+. \}
+. \}
+. el .ds let*str \\*[Letns!\\*[Letnsdef]]
+.\}
+.ne 2
+.nf
+\\*[let*str]
+..
+.de NE
+.fi
+..
+.\"-------------------
+.\" Letter options
+.de LO
+.rm AF AS AE AT AU CS OK TL MT
+.if ''\\$1' .@error "LO: missing option"
+.if !d Let\\$1 .@error "LO: unknown option (\\$1)"
+.ds let*lo-\\$1 \\$2
+.if \n[D]>1 .tm Letter option \\$1 \\$2
+..
+.\"--------------------
+.\" Start with a clean slate
+.init@reset
diff --git a/contrib/mm/tmac.mse b/contrib/mm/tmac.mse
new file mode 100755
index 00000000..3e15ff7c
--- /dev/null
+++ b/contrib/mm/tmac.mse
@@ -0,0 +1,184 @@
+.\" $Id: tmac.mse,v 1.1 2000/02/06 09:34:59 wlemb Exp $
+.\"
+.\" swedish version of mm
+.\" See tmac.m for version-information.
+.ds @language se
+.mso tmac.m
+.ISODATE
+.\"
+.ds App Bilaga
+.ds Lf Figurer
+.ds Lt Tabeller
+.ds Lx Uppställningar
+.ds Le Ekvationer
+.\" Page length
+.if !r L .nr @pl 28.5c
+.\" page width
+.if !r W .nr @ll 13c
+.\" page offset
+.if !r O .nr @po 3.5c
+.\" set the above parameters
+.ll \n[@ll]u
+.po \n[@po]u
+.pl \n[@pl]u
+.ds Lifg Figur
+.ds Litb Tabell
+.ds Liex Uppställning
+.ds Liec Ekvation
+.ds Licon Innehållsförteckning
+.ds Qrf Se kapitel \\*[Qrfh], sidan \\*[Qrfp].
+.ds Rp Referenser
+.ds Letfc Vänliga hälsningar
+.ds Letapp Godkänd av:
+.ds Letdate datum
+.ds Letconf KONFIDENTIELLT
+.ds Letsal Till vederbörande:
+.ds Letatt ATTENTION:
+.ds Letsubj Innehåll:
+.ds Letref Refererande till:
+.\"
+.ds Letns!copy Kopia \" space!
+.ds Letns!to " till
+.ds Letns!0 Kopia till
+.ds Letns!1 Kopia (med att.) till
+.ds Letns!2 Kopia (utan att.) till
+.ds Letns!3 Att.
+.ds Letns!4 Atts.
+.ds Letns!5 Enc.
+.ds Letns!6 Encs.
+.ds Letns!7 Annat försättsblad
+.ds Letns!8 Brev till
+.ds Letns!9 Dokument till
+.ds Letns!10 Kopia (med atts.) till
+.ds Letns!11 Kopia (utan atts.) till
+.ds Letns!12 Endast abstract till
+.ds Letns!13 Hela dokumentet till
+.ds Letns!14 CC:
+.\"
+.ds MO1 januari
+.ds MO2 februari
+.ds MO3 mars
+.ds MO4 april
+.ds MO5 maj
+.ds MO6 juni
+.ds MO7 juli
+.ds MO8 augusti
+.ds MO9 september
+.ds MO10 oktober
+.ds MO11 november
+.ds MO12 december
+.nr pg*footer-size 4\" 1v+footer+even/odd footer+1v
+.\"------------------------------------------------
+.\" Dokumentnamn
+.ds LetDNAMN
+.\" Mottagarens datum
+.ds LetMDAT Ert datum:
+.\" Bilaga
+.ds LetBIL Bilaga \"
+.\" Kompletteringsuppgift
+.ds LetKOMP
+.\" Dokumentbeteckning eller dokumentnummer
+.ds LetDBET
+.\" Beteckning (ärendebeteckning i form av diarienummer e.d.
+.ds LetBET Beteckning:
+.\" Mottagarens beteckning.
+.ds LetMBET Er beteckning:
+.\" Antal sidor
+.ds LetSIDOR
+.\" Svensk standard med högerställd löptext. ---------------------
+.de let@init_SVH
+.in 4.57c
+.ll 17.57c
+..
+.de let@head_SVH
+.rm let@header
+.let@print_SV H
+..
+.de let@sg_SVH
+..
+.de let@fc_SVH
+..
+.\" Svensk standard med vänsterställd löptext. ---------------------
+.de let@init_SVV
+..
+.de let@head_SVV
+.rm let@header
+.let@print_SV V
+..
+.de let@sg_SVV
+..
+.de let@fc_SVV
+..
+.\"--------------------------------
+.de let@print_SV
+.nf
+.\" pos T0 -----------------------------------
+.in 0
+.sp |3
+.if d let@wa-div .let@wa-div
+.\"----- addressat
+.if '\\$1'V' .if d let@ia-div \{\
+. sp |10
+. let@ia-div
+.\}
+.\" pos T4 -----------------------------------
+.in 9.14c
+.\"----- kompletteringsuppgift
+.if d let*lo-KOMP \{\
+. sp |2
+\\*[let*lo-KOMP]
+.\}
+.\"----- dokumentnamn
+.if d let*lo-DNAMN \{\
+. sp |3
+\\*[let*lo-DNAMN]
+.\}
+.\"----- datum
+.if d cov*new-date \{\
+. sp |5
+Datum:
+\\*[cov*new-date]
+.\}
+.\"----- mottagarens datum
+.if d let*lo-MDAT \{\
+. sp |7
+\\*[LetMDAT]
+\\*[let*lo-MDAT]
+.\}
+.\"----- addressat
+.if '\\$1'H' .if d let@ia-div \{\
+. sp |10
+. let@ia-div
+.\}
+.\" pos T6 -----------------------------------
+.in 13.72c
+.\"----- mottagarens beteck.
+.if d let*lo-MBET \{\
+. sp |7
+\\*[LetMBET]
+\\*[let*lo-MBET]
+.\}
+.\"----- dokumentbeteck.
+.if d let*lo-BET \{\
+. sp |3
+\\*[LetBET]
+\\*[let*lo-BET]
+.\}
+.\" pos T7 -----------------------------------
+.in 16c
+.\"----- bilaga
+.if d let*lo-BIL \{\
+. sp |2
+\\*[LetBIL]\\*[let*lo-BIL]
+.\}
+.\"
+.\"----- sidnummer
+.sp |3
+.ie d let*lo-SIDOR \\n[%] (\\*[let*lo-SIDOR])
+.el \\n[%]
+.\"
+.\" Ta hand om special
+.if d TP .TP
+.sp |17
+..
+.\" -----------------------------------
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100755
index 00000000..b82ff180
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,83 @@
+# Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+# Written by James Clark (jjc@jclark.com)
+#
+# This file is part of groff.
+#
+# groff 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.
+#
+# groff 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 groff; see the file COPYING. If not, write to the Free Software
+# Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+FFLAG=-F../font
+TROFF=../src/roff/troff/troff -M../tmac $(FFLAG)
+GROFF=../src/rof/groff/groff -p -e -t
+GROPS=../src/devices/grops/grops $(FFLAG)
+DOCS=meref.ps meintro.ps pic.ps pic.html homepage.html
+MEMACROS=../tmac/tmac.e
+SOELIM=../src/preproc/soelim/soelim
+
+version=`cat ../VERSION`
+# No additional number for the groff archive if revision is zero
+revision=`sed -e 's/^0$$//' -e 's/^[1-9].*$$/.&/' ../REVISION`
+
+all: $(DOCS)
+
+.SUFFIXES: .tr .me .ms .ps .dit
+
+.dit.ps:
+ $(GROPS) $< >$@
+
+.me.dit:
+ $(SOELIM) $< \
+ | sed -e "s;@VERSION@;$(version)$(revision);" \
+ | $(TROFF) -Tps $(FFLAG) -me >$@
+
+.tr.dit:
+ $(TROFF) -Tps $< >$@
+
+%.html: %.ms
+ export GROFF_TMAC_PATH=../tmac ; \
+ sed -e "s;@VERSION@;$(version)$(revision);" $< \
+ | $(GROFF) -Thtml $(FFLAG) -U -ms >$@
+
+%.ascii: %.ms
+ export GROFF_TMAC_PATH=../tmac ; \
+ sed -e "s;@VERSION@;$(version)$(revision);" $< \
+ | $(GROFF) -Tascii $(FFLAG) -U -ms -markup >$@
+
+%.ps: %.ms
+ export GROFF_TMAC_PATH=../tmac ; \
+ sed -e "s;@VERSION@;$(version)$(revision);" $< \
+ | $(GROFF) -Tps $(FFLAG) -U -ms -markup >$@
+
+meref.ps: meref.dit
+meintro.ps: meintro.dit
+
+# This production must use -p -e -t so pic/eqn processing is done
+pic.ps: pic.ms
+ export GROFF_TMAC_PATH=../tmac ; \
+ sed -e "s;@VERSION@;$(version)$(revision);" $< \
+ | $(GROFF) -Tps $(FFLAG) -ms >$@
+
+install:
+
+clean:
+ -rm -f *.ps *.html *.ascii *.png *.gif *.dit core
+ -rm -f *.aux *.cp *.cps *.cv *.cn *.dvi *.fn *.fns *.ky *.kys \
+ *.log *.op *.pg *.pgs *.ps *.toc *.tp *.tps *.tr *.vr *.vrs
+
+distclean: clean
+
+realclean: distclean
+
+extraclean: clean
+ -rm -f core *~ \#* junk temp grot
diff --git a/doc/groff.texinfo b/doc/groff.texinfo
new file mode 100644
index 00000000..344e6443
--- /dev/null
+++ b/doc/groff.texinfo
@@ -0,0 +1,5794 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header (This is for running Texinfo on a region.)
+@setfilename groff
+@settitle The GNU Troff Manual
+@setchapternewpage odd
+@footnotestyle separate
+@c %**end of header (This is for running Texinfo on a region.)
+
+
+@dircategory Miscellaneous
+@direntry
+* Groff: (groff). The GNU troff document formatting system.
+@end direntry
+
+
+@smallbook
+
+
+@iftex
+@finalout
+@end iftex
+
+
+@ifinfo
+This Info file documents GNU troff version 1.16.
+
+Published by the Free Software Foundation
+59 Temple Place, Suite 330
+Boston, MA 02111-1307 USA
+
+Copyright (C) 1994-2000 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission notice
+identical to this one except for the removal of this paragraph (this
+paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation
+approved by the Foundation.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+section entitled ``GNU General Public License'' is included exactly as
+in the original, and provided that the entire resulting derived work is
+distributed under the terms of a permission notice identical to this
+one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that the section entitled ``GNU General Public License'' may be
+included in a translation approved by the Free Software Foundation
+instead of in the original English.
+@end ifinfo
+
+
+@titlepage
+@title groff
+@subtitle The GNU implementation of @code{groff}
+@subtitle Edition 1.16
+@subtitle Spring 2000
+@author by Trent A.@w{ }Fisher
+@author and the maintainer of groff
+
+@c Include the Distribution inside the titlepage environment so
+@c that headings are turned off. Headings on and off do not work.
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1994-2000 Free Software Foundation, Inc.
+
+@sp 2
+Version 1.16 of @code{groff}, @*
+Spring 2000
+@sp 2
+Published by the Free Software Foundation @*
+59 Temple Place, Suite 330 @*
+Boston, MA 02111-1307 USA
+
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+section entitled ``GNU General Public License'' is included
+exactly as in the original, and provided that the entire resulting
+derived work is distributed under the terms of a permission notice
+identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that the section entitled ``GNU General Public License'' may be
+included in a translation approved by the Free Software Foundation
+instead of in the original English.
+
+Cover art by Etienne Suvasa.
+@end titlepage
+@page
+
+
+
+@node Top, Copying, (dir), (dir)
+
+@ifinfo
+This Info file documents groff version 1.16, the GNU implementation of
+the troff typesetting system.
+
+This is an in-progress document; contributions, comments, or
+contributions are welcome. Send them to bug-groff@@gnu.org.
+@end ifinfo
+
+@menu
+* Copying::
+* Introduction::
+* Invoking groff::
+* Tutorial for Macro Users::
+* -man::
+* -ms::
+* -me::
+* -mm::
+* Programming Tutorial::
+* geqn::
+* gtbl::
+* gpic::
+* grap::
+* grefer::
+* gsoelim::
+* Devices::
+* File formats::
+* Installation::
+* Request Index::
+* Register Index::
+* String Index::
+* Macro Index::
+* Program Index::
+* Concept Index::
+@end menu
+
+
+
+@node Copying, Introduction, Top, Top
+@cindex copying
+@unnumbered GNU GENERAL PUBLIC LICENSE
+@center Version 2, June 1991
+
+@display
+Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111, USA
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+@end display
+
+@unnumberedsec Preamble
+
+The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public License is
+intended to guarantee your freedom to share and change free software --
+to make sure the software is free for all its users. This General
+Public License applies to most of the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+(Some other Free Software Foundation software is covered by the GNU
+Library General Public License instead.) You can apply it to your
+programs, 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 software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis
+or for a fee, you must give the recipients all the rights that you have.
+You must make sure that they, too, receive or can get the source code.
+And you must show them these terms so they know their rights.
+
+We protect your rights with two steps: (1)@w{ }copyright the software,
+and (2)@w{ }offer you this license which gives you legal permission to
+copy, distribute and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, 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 redistributors of a free program will
+individually obtain patent licenses, in effect making the program
+proprietary. To prevent this, we have made it clear that any patent
+must be licensed for everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and
+modification follow.
+
+@iftex
+@unnumberedsec TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+@end iftex
+@ifinfo
+@center TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+@end ifinfo
+
+@enumerate 0
+@item
+This License applies to any program or other work which contains a
+notice placed by the copyright holder saying it may be distributed under
+the terms of this General Public License. The ``Program'', below,
+refers to any such program or work, and a ``work based on the Program''
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it, either
+verbatim or with modifications and/or translated into another language.
+(Hereinafter, translation is included without limitation in the term
+``modification''.) Each licensee is addressed as ``you''.
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of running
+the Program is not restricted, and the output from the Program is
+covered only if its contents constitute a work based on the Program
+(independent of having been made by running the Program). Whether that
+is true depends on what the Program does.
+
+@item
+You may copy and distribute verbatim copies of the Program's 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 give any other
+recipients of the Program a copy of this License along with the Program.
+
+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.
+
+@item
+You may modify your copy or copies of the Program or any portion of it,
+thus forming a work based on the Program, and copy and distribute such
+modifications or work under the terms of Section@w{ }1 above, provided
+that you also meet all of these conditions:
+
+@enumerate a
+@item
+You must cause the modified files to carry prominent notices stating
+that you changed the files and the date of any change.
+
+@item
+You must cause any work that you distribute or publish, that in whole or
+in part contains or is derived from the Program or any part thereof, to
+be licensed as a whole at no charge to all third parties under the terms
+of this License.
+
+@item
+If the modified program normally reads commands interactively when run,
+you must cause it, when started running for such interactive use in the
+most ordinary way, to print or display an announcement including an
+appropriate copyright notice and a notice that there is no warranty (or
+else, saying that you provide a warranty) and that users may
+redistribute the program under these conditions, and telling the user
+how to view a copy of this License. (Exception: if the Program itself
+is interactive but does not normally print such an announcement, your
+work based on the Program is not required to print an announcement.)
+@end enumerate
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program, 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 Program, 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 Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of a
+storage or distribution medium does not bring the other work under the
+scope of this License.
+
+@item
+You may copy and distribute the Program (or a work based on it, under
+Section@w{ }2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+@enumerate a
+@item
+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; or,
+
+@item
+Accompany it with a written offer, valid for at least three years, to
+give any third party, for a charge no more than your cost of physically
+performing source distribution, a complete machine-readable copy of the
+corresponding source code, to be distributed under the terms of Sections
+1 and 2 above on a medium customarily used for software interchange; or,
+
+@item
+Accompany it with the information you received as to the offer to
+distribute corresponding source code. (This alternative is allowed only
+for noncommercial distribution and only if you received the program in
+object code or executable form with such an offer, in accord with
+Subsection b above.)
+@end enumerate
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, 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 executable. 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.
+
+If distribution of executable or 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 counts as distribution of the source
+code, even though third parties are not compelled to copy the source
+along with the object code.
+
+@item
+You may not copy, modify, sublicense, or distribute the Program except
+as expressly provided under this License. Any attempt otherwise to
+copy, modify, sublicense or distribute the Program 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.
+
+@item
+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 Program or its derivative works. These actions are prohibited by
+law if you do not accept this License. Therefore, by modifying or
+distributing the Program (or any work based on the Program), you
+indicate your acceptance of this License to do so, and all its terms and
+conditions for copying, distributing or modifying the Program or works
+based on it.
+
+@item
+Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program 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.
+
+@item
+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 Program at all. For example, if a patent license
+would not permit royalty-free redistribution of the Program 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 Program.
+
+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.
+
+@item
+If the distribution and/or use of the Program is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Program 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.
+
+@item
+The Free Software Foundation may publish revised and/or new versions of
+the 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 Program
+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 Program does not specify a version
+number of this License, you may choose any version ever published by the
+Free Software Foundation.
+
+@item
+If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, 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.
+
+@iftex
+@heading NO WARRANTY
+@end iftex
+@ifinfo
+@center NO WARRANTY
+@end ifinfo
+
+@item
+BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW@. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM ``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 PROGRAM IS WITH
+YOU@. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+@item
+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 PROGRAM 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 PROGRAM
+(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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR
+OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+@end enumerate
+
+@iftex
+@heading END OF TERMS AND CONDITIONS
+@end iftex
+@ifinfo
+@center END OF TERMS AND CONDITIONS
+@end ifinfo
+
+
+@page
+@unnumberedsec How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+To do so, attach the following notices to the program. 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.
+
+@smallexample
+@var{one line to give the program's name and an idea of what it does.}
+Copyright (C) 19@var{yy} @var{name of author}
+
+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, USA.
+@end smallexample
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+@smallexample
+Gnomovision version 69, Copyright (C) 19@var{yy} @var{name of author}
+Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type
+`show w'. This is free software, and you are welcome to redistribute it
+under certain conditions; type `show c' for details.
+@end smallexample
+
+The hypothetical commands @samp{show w} and @samp{show c} should show
+the appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than @samp{show w} and
+@samp{show c}; they could even be mouse-clicks or menu items---whatever
+suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a ``copyright disclaimer'' for the program, if
+necessary. Here is a sample; alter the names:
+
+@smallexample
+@group
+Yoyodyne, Inc., hereby disclaims all copyright
+interest in the program `Gnomovision'
+(which makes passes at compilers) written
+by James Hacker.
+
+@var{signature of Ty Coon}, 1 April 1989
+Ty Coon, President of Vice
+@end group
+@end smallexample
+
+This General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications
+with the library. If this is what you want to do, use the GNU Library
+General Public License instead of this License.
+
+
+
+@node Introduction, Invoking groff, Copying, Top
+@chapter Introduction
+@cindex introduction
+
+GNU @code{troff} (or @code{groff}) is a system for typesetting
+documents. @code{troff} is very flexible and has been in existence (and
+use) for about 3@w{ }decades. It is quite widespread and firmly
+entrenched in the @sc{Unix} community.
+
+
+
+@menu
+* What Is groff?::
+* History::
+* groff Capabilities::
+* Macro Packages::
+* Preprocessors::
+* Postprocessors::
+* Credits::
+@end menu
+
+@node What Is groff?, History, Introduction, Introduction
+@section What Is @code{groff}?
+@cindex what is @code{groff}?
+@cindex @code{groff} -- what is it?
+
+
+@code{groff} is of an older generation of document preparation systems,
+which operate more like compilers than the more recent interactive
+WYSIWYG @footnote{What You See Is What You Get} systems. @code{groff}
+and its contemporary counterpart, @TeX{}, both work using a @dfn{batch}
+paradigm: The input (or @dfn{source}) files are normal text files with
+embedded formatting commands. These files can then be processed by
+@code{groff} to produce a typeset document on a variety of devices.
+
+Likewise, @code{groff} should not be confused with a @dfn{word
+processor}, since that term connotes an integrated system which includes
+an editor and a text formatter. Also, many word processors follow the
+WYSIWYG paradigm which was discussed earlier.
+
+Although WYSIWYG systems may be easier to use, they have a number of
+disadvantages compared to @code{troff}:
+
+@itemize @bullet{}
+@item
+They must be used on a bitmapped display to do any operations on your
+document.
+@item
+Most of the WYSIWYG systems are either non-free or are not very
+portable.
+@item
+@code{troff} is firmly entrenched in all @sc{Unix} systems.
+@item
+It is difficult to have a wide range of capabilities available within
+the confines of a GUI/window system.
+@item
+It is more difficult to make global changes to a document.
+@end itemize
+
+@quotation
+``GUIs normally make it simple to accomplish simple actions and
+impossible to accomplish complex actions.'' --Doug Gwyn (22/Jun/91 in
+@code{comp.unix.wizards})
+@end quotation
+
+
+
+@node History, groff Capabilities, What Is groff?, Introduction
+@section History
+@cindex history
+
+@code{troff} can trace its origins back to a formatting program called
+@code{runoff} which ran on MIT's CTSS system. This name came from the
+common phrase of the time ``I'll run off a document.''
+
+The first version of @sc{Unix} was developed on a PDP-7 which was
+sitting around Bell Labs. In 1971 the developers wanted to get a PDP-11
+for further work on the operating system. In order to justify the cost
+for this system, they proposed that they would implement a document
+formatting system for the AT&T patents division. This first formatting
+program was a reimplementation of @code{runoff}. In accordance with
+@sc{Unix}'s penchant for abreviations, it was named @code{roff} (an
+abreviation of @code{runoff}).
+
+When they needed a more flexible language, a new version of @code{roff}
+called @code{nroff} (Newer @code{roff}) was written. It had a much more
+complicated syntax, but provided the basis for all future versions.
+When they got a Graphic Systems CAT Phototypesetter, J.@w{ }F.@w{
+}Ossanna wrote a version of @code{nroff} which would drive it. It was
+dubbed @code{troff} for typesetter @code{roff}, although many people
+have speculated that it actually means Times @code{roff} because of
+@code{troff}'s use of the Times font family by default. As such, the
+name @code{troff} is pronounced t-roff rather than trough.
+
+With @code{troff} came @code{nroff} (they were actually the same program
+except for some @samp{#ifdefs}), which was for producing output for line
+printers and ascii terminals. It understood everything @code{troff}
+did, and ignored the commands which were not aplicable (i.e.@: font
+changes).
+
+Since there are several things which cannot be done easily in
+@code{troff}, work on several preprocessors began. These programs would
+transform certain parts of a document into @code{troff}, which made a
+very natural use of pipes in @sc{Unix}.
+
+The @code{eqn} preprocessor allowed mathematical formul@ae{} to be
+specified in a much simpler and more intuitive manner. @code{tbl} is a
+preprocessor for formatting tables. The @code{refer} preprocessor (and
+the similar program, @code{bib}) processes citations in a document
+according to a bibliographic database.
+
+Unfortunately, Ossanna's @code{troff} was written in PDP-11 assembly
+language and produced output specifically for the CAT phototypesetter.
+He rewrote it in C, although it was now 7000@w{ }lines of uncommented
+code and still dependent on the CAT. As the CAT became less common, and
+was no longer supported by the manufacturer, the need to make it support
+other devices became a priority. However, before this could be done, he
+was killed in an auto accident.
+
+@pindex ditroff
+So, Brian Kernighan took on the task of rewriting @code{troff}. The
+newly rewritten version produced a device independent code which was
+very easy for postprocessors to read and translate to the appropriate
+printer codes. Also, this new version of @code{troff} (called
+@code{ditroff}) had several extentions, which included drawing
+functions.
+
+Due to the additional abilities of the new version of @code{troff},
+several new preprocessors appeared. The @code{pic} preprocessor
+provides a wide range of drawing functions. Likewise the @code{ideal}
+preprocessor did the same, although via a much different paradigm. The
+@code{grap} preprocessor took specifications for graphs, but, unlike
+other preprocessors, produced @code{pic} code.
+
+James Clark began work on a GNU implementation of @code{ditroff} in
+early@w{ }1989. The first version, @code{groff}@w{ }0.3.1, was released
+June@w{ }1990. @code{groff} included
+
+@itemize @bullet{}
+@item
+A replacement for @code{ditroff} with many extentions.
+@item
+The @code{soelim}, @code{pic}, @code{tbl}, and @code{eqn} preprocessors.
+@item
+Postprocessors for ascii devices, PostScript, @TeX{} DVI, and X@w{
+}windows. GNU @code{troff} also eliminated the need for a separate
+@code{nroff} program with a postprocessor which would produce ascii
+output.
+@item
+A version of the @code{-me} macros and an implementation of the
+@code{-man} macros.
+@end itemize
+
+Also, a front-end was included which could construct the, sometimes
+painfully long, pipelines required for all the post- and preprocessors.
+
+Development of GNU @code{troff} progressed rapidly, and saw the
+additions of a replacement for @code{refer}, an implementation of the
+@code{-ms} and @code{-mm} macros, and a program to deduce how to format
+a document (@code{grog}).
+
+It was declared a stable (i.e.@: non beta) package with the release of
+version@w{ }1.04 around November@w{ }1991.
+
+
+
+@node groff Capabilities, Macro Packages, History, Introduction
+@section @code{groff} Capabilities
+@cindex @code{groff} capabilities
+@cindex capabilities of @code{groff}
+
+So what exactly is @code{groff} capable of doing? @code{groff} provides
+a wide range of low-level text formatting operations. Using these, you
+can perform a wide range of formatting tasks, such as footnotes, table
+of contents, multiple columns, etc.
+
+@itemize @bullet{}
+@item
+Text filling, adjusting, and centering
+@item
+Hyphenation
+@item
+Page control
+@item
+Font and character size control
+@item
+Vertical spacing (i.e.@: double spacing)
+@item
+Line length and indenting
+@item
+Macros, strings, diversions, and traps
+@item
+Number registers
+@item
+Tabs, leaders, and fields
+@item
+Input and output conventions and character translation
+@item
+Overstrike, bracket, line drawing, and zero-width functions
+@item
+Local horizontal and vertical motions and the width function
+@item
+Three-part titles
+@item
+Output line numbering
+@item
+Conditional acceptance of input
+@item
+Environment switching
+@item
+Insertions from the standard input
+@item
+Input/output file switching
+@item
+Output and error messages
+@end itemize
+
+
+@node Macro Packages, Preprocessors, groff Capabilities, Introduction
+@section Macro Packages
+@cindex macro packages
+
+Since @code{groff} provides such low level facilities, it can be quite
+difficult to use by itself. However, @code{groff} provides a
+@dfn{macro} facility which allows you to specify how certain routine
+operations (e.g.@w{ }starting paragraphs, printing headers and footers,
+etc.)@: should be done. These macros can be collected together into a
+@dfn{macro package}. There are a number of macro packages available;
+the most common (and the ones described in this manual) are @code{-man},
+@code{-me}, @code{-ms}, and @code{-mm}.
+
+
+@node Preprocessors, Postprocessors, Macro Packages, Introduction
+@section Preprocessors
+@cindex preprocessors
+
+Although @code{groff} provides most functions needed to format a
+document, some operations would be unwieldy (i.e.@: drawing pictures).
+Therefore, programs called preprocessors were written which understand
+their own language and produce the necessary groff operations. These
+preprocessors are able to differentiate their own input from the rest of
+the document via markers.
+
+To use a preprocessor, @sc{Unix} pipes are used to feed the output from
+the preprocessor into @code{groff}. Any number of preprocessors may be
+used on a given document; in this case, the preprocessors are linked
+together into one pipeline. However, in @code{groff}, the user does not
+need to construct the pipe, but only tell @code{groff} what
+preprocessors to use.
+
+@code{groff} currently has preprocessors for producing tables
+(@code{tbl}), typesetting equations (@code{eqn}), drawing pictures
+(@code{pic}), and for processing bibliographies (@code{refer}). An
+associated program which is useful when dealing with preprocessors is
+@code{soelim}.
+
+There are other preprocessors in existence, but there are,
+unfortunately, no free implementations available. They are for drawing
+pictures (@code{ideal} and @code{gremlin}), for drawing graphs
+(@code{grap}), and chemical structures (@code{chem}).
+
+
+@node Postprocessors, Credits, Preprocessors, Introduction
+@section Postprocessors
+@cindex postprocessors
+
+@code{groff} actually produces device independent code which may be fed
+into a postprocessor which will produce output for a particular device.
+Currently, @code{groff} has postprocessors for PostScript, ascii
+terminals, X@w{ }windows (for previewing), @TeX{} DVI format, and HTML.
+
+
+@node Credits, , Postprocessors, Introduction
+@section Credits
+@cindex credits
+
+
+Large portions of this manual were taken from existing documents, most
+notably, the manual pages for the @code{groff} package by James Clark,
+and Eric Allman's papers on the @code{-me} macro package.
+
+
+
+@node Invoking groff, Tutorial for Macro Users, Introduction, Top
+@chapter Invoking @code{groff}
+@cindex invoking @code{groff}
+@cindex @code{groff} invocation
+
+
+@pindex groff
+@pindex gtroff
+This section focuses on how to invoke the @code{groff} front end. This
+front end takes care of the details of constructing the pipeline among
+the preprocessors, @code{gtroff} and the postprocessor.
+
+It has become a tradition that GNU programs get the prefix @dfn{g} to
+distinguish it from its original counterparts provided by the host
+(@pxref{Environment}, for more details). Thus, for example, @code{geqn}
+is GNU @code{eqn}. On operating systems like Linux or the Hurd, which
+don't contain proprietary software, this prefix is omitted since GNU
+@code{troff} is the only used incarnation of @code{troff}. Exception:
+@code{groff} is never replaced by `roff'.
+
+
+@menu
+* Options::
+* Environment::
+* Invocation Examples::
+@end menu
+
+@node Options, Environment, Invoking groff, Invoking groff
+@section Options
+@cindex options
+
+
+@pindex groff
+@pindex gtroff
+@pindex gpic
+@pindex geqn
+@pindex gtbl
+@pindex grefer
+@pindex gsoelim
+@code{groff} is a front-end to the groff document formatting system.
+Normally it runs the @code{gtroff} program and a postprocessor
+appropriate for the selected device. The default device is @samp{ps}.
+It can optionally preprocess with any of @code{gpic}, @code{geqn},
+@code{gtbl}, @code{grefer}, or @code{gsoelim}.
+
+This section only documents options to the @code{groff} front end. Many
+of the arguments to @code{groff} are passed on to @code{gtroff},
+therefore those are also included. Arguments to pre- or postprocessors
+can be found in @ref{Invoking gpic}, @ref{Invoking geqn}, @ref{Invoking
+gtbl}, @ref{Invoking grefer}, @ref{Invoking gsoelim}, @ref{Invoking
+grotty}, @ref{Invoking grops}, @ref{Invoking grohtml}, @ref{Invoking
+grodvi}, and @ref{Invoking gxditview}
+
+The command line format for @code{groff} is:
+
+@example
+groff [ -abehilpstvzCENRSVXZ ] [ -F@var{dir} ] [ -m@var{name} ]
+ [ -T@var{def} ] [ -f@var{fam} ] [ -w@var{name} ] [ -W@var{name} ]
+ [ -M@var{dir} ] [ -d@var{cs} ] [ -r@var{cn} ] [ -n@var{num} ]
+ [ -o@var{list} ] [ -P@var{arg} ] [ -L@var{arg} ]
+ [ @var{files}@dots{} ]
+@end example
+
+The command line format for @code{gtroff} is as follows. As you can
+see, many of the options to @code{groff} are actually passed on to
+@code{gtroff}.
+
+@example
+gtroff [ -abivzCER ] [ -w@var{name} ] [ -W@var{name} ] [ -d@var{cs} ]
+ [ -f@var{fam} ] [ -m@var{name} ] [ -n@var{num} ]
+ [ -o@var{list} ] [ -r@var{cn} ] [ -T@var{name} ]
+ [ -F@var{dir} ] [ -M@var{dir} ] [ @var{files}@dots{} ]
+@end example
+
+Options without an argument can be grouped behind a single @samp{-}. A
+filename of @samp{-} denotes the standard input.
+
+@pindex grog
+The @code{grog} command can be used to guess the correct @code{groff}
+command to use to format a file.
+
+@table @samp
+@item -h
+Print a help message.
+@item -e
+Preprocess with @code{geqn}.
+@item -t
+Preprocess with @code{gtbl}.
+@item -p
+Preprocess with @code{gpic}.
+@item -s
+Preprocess with @code{gsoelim}.
+@item -R
+Preprocess with @code{grefer}. No mechanism is provided for passing
+arguments to @code{grefer} because most @code{grefer} options have
+equivalent commands which can be included in the file. @xref{grefer},
+for more details.
+
+@pindex troffrc
+Note that @code{gtroff} also accepts a @samp{-R} option, which is not
+accessible via @code{groff}. This option prevents the loading of the
+@file{troffrc} file.
+@item -v
+Make programs run by @code{groff} print out their version number.
+@item -V
+Print the pipeline on stdout instead of executing it.
+@item -z
+Suppress output from @code{gtroff}. Only error messages will be printed.
+@item -Z
+Do not postprocess the output of @code{gtroff}. Normally @code{groff}
+will automatically run the appropriate postprocessor.
+@item -P@var{arg}
+Pass @var{arg} to the postprocessor. Each argument should be passed
+with a separate @samp{-P} option. Note that groff does not prepend
+@samp{-} to @var{arg} before passing it to the postprocessor.
+@item -l
+Send the output to a printer. The command used for this is specified by
+the print command in the device description file.
+@item -L@var{arg}
+Pass @var{arg} to the spooler. Each argument should be passed with a
+separate @samp{-L} option. Note that @code{groff} does not prepend a
+@samp{-} to @var{arg} before passing it to the postprocessor.
+@item -T@var{dev}
+Prepare output for device @var{dev}. The default device is @samp{ps}.
+The following are the output devices currently available:
+@table @samp
+@item ps
+For PostScript printers and previewers.
+@item dvi
+For TeX dvi format.
+@item X75
+For a 75 dpi X11 previewer.
+@item X100
+For a 100dpi X11 previewer.
+@item ascii
+For typewriter-like devices.
+@item latin1
+For typewriter-like devices using the ISO Latin-1 (ISO 8859-1) character set.
+@item utf8
+For typewriter-like devices using the Unicode (ISO 10646) character set with
+UTF-8 encoding.
+@item lj4
+For an HP LaserJet4-compatible (or other PCL5-compatible) printer.
+@item html
+To produce HTML output.
+@end table
+
+The postprocessor to be used for a device is specified by the
+@code{postpro} command in the device description file. (@xref{Font
+Files}, for more info.) This can be overridden with the @samp{-X}
+option.
+@item -X
+Preview with @code{gxditview} instead of using the usual postprocessor.
+This is unlikely to produce good results except with @samp{-Tps}.
+@item -N
+Don't allow newlines with @code{eqn} delimiters. This is the same as
+the @samp{-N} option in @code{geqn}.
+@item -S
+Safer mode. Pass the @samp{-S} option to @code{gpic} and use the
+@samp{-msafer} macros with @code{gtroff}.
+@item -a
+Generate an ASCII approximation of the typeset output.
+@item -b
+Print a backtrace with each warning or error message. This backtrace
+should help track down the cause of the error. The line numbers given
+in the backtrace may not always be correct: @code{troff}'s idea of line
+numbers gets confused by @code{as} or @code{am} requests.
+@item -i
+Read the standard input after all the named input files have been
+processed.
+@item -w@var{name}
+Enable warning @var{name}. Available warnings are described in
+@ref{Debugging}. Multiple @samp{-w} options are allowed.
+@item -W@var{name}
+Inhibit warning @var{name}. Multiple @samp{-W} options are allowed.
+@item -E
+Inhibit all error messages.
+@item -C
+Enable compatibility mode.
+@item -d@var{cs}
+@itemx -d@var{name}=s
+Define @var{c} or @var{name} to be a string @var{s}; @var{c} must be a
+one-letter @var{name}.
+@item -f@var{fam}
+Use @var{fam} as the default font family.
+@item -m@var{name}
+Read in the file @file{tmac.@var{name}}. Normally this will be searched
+for in @code{groff}'s lib directory.
+@item -n@var{num}
+Number the first page @var{num}.
+@item -o@var{list}
+Output only pages in @var{list}, which is a comma-separated list of page
+ranges; @var{n} means print page @var{n}, @samp{@var{m}-@var{n}} means
+print every page between @var{m} and @var{n}, @samp{-@var{n}} means
+print every page up to @var{n}, @samp{@var{n}-} means print every page
+from @var{n}. @code{troff} will exit after printing the last page in
+the list.
+@item -r@var{cn}
+@itemx -r@var{name}=@var{n}
+Set number register @var{c} or @var{name} to @var{n}; @var{c} must be a
+one-letter @var{name}; @var{n} can be any troff numeric expression.
+@item -F@var{dir}
+Search @var{dir} for subdirectories dev@var{name} (@var{name} is the
+name of the device) for the @file{DESC} file and font files before the
+normal directory.
+@item -M@var{dir}
+Search directory @var{dir} for macro files before the normal directory.
+@end table
+
+
+
+@node Environment, Invocation Examples, Options, Invoking groff
+@section Environment
+@cindex environment
+
+
+There are also several environment variables which can modify groff's
+behavior.
+
+@table @code
+@item GROFF_COMMAND_PREFIX
+If this is set to @var{X}, then @code{groff} will run
+@var{X}@code{troff} instead of @code{gtroff}. This also applies to
+@code{tbl}, @code{pic}, @code{eqn}, @code{refer}, and @code{soelim}. It
+does not apply to @code{grops}, @code{grodvi}, @code{grotty},
+@code{grohtml}, @code{grolj4}, and @code{gxditview}.
+@item GROFF_TMAC_PATH
+A colon separated list of directories in which to search for macro
+files.
+@item GROFF_TYPESETTER
+Default device.
+@item GROFF_FONT_PATH
+A colon separated list of directories in which to search for the
+@code{dev}@var{name} directory.
+@item PATH
+The search path for commands executed by groff.
+@item GROFF_TMPDIR
+The directory in which temporary files will be created. If this is not
+set and @code{TMPDIR} is set, temporary files will be created in that
+directory. Otherwise temporary files will be created in @code{/tmp}.
+The @code{grops} and @code{grefer} commands can create temporary files.
+@end table
+
+
+@node Invocation Examples, , Environment, Invoking groff
+@section Invocation Examples
+@cindex invocation examples
+@cindex examples of invocation
+
+
+This section will list several common uses of @code{groff} and the
+command line which will accomplish it.
+
+@example
+groff file
+groff -X -me file
+groff -mm -rD1 -z file
+groff -tps -me file | lpr -Plw2
+... any more?? ...
+@end example
+
+@subsection @code{grog}
+
+@code{grog} reads files and guesses which of the @code{groff}
+preprocessors and/or macro packages are are required for formatting
+them, and prints the @code{groff} command including those options on the
+standard output. The options generated are one of @samp{-e},
+@samp{-man}, @samp{-me}, @samp{-mm}, @samp{-ms}, @samp{-p}, @samp{-s},
+and @samp{-t}.
+
+A filename of @samp{-} is taken to refer to the standard input. If no
+files are specified the standard input will be read. Any specified
+options will be included in the printed command. No space is allowed
+between options and their arguments. For example,
+
+@example
+grog -Tdvi paper.ms
+@end example
+
+will guess the approriate command to print @file{paper.ms} and then run
+it after adding the @samp{-Tdvi} option.
+
+
+@node Tutorial for Macro Users, -man, Invoking groff, Top
+@chapter Tutorial for Macro Users
+@cindex tutorial for macro users
+@cindex macro tutorial for users
+@cindex user's tutorial for macros
+@cindex user's macro tutorial
+
+Most users tend to use a macro package to format their papers. This
+means that the whole breadth of @code{groff} is not neccessary for most
+people. This chapter covers the material needed to efficiently use a
+macro package.
+
+
+@menu
+* Basics::
+* Common Features::
+@end menu
+
+@node Basics, Common Features, Tutorial for Macro Users, Tutorial for Macro Users
+@section Basics
+@cindex basics
+
+
+This section covers some of the basic concepts you will need to
+understand to use a macro package.@footnote{This section is derived from
+@cite{Writing Papers with nroff using -me} by Eric P.@w{ }Allman}
+References are made throughout to more detailed information, if desired.
+
+@code{groff} reads an input file prepared by the user and outputs a
+formatted paper suitable for publication or framing. The input consists
+of text, or words to be printed, and embedded commands (@dfn{requests}
+and @dfn{escapes}), which tell @code{groff} how to format the printed
+copy. For more detail on this @pxref{Embedded Commands}.
+
+The word @dfn{argument} is used in this manual to mean a word or number
+which appears on the same line as a request which modifies the meaning
+of that request. For example, the request
+
+@example
+.sp
+@end example
+
+@noindent
+spaces one line, but
+
+@example
+.sp 4
+@end example
+
+@noindent
+spaces four lines. The number@w{ }4 is an argument to the @code{sp}
+request which says to space four lines instead of one. Arguments are
+separated from the request and from each other by spaces. More details
+on this can be found in @ref{Request Arguments}.
+
+The primary function of @code{groff} is to collect words from input
+lines, fill output lines with those words, justify the right hand margin
+by inserting extra spaces in the line, and output the result. For
+example, the input:
+
+@example
+Now is the time
+for all good men
+to come to the aid
+of their party.
+Four score and seven
+years ago,...
+@end example
+
+@noindent
+will be read, packed onto output lines, and justified to produce:
+
+@quotation
+Now is the time for all good men to come to the aid of their party.
+Four score and seven years ago,...
+@end quotation
+
+@cindex break
+@cindex line break
+Sometimes you may want to start a new output line even though the line
+you are on is not yet full; for example, at the end of a paragraph. To
+do this you can cause a @dfn{break}, which starts a new output line.
+Some requests cause a break automatically, as do blank input lines and
+input lines beginning with a space.
+
+Not all input lines are text to be formatted. Some of the input lines
+are requests which describe how to format the text. Requests always
+have a period or an apostrophe (@samp{'}) as the first character of the
+input line.
+
+The text formatter also does more complex things, such as automatically
+numbering pages, skipping over page boundaries putting footnotes in the
+correct place, and so forth.
+
+Here a few hints for preparing text for input to @code{groff}. First,
+keep the input lines short. Short input lines are easier to edit, and
+@code{groff} will pack words onto longer lines for you anyhow. In
+keeping with this, it is helpful to begin a new line after every period,
+comma, or phrase, since common corrections are to add or delete
+sentences or phrases. Secondly, do not hyphenate words at the end of
+lines -- @code{groff} is smart enough to hyphenate words for you as
+needed, but is not smart enough to take hyphens out and join a word back
+together. Also, words such as ``mother-in-law'' should not be broken
+over a line, since then you will get a space where not wanted, such as
+``mother- in-law''.
+
+@findex ls
+@cindex double spacing
+@cindex spacing
+Groff will double space output text automatically if you use the request
+@samp{.ls 2}. You can revert to single spaced mode by typing @samp{.ls
+1}.
+
+A number of requests allow you to change the way the printed copy looks,
+sometimes called the @dfn{layout} of the output page. Most of these
+requests adjust the placing of @dfn{white space} (blank lines or
+spaces).
+
+@findex bp
+@cindex new page
+The @samp{.bp} request starts a new page.
+
+@findex sp
+@cindex blank lines
+@cindex empty lines
+The request @samp{.sp @var{N}} leaves @var{N} lines of blank space.
+@var{N} can be omitted (meaning skip a single line) or can be of the
+form @var{N}i (for @var{N} inches) or @var{N}c (for @var{N}
+centimeters). For example, the input:
+
+@example
+.sp 1.5i
+My thoughts on the subject
+.sp
+@end example
+
+@noindent
+leaves one and a half inches of space, followed by the line ``My
+thoughts on the subject'', followed by a single blank line.
+
+@findex ce
+@cindex centering lines
+Text lines can be centered by using the @samp{.ce} request. The line
+after @samp{.ce} is centered (horizontally) on the page. To center more
+than one line, use @samp{.ce @var{N}} (where @var{N} is the number of
+lines to center), followed by the @var{N} lines. If you want to center
+many lines but don't want to count them, type:
+
+@example
+.ce 1000
+lines to center
+.ce 0
+@end example
+
+@noindent
+The @samp{.ce 0} request tells @code{groff} to center zero more lines,
+in other words, stop centering.
+
+@findex br
+@cindex line break
+@cindex break
+All of these requests cause a break; that is, they always start a new
+line. If you want to start a new line without performing any other
+action, use @samp{.br}.
+
+
+@node Common Features, , Basics, Tutorial for Macro Users
+@section Common Features
+@cindex common features
+@cindex features, common
+
+
+Groff provides very low level operations for formatting a document.
+There are many common routine operations which are done in all documents.
+These common operations are written into @dfn{macros} and collected into a
+@dfn{macro package}.
+
+All macro packages provide certain common capabilities which fall
+into the following categories.
+
+@subsection Paragraphs
+@cindex paragraphs
+
+One of the most common and most used capability is starting a
+paragraph. There are a number of different types of paragraphs,
+any of which can be initiated with macros supplied by the macro
+package. Normally paragraphs start with a blank line and the first
+line indented, like the text in this manual. There are also block
+style paragraphs, which omit the indentation:
+
+@example
+Some men look at constitutions with sanctimonious
+reverence, and deem them like the ark of the covenant, too
+sacred to be touched.
+@end example
+
+And there are also indented paragraphs which begin with a tag or label
+at the margin and the remaining text indented.
+
+@example
+one This is the first paragraph. Notice how the first
+ line of the resulting paragraph lines up with the
+ other lines in the paragraph.
+longlabel
+ This paragraph had a long label. The first
+ character of text on the first line will not line up
+ with the text on second and subsequent lines,
+ although they will line up with each other.
+@end example
+
+A variation of this is a bulleted list....
+
+@subsection Sections and Chapters
+
+Most macro packages supply some form of section headers.
+The simplest kind is simply the heading on a line by itself in bold
+type. Others supply automatically numbered section heading or
+different heading styles at different levels.
+Some, more sophisticated, macro packages supply macros for starting
+chapters and appendicies.
+
+@subsection Headers and Footers
+
+Every macro packages gives you some way to manipulate the headers and
+footers (or @dfn{titles} on each page. Some packages will allow you
+to have different ones on the even and odd pages (for material
+printed in a book form).
+The titles are called three-part titles, that is, there is a
+left-justified part, a centered part, and a right-justified part.
+An automatically generated page number may be put in any of these
+fields with the @samp{%} character.
+
+@subsection Page Layout
+
+Most macro packages let you specify top and bottom margins and other
+details about the appearance of the printed pages.
+
+@subsection Displays
+@cindex displays
+
+Displays are sections of text to be set off from the body
+of the paper. Major quotes, tables, and figures are types of
+displays, as are all the examples used in this document.
+
+@cindex quotes, major
+@cindex major quotes
+Major quotes are quotes which are several lines long,
+and hence are set in from the rest of the text without
+quote marks around them.
+
+@cindex list
+A list is an indented, single spaced, unfilled display. Lists should
+be used when the material to be printed
+should not be filled and justified like normal text, such
+as columns of figures or the examples used in this paper.
+
+@cindex keep
+A keep is a display of lines which are kept on a single page if
+possible. An example of where you would use a
+keep might be a diagram. Keeps differ from lists in that
+lists may be broken over a page boundary whereas keeps will
+not.
+
+@cindex keep, floating
+@cindex floating keep
+Floating keeps move relative to the text. Hence, they
+are good for things which will be referred to by name, such
+as ``See figure 3''. A floating keep will appear at the bottom of the
+current page if it will fit; otherwise, it will
+appear at the top of the next page. Meanwhile, the surrounding text
+will `flow' around the keep, thus leaving now blank areas.
+
+@subsection Footnotes and annotations
+@cindex footnotes
+@cindex annotations
+
+There are a number of requests to save text for later
+printing. Footnotes are printed at the bottom of the current
+page. Delayed text is intended to be a variant form of foot-
+note; the text is printed only when explicitly called for,
+such as at the end of each chapter.
+
+Delayed text is very similar to a footnote except that
+it is printed when called for explicitly. This allows a
+list of references to appear (for example) at the end of
+each chapter, as is the convention in some disciplines.
+
+Most macro packages which supply this functionality also supply a
+means of automatically numbering either type of annotation.
+
+@subsection Table of Contents
+
+Tables of contents are a type of
+delayed text having a tag (usually the page number) attached
+to each entry after a row of dots. The table accumulates
+throughought the paper until printed, usually after the paper has
+ended. Many macro packages will provide the abilitly to have several
+tables of contents (i.e. one standard one, one for tables, &c.)
+
+@subsection Indexes
+
+While some macro packages will use the term @dfn{index}, none
+actually provide that functionality. The facilities they call
+indexes are actually more appropriate for tables of contents.
+
+@subsection Paper formats
+
+Some macro packages provide stock formats for various kinds of
+documents. Many of them provide a common format for the title and
+opening pages of a technical paper. The -mm macros in particular
+provide formats for letters and memorandums.
+
+@subsection Multiple Columns
+
+Some macro packages (except -man) provide the ability to have two or
+more columns on a page.
+
+@subsection Font and Size changes
+
+The builtin font and size functions are not always intuitive, so all
+macro packages provide macros to make these operations simpler.
+
+@subsection Predefined Strings
+
+Most macro packages provide various predefined strings for a variety
+of uses, examples are sub- and super-scripts, printable dates, quotes
+and various special characters.
+
+@subsection Preprocessor Support
+
+All macro packages provide support for the various preprocessors.
+
+@subsection Configuration and Customization
+
+Some macro packages provide means of customizing many of details of
+how the package behaves. This ranges from setting the default type
+size to changing the appearance of section headers.
+
+
+@node -man, -ms, Tutorial for Macro Users, Top
+@chapter -man
+@cindex @code{-man}
+
+
+
+@node -ms, -me, -man, Top
+@chapter -ms
+@cindex @code{-ms}
+
+
+
+@node -me, -mm, -ms, Top
+@chapter -me
+@cindex @code{-me}
+
+
+
+@node -mm, Programming Tutorial, -me, Top
+@chapter -mm
+@cindex @code{-mm}
+
+
+
+@node Programming Tutorial, geqn, -mm, Top
+@chapter Programming Tutorial
+@cindex programming tutorial
+@cindex tutorial for programming
+
+This chapter covers @strong{all} of the facilities of groff.
+If you are intending to use a macro package, you probably do not want
+to read this chapter.
+
+
+@menu
+* Text::
+* Input Conventions::
+* Measurements::
+* Expressions::
+* Identifiers::
+* Embedded Commands::
+* Registers::
+* Manipulating Filling and Adjusting::
+* Manipulating Hyphenation::
+* Manipulating Spacing::
+* Tabs and Fields::
+* Character Translations::
+* Line Layout::
+* Page Layout::
+* Page Control::
+* Fonts::
+* Sizes::
+* Strings::
+* Conditionals and Loops::
+* Writing Macros::
+* Page Motions::
+* Drawing Functions::
+* Traps::
+* Diversions::
+* Environments::
+* I/O::
+* Postprocessor Access::
+* Miscellany::
+* Debugging::
+* Implementation Differences::
+* Summary::
+@end menu
+
+@node Text, Input Conventions, Programming Tutorial, Programming Tutorial
+@section Text
+@cindex text
+
+@code{groff} input files contain text with control commands
+interspersed throughout. But, even without control codes,
+@code{groff} will still do several things with your text:
+filling and adjusting,
+adding additional space after sentences,
+hyphenating
+and
+inserting implicit line breaks.
+
+
+@menu
+* Filling and Adjusting::
+* Hyphenation::
+* Sentences::
+* Tab Stops::
+* Implicit Line Breaks::
+@end menu
+
+@node Filling and Adjusting, Hyphenation, Text, Text
+@subsection Filling and Adjusting
+@cindex filling and adjusting
+@cindex adjusting and filling
+
+
+When troff reads in text it collects words from input and fits as many
+of them together on one output line as it can. This is known as
+@dfn{filling}.
+
+Once troff has a @dfn{filled} line it will try to @dfn{adjust} it.
+which means it will widen the spacing between words until
+the text reaches the right margin (in the default adjustment mode).
+Extra spaces between words are preserved, but
+spaces at the end of lines are ignored.
+Spaces at the front of a line will cause a @dfn{break}
+(breaks will be explained in @ref{Implicit Line Breaks})
+
+@c distribute these through the text
+@xref{Manipulating Filling and Adjusting}
+
+@node Hyphenation, Sentences, Filling and Adjusting, Text
+@subsection Hyphenation
+@cindex hyphenation
+
+
+Since the odds of finding a set of words, for every output line,
+which will fit nicely on a
+line without inserting excessive amounts of space between words
+is not great,
+troff will hyphenate words so that lines can be justified
+without there being too much space between words.
+It uses an internal hyphenation algorithm, to indicate which words can
+be hyphenated and how to do so.
+When a word is hyphenated the first part of the word will be added
+to the current filled line being output (with an attached hyphen),
+and the other portion will be added to the next line to be filled.
+
+@c distribute these through the text
+@xref{Manipulating Hyphenation}
+
+@node Sentences, Tab Stops, Hyphenation, Text
+@subsection Sentences
+@cindex sentences
+
+
+Although it is often debated,
+some typesetting rules say there should be different amounts of space
+after various puctuation marks.
+For example, a period at the end of a sentence
+should have twice as much space following it
+as would a comma or a period as part of an abbreviation.
+
+@cindex sentence spaces
+@cindex spaces between sentences
+Troff does this by flagging certain characters (normally
+@samp{!}, @samp{?} and @samp{.})
+as @dfn{end of sentence} characters.
+When troff encounters one of these characters at the end of a line it
+will append two @dfn{sentence spaces} in the formatted output.
+(thus, one of the conventions mentioned in @ref{Input Conventions}).
+
+@c also describe how characters like ) are treated here -jjc
+@c gotta do some research on this -trent
+
+
+
+@node Tab Stops, Implicit Line Breaks, Sentences, Text
+@subsection Tab Stops
+@cindex tab stops
+@cindex stops, tabulator
+
+
+Groff translates tabs in the input into movements to the next tab
+stop. These tab stops are initially located every half inch across
+the page.
+Using this you can make simple tables. However, this can often be
+deceptive as the appearance (and width) of your text on a terminal and
+the results from groff can vary greatly.
+
+Also, a possible sticking point is that lines beginning with tab
+characters will still be filled, again producing unexpected results.
+For example, the following input
+
+@example
+ 1 2 3
+ 4 5
+@end example
+
+@noindent
+will produce
+
+@example
+ 1 2 3 4 5
+@end example
+
+@c Tab stops are with respect to the input line. -jjc
+@c did that last section address that?? -trent
+
+
+
+@c distribute these through the text
+@xref{Tabs and Fields}
+
+@node Implicit Line Breaks, , Tab Stops, Text
+@subsection Implicit Line Breaks
+@cindex implicit line breaks
+@cindex implicit breaks of lines
+@cindex line, implicit breaks
+@cindex break
+@cindex break, implicit
+@cindex line break
+
+An important concept in troff is the @dfn{break}. When a @dfn{break}
+occurs, troff will output the partially filled line (unadjusted),
+and resume collecting and filling text on the next output line.
+
+@cindex blank line
+@cindex empty line
+@cindex line, blank
+There are several ways to cause a break in troff.
+A blank line will not only cause a break, but it will also cause a
+one line vertical space (effectively a blank line) to be output.
+
+A line which begins with a space will cause a break and the space
+will be output at the beginning of the next line.
+Note that this space isn't adjusted, even in fill mode.
+
+The end of file will also cause a break (otherwise the last line of
+your document may vanish!)
+
+Certain @dfn{requests} also cause breaks, implicitly or explicity.
+This will be discussed later.
+
+@c distribute these through the text
+@xref{Manipulating Filling and Adjusting}
+
+@node Input Conventions, Measurements, Text, Programming Tutorial
+@section Input Conventions
+@cindex input conventions
+@cindex conventions for input
+
+
+Since groff does filling automatically, it is traditional in groff not
+to try and type things in as nicely formatted paragraphs. These are
+some conventions commonly used when typing groff text:
+
+@itemize @bullet{}
+@item
+Break lines after punctuation, particularily at the ends of
+sentences, and in other logical places. Keep separate phrases on
+lines by themselves, as entire phrases are often added or deleted
+when editing.
+@item
+Try to keep lines less than 40-60 characters,
+to allow space for inserting more text.
+@item
+Do not try to do any formatting in a WYSIWYG manner (i.e. don't
+try and use spaces to get proper indentation).
+@end itemize
+
+
+@node Measurements, Expressions, Input Conventions, Programming Tutorial
+@section Measurements
+@cindex measurements
+
+
+@cindex units of measurement
+@cindex basic units
+@cindex machine units
+Troff (like any other programs) requires numeric parameters to
+specify various measurements. Most numeric parameters
+@footnote{those that specify vertical or horizontal motion or a type
+size} may have a measurement unit attached.
+These units are specified as a single
+character which immediately follows the number or expression.
+Each of these units are understood, by troff, to be a multiple of its
+@dfn{basic unit}. So, whenever a different measurement unit is
+specified troff converts this into its basic units.
+This basic unit, represented by a @samp{u} is a
+device dependent measurement which is quite small, ranging from
+1/75th to 1/72000th of an inch.
+
+Some of the measurement units are compleatly independent of any of
+the current settings (e.g. type size) of groff.
+
+@table @samp
+@item i
+@cindex inch
+Inches. An antiquated measurement unit still in use in certain
+backwards countries.
+@item c
+@cindex centimeter
+Centimeters.
+@item p
+@cindex points
+Points. This is a typesetter's measurement used for measure type size.
+It is 72 points to an inch.
+@item P
+@cindex pica
+Pica. Another typesetting measurement. 6 Picas to an inch.
+@item s
+@item z
+@end table
+
+The other measurements understood by troff are dependent on settings
+currently in effect in troff. These are very useful for specifying
+measurements which should look proper with any size of text.
+
+@table @samp
+@item m
+@cindex em
+Ems. This unit is equal to the current font size in points.
+So called because it is @emph{approximately} the width of the letter
+@samp{m} in the current font.
+@item n
+@cindex en
+Ens. This is half of an em.
+@item v
+@cindex vertical space
+@cindex space, vertical
+Vertical space. This is equivalent to the current line spacing.
+@xref{Sizes}, for more information about this.
+@item M
+100ths of an em.
+@end table
+
+@c distribute these through the text
+@xref{Fractional Type Sizes}
+
+@menu
+* Default Units::
+@end menu
+
+@node Default Units, , Measurements, Measurements
+@subsection Default Units
+@cindex default units
+@cindex units, default
+
+
+Many requests take a default unit. While this can be helpful at
+times, it can cause strange errors in some expressions.
+For example, the line length request expects em's.
+Here are several attempts to get 3.5 inches and the results:
+
+@example
+3.5i @result{} 3.5i
+7/2 @result{} 0i
+7/2i @result{} 0i
+7i/2 @result{} .1i
+7i/2u @result{} 3.5i
+@end example
+
+As you can see, the safest way to specify measurements is to always
+attach a scaling indicator.
+
+@node Expressions, Identifiers, Measurements, Programming Tutorial
+@section Expressions
+@cindex expressions
+
+
+Troff has most of operators common to other languages:
+
+@itemize @bullet
+@item
+Arithmetic: +, -, /, *, %
+@item
+Comparison: <, >, >=, <=, =, == (the last two are the same)
+@item
+Logical: &, :
+@item
+Unary operators: -, +, ! (if/while only??)
+@item
+Maximum and minimum: >?, <?
+@item
+Scaling: (@var{c};@var{e})
+Evaluate @var{e} using @var{c} as the default scaling indicator.
+If @var{c} is missing, ignore scaling indicators in the
+evaluation of @var{e}.
+@end itemize
+
+Parenthesis may be used as in any other language.
+However, in groff they are necessary to ensure order of evaluation.
+Groff has no operator precedence,
+expressions are evaluated left to right.
+This means that @samp{3+5*4} is evaluated as if it were parenthesized
+like @samp{(3+5)*4}, not as @samp{3+(5*4)}, like you may expect.
+
+For many requests which cause a motion on the page, the unary
+operators work differently.
+The @samp{+} and @samp{-} operators indicate a motion relative to the
+current position (down or up, respectively). The @samp{|} operator
+indicates an absolute position on the page or input line. (????)
+@code{+} and @code{-} are also treated differently by @code{nr} (?)
+
+Due to the way arguments are parsed, spaces are not allowed in
+expressions, unless the entire expression is surrounded by parenthesis.
+
+@c distribute these through the text
+@xref{Request Arguments}
+@c distribute these through the text
+@xref{Conditionals and Loops}
+
+@node Identifiers, Embedded Commands, Expressions, Programming Tutorial
+@section Identifiers
+@cindex identifiers
+
+Like any other language troff, has rules for properly formed
+identifiers.
+In troff an identifier can be made up of most any printable
+character.
+The only exception is characters which are interpreted by troff
+(backslash, square bracket and ?). So, for example, any of the following
+are valid.
+
+@example
+br
+PP
+(l
+end-list
+@@_
+@end example
+
+You can test whether an identifier is valid in groff with the
+@code{\A} escape. It expands to 1 or 0 according whether its argument
+(given in quotes) is or is not acceptable as the name of a string,
+macro, diversion, number register, environment or font. It will return
+0 if no argument is given. This is useful if you want to lookup user
+input in some sort of associative table.
+
+Identifiers in groff can be any length, but, in some contexts,
+groff needs to told
+where identifiers end and text begins (and in different ways
+depending on their length)
+
+@itemize @bullet{}
+@item
+Single character
+@item
+Two characters
+Must be prefixed with @samp{(} in some situations.
+@item
+Arbitrary length (groff only)
+Must be bracketed with @samp{[}, @samp{]} in some situations.
+Any length identifier can be put in brackets.
+@end itemize
+
+Unlike many other programming languages, undefined identifiers are
+silently ignored or expanded to nothing.
+
+
+@c distribute these through the text
+@xref{Interpolating Registers}
+@c distribute these through the text
+@xref{Strings}
+
+@node Embedded Commands, Registers, Identifiers, Programming Tutorial
+@section Embedded Commands
+@cindex embedded commands
+@cindex commands, embedded
+
+
+With most documents you need more funtionality beyond filling,
+adjusting and implicit line breaking.
+In order to gain further functionality, groff allows commands to be
+embeded into your text, in two ways.
+
+The first is a @dfn{request} which takes up an entire line, and does
+some large scale operation (e.g. break lines, start new pages).
+
+The other is an @dfn{escape} which can be embedded anywhere
+in your text, or even as an argument to a request. (Not always?)
+Escapes generally do more minor operations like sub- and super-
+scripts, print a symbol, &c.
+
+
+
+@menu
+* Requests::
+* Macros::
+* Escapes::
+@end menu
+
+@node Requests, Macros, Embedded Commands, Embedded Commands
+@subsection Requests
+@cindex requests
+
+
+@cindex control character
+@cindex character, control
+A request line begins with a control character,
+which is either a single quote (@samp{'}) or a period (@samp{.}).
+These can be changed @pxref{Character Translations}, for details.
+After this there may be optional tabs or spaces followed by an
+identifier which is the name of the request.
+This may be followed by any number of space separated arguments.
+
+@findex \&
+If you want to begin a line with a control character without it being
+interpreted, precede it with a @code{\&}. This represents a zero
+width space, which means it will not affect you output.
+
+In most cases you will use the period as a control character.
+Several requests will cause a break, using the single quote control
+character will prevent this.
+
+
+@menu
+* Request Arguments::
+@end menu
+
+@node Request Arguments, , Requests, Requests
+@subsubsection Request Arguments
+@cindex request arguments
+@cindex arguments to requests
+
+
+Argument to requests (and macros) are processed much like the shell:
+The line is split into arguments according to spaces.
+An argument which is intended to contain spaces can either be enclosed
+in quotes (single or double), or have the spaces @dfn{escaped} with
+backslashes.
+
+So, for example:
+
+@example
+.uh The Mouse Problem
+.uh "The Mouse Problem"
+.uh The\ Mouse\ Problem
+@end example
+
+The first line is the @code{.uh} macro being called with 3 arguments,
+@samp{The}, @samp{Mouse}, and @samp{Problem}.
+The latter two have the same effect or calling the @code{.uh} macro
+with one argument @samp{The Mouse Problem}.
+
+Note, however, that the @code{.ds} request works differently.
+
+@c distribute these through the text
+@xref{Strings}
+
+@node Macros, Escapes, Requests, Embedded Commands
+@subsection Macros
+@cindex macros
+
+
+Troff has a @dfn{macro} facility for defining a series of lines which
+can be invoked by name.
+They are called in the same manner as requests
+and arguments may be passed in the same manner.
+
+
+@c distribute these through the text
+@xref{Writing Macros}
+@c distribute these through the text
+@xref{Request Arguments}
+
+@node Escapes, , Macros, Embedded Commands
+@subsection Escapes
+@cindex escapes
+
+
+@findex \e
+@findex \\
+Escapes may occur anywhere in the input to groff.
+They begin with a backslash and are followed by a single character
+which indicates the function to be performed.
+If you want to have a backslash appear in your document, you should
+use the escape sequence @code{\e}. Merely escaping the backslash
+with another backslash will work in @emph{some} curcumstances.
+
+Many escapes have no parameters, those that do, do so in one of two
+ways. For escapes which require an identifier there must be a way for
+groff to tell where the identifier ends and the text begins.
+It assumes that the next single character is the identifier, but if
+that character is an open parenthesis, it takes the next two
+characters as the identifier; and if the next character is an open
+bracket, all characters until a close bracket are taken as the
+identifier. Note that in the second case there is no closing
+parenthesis. For example:
+
+@example
+\fB
+\n(XX
+\*[TeX]
+@end example
+
+Other escapes may require several arguments and/or some special
+format. In these cases the @dfn{argument} is enclosed in single
+quotes (not required??) and the enclosing text is decoded according
+to what that escape expects.
+
+@example
+\l'1.5i\(bu'
+@end example
+
+@findex \\
+@findex \e
+@findex \E
+If you want to have a backslash appear in your output, you can use several
+escapes: @code{\\}, @code{\e} or @code{\E}.
+These are very similar, and only differ with respect to being used in
+macros or diversions (@xref{Copy-in Mode}, and @ref{Diversions}, for
+more information)
+
+
+
+@c distribute these through the text
+@xref{Identifiers}
+
+@menu
+* Comments::
+@end menu
+
+@node Comments, , Escapes, Escapes
+@subsubsection Comments
+@cindex comments
+
+
+@findex \"
+Probably one of the most@footnote{Unfortunately, this is a lie. But
+hopefully future troff hackers will believe it :-)}
+common forms of escapes is the comment.
+They begin with the @code{\"} escape and end at the end of the input
+line.
+
+This may sound simple, but it can be tricky to keep the comments from
+interfering with the apperarance of your final outupt.
+
+If the escape is to the right of some text or a request, that portion
+of the line will be ignored, but the space leading up to it will be
+noticed by groff. This only affects the @code{.ds} request (any
+others?).
+
+One possibly irritating idiosyncracy is that you mustn't use tabs to
+line up your comments.
+Tabs are not treated as white space between request and macro
+arguments.
+
+If you have a comment on a line by itself, it will be treated as a
+blank line, because after eliminating the comment, that is all that
+remains. So, it is common to start the line with @code{.\"} which
+will cause the line to be treated as an undefined request.
+
+Another commenting scheme seen sometimes is three consecutive single
+quotes (@code{'''}) at the begining of a line. This works, but groff
+will give a warning about an undefined macro, which is harmless, but
+irritating.
+
+@findex \#
+Now to avoid all this groff has a new comment mechanism using the
+@code{\#} escape. This escape works the same as @code{\"} except
+that the newline is also ignored.
+
+@findex ig
+For large blocks of text, the @code{ig} request may be useful.
+@c distribute these through the text
+@xref{Strings}
+
+@node Registers, Manipulating Filling and Adjusting, Embedded Commands, Programming Tutorial
+@section Registers
+@cindex registers
+
+
+Registers are groff's numeric variables. groff has a number of
+builtin registers, supplying anything from the date to details of
+formatting parameters.
+
+@c distribute these through the text
+@xref{Identifiers}
+
+@menu
+* Setting Registers::
+* Interpolating Registers::
+* Auto-increment::
+* Assigning Formats::
+* Builtin Registers::
+@end menu
+
+@node Setting Registers, Interpolating Registers, Registers, Registers
+@subsection Setting Registers
+@cindex setting registers
+@cindex registers, setting
+
+
+@findex nr
+@findex \R
+Registers are defined/set via the @code{nr}
+request or the @code{\R} escape, for example, the following two lines
+are equivalent:
+
+@example
+.nr a 1
+\R'a 1'
+@end example
+
+@findex rr
+The @code{rr} request will
+remove the register specified by the argument.
+
+@findex rnn
+The @code{rnn} request will rename a number register.
+The format is @samp{.rnn @var{x} @var{y}}, which will
+rename number register @var{x} to @var{y}.
+
+@findex aln
+Aliases can be created for a number register. The format is
+@samp{.aln @var{xx} @var{yy}}, which will create an alias @var{xx} for
+number register object named @var{yy}. The new name and the old name
+will be exactly equivalent. If @var{yy} is undefined, a warning of
+type @samp{reg} will be generated, and the request will be ignored.
+@xref{Debugging}, for information about warnings.
+
+
+@node Interpolating Registers, Auto-increment, Setting Registers, Registers
+@subsection Interpolating Registers
+@cindex interpolating registers
+@cindex registers, interpolating
+
+
+@findex \n
+Numeric registers are @dfn{interpolated} via the @code{\n} escape.
+@c the following is wrong. Should I say any more than the above??
+@c This means that the value of the number register in expanded in-place
+@c on the input line before any other actions, i.e. before requests and
+@c escapes are interpreted.
+
+@example
+.nr as \na+\na
+\n(as
+@end example
+
+
+@node Auto-increment, Assigning Formats, Interpolating Registers, Registers
+@subsection Auto-increment
+@cindex auto-increment
+@cindex increment, automatic
+
+Number registers can also be auto incremented/decremented. You can
+specify the increment/decrement factor with third argument to the
+@code{nr} request. The default value is 0. For example:
+
+@example
+.nr a 0 1
+.nr xx 0 5
+\n+a, \n+a, \n+a, \n+a, \n+a
+.br
+\n+(xx, \n+(xx, \n+(xx, \n+(xx, \n+(xx
+@end example
+
+Produces:
+
+@example
+1, 2, 3, 4, 5
+5, 10, 15, 20, 25
+@end example
+
+If you want to change the increment factor without changing the value
+of a register, the following can be used.
+
+@example
+.nr a \na 10
+@end example
+
+
+@node Assigning Formats, Builtin Registers, Auto-increment, Registers
+@subsection Assigning Formats
+@cindex assigning formats
+@cindex formats, assigning
+
+
+@findex af
+When a register is used in the text of an input file
+(as opposed to part of an expression)
+it is textually replaced (or interpolated) with a representation of
+that number.
+This output format can be changed to a variety of formats
+(numbers, roman numerals, etc)
+This is done using the @code{af} request.
+The first argument to @code{af} is the name of the number register to
+be changed,
+and the second argument is the output format.
+The following output formats are available:
+
+@table @samp
+@item 1
+This is the default format, decimal numbers:
+1, 2, 3, @dots{}
+@item 001
+Decimal numbers with as many leading zeros as specified.
+So, @samp{001} would result in 001, 002, 003, @dots{}
+@item I
+@cindex roman numerals
+@cindex numerals, roman
+Upper-case roman numerals:
+0, I, II, III, IV, @dots{}
+@item i
+Lower-case roman numerals:
+0, i, ii, iii, iv, @dots{}
+@item A
+Upper-case letters:
+A, B, C, @dots{}, Z, AA, AB, @dots{}
+@item a
+Lower-case letters:
+a, b, c, @dots{}, z, aa, ab, @dots{}
+@end table
+
+The following example will produce @samp{10, X, j, 010}.
+
+@example
+.nr a 10
+.af a 1 \" the default format
+\na,
+.af a I
+\na,
+.af a a
+\na,
+.af a 001
+\na
+@end example
+
+@findex \g
+The @code{\g} escape returns the current format of the specified
+register. For example, @samp{\ga} after the following example would
+produce @samp{001}.
+
+
+
+@node Builtin Registers, , Assigning Formats, Registers
+@subsection Builtin Registers
+@cindex builtin registers
+@cindex registers, builtin
+
+
+The following are some builtin registers, which are not listed
+elsewhere in this manual. Any registers which begin with a @samp{.}
+are read-only. A compleat listing of all builtin registers can be
+found in @ref{Register Index}.
+
+@table @code
+@item .H
+@vindex .H
+Horizontal resolution in basic units.
+@item .V
+@vindex .V
+Vertical resolution in basic units.
+@item dw
+@vindex dw
+Day of the week (1-7).
+@item dy
+@vindex dy
+Day of the year (1-31).
+@item mo
+@vindex mo
+Current month (1-12).
+@item year
+@vindex year
+The year.
+@item yr
+@vindex yr
+The year minus 1900. Unfortunately, the Unix Version 7 troff
+documentation had a year 2000 bug: it incorrectly claimed that
+@samp{\n(yr} was the last two digits of the year. That claim has never
+been true of either traditional troff or GNU troff. If you see old
+troff input that looks like this:
+
+@example
+'\" (The following line stopped working after 1999.)
+This document was formatted in 19\n(yr.
+@end example
+
+you can correct it as follows:
+
+@example
+This document was formatted in \n[year].
+@end example
+
+or, if you want to be portable to older troff versions, as follows:
+
+@example
+.nr y4 1900+\n(yr
+This document was formatted in \n(y4.
+@end example
+
+@item .c
+@vindex .c
+@itemx c.
+@vindex c.
+The current @emph{input} line number.
+@item ln
+@vindex ln
+The current @emph{output} line number.
+@item .x
+@vindex .x
+The major version number. For example, if the version number is 1.03
+then @code{.x} will contain 1.
+@item .y
+@vindex .y
+The minor version number. For example, if the version number is 1.03
+then @code{.y} will contain 03.
+@item .Y
+@vindex .Y
+The revision number of groff.
+@item .g
+@vindex .g
+Always 1.
+Macros should use this to determine whether they are running
+under GNU troff.
+@item .A
+@vindex .A
+If the current output device is ascii, this is set to 1,
+zero otherwise.
+@item .P
+@vindex .P
+This register indicates whether the current page is actualy being
+printed, i.e. if the @samp{-o} option is being used to only print
+selected pages.
+@xref{Options}, for more information.
+@end table
+
+@node Manipulating Filling and Adjusting, Manipulating Hyphenation, Registers, Programming Tutorial
+@section Manipulating Filling and Adjusting
+@cindex manipulating filling and adjusting
+@cindex filling and adjusting, manipulating
+@cindex adjusting and filling, manipulating
+
+
+@findex br
+@cindex break
+@cindex line break
+Several ways of causing @dfn{breaks} were given in
+@ref{Implicit Line Breaks}.
+The @code{br} request will likewise cause a break.
+Several other requests will also cause breaks, implicitly.
+They are
+@code{bp},
+@code{ce},
+@code{fi},
+@code{fl},
+@code{in},
+@code{nf},
+@code{sp} and
+@code{ti}.
+
+@findex nf
+@findex fi
+@vindex .u
+Initially, groff will fill and ajust text to both margins.
+Filling can be disabled via the @code{nf} request
+and re-enabled with the @code{fi} request.
+These implicitly disable and re-enable adjusting.
+Both of these will cause break in text currently being filled.
+The number register @code{.u} is equal to 1 in fill mode and 0 in
+no-fill mode.
+
+@findex ad
+@findex na
+@vindex .j
+Adjusting can be disabled with the @code{ad} request and re-enabled
+with the @code{na} request.
+The @code{ad} request takes a single argument to indicate how to
+adjust text.
+The current adjustment mode is available in the number register
+@code{.j}.
+
+@table @samp
+@item l
+@cindex ragged-right
+Adjust text to the left margin. This produces what is traditionally
+called ragged-right text.
+@item r
+Adjust text to the right margin.
+@item c
+Center filled text.
+@item b
+@itemx n
+Justify to both margins. This is groff's default.
+@end table
+
+With no argument to @code{ad}, troff will adjust lines the same way
+it was the last time it was filling. For example:
+
+@example
+text
+.ad r
+text
+.ad c
+text
+.na
+text
+.ad \" back to centering
+text
+@end example
+
+@findex \p
+The escape @code{\p} will cause a break and cause the remaining text
+to be adjusted.
+
+@findex ss
+The @code{ss} request allows you to change the minimum size of a
+space between filled words.
+This request takes it's units as one twelfth of the
+spacewidth parameter for the current font. Initially both the word
+space size and the sentence space size are 12.
+
+When two arguments are given to the @code{ss} request, the second argument
+gives the sentence space size. If the second argument is not given, the
+sentence space size will be the same as the word space size.
+The sentence space size
+is used in two circumstances: if the end of a sentence occurs at the end
+of a line in fill mode, then both an inter-word space and a sentence
+space will be added; if two spaces follow the end of a sentence in the
+middle of a line, then the second space will be a sentence space. Note
+that the behaviour of @sc{Unix} troff will be exactly that exhibited by GNU
+troff if a second argument is never given to the @code{ss} request. In GNU
+troff, as in @sc{Unix} troff, you should always follow a sentence with either
+a newline or two spaces.
+
+@vindex .ss
+@vindex .sss
+The number registers @code{.ss} and @code{.sss} are
+the values of the parameters set by the first and second
+arguments of the @code{ss} request.
+
+@findex ce
+The @code{ce} request will center text.
+While the @samp{ad c} request will also center text, it has the side
+effect of filling the text. The @code{.ce} request will not fill the
+text it affects.
+This request causes a break.
+
+With no arguments, @code{ce} will fill the next line of text.
+The single argument @code{ce} takes is a number indicating the
+number of lines to be centered. With no argument centering is
+disabled.
+
+A common idiom is to turn on centering for a large number of lines,
+and then turn off centering when you are done with the centered text.
+This is useful for any request which takes a number of lines as an
+argument.
+
+@example
+.ce 1000
+replace this
+with
+something
+more interesting
+@dots{}
+.ce 0
+@end example
+
+@vindex .ce
+The @code{.ce} number register contains the number of lines remaining
+to be centered, as set by the @code{ce} request.
+
+
+@findex rj
+@vindex .rj
+A similar request is @code{rj} request which will justify unfilled
+text to the right margin. Its arguments are identical to the
+@code{ce} request.
+The @code{.rj} number register is
+the number of lines to be right-justified as set by the @code{rj}
+request.
+
+
+
+@node Manipulating Hyphenation, Manipulating Spacing, Manipulating Filling and Adjusting, Programming Tutorial
+@section Manipulating Hyphenation
+@cindex manipulating hyphenation
+@cindex hyphenation, manipulating
+
+
+As discussed in @ref{Hyphenation}, groff will hyphenate words.
+There are a number of ways to modify the how hyphenation is done.
+
+@findex nh
+@findex hy
+@vindex .hy
+This hyphenation can be turned off with the @code{nh} request, and
+turned back on with the @code{hy} request. However, troff's
+hyphenation facilities are far more flexible than this. The @code{hy}
+request can be used to tell troff to restrict hypenation to certain
+cases. The request takes a single numeric argument.
+The current hyphenation restrictions can be found in the number
+register @code{.hy}
+
+@table @samp
+@item 1
+The default argument, which
+indicates to hyphenate without restrictions.
+@item 2
+Do not hyphenate the last word on a page or column.
+@item 4
+Do not hyphenate the last two characters of a word.
+@item 8
+Do not hyphenate the first two characters of a word.
+@end table
+
+@findex hlm
+@vindex .hlc
+@vindex .hlm
+The @code{hlm} request will
+set the maximum number of consecutive hyphenated lines to the value
+given as the first argument.
+If this number is
+negative, there is no maximum. The default value is -1.
+This value is
+associated with the current environment. Only lines output from an
+environment count towards the maximum associated with that environment.
+Hyphens resulting from @code{\%} are counted; explicit hyphens are not.
+The current setting of this is available in the @code{.hlm} request.
+Also the number of immediately preceding consecutive hyphenated lines
+are available in the number register @code{.hlc}.
+
+@findex hw
+The @code{hw} request allows you to specify how a specific word is
+to be hyphenated. It takes only one argument which is the word with
+hyphens at the hyphenation points. For example:
+@samp{.hw in-sa-lub-rious}.
+@c In old versions of troff there was a
+@c limited amount of space to store such information, fortunately,
+@c with groff, this is no longer a restriction.
+
+@findex \%
+@cindex hyphenation character
+@cindex character, hyphenation
+You can also tell troff how to hyphenate words on the fly with the
+use of the @code{\%} escape, also known as the @dfn{hyphenation
+character}. Preceding a word with this character will prevent it
+from being hyphenated, putting it in a word will indicate to troff
+that the word may be hyphenated at that point. Note that this
+mechanism will only affect one word, if you want to change the
+hyphenation of a word for the entire document, use the @code{hw}
+request.
+
+@findex hc
+The @code{hc} request allows you to change the hyphenation character.
+The character specified as an argument will then work the same as the
+@code{\%} escape, and, thus, no longer appear in the output. Without
+an argument it will return the hyphenation character to @code{\%}.
+
+@findex hpf
+To further customize hyphenation the @code{hpf} request will read in
+a file of hyphenation patterns.
+This file will be searched for in the
+same way that @file{tmac.@var{name}} is searched for when the
+@samp{-m@var{name}} option is specified.
+
+It should have the same format as the argument to the
+\patterns primitive in @TeX{}; the letters appearing in this file are
+interpreted as hyphenation codes.
+A @samp{%} character in the patterns file
+introduces a comment that continues to the end of the line.
+
+@findex hla
+@findex hpf
+@pindex troffrc
+The set of
+hyphenation patterns is associated with the current language set by the
+@code{hla} request. The @code{hpf} request is usually invoked by the
+@file{troffrc} file.
+
+@findex hcode
+@code{.hcode @var{c1 code1 c2 code2...}}
+Set the hyphenation code of character @var{c1} to code1 and that of
+@var{c2} to @var{code2}.
+A hyphenation code must be a single input character (not a
+special character) other than a digit or a space. Initially each
+lower-case letter has a hyphenation code, which is itself, and each
+upper-case letter has a hyphenation code which is the lower case
+version of itself.
+
+@findex hym
+@vindex .hym
+The @code{hym} request will set the hyphenation margin to the value
+given as the first argument: when the current adjustment mode is not
+@samp{b}, the line will not be hyphenated if the line is no more than
+that amount short.
+The default hyphenation margin is 0. The default scaling
+indicator for this request is m. The hyphenation margin is associated
+with the current environment. The current hyphenation margin is
+available in the @code{.hym} register.
+
+@findex hys
+@vindex .hys
+The @code{hys} request set the hyphenation space to the value given as
+the first argument: when the current adjustment mode is b, don't
+hyphenate the line if the line can be justified by adding no more than
+that amount of extra space to each word space. The default
+hyphenation space is 0. The default scaling indicator for this
+request is m. The hyphenation space is associated with the current
+environment. The current hyphenation space is available in the
+@code{.hys} register.
+
+@findex shc
+The @code{shc} request will set the soft hyphen character to the
+argument given as an argument. If the argument is omitted, the soft
+hyphen character will be set to the default @code{\(hy}. The soft
+hyphen character is the character which will be inserted when a word
+is hyphenated at a line break. If the soft hyphen character does not
+exist in the font of the character immediately preceding a potential
+break point, then the line will not be broken at that point. Neither
+definitions (specified with the @code{char} request) nor translations
+(specified with the @code{tr} request) are considered when finding the soft
+hyphen character.
+
+@findex hla
+@vindex .hla
+@pindex troffrc
+The @code{hla} request will set the current hyphenation language to
+that given by the first argument. Hyphenation exceptions specified
+with the @code{hw} request and hyphenation patterns specified with the
+@code{hpf} request are both associated with the current hyphenation
+language. The @code{hla} request is usually invoked by the
+@file{troffrc} file. The current hyphenation language is available
+in the number register @code{.hla}.
+
+
+
+@node Manipulating Spacing, Tabs and Fields, Manipulating Hyphenation, Programming Tutorial
+@section Manipulating Spacing
+@cindex manipulating spacing
+@cindex spacing, manipulating
+
+
+@findex sp
+The @code{sp} request will cause troff to space downwards the
+distance specified as the first argument. With no argument it will
+advance 1 line.
+A negative argument will cause troff to move up the page the
+specified distance.
+If the argument is preceded by a @samp{|} troff will move that
+distance from the top of the page.
+
+@findex ls
+@vindex .L
+Often you may want your output to be double or triple spaced.
+The @code{ls} request will cause troff to output @var{n}-1 blank
+lines after each line of text, where @var{n} is the argument given to
+the @code{ls} request. With no argument troff will go back to single
+spacing. The number register @code{.L} contains the current line
+spacing setting.
+
+@findex \x
+@vindex .a
+Sometimes, extra vertical spacing is only needed occasionaly,
+i.e. to allow space for a tall construct (like an equation).
+The @code{\x} escape will do this.
+The escape is given a numerical argument (like @samp{\x'3p'}).
+If this number is positive extra vertical space will be inserted
+below the current line. A negative number will add space above.
+If this escape is used multiple times on the same line, the maximum
+values are used.
+The @code{.a} number register contains the most recent
+extra vertical @strong{emph} line space.
+
+@example
+... example of inline equation ...
+@end example
+
+@findex ns
+@findex rs
+@cindex no-space mode
+@cindex mode, no-space
+Spacing (via either @code{sp} or via blank lines) can be disabled
+with the @code{ns} request. This will enable @dfn{no-space mode}.
+This mode will end when actual text is output or the @code{rs}
+request is encountered. No-space mode will also prevent requests to
+advance to the next page unless they are accompanied by a page number
+(@pxref{Page Control}, for more information.)
+
+
+@node Tabs and Fields, Character Translations, Manipulating Spacing, Programming Tutorial
+@section Tabs and Fields
+@cindex tabs and fields
+@cindex fields and tabs
+
+
+@findex \t
+Tab stops are much like those on a typewriter: a tab character (or the
+@code{\t} escape) on input will cause horizontal motion to the next
+tab stop.
+
+@findex ta
+Tab stops can be changed with the @code{ta} request.
+This request takes a series of numbers as arguments which indicate
+where each tab stop is to be (overriding any previous settings).
+These can be specified absolutely,
+i.e. as the distance from the left margin.
+For example, the following wil set tab stops every one inch.
+
+@example
+.ta 1i 2i 3i 4i 5i 6i
+@end example
+
+Tab stops can also be specified relatively (using a leading @samp{+})
+which means that the specified tab stop will be set that distance
+from the previous tab stop. For example the following is equivalent
+to the previous example.
+
+@example
+.ta 1i +1i +1i +1i +1i +1i
+@end example
+
+After the specified tab stops repeat values may be set for tabs beyond
+the last one specified. This is most commonly used to specify tabs
+set at equal intervals. The compleat syntax for setting tabs is
+@code{ta @var{n1} @var{n2} @dots{} @var{nn} T @var{r1} @var{r2}
+@dots{} @var{rn}} This will set tabs at positions @var{n1}, @var{n2},
+@dots{}, @var{nn} and then set tabs at @var{nn}+@var{r1},
+@var{nn}+@var{r2}, @dots{}, @var{nn}+@var{rn} and then at
+@var{nn}+@var{rn}+@var{r1}, @var{nn}+@var{rn}+@var{r2}, @dots{},
+@var{nn}+@var{rn}+@var{rn}, and so on. For example the following is,
+yet again, the same as the previous examples.
+
+@example
+.ta T 1i
+@end example
+
+The material in each tab column may be justified to the right or left
+or centered in the column. This is specified by appending an
+@samp{R}, @samp{L} or @samp{C} to the number specifying that tab stop.
+The default justification is @samp{L}.
+
+@example
+.ta 1i 2iC 2iR
+@end example
+
+@vindex .tabs
+The number register @code{.tabs} contains
+a string representation of the current tab settings suitable for use as
+an argument to the @code{ta} request.
+
+@findex tc
+Normally troff will fill the space to the next tab stop with spaces.
+In some cases you may wish to change this. The @code{tc} request
+will do this. With no argument troff will revert to using spaces.
+
+@subsection Leaders
+@cindex leaders
+
+@findex lc
+Sometimes you may wish to use the @code{tc} request to fill a tab
+stop with a given character, but also, you want to use normal tab
+stops on the rest of the line. For this groff provides an alternate
+tab mechanism, called @dfn{leaders} which will do just that.
+They are used exclusively to produce a repeated run of characters to
+the next tab stop.
+
+You can declare what character will be repeated with the @code{lc}
+request. If you do not give it an argument, the leaders will act the
+same as tabs.
+
+@findex \a
+The difference is that a leader is invoked by using the @code{\a}
+escape.
+
+@cindex table of contents
+@cindex contents, table of
+So for a table of contents you may want to have tab stops defined so
+that the section number is one tab stop, the title is the second with
+the remaining space being filled with a line of dots and then the
+page number slightly separated from the dots.
+
+@example
+.lc .
+.ta .5iR 5i +.25i
+1.1\tFoo\a\t12
+@end example
+
+@subsection Fields
+@cindex fields
+
+@findex fc
+Fields are a more general way of laying out tabular data.
+@code{fc}
+
+@node Character Translations, Line Layout, Tabs and Fields, Programming Tutorial
+@section Character Translations
+@cindex character translations
+@cindex translations of characters
+
+
+@findex cc
+@findex c2
+The control character (@samp{.}) and the no-break control character
+(@samp{'}) can be changed with the @code{cc} and @code{c2} requests,
+respectively.
+The single argument is the new character to be used, with no argument
+the normal control character is restored.
+
+@findex ec
+@findex eo
+The @code{eo} request will compleatly disable the escape mechanism.
+The @code{ec} request can be used to change the escape character from
+the default @samp{\} to what is specified as an argument.
+
+@findex tr
+The @code{tr} request will translate characters.
+
+@findex trnt
+@findex \!
+@code{trnt}
+This is the same as the @code{tr} request except that the
+translations do not
+apply to text that is transparently throughput into a diversion with
+@code{\!}. @xref{Diversions}, for more information.
+For example,
+
+@example
+.tr ab
+.di x
+\!.tm a
+.di
+.x
+@end example
+
+will print @samp{b}; if @code{trnt} is used instead of @code{tr} it
+will print @samp{a}.
+
+
+@node Line Layout, Page Layout, Character Translations, Programming Tutorial
+@section Line Layout
+@cindex line layout
+@cindex layout, line
+
+
+@cindex dimensions, line
+@cindex line dimensions
+The following drawing shows the dimensions which troff uses for
+placing a line of output onto the page. They are labeled with the
+request which manipulates that dimension.
+
+@example
+@group
+ | -->| in |<-- |
+ -->| po |<-----------ll------------>|
+ +----+----+----------------------+----+
+ | : : : |
+ +----+----+----------------------+----+
+@end group
+@end example
+
+These dimensions are:
+
+@ftable @code
+@item po
+@vindex .o
+@dfn{Page offset}--This is the leftmost postition of text on the final
+output. This can be adjusted with the @code{po} request, and the
+current setting can be found in the builtin number register @code{.o}
+Note, that this request does not cause a break, so changing the page
+offset in the middle of text being filled may not do what you expect.
+@item in
+@vindex .i
+@dfn{Indentation}--This is the distance from the left margin where text
+will be printed. This can be adjusted with the @code{in} request, and
+the current setting can be found in the builtin number register.
+@code{.i}
+This request causes a break.
+
+@findex ti
+@findex .in
+There is also the request @code{ti} which will cause one output line
+to be indented, after which the indentation returns to 0.
+This request causes a break.
+The number register @code{.in} is the indent that applies to the
+current output line.
+@item ll
+@findex .l
+@findex .ll
+@dfn{Line length}--This is the distance from the left margin to right
+margin. This can be adjusted with the @code{.ll} request, and the
+current setting can be found in the builtin number register @code{.l}
+Note, as the figure implies, line length is not affected by the current
+indentation.
+The number register @code{.ll} is
+the line length that applies to the current output line.
+@end ftable
+
+@example
+.in +.5i
+.ll -.5i
+A bunch of really boring text which should
+be indented from both margins.
+replace me with a better (and more) example!
+.in -.5i
+.ll +.5i
+@end example
+
+
+@node Page Layout, Page Control, Line Layout, Programming Tutorial
+@section Page Layout
+@cindex page layout
+@cindex layout, page
+
+
+Troff provides some very primitive operations for controlling page
+layout.
+
+@findex pl
+@vindex .p
+Troff lets you specify the @dfn{page length} via the @code{pl} request.
+This is the length of the physical output page.
+The current setting can
+be found in the builtin number register @code{.p}. Note that this only
+specifies the size of the page, not the not the top and bottom margins.
+Those are not done by groff directly, @xref{Traps}, for further
+information on how to do this.
+
+@cindex headers
+@cindex footers
+@cindex titles
+Troff provides several operations which help in setting up top and
+bottom titles (or headers and footers)
+
+@findex tl
+The @code{tl} request will print a @dfn{title line}, which consists
+of three parts: a left justified portion, a centered portion and a
+right justified portion. The argument to @code{tl} is specified as
+@code{'@var{left}'@var{center}'@var{right}'}
+The @samp{%} character is replaced with the current page number.
+
+@findex lt
+@vindex .lt
+The title line is printed using its own line length, which is
+specified with the @code{lt} request. The current setting of this is
+available in the @code{.lt} number register.
+
+@findex pn
+The @code{pn} request will change the page number of the @emph{next}
+page. The only argument is the page number.
+
+@vindex %
+@vindex .pn
+The current page number is stored in the number register @code{%}.
+The number register @code{.pn} contains the
+number of the next page:
+either the value set by a @code{pn} request, or
+the number of the current page plus 1.
+
+@findex pc
+The @code{pc} request will change the page number character (used by
+the @code{tl} request) to a different character. With no argument,
+this mechanism is disabled.
+
+
+@c distribute these through the text
+@xref{Traps}
+
+@node Page Control, Fonts, Page Layout, Programming Tutorial
+@section Page Control
+@cindex page control
+@cindex control, page
+
+
+@findex bp
+To stop processing the current page, and move to the next page, you
+can invoke the @code{bp} request. This request will also cause a
+break. This request can also take an argument of what the next page
+should be numbered.
+The only difference
+between @code{bp} and @code{pn} is that @code{pn} does not cause a
+break or actually eject a page.
+
+@example
+.de newpage
+'bp
+'sp .5i
+.tl 'left top'center top'right top'
+'sp .3i
+..
+@end example
+
+@cindex orphan
+@findex ne
+Often you may want to make sure that you have a certain amount of
+space before a new page occurs. This is most useful to make sure
+that there is not a single @dfn{orphan} line left at the bottom of a
+page. The @code{ne} request will ensure that there is a certain
+distance, specified by the first argument, before the next page is
+triggered (@pxref{Traps}, for further information).
+The default unit for @code{ne} is v's and the default argument
+is 1v.
+
+For example, to make sure that no fewer than 2 lines get orphaned,
+you can do the following before each paragraph.
+
+@example
+.ne 2
+.ti +5n
+text
+@end example
+
+@findex sv
+@findex os
+The @code{sv} is similar to the @code{ne} request, it reserves the
+specified amount of vertical space. If the desired amount of space
+exists before the next trap (bottom page boundary), the space will be
+output immediately. If there is not enough space, it is stored for
+later output via the @code{os} request.
+The default argument is 1v and the default units are v's.
+
+
+@node Fonts, Sizes, Page Control, Programming Tutorial
+@section Fonts
+@cindex fonts
+
+
+@findex ft
+@findex \f
+Groff gives you the ability to switch fonts at any point in your
+text. There are two ways to do this, via the @code{ft} request and
+the @code{\f} escape.
+
+Fonts are generaly specified as uppercase strings, which are usually
+1 to 4 characters representing an abreviation of acronym of the font
+name.
+
+The basic set of fonts are R, I, B, and BI. These are Times Roman,
+Italic, Bold, and Bold Italic. There is also at least one symbol
+font which contains various special symbols (greek, mathematics).
+These latter fonts cannot be used directly, but should be used via an
+escape.
+
+
+@menu
+* Changing Fonts::
+* Font Families::
+* Font Positions::
+* Using Symbols::
+* Artificial Fonts::
+* Ligatures and Kerning::
+@end menu
+
+@node Changing Fonts, Font Families, Fonts, Fonts
+@subsection Changing Fonts
+@cindex changing fonts
+@cindex fonts, changing
+
+
+@findex ft
+You can change fonts with both the @code{ft} request.
+With no arguments it
+will switch to the previous font (also known as P).
+
+@example
+eggs, bacon,
+.ft B
+spam
+.ft
+and sausage.
+@end example
+
+@findex \f
+The @code{\f} escape is useful for changing fonts in the middle of words
+
+@example
+eggs, bacon, \fBspam\fP and sausage.
+@end example
+
+Both of the above examples will produce the same output.
+
+Sometimes when putting letters of different fonts, you need more or
+less space at such boundaries. There are two escapes to help with
+this.
+
+@findex \/
+The @code{\/} escape
+increases the width of the preceding character so that the spacing
+between that character and the following character will be correct if
+the following character is a roman character. For example, if an italic
+f is immediately followed by a roman right parenthesis, then in many
+fonts the top right portion of the f will overlap the top left of the
+right parenthesis.
+It is a good idea to use this escape sequence
+whenever an italic character is immediately followed by a roman
+character without any intervening space.
+
+@c producing @i{f}), which is ugly. Inserting \/ produces f) and avoids this problem.
+
+@findex \,
+The @code{\,} escape
+modifies the spacing of the following character so that the spacing
+between that character and the preceding character will correct if the
+preceding character is a roman character.
+It is a good idea
+to use this escape sequence whenever a roman character is immediately
+followed by an italic character without any intervening space.
+
+@c For example, inserting \, between the parenthesis and the f changes (f to (f.
+
+@findex ftr
+The @code{ftr} request will translate fonts, it is called as
+@samp{.ftr @var{F G}}, which
+Translate font @var{F} to @var{G}.
+Whenever a font named @var{F} is referred to in @code{\f}
+escape sequence,
+or in the @code{ft}, @var{ul}, @var{bd}, @var{cs}, @var{tkf},
+@var{special}, @var{fspecial}, @var{fp},
+or @var{sty} requests, font @var{G} will be used. If @var{G} is
+missing, or equal to @var{F} then font @var{F} will not be translated.
+
+
+@node Font Families, Font Positions, Changing Fonts, Fonts
+@subsection Font Families
+@cindex font families
+@cindex families, font
+
+
+Due to the variety of fonts available, groff has added the concept of
+font families. Each of these families has four styles (R, I, B and BI),
+
+The fonts are specified as the concatenation of the font family and
+style. Specifying a font without the family part will cause groff to
+use that style of the current family.
+By default, groff uses the Times family.
+
+This way, you can just use the basic four fonts and select a
+different font family on the command line.
+
+@findex fam
+@vindex .fam
+You can also switch font families with the @code{fam} request
+The current font family is available in the number register
+@code{.fam}.
+This is a string-valued register.
+
+@example
+spam,
+.fam H
+spam,
+.ft B
+spam,
+.fam T
+spam,
+.ft AR
+baked beans,
+.ft R
+and spam.
+@end example
+
+
+
+@node Font Positions, Using Symbols, Font Families, Fonts
+@subsection Font Positions
+@cindex font positions
+@cindex positions, font
+
+
+For the sake of old phototypesetters and compatability with old
+versions of troff, groff has the concept of font
+@dfn{positions}, on which various fonts are mounted.
+The last one or two are reserved for the symbol font(s).
+
+@findex fp
+New fonts can be mounted with the @code{fp} request.
+These numeric positions can then be referred to with font changing commands.
+When groff starts it is using font number one.
+
+@example
+.fp 1 H
+.fp 2 HI
+.fp 3 HB
+wink, wink,
+.ft 2
+nudge, nudge,
+.ft
+.ft 3
+say no more!
+.ft
+@end example
+
+(note that after these font changes have taken place the original
+font is restored.)
+
+@vindex .f
+The current font in use, as a font position.
+This can be useful to remember the current font, for later recall.
+
+@example
+.nr save-font \n(.f
+... lots 'o text ...
+.ft \n[save-font]
+@end example
+
+@vindex .fp
+The number of the next free font position is available in the number
+register @code{.fp}. This is useful when mounting a new font, like so:
+
+@example
+.fp \n[.fp] NEATOFONT
+@end example
+
+@pindex DESC
+Fonts not listed in the @file{DESC} file are automatically mounted on
+the next available font position when they are referenced.
+If a font is to be
+mountfed explicitly with the @code{fp} request on an unused font position, it
+should be mounted on the first unused font position, which can be found
+in the @code{.fp} register; although troff does not enforce this strictly,
+it will not allow a font to be mounted at a position whose number is
+much greater than that of any currently used position.
+
+The @code{fp} request has an optional third argument.
+This argument gives the
+external name of the font, which is used for finding the font
+description file. The second argument gives the internal name of the
+font which is used to refer to the font in troff after it has been
+mounted. If there is no third argument then the internal name will be
+used as the external name. This feature allows you to use fonts with
+long names in compatibility mode.
+
+
+
+@node Using Symbols, Artificial Fonts, Font Positions, Fonts
+@subsection Using Symbols
+@cindex using symbols
+@cindex symbols, using
+
+
+@findex \(
+@findex \[
+Symbols can be inserted by using a special escape sequence.
+This escape is simply the escape character (a backslash) followed by
+an identifier. The symbol identifiers have to be two or more
+characters, since single characters conflict with all the other
+escapes. The identifier can be either preceded by a parenthesis if
+it is two character, or surrounded by square brackets.
+So, the symbol for pi can be produced either by @code{\(*p} or
+@code{\[*p]}.
+
+@example
+area = \(*p\fIr\fP\u2\d
+@end example
+
+@findex \C
+The escape @code{\C'@var{xxx}'} will typeset character named
+@var{xxx}. Normally it is more convenient to use @code{\[@var{xxx}]}.
+But @code{\C} has the advantage that it is compatible with recent
+versions of ditroff and is available in compatibility mode.
+
+@findex \N
+The escape @code{\N'@var{n}'} will typeset the character with code
+@var{n} in the current font. @var{n} can be any integer. Most devices only
+have characters with codes between 0 and 255. If the current font
+does not contain a character with that code, special fonts will not be
+searched. The @code{\N} escape sequence can be conveniently used on
+conjunction with the @code{char} request:
+
+@example
+.char \[phone] \f(ZD\N'37'
+@end example
+
+The code of each character is given in the fourth column in the font
+description file after the charset command. It is possible to include
+unnamed characters in the font description file by using a name of
+@samp{---}; the @code{\N} escape sequence is the only way to use these.
+
+@findex cflags
+Each character has certain properties associated with it.
+These properties can be modified with the @code{cflags} request.
+The first argument is the the sum of the desired flags and the
+remaining arguments are the characters to have those properties.
+@table @code
+@item 1
+the character ends sentences (initially characters @samp{.?!} have this
+property);
+@item 2
+lines can be broken before the character (initially no characters have
+this property);
+@item 4
+lines can be broken after the character (initially characters
+@samp{-\(hy\(em} have this property);
+@item 8
+the character overlaps horizontally (initially characters
+@samp{\(ul\(rn\(ru} have this property);
+@item 16
+the character overlaps vertically (initially character @samp{\(br} has
+this property);
+@item 32
+an end of sentence character followed by any number of characters with
+this property will be treated as the end of a sentence if followed by a
+newline or two spaces; in other words the character is transparent for
+the purposes of end of sentence recognition; this is the same as having
+a zero space factor in @TeX{} (initially characters
+@samp{"')]*\(dg\(rq} have this property).
+@end table
+
+@findex char
+You can create new characters with the @code{char} request. It is
+called as @samp{.char @var{c} @var{string}} Define character @var{c}
+to be @var{string}. Every time character @var{c} needs to be printed,
+@var{string} will be processed in a temporary environment and the
+result will be wrapped up into a single object. Compatibility mode
+will be turned off and the escape character will be set to \ while
+@var{string} is being processed. Any emboldening, constant spacing or
+track kerning will be applied to this object rather than to individual
+characters in @var{string}. A character defined by this request can
+be used just like a normal character provided by the output device.
+In particular other characters can be translated to it with the
+@code{tr} request; it can be made the leader character by the
+@code{lc} request; repeated patterns can be drawn with the character
+using the @code{\l} and @code{\L} escape sequences; words containing
+the character can be hyphenated correctly, if the @code{hcode} request
+is used to give the character a hyphenation code. There is a special
+anti-recursion feature: use of character within the character's
+definition will be handled like normal characters not defined with
+@code{char}.
+
+@findex rchar
+A character definition can be removed with the @code{rchar} request. Its
+arguments are the characters to be removed. This undoes the effect of
+a @code{char} request.
+
+@c distribute these through the text
+@xref{Special Characters}
+
+@node Artificial Fonts, Ligatures and Kerning, Using Symbols, Fonts
+@subsection Artificial Fonts
+@cindex artificial fonts
+@cindex fonts, artificial
+
+
+There are a number of requests for artificially creating fonts.
+These are largely vestigal remains from the days when output devices
+did not have a wide variety of fonts, and when nroff and troff were
+separate programs.
+These are no longer necessary in GNU Troff.
+
+@findex ul
+The @code{ul} request will print subsequent lines in italics on a
+device capable of it, or underline the text on an ascii output device.
+The single argument is the number of lines to be ``underlined,''
+with no argument, the next line will be underlined.
+
+@findex cu
+The @code{cu} request is similar to @code{ul} ...
+
+@findex uf
+The @code{uf} request will set the underline font used by @code{ul}
+and @code{cu}.
+
+@findex bd
+The @code{bd} request artificially creates a bold font by printing
+each character twice, slightly offset.
+The first argument specifies the font to embolden, and the second is
+the number of basic units, minus one, by which the two characters
+will be offset. If the second argument is missing, emboldening will
+be turned off.
+
+
+@node Ligatures and Kerning, , Artificial Fonts, Fonts
+@subsection Ligatures and Kerning
+@cindex ligatures and kerning
+@cindex kerning and ligatures
+
+
+@findex lg
+@vindex .lg
+@code{lg}
+@code{.lg}
+The current ligature mode.
+
+What is kerning??
+
+If the font description file contains pairwise kerning information,
+characters from that font will be kerned. Kerning between two
+characters can be inhibited by placing a @code{\&} between them.
+
+@findex kern
+@vindex .kern
+@code{kern}
+If n is non-zero or missing, enable pairwise kerning, otherwise disable
+it.
+@code{.kern}
+1 if pairwise kerning is enabled, 0 otherwise.
+
+@findex tkf
+.tkf f s1 n1 s2 n2
+Enable track kerning for font f. When the current font is f the width
+of every character will be increased by an amount between n1 and n2;
+when the current point size is less than or equal to s1 the width will
+be increased by n1; when it is greater than or equal to s2 the width
+will be increased by n2; when the point size is greater than or equal to
+s1 and less than or equal to s2 the increase in width is a linear
+function of the point size.
+
+
+@node Sizes, Strings, Fonts, Programming Tutorial
+@section Sizes
+@cindex sizes
+
+
+@cindex baseline
+Groff uses two dimensions with each line of text, type size and
+vertical spacing. The type size is the height from the text
+@dfn{baseline} to the top of the tallest character (decenders may drop
+below this baseline). Vertical spacing is the amount of space groff
+allows for a line of text, normally, this is about 20% larger than the
+current type size. Ratios smaller than this can result in
+hard-to-read text, larger that this, it will spread your text out more
+vertically (useful for term papers). By default, troff uses 10 point
+type on 12 point spacing.
+
+@cindex leading
+The difference between type size and vertical spacing is known, by
+typesetters, as @dfn{leading}.
+
+
+@menu
+* Changing Type Sizes::
+* Fractional Type Sizes::
+@end menu
+
+@node Changing Type Sizes, Fractional Type Sizes, Sizes, Sizes
+@subsection Changing Type Sizes
+@cindex changing type sizes
+@cindex type sizes, changing
+
+
+@findex ps
+@findex vs
+@findex \s
+@vindex .s
+@vindex .v
+Using the @code{ps} request and the @code{\s} escape you can change
+the type size. The @code{vs} request will change the vertical
+spacing. The default unit for the @code{ps} and @code{vs} requests are
+points.
+The number registers @code{.s} and @code{.v} contain the current
+type size and vertical spacing.
+
+These requests take parameters in units of points. You can specify
+sizes as an absolute size, or as a relative change from the current
+size. The size 0 means go back to the previous size. With no
+argument it will revert to the previous size.
+
+@example
+snap, snap,
+.ps +2
+grin, grin,
+.ps +2
+wink, wink, \s+2nudge, nudge,\s+8 say no more!
+.ps 10
+@end example
+
+The @code{\s} escape may be called in a variety of ways.
+Much like other escapes there must be a way to determine where the
+argument ends and the text begins.
+Any of the following forms are valid:
+@code{\s@var{n}},
+@code{\s+@var{n}},
+@code{\s-@var{n}},
+@code{\s(@var{nn}},
+@code{\s+(@var{nn}},
+@code{\s-(@var{nn}},
+@code{\s[+@var{nnn}]},
+@code{\s[-@var{nnn}]},
+@code{\s+[@var{nnn}]},
+@code{\s-[@var{nnn}]}.
+
+Some devices may only have certain permissible sizes, in which case
+groff will round to the nearest permissible size.
+
+@example
+... .sz macro example?? ...
+@end example
+
+@node Fractional Type Sizes, , Changing Type Sizes, Sizes
+@subsection Fractional Type Sizes
+@cindex fractional type sizes
+@cindex type sizes, fractional
+
+
+A @dfn{scaled point} is equal to 1/@var{sizescale} points, where
+@var{sizescale} is specified in the @file{DESC} file (1 by default.)
+There is a new scale indicator @samp{z} which has the effect of
+multiplying by @var{sizescale}. Requests and escape sequences in
+troff interpret arguments that represent a pointsize as being in units
+of scaled points, but they evaluate each such argument using a default
+scale indicator of @samp{z}. Arguments treated in this way are the
+argument to the @code{ps} request, the third argument to the @code{cs}
+request, the second and fourth arguments to the @code{tkf} request,
+the argument to the @code{\H} escape sequence, and those variants of
+the @code{\s} escape sequence that take a numeric expression as their
+argument.
+
+For example, suppose @var{sizescale} is 1000; then a scaled point will be
+equivalent to a millipoint; the request @samp{.ps 10.25} is equivalent to
+@samp{.ps 10.25z} and so sets the pointsize to 10250 scaled points, which is
+equal to 10.25 points.
+
+The number register @code{\n(.s} returns the pointsize in points as
+decimal fraction. There is also a new number register @code{\n[.ps]}
+that returns the pointsize in scaled points.
+
+It would make no sense to use the @samp{z} scale indicator in a
+numeric expression whose default scale indicator was neither @samp{u}
+nor @samp{z}, and so troff disallows this. Similarily it would make
+no sense to use a scaling indicator other than @samp{z} or @samp{u} in a
+numeric expression whose default scale indicator was @samp{z}, and so
+troff disallows this as well.
+
+There is also new scale indicator @samp{s} which multiplies by the
+number of units in a scaled point. So, for example, @samp{\n[.ps]s}
+is equal to 1m. Be sure not to confuse the @samp{s} and @samp{z}
+scale indicators.
+
+@code{\s'+@var{n}'}
+@code{\s'-@var{n}'}
+@code{\s+'@var{n}'}
+@code{\s-'@var{n}'}
+Set the point size to @var{n} scaled points; @var{n} is a numeric
+expression with a default scale indicator of @samp{z}.
+
+@code{\n[.ps]}
+The current pointsize in scaled points.
+
+@code{\n[.psr]}
+The last-requested pointsize in scaled points.
+
+@code{\n[.sr]}
+The last requested pointsize in points as a decimal fraction. This is a
+string-valued register.
+
+
+@c distribute these through the text
+@xref{Font Files}
+
+@node Strings, Conditionals and Loops, Sizes, Programming Tutorial
+@section Strings
+@cindex strings
+
+
+@findex ds
+Groff has string variables, which are entirely for user convenience
+(i.e. there are no builtin strings) They are defined via the
+@code{ds} request.
+
+@example
+.ds UX \s-1UNIX\s0\u\s-3tm\s0\d
+@end example
+
+@findex \*
+The are interpolated, or expanded in-place, via the @code{\*} escape:
+
+@example
+The \*(UX Operating System
+@end example
+
+Will produce:
+
+@example
+The UNIXtm Operating System
+@end example
+
+If the string named by the @code{\*} does not exist, the escape will
+be replaced by nothing.
+
+@cindex comments, with @code{ds}
+NOTE: Unlike other requests the third argument takes up the entire
+line including trailing spaces. This means that comments on a line
+with such a request can introduce unwanted space into a string.
+
+@example
+.ds UX \s-1UNIX\s0\u\s-3tm\s0\d \" trademark of you-know-who
+@end example
+
+Instead you should either put the comment on another line or
+have the comment escape adjacent with the end of the string.
+
+@example
+.ds UX \s-1UNIX\s0\u\s-3tm\s0\d\" trademark of you-know-who
+@end example
+
+If you need leading space you can start the string with a double
+quote. No trailing quote is needed, in fact any trailing quote is
+included in your string.
+
+@cindex canibalism
+@example
+.ds sign " Yours in a white wine sauce,
+@end example
+
+@findex as
+@cindex appending to strings
+@cindex strings, appending
+You can also append onto a string with the @code{as} request.
+It works the same as the @code{ds} request except that it appends the
+second argument onto the string named by the first argument.
+
+@example
+.as sign " with shallots, onions and garlic,
+@end example
+
+@findex \@key{ret}
+Strings are not limited to a sigle line of text. A string can span
+several lines by escaping the newlines with a backslash. The
+resulting string will be stored @emph{without} the newlines.
+
+@example
+.ds foo lots and lots \
+of text are on these \
+next several lines
+@end example
+
+@findex rn
+@code{rn}
+
+@findex rm
+@code{rm}
+
+@findex als
+@code{als}
+
+@findex chop
+@code{chop}
+
+@c distribute these through the text
+@xref{Identifiers}
+@c distribute these through the text
+@xref{Comments}
+
+@node Conditionals and Loops, Writing Macros, Strings, Programming Tutorial
+@section Conditionals and Loops
+@cindex conditionals and loops
+@cindex loops and conditionals
+
+
+@findex if
+@findex while
+In @code{if} and @code{while} requests, there are several more operators
+available:
+
+@table @code
+@item e
+@itemx o
+True if the current page is even or odd numbered (respectively)
+@item n
+@itemx t
+True if the document is being processed by
+nroff (or an ascii device) or troff.
+@item '@var{xxx}'@var{yyy}'
+True if the string @var{xxx} is equal to the string @var{yyy}.
+Other characters can be used in place of the single quotes.
+(Which?)
+The strings are `formatted' before being compared. (?)
+@item r@var{xxx}
+True if there is a number register named @var{xxx}.
+@item d@var{xxx}
+True if there is a string, macro, diversion, or request named @var{xxx}.
+@item c@var{ch}
+True if there is a character @var{ch} available; @var{ch} is
+either an ASCII character or a special character @code{\(@var{ch}} or
+@code{\[@var{ch}]}; the condition will also be true if @var{ch} has been
+defined by the @code{char} request.
+@end table
+
+
+@menu
+* if-else::
+* while::
+@end menu
+
+@node if-else, while, Conditionals and Loops, Conditionals and Loops
+@subsection if-else
+@cindex if-else
+
+
+Troff has if-then-else constructs like other languages, although
+the formatting can be painful.
+
+@findex if
+The @code{if} request is troff's if statement, it is called as
+@samp{.if @var{expr} @var{anything}}, where @var{expr} is the
+expression to be evaluated,
+and @var{anything} (the remainder of the line)
+which will be executed if
+the @var{expr} evaluates to non-zero (true).
+@var{anything} will be interpreted as though it was on a line by
+itself.
+@xref{Expressions}, for more info.
+
+Here are some examples:
+
+@example
+.if t .ls 2 \" double spacing in troff
+.if 0 .ab how'd this happen??
+@end example
+
+@findex ie
+@findex el
+An if-then-else is written using two requests @code{ie} and @code{el}
+the first request is the if part and the latter is the else part.
+
+@example
+.ie
+.el
+@end example
+
+@findex \@{
+@findex \@}
+In many cases you will want more than one request to be executed as a
+result of any of these requests, this can be done using the \@{ and
+\@} escapes.
+The following example shows the possible ways to use these escapes.
+
+@example
+.ie t \@{\
+. ds lq ``
+. ds rq ''
+.\@}
+.el \
+.\@{\
+. ds lq "
+. ds rq "\@}
+.ds qq "
+@end example
+
+
+@c distribute these through the text
+@xref{Expressions}
+
+@node while, , if-else, Conditionals and Loops
+@subsection while
+@cindex while
+
+
+@findex while
+Groff provides a looping construct using the @code{while} request,
+which is used much like the @code{if} (and related) requests.
+The first argument is an expression which will be evaluated.
+The @code{while} request will interpret the remainder of the line
+until the expression evaluates to 0 or false.
+
+@example
+.nr a 0 1
+.while (\na<9) \&\n+a,
+\&\n+a
+@end example
+
+The preceding example produces:
+
+@example
+1, 2, 3, 4, 5, 6, 7, 8, 9, 10
+@end example
+
+@findex break
+@findex continue
+The @code{break} request will
+@dfn{break} out of a while loop.
+Be sure not to confuse this with the @code{.br} request.
+The @code{continue} request will
+finish the current iteration of a while loop.
+
+@c distribute these through the text
+@xref{Expressions}
+
+@node Writing Macros, Page Motions, Conditionals and Loops, Programming Tutorial
+@section Writing Macros
+@cindex writing macros
+@cindex macros, writing
+
+
+@findex de
+A macro is a collection of text and embedded commands which can be
+invoked multiple times. Macros are used for defining common operations.
+Macros are defined using the @code{de} request. This request takes
+a name for the macro as the first argument. Subsequent lines are
+copied into an internal buffer until the line @code{..} is
+encountered. The optional second argument to @code{de} can change
+this ending token.
+
+For example, suppose at the beginning of each paragraph, you want
+cause a break, move down a partial line and indent the first line.
+Such a macro could be defined as follows:
+
+@example
+.de P
+.br
+.sp .8v
+..
+@end example
+
+@findex am
+The @code{am} request works similarily to @code{de} except it appends
+onto the macro named by the first argument. So, if we decide we want
+our previously @code{P} macro to actually do indented instead of
+block paragraphs we can add the necessary code to our existing macro.
+
+@example
+.am P
+.ti +5n
+..
+@end example
+
+@findex als
+@cindex aliases, macro
+@cindex macro aliases
+Macros can be aliased with the @code{als} request.
+
+@findex rn
+@code{rn}
+
+@findex rm
+@code{rm}
+
+@findex chop
+@code{chop}
+
+
+@menu
+* Copy-in Mode::
+* Parameters::
+@end menu
+
+@node Copy-in Mode, Parameters, Writing Macros, Writing Macros
+@subsection Copy-in Mode
+@cindex copy-in mode
+@cindex mode, copy-in
+
+
+@findex \n
+@findex \$
+@findex \*
+@findex \\
+@findex \@key{RET}
+When troff reads in the test for a macro or diversion it copies the
+text (including request lines) into an internal buffer, except for
+escapes. Escapes will be converted into an internal form, except for
+@code{\n}, @code{\$}, @code{\*}, @code{\\} and @code{\@key{RET}} which
+are evaluated and inserted into the text where the escape was located.
+This is known as @dfn{copy-in} mode.
+
+What this means is that you can specify when these escapes are to be
+evaluated (copy-in time or time of use) by insulating the escapes
+with an extra backslash.
+
+For example, the following will result in the numbers 20 and 10 being
+printed.
+
+@example
+.nr x 20
+.de y
+.nr x 10
+\&\nx
+\&\\nx
+..
+.y
+@end example
+
+
+
+@node Parameters, , Copy-in Mode, Writing Macros
+@subsection Parameters
+@cindex parameters
+
+
+@findex \$
+@vindex .$
+The arguments to a macro can be examined using a variety of escapes.
+The number of arguments is available in the @code{.$} number register.
+Any individual argument can be retrieved with one of the following
+escapes:
+
+The escapes @code{\$@var{n}}, @code{\$(@var{nn}}
+and @code{\$[@var{nnn}]}
+will result in the @var{n}th, @var{nn}th or @var{nnn}th
+argument. Macros can have a unlimited number of arguments.
+Note that due to copy-in mode, you will want to have two backslashes
+on these in actual use, since you do not want them interpolated until
+the macro is actually invoked.
+
+@findex shift
+The request @code{shift} will shift the arguments 1 position, or as
+many positions as specified by the first argument.
+After executing this request, argument
+@var{i} will become argument @var{i}-@var{n}; arguments 1 to @var{n}
+will no longer be available.
+Shifting by negative amounts is currently undefined.
+
+@findex \$*
+@findex \$@@
+In some cases you will want to just use all of the arguments at once.
+For example if you pass the arguments along to another macro.
+The @code{\$*} escape is
+the concatenation of all the arguments separated by spaces.
+A similar escape is @code{\$@@},
+which is
+the concatenation of all the arguments with each surrounded
+by double quotes, and separated by spaces.
+
+@findex \$0
+@findex als
+The @code{\$0} escape is
+the name by which the current macro was invoked. The @code{als}
+request can make a macro have more than one name.
+
+@example
+.de vl
+.ie \\n(.$=1 .ds Vl Pre-Release Version
+.el .ds Vl Version \\$3, \\$4.
+..
+@end example
+
+This would be called as
+
+@example
+.vl $Id: groff.texinfo,v 1.1 2000/02/06 09:39:38 wlemb Exp $
+@end example
+
+
+@c distribute these through the text
+@xref{Request Arguments}
+
+@node Page Motions, Drawing Functions, Writing Macros, Programming Tutorial
+@section Page Motions
+@cindex page motions
+@cindex motions, page
+
+
+@findex sp
+Motions up and down the page can be done with the @code{sp} request.
+However, this causes a break so that the actual effect is to move to
+the left margin and then to the specified location.
+
+@findex mk
+@findex rt
+The request @code{mk} can be used to mark a location on a page, for
+movement to later. This request takes a register name as an
+argument in which to store the current page location, with no
+argument it will store the location in an internal register.
+The results of this can be used later by the @code{rt} or the
+@code{sp} request. The @code{rt} request will return
+@strong{upwards} to the location given in the register name given as
+an argument, with no argument it will return to the location marked
+with the @code{mk} request
+
+@example
+... dual column example ...
+@end example
+
+There are escapes which will give you much finer control of movements
+about the page.
+
+@findex \v
+The @code{\v'@var{e}'} will let you do arbitrary vertical motion from
+the current location on the page. The argument @var{e} specifies the
+distance to move, positive is downwards and negative upwards. The
+default unit for this escape is vertical spaces, @code{v}'s. Beware,
+however, that troff will leave text processing to continue wherever
+the motion ends, so if you don't want to interfere with text
+processing, make sure your motions are balanced.
+
+There are some special case escapes for vertical motion.
+
+@ftable @code
+@item \r
+move upwards 1v.
+@item \u
+move upwards .5v.
+@item \d
+move down .5v.
+@end ftable
+
+@findex \h
+Horizontal motions can be done via the @code{\h'@var{e}'} escape.
+The expression @var{e} indicates how far to move: positive is
+rightwards and negative leftwards.
+
+There are a number of special case escapes for horizontal motion:
+
+@ftable @code
+@item \@key{SP}
+An unbreakable and unpadable (i.e. not expanded during filling) space.
+(Note: it is a backslash followed by a space.)
+@item \~
+This produces an unbreakable space that stretches like a normal
+interword space when a line is adjusted.
+@item \|
+a 1/6th em space.
+@item \^
+a 1/12th em space.
+@item \0
+a space the size of a digit.
+@item \&
+A zero width space.
+@item \)
+Like @code{\&} except that it behaves like a character declared with
+the @code{cflags} request to be transparent for the purposes of end
+of sentence recognition.
+@end ftable
+
+@example
+... tex logo example ...
+@end example
+
+@findex \w
+@cindex width escape
+@cindex escape, width
+Often you will want to do horizontal movement based on the width of
+some arbitrary text (e.g. given as an argument to a macro).
+For that, there is the escape @code{\w'@var{text}'} which will
+interpolate to the width of the given @var{text} in basic units.
+
+@example
+... strlen example ...
+@end example
+
+Font changes may occur in @var{text} and not affect current settings.
+
+Also after use, @code{\w} sets several registers:
+
+@table @code
+@item st
+@vindex st
+@itemx sb
+@vindex sb
+The highest and lowest point, respectively, in @var{text}.
+@item rst
+@vindex rst
+@itemx rsb
+@vindex rsb
+Like the @code{st} and @code{sb} registers, but takes account of the
+heights and depths of characters.
+@item ct
+@vindex ct
+is set according to what kinds of characters occur in @var{text}.
+@table @asis
+@item 0
+all short characters, no decenders or tall characters.
+@item 1
+decender
+@item 2
+tall character
+@item 3
+both a decender and a tall character
+@end table
+@item ssc
+@vindex ssc
+The amount of horizontal space (possibly negative) that should be
+added to the last character before a subscript.
+@item skw
+@vindex skw
+How far to right of the center of the last character in the @code{\w}
+argument, the center of an accent from a roman font should be
+placed over that character.
+@end table
+
+@findex \k
+@vindex .k
+@code{\k}
+@code{.k}
+
+@node Drawing Functions, Traps, Page Motions, Programming Tutorial
+@section Drawing Functions
+@cindex drawing functions
+@cindex functions for drawing
+
+
+Groff provides a number of ways to draw lines, and other figures on
+the page. Used in combination with the page motion commands
+(@pxref{Page Motions}, for more info) you can draw a wide variety of
+figures. However, for complex drawings these operations can be quite
+cumbersome, and it may be wise to use the pic preprocessor.
+@xref{gpic}, for more information.
+
+All drawing is done via escapes.
+
+@findex \l
+The @code{\l} will draw a line rightwards from the current location.
+The full syntax for this escape is @samp{\l'@var{l}@var{c}'}, where
+@var{l} is the length of the line to be drawn, starting at the
+current location, positive numbers will draw to the right, and
+negative will draw towards the left. This can also be specified
+absolutely (i.e. with a leading |) which will draw back to the
+begining of the line.
+
+The optional second parameter @var{c} is a character to draw the line
+with. If this second argument is not specified, troff will use the
+underscore character.
+
+If you need to separate the two arguments (to prevent troff from
+interpreting a drawing character as a scaling indicator), you can
+separate them with @code{\&}.
+
+And now, for a useful example:
+
+@example
+.de box
+\(br\\$*\(br\l'|0\(rn'\l'|0\(ul'
+..
+@end example
+
+Note that this works by outputing a box rule (a vertical line), then
+the text given as an argument and then another box rule.
+Then the line drawing escapes both draw from the current location to
+the beginning of the @emph{input} line.
+
+@findex \L
+Vertical lines are drawn using the @code{\L} escape. It's parameters
+are specified the same as the @code{\l} escape. If the length is
+positive, the movement will be downwards, and upwards for negative.
+The default character is the box rule character.
+As with the vertical motion escapes, text processing will blindly
+continue where the line ends.
+
+@example
+...box macro...
+@end example
+
+@findex \D
+More flexible drawing functions are available via the @code{\D}
+escape. While the previous escapes will work on an ascii device,
+these escapes will not.
+
+@table @code
+@item \D'l @var{x} @var{y}'
+Draw a line from the current location to the relative point specified
+by @var{x}, @var{y}.
+
+@example
+...revised box macro...
+@end example
+
+@item \D'c @var{d}'
+Draw a circle with a diameter of @var{d} with the leftmost point at
+the current position.
+@item \D'C @var{d}'
+Draw a solid circle with the same parameters as an outlined circle.
+@item \D'e @var{dx} @var{dy}'
+Draw an ellipse with a horizontal diameter of @var{dx} and a vertical
+diameter of @var{dy} with the leftmost point at the current position.
+@item \D'E @var{dx} @var{dy}'
+Draw a solid elipse with the same parameters as an outlined elipse.
+@item \D'a @var{dx1} @var{dy1} @var{dx2} @var{dy2}'
+Draw an arc clockwise from the current location through the two
+specified locations.
+@item \D'~ @var{dx1} @var{dy1} @var{dx2} @var{dy2} ...'
+Draw a spline from the current location to
+@var{dx1}, @var{dy1} and then to @var{dx2}, @var{dy2}, and so on.
+@item \D'f @var{n}'
+Set the shade of gray to be used for filling solid objects to @var{n};
+@var{n} must be an integer between 0 and 1000, where 0 corresponds
+solid white and 1000 to solid black, and values in between correspond
+to intermediate shades of gray. This applies only to solid circles,
+solid ellipses and solid polygons. By default, a level of 1000 will
+be used.
+@item \D'p @var{dx1} @var{dy1} @var{dx2} @var{dy2} ...'
+Draw a polygon from the current location to @var{dx1}, @var{dy1}
+and then to @var{dx2}, @var{dy2} and so on. When the specified data
+points are exhausted, a line is drawn back to the starting point.
+
+@example
+... box example (yes, again)...
+@end example
+
+@itemx \D'P @var{dx1} @var{dy1} @var{dx2} @var{dy2} ...'
+Draw a solid polygon with the same parameters as an outlined polygon.
+
+@example
+... shaded box example ...
+@end example
+
+@item \D't @var{n}'
+Set the current line thickness to @var{n} machine units.
+A value of zero selects the smallest available line thickness.
+
+@end table
+
+Current position
+
+@findex \b
+@cindex pile, character
+@cindex character pile
+The @code{\b} escape will @dfn{pile} a sequence of characters
+vertically, and center it vertically on the current line.
+This can be used to build large brackets and braces.
+
+@example
+\b'\(lt\(bv\(lk\(bv\(lb'
+@end example
+
+
+
+
+@node Traps, Diversions, Drawing Functions, Programming Tutorial
+@section Traps
+@cindex traps
+
+
+Traps are locations, which, when reached, will call a specified macro.
+These traps can occur at a given location on the page, at a given
+location in the current diversion, after a certain number of input
+lines or at the end of input.
+
+@findex ch
+Any of these traps can be changed after they have been set with the
+@code{ch} request. The first arguemnt is the name of the trap or
+macro, and the second is the new value for that trap.
+
+
+@menu
+* Page Location Traps::
+* Diversion Traps::
+* Input Line Traps::
+* End-of-input Traps::
+@end menu
+
+@node Page Location Traps, Diversion Traps, Traps, Traps
+@subsection Page Location Traps
+@cindex page location traps
+@cindex traps, page location
+
+
+Page location traps are frequently used for page headers and
+footers. The following is a simple example of this.
+
+@example
+.de hd \" Page header
+'sp .5i
+.tl 'Title''date'
+'sp .3i
+..
+.de fo \" Page footer
+'sp 1v
+.tl ''%''
+'bp
+..
+.wh 0 hd \" top of the page
+.wh -1i fo \" one inch from bottom
+@end example
+
+@vindex .t
+The number register @code{.t} is the distance to the next trap.
+
+@findex ch
+The location of a trap can be changed later on with the @code{ch}
+request.
+The first argument is the name of the macro to be invoked at the trap
+and the second argument is the new location for the trap.
+This is useful when you are building up footnotes in a diversion, and
+you need to allow more space at the bottom of the page for them.
+
+@example
+... (simplified) footnote example ...
+@end example
+
+@findex vpt
+@findex wh
+@findex dt
+@vindex .vpt
+The @code{vpt} request will enable vertical position traps if the argment is
+non-zero, disable them otherwise. Vertical position traps are traps
+set by the @code{wh} or @code{dt} requests. Traps set by the
+@code{it} request are not vertical position traps. The parameter that
+controls whether vertical position traps are enabled is global.
+Initially vertical position traps are enabled. The current setting of
+this is available in the number register @code{.vpt}.
+
+@vindex .trunc
+@findex ne
+The number register @code{.trunc} contains
+the amount of vertical space truncated by the most recently
+sprung vertical position trap, or, if the trap was sprung by a
+@code{ne} request, minus the amount of vertical motion produced by
+the @code{ne} request. In other words, at the point a trap is
+sprung, it represents the difference of what the vertical position
+would have been but for the trap, and what the vertical position
+actually is.
+
+@vindex .ne
+The number register @code{.ne} contains
+the amount of space that was needed in the last @code{ne} request that caused
+a trap to be sprung. Useful in conjunction with the @code{.trunc}
+register. @xref{Page Control}, for more information.
+
+
+
+@node Diversion Traps, Input Line Traps, Page Location Traps, Traps
+@subsection Diversion Traps
+@cindex diversion traps
+@cindex traps, diversion
+
+
+@findex dt
+@vindex .t
+Traps can also be set @emph{within} a diversion using the @code{dt}
+request. Like @code{wh} the first argument is the location of the
+trap and the second argument is the name of the macro to be invoked.
+The number register @code{.t} will still work within diversions.
+@xref{Diversions}, for more information.
+
+@node Input Line Traps, End-of-input Traps, Diversion Traps, Traps
+@subsection Input Line Traps
+@cindex input line traps
+@cindex traps, input line
+
+
+@findex it
+The @code{it} request will set an input line trap. The format for
+calling this is @samp{.it @var{n} @var{name}}, where @var{n} is the
+number of lines of input which may be read before @dfn{springing} the
+trap, @var{name} is the macro to be invoked. Request lines are not
+counted as input lines.
+
+For example, one possible use is to have a macro which will print the
+next @var{n} lines in a bold font.
+
+@example
+.de B
+.it B-end \\$1
+.ft B
+..
+.de B-end
+.ft R
+..
+@end example
+
+@node End-of-input Traps, , Input Line Traps, Traps
+@subsection End-of-input Traps
+@cindex end-of-input traps
+@cindex traps, end-of-input
+
+
+@findex em
+The @code{em} request will set a trap at the end of input.
+The macro specified as an arguement will be executed after the last
+line of the input file has been processed.
+
+For example, if your document had to have a section at the bottom of
+the last page for someone to approve you document, you could set it
+up with @code{em}.
+
+@example
+.de approval
+.ne 5v
+.sp |(\\n(.t-6v)
+.in +4i
+.lc _
+.br
+Approved:\t\a
+.sp
+Date:\t\t\a
+..
+.em approval
+@end example
+
+
+@node Diversions, Environments, Traps, Programming Tutorial
+@section Diversions
+@cindex diversions
+
+
+In Troff you can divert text into a named storage area, due to the
+similarity to defining macros it is sometimes said to be stored in a
+macro. This is used for saving text for output at a later time,
+which is useful for keeping blocks of text on the same page,
+footnotes, tables of contents and indexes.
+
+@findex di
+@findex da
+Diversion is initiated by the @code{di} request, like the @code{de}
+request it takes an argument of a macro name to divert subsequent
+text to into. The @code{da} macro will append to an existing diversion.
+
+@example
+... end-note example ...
+@end example
+
+@vindex .z
+@vindex .d
+@vindex nl
+@vindex .h
+Diversions may be nested.
+The number register @code{.z} contains the name of the current diversion.
+The number register @code{.d} contains the current vertical place in
+the diversion. If not in a diversion it is the same as the register
+@code{nl}.
+@code{.h}
+
+@vindex dn
+@vindex dl
+After compleating a diversion, the builtin number registers @code{dn}
+and @code{dl} contain the vertical and horizontal size of the diversion.
+
+@example
+.\" Center text both horizontally & vertically
+.de (c
+.br
+.nf
+.di @@c
+..
+.de )c
+.br
+.di
+.nr @@s (((\\n(.tu-\\n(dnu)/2u)-1v)
+.sp \\n(@@su
+.ce 1000
+.nf
+.@c
+.br
+.ce 0
+.sp \\n(@@su
+.br
+.fi
+.rr @@s
+..
+@end example
+
+@findex \!
+Requests, macros and escapes are interpreted when read into a
+diversion.
+There are two ways to prevent this, either way will take the given
+text and @dfn{transparently} embed it into the diversion.
+The first method is to prefix the line with @code{\!}. This will
+cause the entire line to be transparently inserted into the diversion.
+This is useful for macros you do not want invoked until the diverted
+text is actually output.
+
+@c anything is read in copy mode. (what about \! ??)
+
+@findex \?
+The other way is to surround the text by the @code{\?} escape, i.e.
+@samp{\?@var{anything}\?}.
+@var{anything} may not contain
+newlines; use @code{\!} if you want to embed newlines in a diversion. The
+escape sequence @code{\?} is also recognised in copy mode and turned into a
+single internal code; it is this code that terminates anything. Thus
+the followin example will print 4.
+
+@example
+.nr x 1
+.nf
+.di d
+\?\\?\\\\?\\\\\\\\nx\\\\?\\?\?
+.di
+.nr x 2
+.di e
+.d
+.di
+.nr x 3
+.di f
+.e
+.di
+.nr x 4
+.f
+@end example
+
+@findex rn
+@code{rn}
+
+@findex rm
+@code{rm}
+
+@findex als
+@code{als}
+
+@findex chop
+@code{chop}
+
+@findex asciify
+@code{asciify}
+This request only exists in order to make it possible to make certain
+gross hacks work with GNU troff. It @dfn{unformats} the diversion
+specified as an argument in
+such a way that ASCII characters that were formatted and diverted
+will be treated like ordinary input characters when the diversion is
+reread. For example, the following will set register @code{n} to 1.
+
+@example
+.tr @@.
+.di x
+@@nr\ n\ 1
+.br
+.di
+.tr @@@@
+.asciify x
+.x
+@end example
+
+
+@c distribute these through the text
+@xref{Copy-in Mode}
+
+@node Environments, I/O, Diversions, Programming Tutorial
+@section Environments
+@cindex environments
+
+
+Often you will need to print some text in a certain format regardless
+of what may be in effect at the time, for example, in a trap invoked
+macro to print headers and footers.
+To solve this groff has @dfn{environments} in which text is processed.
+An environment contains most of the parameters that control
+text processing. You can switch amongst these environments, by
+default groff processes text in environment 0.
+The following is the information kept in an environment.
+
+@itemize @bullet{}
+@item
+Type size
+@item
+Font (family and style)
+@item
+Page parameters
+@item
+Fill/adjust mode
+@item
+Tab stops
+@item
+Partially collected lines
+@end itemize
+
+These environments may be given arbitrary names
+(@pxref{Identifiers}, for more info.)
+Old versions of troff only had environments named 0, 1 and 2.
+
+@findex ev
+@vindex .ev
+The @code{ev} request will switch among these environments.
+The single argument is the name of the environment to switch to, with
+no argument groff will switch back to the previous enviroment.
+There is no limit on the number of named environments;
+they will be created the first time that they are referenced.
+The @code{.ev} number register contains
+the name or number of the current environment. This is a string-valued
+register.
+
+@example
+... page break macro, revised ...
+@end example
+
+@example
+.ev footnote-env
+.fam N
+.ps 6
+.vs 8
+.ll -.5i
+.ev
+...
+.ev footnote-env
+\(dg Note the large, friendly letters.
+.ev
+@end example
+
+
+
+
+@node I/O, Postprocessor Access, Environments, Programming Tutorial
+@section I/O
+@cindex i/o
+
+
+@findex so
+The @code{so} request will read in the file given as an argument and
+include it in place of the @code{so} request. This is quite useful
+for large documents, i.e. keeping each chapter in a separate file.
+@xref{gsoelim}, for more information.
+
+@findex mso
+The @code{mso} request is
+the same as the @code{so} request except that file is searched for in
+the same way that @file{tmac.@var{name}} is searched for when the
+@samp{-m@var{name}} option is specified.
+
+@findex cf
+@findex trf
+The @code{cf} and @code{trf} requests are to include a file.
+It will transparently output the contents of file filename. Each
+line is output
+as it would be were it preceded by @code{\!}; however, the lines are not
+subject to copy-mode interpretation. If the file does not end with a
+newline, then a newline will be added. For example, you can define a
+macro @code{x} containing the contents of file @file{f}, using
+
+@example
+.di x
+.trf f
+.di
+@end example
+
+.cf filename
+When used in a diversion, this will embed in the diversion an object
+which, when reread, will cause the contents of filename to be
+transparently copied through to the output. In @sc{Unix} troff, the contents
+of filename is immediately copied through to the output regardless of
+whether there is a current diversion; this behaviour is so anomalous
+that it must be considered a bug.
+
+
+With @code{trf}, unlike @code{cf}, the file cannot contain characters
+such as NUL that are not legal troff input characters.
+
+@findex nx
+The @code{nx} request will force groff to continue processing of the
+file specified as an argument.
+
+@findex rd
+The @code{rd} request will read from standard input, and include what
+is read as though it were part of the input file. Text is read until
+a blank line is encountered.
+
+@cindex form letters
+@cindex letters, form
+Using these two requests you can set up form letters.
+The form letter template is constructed like this:
+
+@example
+.ce
+\*(td
+.sp 2
+.nf
+.rd
+.sp
+.rd
+.fi
+Body of letter.
+.bp
+.nx repeat.let
+@end example
+
+@findex ex
+When this is run, the following file should be redirected in.
+Note that requests included in this file are executed as though they
+were part of the form letter. The last block of input is the
+@code{ex} requests which tells groff to stop processing. If this was
+not there, groff would not know when to stop.
+
+@cindex Beagle Brothers
+@example
+Trent A. Fisher
+708 NW 19th Av., #202
+Portland, OR 97209
+
+Dear Trent,
+
+Len Adollar
+4315 Sierra Vista
+San Diego, CA 92103
+
+Dear Mr. Adollar,
+
+.ex
+@end example
+
+@findex pi
+@code{pi}
+
+@findex sy
+The @code{sy} request will allow arbitrary system commands to be
+executed from within a groff document. The output is not saved
+anyplace, so it is up to you to do so.
+
+For example, the following example will introduce the current time
+into your document:
+
+@cindex time
+@pindex perl
+@example
+.sy perl -e 'printf ".nr H %d\\n.nr M %d\\n.nr S %d\\n",\
+ (localtime(time))[2,1,0]' > /tmp/x\n[$$]
+.so /tmp/x\n[$$]
+.sy rm /tmp/x\n[$$]
+\nH:\nM:\nS
+@end example
+
+Note that this works by having the perl script (run by @code{sy})
+print out the @code{nr} requests which will set the number registers
+@samp{H}, @samp{M} and @samp{S}, and then reads those commands in
+with the @code{so} request.
+
+@vindex systat
+The @code{systat} number register contains
+The return value of the @code{system()} function executed by the last
+@code{sy} request.
+
+@findex open
+The @code{open} request will open
+a file (specified as the second argument) for writing and associate
+the stream (specified as the first argument) with it.
+
+@findex opena
+The @code{opena} is
+like open, but if filename exists, append to it instead of truncating
+it.
+
+@findex write
+@findex ds
+@cindex copy-in mode
+@cindex mode, copy-in
+The @code{write} request will write to the file associated with the
+stream specified by the first argument. The stream must previously
+have been the subject of an open request. The remainder of the line
+in interpreted as the @code{ds} request reads its second argument: a
+leading @code{"} will be stripped, and it will be read in copy-in mode.
+
+@findex close
+The @code{close} request will
+close the stream specified by the first argument; stream will no
+longer be an acceptable argument to the @code{write} request.
+
+@example
+... example of open write &c...
+@end example
+
+@findex \v
+The @code{\V} escape will
+interpolate the contents of the specified environment variable, as returned
+by getenv(3).
+The argument to @code{\V} is specified as an identifier, i.e.
+@samp{\V@var{x}}, @samp{\V(@var{xx}} or @samp{\V[@var{xxx}]}.
+@code{\V} is interpreted in copy-in mode.
+
+
+@node Postprocessor Access, Miscellany, I/O, Programming Tutorial
+@section Postprocessor Access
+@cindex postprocessor access
+@cindex access of postprocessor
+
+
+There are two escapes which will allow you to give information
+directly to the postprocessor. This is particularly useful for
+embedding PostScript into your final document.
+
+@findex \X
+The @code{\X} escape will embed its argument into the gtroff output
+preceded with @samp{x X}.
+
+@findex \Y
+The @code{\Y} escape is called with an identifier (i.e.
+@code{\Y@var{x}},
+@code{\Y(@var{xx}} or
+@code{\Y[@var{xxx}]}).
+This is approximately equivalent to @samp{\X'\*[@var{xxx}]'}.
+However the contents
+of the string or macro @var{xxx} are not interpreted; also it is
+permitted for
+@var{xxx} to have been defined as a macro and thus contain newlines
+(it is not permitted for the argument to @code{\X} to contain newlines).
+The inclusion of
+newlines requires an extetension to the @sc{Unix} troff output format, and will
+confuse drivers that do not know about this extension.
+
+
+@c distribute these through the text
+@xref{Devices}
+
+@node Miscellany, Debugging, Postprocessor Access, Programming Tutorial
+@section Miscellany
+@cindex miscellany
+
+
+This section contains parts of troff which cannot (yet) be
+categorized elsewhere in this manual.
+
+@findex nm
+Line numbers can be printed in the left margin
+using the @code{nm} request.
+The first argument is the line number of the @emph{next} output line,
+this defaults to 1.
+The second argument indicates on which lines numbers will be printed,
+i.e. 5 means put line numbers on every 5 lines, this defaults to 1.
+The third argument is the space to be left between the number and
+your text, this defaults to 1.
+The fourth argument is the indentation of the line numbers.
+Without arguments, line numbers are turned off.
+
+@findex nn
+The @code{nn} request will temporarily turn off line numbering.
+The first argument is the number of lines not to be numbered,
+this defaults to 1. (does this disable incrementing or display?)
+
+@example
+... line numbering example ...
+@end example
+
+@findex mc
+margin characters can be automatically printed to the right of your
+text with the @code{mc} request.
+The first argument is the character to be printed and the second
+argument is the distance away from your text.
+With no arguments the margin characters are turned off.
+If this occurs before a break, no margin character will be printed.
+
+This is quite useful for indicating text that has changed, and, in
+fact, there are programs available for doing this (they are called
+@code{nrchbar} and @code{changebar} and can be found in any
+@samp{comp.sources.unix} archive.
+
+@example
+... margin char example ...
+@end example
+
+@findex lf
+@pindex soelim
+The @code{lf} primary reason for existence is to make debugging
+documents which are split into many files, which are then put
+together with @code{soelim} and other preprocessors.
+The first argument is the name of the file and the second argument is
+the input line number in that file.
+This way troff can produce error messages which are intelligible to
+the user.
+
+@example
+... example of soelim'ed doc ...
+@end example
+
+@node Debugging, Implementation Differences, Miscellany, Programming Tutorial
+@section Debugging
+@cindex debugging
+
+
+Troff is not easy to debug, but there are some useful features and
+strategies for debugging.
+
+@itemize @bullet{}
+@item
+@findex tm
+The @code{tm} request will send output to stderr, this is very useful for
+printing debugging output.
+@item
+When doing something involved it is useful to leave the debugging
+statements in the code and have them turned on by a command line
+flag.
+
+@example
+.if \n(DB .tm debugging output
+@end example
+
+Then you can activate these statements with:
+
+@example
+groff -rDB=1 file
+@end example
+
+@item
+@findex ab
+The @code{ab} request is similar to the @code{tm} request,
+except that it will cause groff to stop processing.
+With no argument it will print @samp{User Abort}.
+@item
+@findex ex
+The @code{ex} request will also cause groff to stop processing.
+@item
+If you know you are going to get many errors and no useful output,
+you can tell groff to suppress formatted output with the @samp{-z}
+flag.
+@item
+@findex pm
+The @code{pm} request will dump out the entire symbol table.
+@item
+@findex pnr
+The @code{pnr} request will print the names and contents of all
+currently defined number registers on stderr.
+@item
+@findex ptr
+The @code{ptr} request will
+print the names and positions of all traps (not including input line
+traps and diversion traps) on stderr. Empty slots in the page trap list
+are printed as well, because they can affect the priority of
+subsequently planted traps.
+@item
+@findex fl
+The @code{fl} request instructs groff to flush its output immediately.
+The intention is that this be used when using troff interactively.
+There is little other use for it.
+@item
+@findex backtrace
+The @code{backtrace} request will
+print a backtrace of the input stack on stderr.
+@item
+Groff has command line options for printing out more warnings
+(@samp{-w}) and for printing backtraces (@samp{-b}) when a warning or
+an error occurs. The most verbose level of warnings is @samp{-ww}.
+@item
+@findex warn
+@vindex .warn
+The @code{warn} request controls the level of warnings checked for.
+The one argument is the sum of the numbers associated with each
+warning that is to be enabled; all other warnings will be disabled.
+The number associated with each warning is listed below.
+For example, @code{.warn 0} will disable all warnings, and
+@code{.warn 1} will disable
+all warnings except that about missing characters. If an argument
+is not given, all warnings will be enabled.
+The number register @code{.warn} contains the current warning level.
+@end itemize
+
+@subsection Warnings
+@cindex warnings
+
+The warnings that can be given by troff are divided into the
+following categories. The name associated with each warning is used
+by the @samp{-w} and @samp{-W} options; the number is used by the
+@code{warn} request, and by the @code{.warn} register.
+
+@table @samp
+@item char
+@itemx 1
+Non-existent characters. This is enabled by default.
+@item number
+@itemx 2
+Invalid numeric expressions. This is enabled by default.
+@item break
+@itemx 4
+In fill mode, lines which could not be broken so that
+their length was less than the line length. This is
+enabled by default.
+@item delim
+@itemx 8
+Missing or mismatched closing delimiters.
+@item el
+@itemx 16
+Use of the @code{el} request with no matching @code{ie} request.
+@xref{if-else}, for more information.
+@item scale
+@itemx 32
+Meaningless scaling indicators.
+@item range
+@itemx 64
+Out of range arguments.
+@item syntax
+@itemx 128
+Dubious syntax in numeric expressions.
+@item di
+@itemx 256
+@findex di
+@findex da
+Use of @code{di} or @code{da} without an argument when there is no
+current diversion.
+@item mac
+@itemx 512
+Use of undefined strings, macros and diversions.
+When an undefined string, macro or diversion is used,
+that string is automatically defined as empty. So,
+in most cases, at most one warning will be given for
+each name.
+@item reg
+@itemx 1024
+Use of undefined number registers. When an undefined
+number register is used, that register is
+automatically defined to have a value of 0. a
+definition is automatically made with a value of 0.
+So, in most cases, at most one warning will be given
+for use of a particular name.
+@item tab
+@itemx 2048
+Use of a tab character where a number was expected.
+@item right-brace
+@itemx 4096
+@findex \@}
+Use of @code{\@}} where a number was expected.
+@item missing
+@itemx 8192
+Requests that are missing non-optional arguments.
+@item input
+@itemx 16384
+Illegal input characters.
+@item escape
+@itemx 32768
+Unrecognized escape sequences. When an unrecognized
+escape sequence is encountered, the escape character
+is ignored.
+@item space
+@itemx 65536
+Missing space between a request or macro and its
+argument. This warning will be given when an
+undefined name longer than two characters is
+encountered, and the first two characters of the name
+make a defined name. The request or macro will not
+be invoked. When this warning is given, no macro is
+automatically defined. This is enabled by default.
+This warning will never occur in compatibility mode.
+@item font
+@itemx 131072
+Non-existent fonts. This is enabled by default.
+@item all
+All warnings except @samp{di}, @samp{mac} and @samp{reg}. It is
+intended that this covers
+all warnings that are useful with traditional macro packages.
+@item w
+All warnings.
+@end table
+
+
+@node Implementation Differences, Summary, Debugging, Programming Tutorial
+@section Implementation Differences
+@cindex implementation differences
+@cindex differences in implementation
+
+
+GNU troff has a number of features which cause incompatibilites with
+documents written with old versions of troff.
+
+Long names cause some incompatibilities. @sc{Unix} troff will interpret
+
+@example
+.dsabcd
+@end example
+
+@findex \*
+@findex \n
+@findex cp
+@vindex .C
+as defining a string @samp{ab} with contents @samp{cd}.
+Normally, GNU troff will interpret this as a call of a macro named
+@code{dsabcd}. Also @sc{Unix} troff will interpret @code{\*[} or
+@code{\n[} as references to a string or number register called
+@samp{[}. In GNU troff, however, this will normally be interpreted as the
+start of a long name. In compatibility mode GNU troff will interpret
+these things in the traditional way. In compatibility mode, however,
+long names are not recognised. Compatibility mode can be turned on with
+the @samp{-C} command line option, and turned on or off with the
+@code{cp} request.
+The number register @code{.C} is 1 if compatibility mode is on, 0 otherwise.
+
+@findex \A
+GNU troff does not allow the use of the escape sequences
+@samp{\| \^ \& \@} \@{ \@key{SP} \' \` \- \_ \! \% \c} in names of
+strings, macros,
+diversions, number registers, fonts or environments; @sc{Unix} troff does.
+The @code{\A} escape sequence may be helpful in avoiding use of these escape
+sequences in names.
+
+@cindex fractional point sizes
+@cindex point sizes, fractional
+@findex ps
+Fractional pointsizes cause one noteworthy incompatibility. In @sc{Unix}
+troff the @code{ps} request ignores scale indicators and so
+
+@example
+.ps 10u
+@end example
+
+will set the pointsize to 10 points, whereas in GNU troff it will set
+the pointsize to 10 scaled points.
+@xref{Fractional Type Sizes}, for more information.
+
+@findex bd
+@findex cs
+@findex tkf
+@findex tr
+@findex fp
+In GNU troff there is a fundamental difference between unformatted,
+input characters, and formatted, output characters. Everything that
+affects how an output character will be output is stored with the
+character; once an output character has been constructed it is
+unaffected by any subsequent requests that are executed, including
+@code{bd}, @code{cs}, @code{tkf}, @code{tr}, or @code{fp}
+requests. Normally output characters are constructed
+from input characters at the moment immediately before the character is
+added to the current output line. Macros, diversions and strings are
+all, in fact, the same type of object; they contain lists of input
+characters and output characters in any combination. An output
+character does not behave like an input character for the purposes of
+macro processing; it does not inherit any of the special properties that
+the input character from which it was constructed might have had. For
+example,
+
+@example
+.di x
+\\\\
+.br
+.di
+.x
+@end example
+
+@findex \e
+@findex \!
+@findex \?
+will print @samp{\\} in GNU troff; each pair of input backslashes is
+turned into one
+output backslash and the resulting output backslashes are not
+interpreted as escape
+characters when they are reread. @sc{Unix} troff would interpret them as
+escape characters when they were reread and would end up printing one
+@samp{\}.
+The correct way to obtain a printable backslash is to use the
+@code{\e} escape
+sequence: this will always print a single instance of the current escape
+character, regardless of whether or not it is used in a diversion; it
+will also work in both GNU troff and @sc{Unix} troff. If you wish for some
+reason to store in a diversion an escape sequence that will be
+interpreted when the diversion is reread, you can either use the
+traditional @code{\!} transparent output facility, or, if this is unsuitable,
+the new @code{\?} escape sequence. @xref{Diversions}, for more information.
+
+
+@node Summary, , Implementation Differences, Programming Tutorial
+@section Summary
+@cindex summary
+
+
+@node geqn, gtbl, Programming Tutorial, Top
+@chapter @code{geqn}
+@cindex @code{eqn}
+@cindex @code{geqn}
+
+
+@menu
+* Invoking geqn::
+@end menu
+
+@node Invoking geqn, , geqn, geqn
+@section Invoking @code{geqn}
+@cindex invoking @code{geqn}
+@cindex @code{geqn}, invoking
+
+
+
+@node gtbl, gpic, geqn, Top
+@chapter @code{gtbl}
+@cindex @code{tbl}
+@cindex @code{gtbl}
+
+
+@menu
+* Invoking gtbl::
+@end menu
+
+@node Invoking gtbl, , gtbl, gtbl
+@section Invoking @code{gtbl}
+@cindex invoking @code{gtbl}
+@cindex @code{gtbl}, invoking
+
+
+@node gpic, grap, gtbl, Top
+@chapter @code{gpic}
+@cindex @code{pic}
+@cindex @code{gpic}
+
+
+@menu
+* Invoking gpic::
+@end menu
+
+@node Invoking gpic, , gpic, gpic
+@section Invoking @code{gpic}
+@cindex invoking @code{gpic}
+@cindex @code{gpic}, invoking
+
+
+
+@node grap, grefer, gpic, Top
+@chapter @code{grap}
+@cindex @code{grap}
+
+
+
+@node grefer, gsoelim, grap, Top
+@chapter @code{grefer}
+@cindex @code{refer}
+@cindex @code{grefer}
+
+
+@menu
+* Invoking grefer::
+@end menu
+
+@node Invoking grefer, , grefer, grefer
+@section Invoking @code{grefer}
+@cindex invoking @code{grefer}
+@cindex @code{grefer}, invoking
+
+
+
+@node gsoelim, Devices, grefer, Top
+@chapter @code{gsoelim}
+@cindex @code{soelim}
+@cindex @code{gsoelim}
+
+
+@menu
+* Invoking gsoelim::
+@end menu
+
+@node Invoking gsoelim, , gsoelim, gsoelim
+@section Invoking @code{gsoelim}
+@cindex invoking @code{gsoelim}
+@cindex @code{gsoelim}, invoking
+
+
+
+@node Devices, File formats, gsoelim, Top
+@chapter Devices
+@cindex devices
+
+
+
+@menu
+* Special Characters::
+* grotty::
+* grops::
+* grodvi::
+* grolj4::
+* grohtml::
+* gxditview::
+@end menu
+
+@node Special Characters, grotty, Devices, Devices
+@section Special Characters
+@cindex special characters
+@cindex characters, special
+
+
+@c distribute these through the text
+@xref{Font Files}
+
+@node grotty, grops, Special Characters, Devices
+@section @code{grotty}
+@cindex @code{grotty}
+
+
+
+@menu
+* Invoking grotty::
+@end menu
+
+@node Invoking grotty, , grotty, grotty
+@subsection Invoking @code{grotty}
+@cindex invoking @code{grotty}
+@cindex @code{grotty}, invoking
+
+
+
+@node grops, grodvi, grotty, Devices
+@section @code{grops}
+@cindex @code{grops}
+
+
+
+@menu
+* Invoking grops::
+* Embedding PostScript::
+@end menu
+
+@node Invoking grops, Embedding PostScript, grops, grops
+@subsection Invoking @code{grops}
+@cindex invoking @code{grops}
+@cindex @code{grops}, invoking
+
+
+
+@node Embedding PostScript, , Invoking grops, grops
+@subsection Embedding PostScript
+@cindex embedding postscript
+@cindex postscript, embedding
+
+
+
+@node grodvi, grolj4, grops, Devices
+@section @code{grodvi}
+@cindex @code{grodvi}
+
+
+
+@menu
+* Invoking grodvi::
+@end menu
+
+@node Invoking grodvi, , grodvi, grodvi
+@subsection Invoking @code{grodvi}
+@cindex invoking @code{grodvi}
+@cindex @code{grodvi}, invoking
+
+
+
+@node grolj4, grohtml, grodvi, Devices
+@section @code{grolj4}
+@cindex @code{grolj4}
+
+
+
+@menu
+* Invoking grolj4::
+@end menu
+
+@node Invoking grolj4, , grolj4, grolj4
+@subsection Invoking @code{grolj4}
+@cindex invoking @code{grolj4}
+@cindex @code{grolj4}, invoking
+
+
+
+@node grohtml, gxditview, grolj4, Devices
+@section @code{grohtml}
+@cindex @code{grohtml}
+
+
+
+@menu
+* Invoking grohtml::
+@end menu
+
+@node Invoking grohtml, , grohtml, grohtml
+@subsection Invoking @code{grohtml}
+@cindex invoking @code{grohtml}
+@cindex @code{grohtml}, invoking
+
+
+
+@node gxditview, , grohtml, Devices
+@section @code{gxditview}
+@cindex @code{gxditview}
+
+
+
+@menu
+* Invoking gxditview::
+@end menu
+
+@node Invoking gxditview, , gxditview, gxditview
+@subsection Invoking @code{gxditview}
+@cindex invoking @code{gxditview}
+@cindex @code{gxditview}, invoking
+
+
+
+@node File formats, Installation, Devices, Top
+@chapter File formats
+@cindex file formats
+@cindex formats, file
+
+
+
+@menu
+* gtroff Output::
+* Font Files::
+@end menu
+
+@node gtroff Output, Font Files, File formats, File formats
+@section @code{gtroff} Output
+@cindex @code{gtroff} output
+@cindex output, @code{gtroff}
+
+
+This section describes the format output by GNU troff. The output
+format used by GNU troff is very similar to that used by @sc{Unix}
+device-independent troff.
+
+The output format is ascii based, as opposed to a binary format (like
+@TeX{} dvi).
+The output format is 8 bit clean, thus single characters can have the
+eighth bit set, as can the names of fonts and special characters.
+
+The output format consists of single command characters with attached
+parameters which are separated from subsequent text by whitespace, or
+a newline.
+
+The names of characters and fonts an be of arbitrary length; drivers
+should not assume that they will be only two characters long (as
+device-independent troff did).
+
+When a character is to be printed, that character will always be in the
+current font.
+Unlike device-independent troff, it is not necessary for
+drivers to search special fonts to find a character.
+
+@table @code
+@item H@var{n}
+@item V@var{n}
+@item h@var{n}
+@item v@var{n}
+@item c@var{n}
+@item C@var{n}
+@item @var{nn}@var{c}
+@item t@var{xxx}
+@var{xxx} is any sequence of characters terminated by a space or a
+newline; the first character should be printed at the current
+position, the the current horizontal position should be increased by
+the width of the first character, and so on for each character.
+The width of the character is that given in the font file,
+appropriately scaled for the current point size,
+and rounded so that it is a multiple of the horizontal resolution.
+Special characters cannot be printed using this command.
+
+This command is only allowed if the @samp{tcommand} line is present
+in the @file{DESC} file.
+@item u@var{n} @var{xxx}
+@pindex DESC
+This is same as the @code{t} command except that after printing each
+character, the current horizontal position is increased by the sum of
+the width of that character and @code{n}.
+
+This command is only allowed if the @samp{tcommand} line is present
+in the @file{DESC} file.
+@item n@var{a}@var{b}
+@item p@var{n}
+@item s@var{n}
+The argument to the s command is in scaled points (units of points/n,
+where n is the argument to the sizescale command in the DESC file.)
+@item f@var{n}
+@item x @dots{} \n
+Device control.
+@item D@var{c} @var{x}@dots{}\n
+@end table
+
+@subsection Device Control
+
+The @code{x} command is normally followed by a letter or word
+indicating the function to perform, followed by white space separated
+arguments.
+
+The first argument can be abreviated to the first letter.
+
+@table @code
+@item x init
+@item x T
+@item x res @var{n} @var{h} @var{v}
+@item x H
+The argument to the x Height command is also in scaled points.
+@end table
+
+The first three output commands are guaranteed to be:
+
+@example
+x T device
+x res n h v
+x init
+@end example
+
+For example, the input @samp{crunchy \fH\s+2frog\s0\fP!?} will produce:
+
+@example
+... sample output here ...
+@end example
+
+@subsection Drawing Functions
+
+The D drawing command has been extended. These extensions will only be
+used by GNU pic if the -x option is given.
+
+@table @code
+...
+@item Df n\n
+Set the shade of gray to be used for filling solid objects to n; n must
+be an integer between 0 and 1000, where 0 corresponds solid white and
+1000 to solid black, and values in between correspond to intermediate
+shades of gray. This applies only to solid circles, solid ellipses and
+solid polygons. By default, a level of 1000 will be used. Whatever
+color a solid object has, it should completely obscure everything
+beneath it. A value greater than 1000 or less than 0 can also be used:
+this means fill with the shade of gray that is currently being used for
+lines and text. Normally this will be black, but some drivers may
+provide a way of changing this.
+@item DC d\n
+Draw a solid circle with a diameter of d with the leftmost point at the
+current position.
+@item DE dx dy\n
+Draw a solid ellipse with a horizontal diameter of dx and a vertical
+diameter of dy with the leftmost point at the current position.
+@item Dp $dx sub 1$ $dy sub 1$ $dx sub 2$ $dy sub 2$ $...$ $dx sub n$ $dy sub
+n$\n
+Draw a polygon with, for $i = 1 ,..., n+1$, the i-th vertex at the
+current position $+ sum from j=1 to i-1 ( dx sub j , dy sub j )$. At
+the moment, GNU pic only uses this command to generate triangles and
+rectangles.
+@item DP $dx sub 1$ $dy sub 1$ $dx sub 2$ $dy sub 2$ $...$ $dx sub n$ $dy sub
+n$\n
+Like Dp but draw a solid rather than outlined polygon.
+@item Dt n\n
+Set the current line thickness to n machine units. Traditionally @sc{Unix}
+troff drivers use a line thickness proportional to the current point
+size; drivers should continue to do this if no Dt command has been
+given, or if a Dt command has been given with a negative value of n. A
+zero value of n selects the smallest available line thickness.
+@end table
+
+A difficulty arises in how the current position should be changed after
+the execution of these commands. This is not of great importance since
+the code generated by GNU pic does not depend on this. Given a drawing
+command of the form
+
+\D'c $x sub 1$ $y sub 1$ $x sub 2$ $y sub 2$ $...$ $x sub n$ $y sub n$'
+
+where c is not one of c, e, l, a or ~, @sc{Unix} troff will treat each of the
+$x sub i$ as a horizontal quantity, and each of the $y sub i$ as a
+vertical quantity and will assume that the width of the drawn object is
+$sum from i=1 to n x sub i$, and that the height is $sum from i=1 to n y
+sub i$. (The assumption about the height can be seen by examining the
+st and sb registers after using such a D command in a \w escape
+sequence.) This rule also holds for all the original drawing commands
+with the exception of De. For the sake of compatibility GNU troff also
+follows this rule, even though it produces an ugly result in the case of
+the Df, Dt, and, to a lesser extent, DE commands. Thus after executing
+a D command of the form
+
+Dc $x sub 1$ $y sub 1$ $x sub 2$ $y sub 2$ $...$ $x sub n$ $y sub n$\n
+
+the current position should be increased by $( sum from i=1 to n x sub i
+, sum from i=1 to n y sub i )$.
+
+@subsection Line Continuation
+
+There is a continuation convention which permits the argument to the x X
+command to contain newlines: when outputting the argument to the x X
+command, GNU troff will follow each newline in the argument with a +
+character (as usual, it will terminate the entire argument with a
+newline); thus if the line after the line containing the x X command
+starts with +, then the newline ending the line containing the x X
+command should be treated as part of the argument to the x X command,
+the + should be ignored, and the part of the line following the + should
+be treated like the part of the line following the x X command.
+
+
+
+
+@node Font Files, , gtroff Output, File formats
+@section Font Files
+@cindex font files
+@cindex files, font
+
+
+The groff font format is roughly a superset of the ditroff font
+format. Unlike the ditroff font format, there is no associated binary
+format. The font files for device name are stored in a directory
+@file{dev@var{name}}. There are two types of file: a device
+description file called @file{DESC} and for each font @samp{F} a font
+file called @file{F}. These are text files; there is no associated
+binary format.
+
+@subsection @file{DESC} file format
+@pindex DESC
+
+The @file{DESC} file can contain the following types of line:
+
+@table @code
+@item res @var{n}
+There are @var{n} machine units per inch.
+@item hor @var{n}
+The horizontal resolution is @var{n} machine units.
+@item vert @var{n}
+The vertical resolution is @var{n} machine units.
+@item sizescale @var{n}
+The scale factor for pointsizes. By default this has a value of 1. One
+scaled point is equal to one point/@var{n}. The arguments to the
+@code{unitwidth} and @code{sizes} commands are given in scaled points.
+@xref{Fractional Type Sizes}, for more information.
+@item unitwidth @var{n}
+Quantities in the font files are given in machine units for fonts whose
+point size is @var{n} scaled points.
+@item tcommand
+This means that the postprocessor can handle the @code{t} and
+@code{u} output commands.
+@item sizes @var{s1} @var{s2}@dots{}@var{sn} 0
+This means that the device has fonts at @var{s1}, @var{s2},
+@dots{}@var{sn} scaled points. The list of sizes must be terminated
+by a 0. Each @var{si} can also be a range of
+sizes @var{m}-@var{n}. The list can extend over more than one line.
+@item styles @var{S1 S2@dots{}Sm}
+The first @var{m} font positions will be associated with styles
+@var{S1}@dots{}@var{Sm}.
+@item fonts @var{n} @var{F1 F2 F3@dots{}Fn}
+Fonts @var{F1@dots{}Fn} will be mounted in the font positions
+@var{m}+1, @dots{}, @var{m}+@var{n} where @var{m}
+is the number of styles. This command may extend over more than one
+line. A font name of 0 will cause no font to be mounted on the
+corresponding font position.
+@item family @var{fam}
+The default font family is @var{fam}.
+@item charset
+This line and everything following in the file are ignored. It is
+allowed for the sake of backwards compatibility.
+@end table
+
+The @code{res}, @code{unitwidth}, @code{fonts} and @code{sizes} lines
+are compulsory. Other commands are ignored by troff but may be used
+by postprocessors to store arbitrary information about the device in
+the @file{DESC} file.
+
+
+@subsection Font file format
+
+A font file has two sections. The first section is a sequence of lines
+each containing a sequence of blank delimited words; the first word in
+the line is a key, and subsequent words give a value for that key.
+
+@table @code
+@item name @var{F}
+The name of the font is @var{F}.
+@item spacewidth @var{n}
+The normal width of a space is @var{n}.
+@item slant @var{n}
+The characters of the font have a slant of @var{n} degrees.
+(Positive means forward.)
+@item ligatures @var{lig1} @var{lig2}@dots{}@var{lign} [0]
+Characters @var{lig1}, @var{lig2}, @dots{}, @var{lign} are ligatures;
+possible ligatures are ff, fi, fl and ffl. For backwards
+compatibiliy, the list of ligatures may be terminated with a 0. The
+list of ligatures may not extend over more than one line.
+@item special
+The font is special; this means that when a character is requested that
+is not present in the current font, it will be searched for in any
+special fonts that are mounted.
+@end table
+
+Other commands are ignored by troff but may be used by postprocessors to
+store arbitrary information about the font in the font file.
+
+The first section can contain comments which start with the # character
+and extend to the end of a line.
+
+The second section contains one or two subsections. It must contain a
+@code{charset} subsection and it may also contain a @code{kernpairs}
+subsection. These subsections can appear in any order. Each
+subsection starts with a word on a line by itself.
+
+The word @code{charset} starts the @code{charset} subsection. The
+@code{charset} line is followed by a sequence of lines. Each line
+gives information for one character. A line comprises a number of
+fields separated by blanks or tabs. The format is
+
+@display
+@var{name} @var{metrics} @var{type} @var{code} @var{comment}
+@end display
+
+@var{name} identifies the character: if @var{name} is a single
+character @var{c} then it corresponds to the groff input character
+@var{c}; if it is of the form @samp{\@var{c}} where @var{c} is a
+single character, then it corresponds to the groff input character
+@samp{\@var{c}}; otherwise it corresponds to the groff input character
+@samp{\[@var{name}]} (if it is exactly two characters @var{xx} it can
+be entered as @samp{\(@var{xx}}.) Groff supports eight bit characters;
+however some utilities has difficulties with eight bit characters.
+For this reason, there is a convention that the @var{name}
+@samp{char@var{n}} is equivalent to the single character whose code is
+@var{n}. For example, @samp{char163} would be equivalent to the
+character with @var{code} 163 which is the pounds sterling sign in ISO
+Latin-1 character set. The name @samp{---} is special and indicates
+that the character is unnamed; such characters can only be used by
+means of the @code{\N} escape sequence in troff.
+
+The @var{type} field gives the character type:
+
+@table @code
+@item 1
+means the character has an descender, for example, p;
+@item 2
+means the character has an ascender, for example, b;
+@item 3
+means the character has both an ascender and a descender, for example,
+@samp{(}.
+@end table
+
+The @var{code} field gives the code which the postprocessor uses to
+print the character. The character can also be input to groff using
+this code by means of the @code{\N} escape sequence. The code can be any
+integer. If it starts with a 0 it will be interpreted as octal; if it
+starts with 0x or 0X it will be intepreted as hexdecimal.
+
+Anything on the line after the @var{code} field will be ignored.
+
+The @var{metrics} field has the form:
+
+@smallexample
+@var{width[,height[,depth[,italic_correction[,left_italic_correction[,subscript_correction]]]]]}
+@end smallexample
+
+There must not be any spaces between these subfields. Missing
+subfields are assumed to be 0. The subfields are all decimal
+integers. Since there is no associated binary format, these values
+are not required to fit into a variable of type @samp{char} as they
+are in ditroff. The @var{width} subfields gives the width of the
+character. The @var{height} subfield gives the height of the
+character (upwards is positive); if a character does not extend above
+the baseline, it should be given a zero height, rather than a negative
+height. The @var{depth} subfield gives the depth of the character,
+that is, the distance below the lowest point below the baseline to
+which the character extends (downwards is positive); if a character
+does not extend below above the baseline, it should be given a zero
+depth, rather than a negative depth. The @var{italic_correction}
+subfield gives the amount of space that should be added after the
+character when it is immediately to be followed by a character from a
+roman font. The @var{left_italic_correction} subfield gives the
+amount of space that should be added before the character when it is
+immediately to be preceded by a character from a roman font. The
+@var{subscript_correction} gives the amount of space that should be
+added after a character before adding a subscript. This should be less
+than the italic correction.
+
+A line in the @code{charset} section can also have the format
+
+@example
+@var{name} "
+@end example
+
+This indicates that @var{name} is just another name for the character
+mentioned in the preceding line.
+
+The word @code{kernpairs} starts the kernpairs section. This contains a
+sequence of lines of the form:
+
+@display
+@var{c1 c2 n}
+@end display
+
+This means that when character @var{c1} appears next to character
+@var{c2} the space between them should be increased by @var{n}. Most
+entries in kernpairs section will have a negative value for @var{n}.
+
+
+
+@node Installation, Request Index, File formats, Top
+@chapter Installation
+@cindex installation
+
+
+
+@node Request Index, Register Index, Installation, Top
+@chapter Request Index
+
+@printindex fn
+
+
+@node Register Index, String Index, Request Index, Top
+@chapter Register Index
+
+@printindex vr
+
+
+@node String Index, Macro Index, Register Index, Top
+@chapter String Index
+
+
+
+@node Macro Index, Program Index, String Index, Top
+@chapter Macro Index
+
+
+
+@node Program Index, Concept Index, Macro Index, Top
+@chapter Program Index
+
+@printindex pg
+
+
+
+@node Concept Index, , Program Index, Top
+@chapter Concept Index
+
+@printindex cp
+
+
+
+@summarycontents
+@contents
+@bye
diff --git a/doc/homepage.ms b/doc/homepage.ms
new file mode 100755
index 00000000..b542d732
--- /dev/null
+++ b/doc/homepage.ms
@@ -0,0 +1,162 @@
+.\" This file gives a small example how a web page could look like if created
+.\" with groff.
+.\"
+.\"
+.\" To make it work with other output devices also, we include tmac.arkup
+.\" directly.
+.mso tmac.arkup
+.\"
+.LP
+.\"
+.\" set a longer line than the default as we have some long ftp addresses
+.\" which groff cannot split
+.nr LL 7i
+.TL
+Home of Groff (GNU Troff).
+.sp 1i
+.LP
+GNU Troff
+.URL (Groff) http://groff.ffii.org/
+\(em a
+.URL GNU http://www.gnu.org/
+project.
+Hosted by
+.URL FFII http://ffii.org/ .
+.br
+.LINE
+.LP
+Groff (GNU Troff) is a document processor which reads plain text mixed with
+formatting commands and produces formatted output.
+.LP
+Groff now supports HTML for the Web.
+Please see
+.URL "Groff Web Tips" "#Web Tips" .
+.sp
+.SH
+Download
+.LP
+.URL Germany "ftp://groff.ffii.org/pub/groff/"
+|
+.URL USA "ftp://ftp.gnu.org/gnu/groff/"
+.LP
+.URL License http://www.gnu.org/copyleft/gpl.html
+|
+.URL "Mailing list" http://ffii.org/mailman/listinfo/groff/
+|
+.URL "Groff for Windows" "http://www.cs.vu.nl/~tmgil/misc/wingroff.html"
+.sp
+User issues lead:
+.MAILTO Ted.Harding@nessie.mcc.ac.uk "Ted Harding"
+.br
+Technical issues lead:
+.MAILTO wl@gnu.org "Werner Lemberg"
+.SH
+README
+.LP
+This is the GNU groff document formatting system.
+The version number is given in the file VERSION.
+.LP
+Included in this release are implementations of troff, pic, eqn, tbl, refer,
+the -man macros and the -ms macros, and drivers for PostScript, TeX dvi
+format, HP LaserJet 4 printers, HTML format (still alpha), and
+typewriter-like devices.
+Also included is a modified version of the Berkeley -me macros, an enhanced
+version of the X11 xditview previewer, and an implementation of the -mm
+macros contributed by
+.MAILTO jh@axis.se "J\(:orgen H\(:agg" .
+.LP
+See the file INSTALL for installation instructions.
+You will require a C++ compiler.
+.LP
+The file NEWS describes recent user-visible changes to groff.
+.LP
+Groff is free software.
+See the file COPYING for copying permission.
+.LP
+The file PROBLEMS describes various problems that have been encountered in
+compiling, installing, and running groff.
+.LP
+For the moment, the documentation assumes that you are already familiar with
+the Unix versions of troff, -man, -ms and the preprocessors.
+.LP
+The most recent released version of groff is always available by anonymous
+ftp from ftp.gnu.org in the directory pub/gnu/groff.
+.LP
+A CVS repository is now available, containing the current development
+version of groff.
+You can access it with the commands:
+.sp
+.RS
+.nf
+\fC
+export CVSROOT=:pserver:anoncvs@anoncvs.ffii.org:/var/cvs
+cvs login
+cvs -z9 co groff
+\fR
+.fi
+.RE
+.sp
+.LP
+(if the prompt for the password appears, just press the enter key).
+After a successful login you no longer need the first two commands; an
+update of a checked out repository should be done with:
+.sp
+.RS
+\fC
+cvs -z9 update -dP
+\fR
+.RE
+.sp
+.LP
+Please read the info pages of cvs for further details.
+.LP
+Alternatively, you can download snapshots (which are updated twice a day)
+from
+.URL here ftp://ftp.ffii.org/pub/groff/devel/groff-current.tar.gz
+or a diff file relative to the latest official groff release as:
+.sp
+.RS
+\fC
+ftp://ftp.ffii.org/pub/groff/devel/groff-[version]-current.diff.gz
+\fR
+.RE
+.sp
+.LP
+Please report bugs using the form in the file BUG-REPORT; the idea of this
+is to make sure that FSF has all the information it needs to fix the bug.
+At the very least, read the BUG-REPORT form and make sure that you supply
+all the information that it asks for.
+Even if you are not sure that something is a bug, report it using
+BUG-REPORT: this will enable us to determine whether it really is a bug or
+not.
+.LP
+Three mailing lists are available:
+.sp
+.RS
+.nf
+\fC
+bug-groff@gnu.org for reporting bugs
+groff@gnu.org for general discussion of groff
+groff-commit@ffii.org a read-only list showing logs of
+ commitments to the CVS repository
+\fR
+.fi
+.RE
+.sp
+.LP
+Note that groff@gnu.org is an alias for groff@ffii.org; you must be
+subscribed to the `groff' and `groff-commit' lists to send mails.
+.LP
+To subscribe, send e-mail to [list]-request@[domain] (example:
+groff-request@ffii.org) with the word `subscribe' in either the
+subject or body of the e-mail (don't include the quotes).
+.LP
+GNU groff was written by
+.MAILTO jjc@jclark.com "James Clark" .
+It is now maintained by
+.MAILTO Ted.Harding@nessie.mcc.ac.uk "Ted Harding"
+and
+.MAILTO wl@gnu.org "Werner Lemberg" .
+.LINE
+.
+.\" EOF
diff --git a/doc/meintro.me b/doc/meintro.me
new file mode 100644
index 00000000..192edb7b
--- /dev/null
+++ b/doc/meintro.me
@@ -0,0 +1,2246 @@
+.\" Copyright (c) 1986 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms are permitted
+.\" provided that the above copyright notice and this paragraph are
+.\" duplicated in all such forms and that any documentation,
+.\" advertising materials, and other materials related to such
+.\" distribution and use acknowledge that the software was developed
+.\" by the University of California, Berkeley. The name of the
+.\" University may not be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\" @(#)intro.me 6.4 (Berkeley) 7/17/89
+.\"
+.\" Modified for groff by jjc@jclark.com.
+.\"UC 7
+.ll 6.5i
+.lt 6.5i
+.ds MO @VERSION@
+.nr si 3n
+.he 'USING GROFF AND \-ME''%'
+.\"eh 'USD:22-%''Writing Papers with NROFF using \-me'
+.\"oh 'Writing Papers with NROFF using \-me''USD:22-%'
+.ds U \s-1UNIX\s0
+.ds N \s-1NROFF\s0
+.ds T \s-1TROFF\s0
+.ds G \s-1GROFF\s0
+.+c
+.(l C
+.sz 14
+.b "Writing Papers with GROFF using \-me"
+.sz
+.sp 2
+.ul
+Eric P. Allman*
+.(f
+*Author's current address:
+Britton Lee, Inc.,
+1919 Addison Suite 105,
+Berkeley, California 94704.
+.)f
+.sp
+Project INGRES
+Electronics Research Laboratory
+University of California, Berkeley
+Berkeley, California 94720
+.sp 2
+.i "Modified for \*G by James Clark"
+.)l
+.sp 4
+.pp
+This document describes
+the text processing facilities
+available on the \*U\(dg
+.(f
+\(dg\*U is a trademark
+of AT&T Bell Laboratories
+.)f
+operating system
+via \*G and the
+\-me
+macro package.
+It is assumed
+that the reader
+already is generally familiar
+with the \*U operating system
+and a text editor
+such as
+.b ex .
+This is intended to be a casual introduction,
+and
+as such not all material is covered.
+In particular,
+many variations and additional features
+of the \-me macro package
+are not explained.
+For a complete discussion of this
+and other issues,
+see
+.ul
+The \-me Reference Manual
+and
+.ul
+The \*N/\*T Reference Manual.
+.pp
+\*G, a computer program
+that runs on the \*U operating system,
+reads an input file
+prepared by the user
+and outputs a formatted paper
+suitable for publication or framing.
+The input consists of
+.i text ,
+or words to be printed,
+and
+.i requests ,
+which give instructions
+to the \*G program
+telling how to format the printed copy.
+.pp
+Section 1
+describes the basics
+of text processing.
+Section 2
+describes the basic requests.
+Section 3
+introduces displays.
+Annotations,
+such as footnotes,
+are handled in
+section 4.
+The more complex requests
+which are not discussed in section 2
+are covered in section 5.
+Finally,
+section 6
+discusses things you will need
+to know
+if you want to typeset documents.
+If you are a novice,
+you probably won't want to read beyond section 4
+until you have tried some of the basic features out.
+.pp
+When you have your raw text ready,
+call the \*G formatter by typing
+as a request to the \*U shell:
+.(b
+groff \-me \-T\c
+.i "type files"
+.)b
+where
+.i type
+describes the type of
+output device you are using.
+A complete description of options
+to the \*G command can be found in
+.b groff (1).
+.pp
+The word
+.i argument
+is used in this manual
+to mean a word or number
+which appears on the same line
+as a request
+which modifies the meaning
+of that request.
+For example,
+the request
+.(b
+\&.sp
+.)b
+spaces one line,
+but
+.(b
+\&.sp 4
+.)b
+spaces four lines.
+The number
+.b 4
+is an
+.i argument
+to the
+.b .sp
+request
+which says to space four lines
+instead of one.
+Arguments are separated from the request
+and from each other
+by spaces.
+.sh 1 "Basics of Text Processing"
+.pp
+The primary function
+of \*G
+is to
+.i collect
+words from input lines,
+.i fill
+output lines with those words,
+.i justify
+the right hand margin by inserting extra spaces
+in the line,
+and output the result.
+For example,
+the input:
+.(b
+Now is the time
+for all good men
+to come to the aid
+of their party.
+Four score and seven
+years ago,...
+.)b
+will be read,
+packed onto output lines,
+and justified
+to produce:
+.(b F
+Now is the time
+for all good men
+to come to the aid
+of their party.
+Four score and seven
+years ago,...
+.)b
+Sometimes you may want to start a new output line
+even though the line you are on
+is not yet full;
+for example,
+at the end of a paragraph.
+To do this
+you can cause a
+.i break ,
+which
+starts a new output line.
+Some requests
+cause a break automatically,
+as do blank input lines
+and input lines beginning with a space.
+.pp
+Not all input lines
+are text to be formatted.
+Some of the input lines
+are
+.i requests
+which describe
+how to format the text.
+Requests always have a period
+or an apostrophe
+(\c
+.q "\|\(aa\|" )
+as the first character
+of the input line.
+.pp
+The text formatter
+also does more complex things,
+such as automatically numbering pages,
+skipping over page folds,
+putting footnotes in the correct place,
+and so forth.
+.pp
+I can offer you a few hints
+for preparing text
+for input to \*G.
+First,
+keep the input lines short.
+Short input lines are easier to edit,
+and \*G will pack words onto longer lines
+for you anyhow.
+In keeping with this,
+it is helpful
+to begin a new line
+after every period,
+comma,
+or phrase,
+since common corrections
+are to add or delete sentences
+or phrases.
+Second,
+do not put spaces at the end of lines,
+since this can sometimes confuse the \*N
+processor.
+Third,
+do not hyphenate words at the end of lines
+(except words that should have hyphens in them,
+such as
+.q mother-in-law );
+\*G is smart enough to hyphenate words
+for you as needed,
+but is not smart enough
+to take hyphens out
+and join a word back together.
+Also,
+words such as
+.q mother-in-law
+should not be broken
+over a line,
+since then you will get a space
+where not wanted,
+such as
+.tr @-
+.nh
+.q "mother@\ in@law" .
+.br
+.tr @@
+.hy 14
+.sh 1 "Basic Requests"
+.sh 2 "Paragraphs"
+.pp
+Paragraphs are begun
+by using the
+.b .pp
+request.
+For example,
+the input:
+.(b
+\&.pp
+Now is the time for all good men
+to come to the aid of their party.
+Four score and seven years ago,...
+.)b
+produces a blank line
+followed by an indented first line.
+The result is:
+.(b F
+.ti +\n(piu
+Now is the time for all good men
+to come to the aid of their party.
+Four score and seven years ago,...
+.)b
+.pp
+Notice that the sentences
+of the paragraphs
+.i "must not"
+begin with a space,
+since blank lines
+and lines beginning with spaces
+cause a break.
+For example,
+if I had typed:
+.(b
+\&.pp
+Now is the time for all good men
+ to come to the aid of their party.
+Four score and seven years ago,...
+.)b
+The output would be:
+.(b F
+.ti +\n(piu
+Now is the time for all good men
+ to come to the aid of their party.
+Four score and seven years ago,...
+.)b
+A new line begins after the word
+.q men
+because the second line began with a space character.
+.pp
+There are many
+fancier
+types of paragraphs,
+which will be described later.
+.sh 2 "Headers and Footers"
+.pp
+Arbitrary headers and footers
+can be put
+at the top and bottom
+of every page.
+Two requests
+of the form
+.b .he \ \c
+.i title
+and
+.b .fo \ \c
+.i title
+define the titles to put at the head and the foot
+of every page,
+respectively.
+The titles are called
+.i three-part
+titles,
+that is,
+there is a left-justified part,
+a centered part,
+and a right-justified part.
+To separate these three parts
+the first character of
+.i title
+(whatever it may be)
+is used as a delimiter.
+Any character may be used,
+but
+backslash
+and double quote marks
+should be avoided.
+The percent sign
+is replaced by the current page number
+whenever found in the title.
+For example,
+the input:
+.(b
+\&.he \(aa\(aa%\(aa\(aa
+\&.fo \(aaJane Jones\(aa\(aaMy Book\(aa
+.)b
+results in the page number
+centered at the top
+of each page,
+.q "Jane Jones"
+in the lower left corner,
+and
+.q "My Book"
+in the lower right corner.
+.sh 2 "Double Spacing"
+.pp
+.ls 2
+\*G will double space output text automatically if you
+use the request
+.b ".ls\ 2" ,
+as is done in this section.
+You can revert to single spaced mode
+by typing
+.b ".ls\ 1" .
+.ls 1
+.sh 2 "Page Layout"
+.pp
+A number of requests allow
+you to change the way the printed copy looks,
+sometimes called the
+.i layout
+of the output page.
+Most of these requests adjust the placing
+of
+.q "white space"
+(blank lines or spaces).
+In these explanations,
+characters in italics
+should be replaced with values you wish to use;
+bold characters
+represent characters which should actually be typed.
+.pp
+The
+.b .bp
+request
+starts a new page.
+.pp
+The request
+.b .sp \ \c
+.i N
+leaves
+.i N
+lines of blank space.
+.i N
+can be omitted
+(meaning skip a single line)
+or can be of the form
+.i N \^\c
+.b i
+(for
+.i N
+inches)
+or
+.i N \^\c
+.b c
+(for
+.i N
+centimeters).
+For example, the input:
+.(b
+\&.sp 1.5i
+My thoughts on the subject
+\&.sp
+.)b
+leaves one and a half inches of space,
+followed by the line
+.q "My thoughts on the subject" ,
+followed by a single blank line.
+.pp
+The
+.b .in \ \c
+.i +N
+request
+changes the amount of white space
+on the left of the page
+(the
+.i indent ).
+The argument
+.i N
+can be of the form
+.b + \c
+.i N
+(meaning leave
+.i N
+spaces more than you are already leaving),
+.b \- \c
+.i N
+(meaning leave less than you do now),
+or just
+.i N
+(meaning leave exactly
+.i N
+spaces).
+.i N
+can be of the form
+.i N \^\c
+.b i
+or
+.i N \^\c
+.b c
+also.
+For example,
+the input:
+.(b
+initial text
+\&.in 5
+some text
+\&.in +1i
+more text
+\&.in \-2c
+final text
+.)b
+produces
+.q "some text"
+indented exactly five spaces
+from the left margin,
+.q "more text"
+indented five spaces
+plus one inch
+from the left margin
+(fifteen spaces
+on a pica typewriter),
+and
+.q "final text"
+indented five spaces
+plus one inch
+minus two centimeters
+from the margin.
+That is,
+the output is:
+.(b
+initial text
+.in +5
+some text
+.in +1i
+more text
+.in -2c
+final text
+.)b
+.pp
+The
+.b .ti \ \c
+.i +N
+(temporary indent)
+request is used like
+.b .in \ \c
+.i +N
+when the indent
+should apply to one line only,
+after which it should revert
+to the previous indent.
+For example,
+the input:
+.(b
+\&.in 1i
+\&.ti 0
+Ware, James R. The Best of Confucius,
+Halcyon House, 1950.
+An excellent book containing translations of
+most of Confucius\(aa most delightful sayings.
+A definite must for anyone interested in the early foundations
+of Chinese philosophy.
+.)b
+produces:
+.in 1i+\n($iu
+.ti \n($iu
+Ware, James R. The Best of Confucius,
+Halcyon House, 1950.
+An excellent book containing translations of
+most of Confucius' most delightful sayings.
+A definite must for anyone interested in the early foundations
+of Chinese philosophy.
+.pp
+Text lines can be centered
+by using the
+.b .ce
+request.
+The line after the
+.b .ce
+is centered
+(horizontally)
+on the page.
+To center more than one line,
+use
+.b .ce \ \c
+.i N
+(where
+.i N
+is the number of lines to center),
+followed by the
+.i N
+lines.
+If you want to center many lines
+but don't want to count them,
+type:
+.(b
+\&.ce 1000
+lines to center
+\&.ce 0
+.)b
+The
+.b ".ce\ 0"
+request tells \*G to center zero more lines,
+in other words,
+stop centering.
+.pp
+All of these requests
+cause a break;
+that is,
+they always start
+a new line.
+If you want to start a new line
+without performing any other action,
+use
+.b .br .
+.sh 1 "Displays"
+.pp
+Displays are sections of text
+to be set off
+from the body of the paper.
+Major quotes,
+tables,
+and figures
+are types of displays,
+as are all the examples
+used in this document.
+All displays
+except centered blocks
+are output
+single spaced.
+.sh 2 "Major Quotes"
+.pp
+Major quotes
+are quotes which are several lines long,
+and hence are set in from the rest
+of the text
+without quote marks
+around them.
+These can be generated
+using the commands
+.b .(q
+and
+.b .)q
+to surround the quote.
+For example,
+the input:
+.(b
+As Weizenbaum points out:
+\&.(q
+It is said that to explain is to explain away.
+This maxim is nowhere so well fulfilled
+as in the areas of computer programming,...
+\&.)q
+.)b
+generates as output:
+.lp
+As Weizenbaum points out:
+.(q
+It is said that to explain is to explain away.
+This maxim is nowhere so well fulfilled
+as in the areas of computer programming,...
+.)q
+.sh 2 "Lists"
+.pp
+A
+.i list
+is an indented,
+single spaced,
+unfilled display.
+Lists should be used
+when the material to be printed
+should not be filled and justified
+like normal text,
+such as columns of figures
+or the examples used in this paper.
+Lists are surrounded
+by the requests
+.b .(l
+and
+.b .)l .
+For example,
+type:
+.(b
+Alternatives to avoid deadlock are:
+\&.(l
+Lock in a specified order
+Detect deadlock and back out one process
+Lock all resources needed before proceeding
+\&.)l
+.)b
+will produce:
+.br
+Alternatives to avoid deadlock are:
+.(l
+Lock in a specified order
+Detect deadlock and back out one process
+Lock all resources needed before proceeding
+.)l
+.sh 2 "Keeps"
+.pp
+A
+.i keep
+is a display of lines
+which are kept on a single page
+if possible.
+An example of where you would use a keep
+might be a diagram.
+Keeps differ from lists
+in that lists may be broken
+over a page boundary
+whereas keeps will not.
+.pp
+Blocks are the basic kind of keep.
+They begin with the request
+.b .(b
+and end with the request
+.b .)b .
+If there is not room on the current page
+for everything in the block,
+a new page is begun.
+This has the unpleasant effect
+of leaving blank space
+at the bottom of the page.
+When this is not appropriate,
+you can use the alternative,
+called
+.i "floating keeps" .
+.pp
+.i "Floating keeps"
+move relative to the text.
+Hence,
+they are good for things
+which will be referred to
+by name,
+such as
+.q "See figure 3" .
+A floating keep will appear
+at the bottom of the current page
+if it will fit;
+otherwise,
+it will appear at the top
+of the next page.
+Floating keeps begin with the line
+.b .(z
+and end with the line
+.b .)z .
+For an example of a floating keep,
+see figure 1.
+.(z
+.in 1i
+.xl -1i
+.hl
+\&.(z
+\&.hl
+Text of keep to be floated.
+\&.sp
+\&.ce
+Figure 1. Example of a Floating Keep.
+\&.hl
+\&.)z
+.sp
+.ce
+Figure 1. Example of a Floating Keep.
+.hl
+.)z
+The
+.b .hl
+request is used
+to draw a horizontal line
+so that the figure
+stands out from the text.
+.sh 2 "Fancier Displays"
+.pp
+Keeps and lists are normally collected in
+.i nofill
+mode,
+so that they are good for tables and such.
+If you want a display
+in fill mode
+(for text),
+type
+.b ".(l\ F"
+(Throughout this section,
+comments applied to
+.b .(l
+also apply to
+.b .(b
+and
+.b .(z ).
+This kind of display
+will be indented from both margins.
+For example,
+the input:
+.(b
+\&.(l F
+And now boys and girls,
+a newer, bigger, better toy than ever before!
+Be the first on your block to have your own computer!
+Yes kids, you too can have one of these modern
+data processing devices.
+You too can produce beautifully formatted papers
+without even batting an eye!
+\&.)l
+.)b
+will be output as:
+.(b F
+And now boys and girls,
+a newer, bigger, better toy than ever before!
+Be the first on your block to have your own computer!
+Yes kids, you too can have one of these modern
+data processing devices.
+You too can produce beautifully formatted papers
+without even batting an eye!
+.)b
+.pp
+Lists and blocks are also normally indented
+(floating keeps are normally left justified).
+To get a left-justified list,
+type
+.b ".(l\ L" .
+To get a list centered
+line-for-line,
+type
+.b ".(l C" .
+For example,
+to get a filled,
+left justified list, enter:
+.(b
+\&.(l L F
+text of block
+\&.)l
+.)b
+The input:
+.(b
+\&.(l
+first line of unfilled display
+more lines
+\&.)l
+.)b
+produces the indented text:
+.(b
+first line of unfilled display
+more lines
+.)b
+Typing the character
+.b L
+after the
+.b .(l
+request produces the left justified result:
+.(b L
+first line of unfilled display
+more lines
+.)b
+Using
+.b C
+instead of
+.b L
+produces the line-at-a-time centered output:
+.(b C
+first line of unfilled display
+more lines
+.)b
+.pp
+Sometimes it may be
+that you want to center several lines
+as a group,
+rather than centering them
+one line at a time.
+To do this
+use centered blocks,
+which are surrounded by the requests
+.b .(c
+and
+.b .)c .
+All the lines are centered as a unit,
+such that the longest line is centered
+and the rest are
+lined up around that line.
+Notice that lines
+do not move
+relative to each other
+using centered blocks,
+whereas they do
+using the
+.b C
+argument to keeps.
+.pp
+Centered blocks are
+.i not
+keeps,
+and may be used
+in conjunction
+with keeps.
+For example,
+to center a group of lines
+as a unit
+and keep them
+on one page,
+use:
+.(b
+\&.(b L
+\&.(c
+first line of unfilled display
+more lines
+\&.)c
+\&.)b
+.)b
+to produce:
+.(b L
+.(c
+first line of unfilled display
+more lines
+.)c
+.)b
+If the block requests
+(\c
+.b .(b
+and
+.b .)b )
+had been omitted
+the result would have been the same,
+but with no guarantee
+that the lines of the centered block
+would have all been on one page.
+Note the use of the
+.b L
+argument to
+.b .(b ;
+this causes the centered block
+to center within the entire line
+rather than within the line
+minus the indent.
+Also,
+the center requests
+must
+be nested
+.i inside
+the keep requests.
+.sh 1 "Annotations"
+.pp
+There are a number of requests
+to save text
+for later printing.
+.i Footnotes
+are printed at the bottom of the current page.
+.i "Delayed text"
+is intended to be a variant form
+of footnote;
+the text is printed only
+when explicitly called for,
+such as at the end of each chapter.
+.i Indexes
+are a type of delayed text
+having a tag
+(usually the page number)
+attached to each entry
+after a row of dots.
+Indexes are also saved
+until called for explicitly.
+.sh 2 "Footnotes"
+.pp
+Footnotes begin with the request
+.b .(f
+and end with the request
+.b .)f .
+The current footnote number is maintained
+automatically,
+and can be used by typing \e**,
+to produce a footnote number\**.
+.(f
+\**Like this.
+.)f
+The number is automatically incremented
+after every footnote.
+For example,
+the input:
+.(b
+\&.(q
+A man who is not upright
+and at the same time is presumptuous;
+one who is not diligent and at the same time is ignorant;
+one who is untruthful and at the same time is incompetent;
+such men I do not count among acquaintances.\e**
+\&.(f
+\e**James R. Ware,
+\&.ul
+The Best of Confucius,
+Halcyon House, 1950.
+Page 77.
+\&.)f
+\&.)q
+.)b
+generates the result:
+.(q
+A man who is not upright
+and at the same time is presumptuous;
+one who is not diligent and at the same time is ignorant;
+one who is untruthful and at the same time is incompetent;
+such men I do not count among acquaintances.\**
+.(f
+\**James R. Ware,
+.ul
+The Best of Confucius,
+Halcyon House, 1950.
+Page 77.
+.)f
+.)q
+It is important
+that the footnote
+appears
+.i inside
+the quote,
+so that you can be sure
+that the footnote
+will appear
+on the same page
+as the quote.
+.sh 2 "Delayed Text"
+.pp
+Delayed text
+is very similar to a footnote
+except that it is printed
+when called for explicitly.
+This allows a list of
+references to
+appear
+(for example)
+at the end of each chapter,
+as is the convention in some disciplines.
+Use
+.b \e*#
+on delayed text
+instead of
+.b \e**
+as on footnotes.
+.pp
+If you are using delayed text
+as your standard reference mechanism,
+you can still use footnotes,
+except that you may want to reference them
+with special characters*
+.(f
+*Such as an asterisk.
+.)f
+rather than numbers.
+.sh 2 "Indexes"
+.pp
+An
+.q index
+(actually more like a table of contents,
+since the entries are not sorted alphabetically)
+resembles delayed text,
+in that it is saved until called for.
+However,
+each entry has the page number
+(or some other tag)
+appended to the last line
+of the index entry
+after a row of dots.
+.pp
+Index entries begin with the request
+.b .(x
+and end with
+.b .)x .
+The
+.b .)x
+request may have a argument,
+which is the value to print
+as the
+.q "page number" .
+It defaults to the current page number.
+If the page number given is an underscore
+(\c
+.q _ )
+no page number
+or line of dots
+is printed at all.
+To get the line of dots
+without a page number,
+type
+.b ".)x """"" ,
+which specifies an explicitly null page number.
+.pp
+The
+.b .xp
+request prints the index.
+.pp
+For example,
+the input:
+.(b
+\&.(x
+Sealing wax
+\&.)x
+\&.(x
+Cabbages and kings
+\&.)x _
+\&.(x
+Why the sea is boiling hot
+\&.)x 2.5a
+\&.(x
+Whether pigs have wings
+\&.)x ""
+\&.(x
+This is a terribly long index entry, such as might be used
+for a list of illustrations, tables, or figures; I expect it to
+take at least two lines.
+\&.)x
+\&.xp
+.)b
+generates:
+.(x
+Sealing wax
+.)x
+.(x
+Cabbages and kings
+.)x _
+.(x
+Why the sea is boiling hot
+.)x 2.5a
+.(x
+Whether pigs have wings
+.)x ""
+.(x
+This is a terribly long index entry, such as might be used
+for a list of illustrations, tables, or figures; I expect it to
+take at least two lines.
+.)x
+.xp
+.pp
+The
+.b .(x
+request may have a single character
+argument,
+specifying the
+.q name
+of the index;
+the normal index is
+.b x .
+Thus,
+several
+.q indices
+may be maintained simultaneously
+(such as a list of tables, table of contents, etc.).
+.pp
+Notice that the index must be printed
+at the
+.i end
+of the paper,
+rather than at the beginning
+where it will probably appear
+(as a table of contents);
+the pages may have to be physically rearranged
+after printing.
+.sh 1 "Fancier Features"
+.pp
+A large number of fancier requests
+exist,
+notably requests to provide other sorts of paragraphs,
+numbered sections of the form
+.b 1.2.3
+(such as used in this document),
+and multicolumn output.
+.sh 2 "More Paragraphs"
+.pp
+Paragraphs generally start with
+a blank line
+and with the first line
+indented.
+It is possible to get
+left-justified block-style paragraphs
+by using
+.b .lp
+instead of
+.b .pp ,
+as demonstrated by the next paragraph.
+.lp
+Sometimes you want to use paragraphs
+that have the
+.i body
+indented,
+and the first line
+exdented
+(opposite of indented)
+with a label.
+This can be done with the
+.b .ip
+request.
+A word specified on the same line as
+.b .ip
+is printed in the margin,
+and the body is lined up
+at a prespecified position
+(normally five spaces).
+For example,
+the input:
+.(b
+\&.ip one
+This is the first paragraph.
+Notice how the first line
+of the resulting paragraph lines up
+with the other lines in the paragraph.
+\&.ip two
+And here we are at the second paragraph already.
+You may notice that the argument to \c
+.b .ip
+appears
+in the margin.
+\&.lp
+We can continue text...
+.)b
+produces as output:
+.ip one
+This is the first paragraph.
+Notice how the first line of the resulting paragraph lines up
+with the other lines in the paragraph.
+.ip two
+And here we are at the second paragraph already.
+You may notice that the argument to
+.b .ip
+appears
+in the margin.
+.lp
+We can continue text without starting a new indented
+paragraph
+by using the
+.b .lp
+request.
+.pp
+If you have spaces in the label of a
+.b .ip
+request,
+you must use an
+.q "unpaddable space"
+instead of a regular space.
+This is typed as a backslash character
+(\c
+.q \e )
+followed by a space.
+For example,
+to print the label
+.q "Part 1" ,
+enter:
+.(b
+\&.ip "Part\e 1"
+.)b
+.pp
+If a label of an indented paragraph
+(that is, the argument to
+.b .ip )
+is longer than the space allocated for the label,
+.b .ip
+will begin a new line after the label.
+For example,
+the input:
+.(b
+\&.ip longlabel
+This paragraph had a long label.
+The first character of text on the first line
+will not line up with the text on second and subsequent lines,
+although they will line up with each other.
+.)b
+will produce:
+.ip longlabel
+This paragraph had a long label.
+The first character of text on the first line
+will not line up with the text on second and subsequent lines,
+although they will line up with each other.
+.pp
+It is possible to change the size of the label
+by using a second argument
+which is the size of the label.
+For example,
+the above example could be done correctly
+by saying:
+.(b
+\&.ip longlabel 10
+.)b
+which will make the paragraph indent
+10 spaces for this paragraph only.
+If you have many paragraphs to indent
+all the same amount,
+use the
+.i "number register"
+.b ii .
+For example, to leave one inch of space
+for the label,
+type:
+.(b
+\&.nr ii 1i
+.)b
+somewhere before the first call to
+.b .ip .
+Refer to the reference manual
+for more information.
+.pp
+If
+.b .ip
+is used
+with no argument at all
+no hanging tag will be printed.
+For example,
+the input:
+.(b
+\&.ip [a]
+This is the first paragraph of the example.
+We have seen this sort of example before.
+\&.ip
+This paragraph is lined up with the previous paragraph,
+but it has no tag in the margin.
+.)b
+produces as output:
+.ip [a]
+This is the first paragraph of the example.
+We have seen this sort of example before.
+.ip
+This paragraph is lined up with the previous paragraph,
+but it has no tag in the margin.
+.pp
+A special case of
+.b .ip
+is
+.b .np ,
+which automatically
+numbers paragraphs sequentially from 1.
+The numbering is reset at the next
+.b .pp ,
+.b .lp ,
+or
+.b .sh
+(to be described in the next section)
+request.
+For example,
+the input:
+.(b
+\&.np
+This is the first point.
+\&.np
+This is the second point.
+Points are just regular paragraphs
+which are given sequence numbers automatically
+by the .np request.
+\&.pp
+This paragraph will reset numbering by .np.
+\&.np
+For example,
+we have reverted to numbering from one now.
+.)b
+generates:
+.np
+This is the first point.
+.np
+This is the second point.
+Points are just regular paragraphs
+which are given sequence numbers automatically
+by the .np request.
+.pp
+This paragraph will reset numbering by .np.
+.np
+For example,
+we have reverted to numbering from one now.
+.pp
+The
+.b .bu
+request gives lists of this sort that are identified with
+bullets rather than numbers.
+The paragraphs are also crunched together.
+For example,
+the input:
+.(b
+\&.bu
+\&One egg yolk
+\&.bu
+\&One tablespoon cream or top milk
+\&.bu
+\&Salt, cayenne, and lemon juice to taste
+\&.bu
+\&A generous two tablespoonfuls of butter
+.)b
+produces\**:
+.(f
+\**By the way,
+if you put the first three ingredients in a a heavy, deep pan
+and whisk the ingredients madly over a medium flame
+(never taking your hand off the handle of the pot)
+until the mixture reaches the consistency of custard
+(just a minute or two),
+then mix in the butter off-heat,
+you will have a wonderful Hollandaise sauce.
+.)f
+.bu
+One egg yolk
+.bu
+One tablespoon cream or top milk
+.bu
+Salt, cayenne, and lemon juice to taste
+.bu
+A generous two tablespoonfuls of butter
+.sh 2 "Section Headings"
+.pp
+Section numbers
+(such as the ones used in this document)
+can be automatically generated
+using the
+.b .sh
+request.
+You must tell
+.b .sh
+the
+.i depth
+of the section number
+and a section title.
+The depth
+specifies how many numbers
+are to appear
+(separated by decimal points)
+in the section number.
+For example,
+the section number
+.b 4.2.5
+has a depth of three.
+.pp
+Section numbers
+are incremented
+in a fairly intuitive fashion.
+If you add a number
+(increase the depth),
+the new number starts out
+at one.
+If you subtract section numbers
+(or keep the same number)
+the final number is incremented.
+For example,
+the input:
+.(b
+\&.sh 1 "The Preprocessor"
+\&.sh 2 "Basic Concepts"
+\&.sh 2 "Control Inputs"
+\&.sh 3
+\&.sh 3
+\&.sh 1 "Code Generation"
+\&.sh 3
+.)b
+produces as output the result:
+.(b
+.b
+1. The Preprocessor
+1.1. Basic Concepts
+1.2. Control Inputs
+1.2.1.
+1.2.2.
+2. Code Generation
+2.1.1.
+.)b
+.pp
+You can specify the section number to begin
+by placing the section number after the section title,
+using spaces instead of dots.
+For example,
+the request:
+.(b
+\&.sh 3 "Another section" 7 3 4
+.)b
+will begin the section numbered
+.b 7.3.4 ;
+all subsequent
+.b .sh
+requests will number relative to this number.
+.pp
+There are more complex features
+which will cause each section to be indented
+proportionally to the depth of the section.
+For example, if you enter:
+.(b
+\&.nr si \c
+.i N
+.)b
+each section will be indented by an amount
+.i N .
+.i N
+must have a scaling factor attached,
+that is, it must be of the form
+.i Nx ,
+where
+.i x
+is a character telling what units
+.i N
+is in.
+Common values for
+.i x
+are
+.b i
+for inches,
+.b c
+for centimeters,
+and
+.b n
+for
+.i ens
+(the width of a single character).
+For example,
+to indent each section
+one-half inch,
+type:
+.(b
+\&.nr si 0.5i
+.)b
+After this,
+sections will be indented by
+one-half inch
+per level of depth in the section number.
+For example,
+this document was produced
+using the request
+.(b
+\&.nr si 3n
+.)b
+at the beginning of the input file,
+giving three spaces of indent
+per section depth.
+.pp
+Section headers without automatically generated numbers
+can be done using:
+.(b
+\&.uh "Title"
+.)b
+which will do a section heading,
+but will put no number on the section.
+.sh 2 "Parts of the Basic Paper"
+.pp
+There are some requests
+which assist in setting up
+papers.
+The
+.b .tp
+request
+initializes for a title page.
+There are no headers or footers
+on a title page,
+and unlike other pages
+you can space down
+and leave blank space
+at the top.
+For example,
+a typical title page might appear as:
+.(b
+\&.tp
+\&.sp 2i
+\&.(l C
+THE GROWTH OF TOENAILS
+IN UPPER PRIMATES
+\&.sp
+by
+\&.sp
+Frank N. Furter
+\&.)l
+\&.bp
+.)b
+.pp
+The
+.b .+c \ \c
+.i T
+request can be used
+to start chapters.
+Each chapter is automatically numbered
+from one,
+and a heading is printed at the top of each chapter
+with the chapter number
+and the chapter name
+.i T .
+For example,
+to begin a chapter called
+.q Conclusions ,
+use the request:
+.(b
+\&.+c "CONCLUSIONS"
+.)b
+which will produce,
+on a new page,
+the lines
+.(b C
+CHAPTER 5
+CONCLUSIONS
+.)b
+with appropriate spacing for a thesis.
+Also, the header is moved to the foot of the page
+on the first page of a chapter.
+Although the
+.b .+c
+request was not designed to work only with the
+.b .th
+request,
+it is tuned for the format acceptable
+for a PhD thesis
+at Berkeley.
+.pp
+If the
+title parameter
+.i T
+is omitted from the
+.b .+c
+request,
+the result is a chapter with no heading.
+This can also be used at the beginning
+of a paper;
+for example,
+.b .+c
+was used to generate page one
+of this document.
+.pp
+Although
+papers traditionally have the abstract,
+table of contents,
+and so forth at the front of the paper,
+it is more convenient to format
+and print them last
+when using \*G.
+This is so that index entries
+can be collected and then printed
+for the table of contents
+(or whatever).
+At the end of the paper,
+issue the
+.b ".++ P"
+request,
+which begins the preliminary part
+of the paper.
+After issuing this request,
+the
+.b .+c
+request will begin a preliminary section
+of the paper.
+Most notably,
+this prints the page number
+restarted from one
+in lower case Roman numbers.
+.b .+c
+may be used repeatedly
+to begin different parts of the
+front material
+for example,
+the abstract,
+the table of contents,
+acknowledgments,
+list of illustrations,
+etc.
+The request
+.b ".++ B"
+may also be used
+to begin the bibliographic section
+at the end of the paper.
+For example,
+the paper might appear
+as outlined in figure 2.
+(In this figure,
+comments begin with the sequence
+.b \e" .)
+.(z
+.hl
+.if t .in 0.5i
+.if t .ta 2i
+.if n .ta 3i
+\&.th \e" set for thesis mode
+\&.fo \(aa\(aaDRAFT\(aa\(aa \e" define footer for each page
+\&.tp \e" begin title page
+\&.(l C \e" center a large block
+THE GROWTH OF TOENAILS
+IN UPPER PRIMATES
+\&.sp
+by
+\&.sp
+Frank Furter
+\&.)l \e" end centered part
+\&.+c INTRODUCTION \e" begin chapter named "INTRODUCTION"
+\&.(x t \e" make an entry into index `t'
+Introduction
+\&.)x \e" end of index entry
+text of chapter one
+\&.+c "NEXT CHAPTER" \e" begin another chapter
+\&.(x t \e" enter into index `t' again
+Next Chapter
+\&.)x
+text of chapter two
+\&.+c CONCLUSIONS
+\&.(x t
+Conclusions
+\&.)x
+text of chapter three
+\&.++ B \e" begin bibliographic information
+\&.+c BIBLIOGRAPHY \e" begin another `chapter'
+\&.(x t
+Bibliography
+\&.)x
+text of bibliography
+\&.++ P \e" begin preliminary material
+\&.+c "TABLE OF CONTENTS"
+\&.xp t \e" print index `t' collected above
+\&.+c PREFACE \e" begin another preliminary section
+text of preface
+.sp 2
+.in 0
+.ce
+Figure 2. Outline of a Sample Paper
+.hl
+.)z
+.sh 2 "Equations and Tables"
+.pp
+Two special \*U programs exist
+to format special types of material.
+.b Eqn
+sets equations.
+.b Tbl
+arranges to print
+extremely pretty tables
+in a variety of formats.
+This document will only describe
+the embellishments
+to the standard features;
+consult the reference manuals
+for those processors
+for a description of their use.
+.pp
+The
+.b eqn
+program is described fully
+in the document
+.ul
+Typesetting Mathematics \- User's Guide
+by Brian W. Kernighan
+and Lorinda L. Cherry.
+Equations are centered,
+and are kept on one page.
+They are introduced by the
+.b .EQ
+request and terminated by the
+.b .EN
+request.
+.pp
+The
+.b .EQ
+request may take an
+equation number as an
+optional argument,
+which is printed vertically centered
+on the right hand side
+of the equation.
+If the equation becomes too long
+it should be split
+between two lines.
+To do this, type:
+.(b
+\&.EQ (eq 34)
+text of equation 34
+\&.EN C
+\&.EQ
+continuation of equation 34
+\&.EN
+.)b
+The
+.b C
+on the
+.b .EN
+request
+specifies that the equation
+will be continued.
+.pp
+The
+.b tbl
+program produces tables.
+It is fully described
+(including numerous examples)
+in the document
+.ul
+Tbl \- A Program to Format Tables
+by M. E. Lesk.
+Tables begin with the
+.b .TS
+request
+and end with the
+.b .TE
+request.
+Tables are normally kept on a single page.
+If you have a table which is too big
+to fit on a single page,
+so that you know it will extend
+to several pages,
+begin the table with the request
+.b ".TS\ H"
+and put the request
+.b .TH
+after the part of the table
+which you want
+duplicated at the top of every page
+that the table is printed on.
+For example, a table definition
+for a long table might look like:
+.ds TA \|\h'.4n'\v'-.2n'\s-4\zT\s0\v'.2n'\h'-.4n'\(ci\|
+.if n .ds TA \ \o'-T'\ \"
+.(b
+\&.TS H
+c s s
+n n n.
+THE TABLE TITLE
+\&.TH
+text of the table
+\&.TE
+.)b
+.pp
+.sh 2 "Two Column Output"
+.pp
+You can get two column output
+automatically
+by using the request
+.b .2c .
+This causes everything after it
+to be output in two-column form.
+The request
+.b .bc
+will start a new column;
+it differs from
+.b .bp
+in that
+.b .bp
+may leave a totally blank column
+when it starts a new page.
+To revert to single column output,
+use
+.b .1c .
+.sh 2 "Defining Macros"
+.pp
+A
+.i macro
+is a collection of requests and text
+which may be used
+by stating a simple request.
+Macros begin with the line
+.b ".de" \ \c
+.i xx
+(where
+.i xx
+is the name of the macro to be defined)
+and end with the line consisting of two dots.
+After defining the macro,
+stating the line
+.b . \c
+.i xx
+is the same as stating all the other lines.
+For example,
+to define a macro
+that spaces 3 lines
+and then centers the next input line,
+enter:
+.(b
+\&.de SS
+\&.sp 3
+\&.ce
+\&..
+.)b
+and use it by typing:
+.(b
+\&.SS
+\&Title Line
+(beginning of text)
+.)b
+.pp
+Macro names may be one or two characters.
+In order to avoid conflicts
+with names in \-me,
+always use upper case letters as names.
+The only names to avoid are
+.b TS ,
+.b TH ,
+.b TE ,
+.b EQ ,
+and
+.b EN .
+.sh 2 "Annotations Inside Keeps"
+.pp
+Sometimes you may want to put
+a footnote
+or index entry inside a keep.
+For example,
+if you want to maintain a
+.q "list of figures"
+you will want to do something like:
+.(b
+\&.(z
+\&.(c
+text of figure
+\&.)c
+\&.ce
+Figure 5.
+\&.(x f
+Figure 5
+\&.)x
+\&.)z
+.)b
+which you may hope
+will give you a figure
+with a label
+and an entry in the index
+.b f
+(presumably a list of figures index).
+Unfortunately,
+the
+index entry
+is read and interpreted
+when the keep is read,
+not when it is printed,
+so the page number in the index is likely to be wrong.
+The solution is to use the magic string
+.b \e!
+at the beginning of all the lines dealing with the index.
+In other words,
+you should use:
+.(b
+\&.(z
+\&.(c
+Text of figure
+\&.)c
+\&.ce
+Figure 5.
+\e!.(x f
+\e!Figure 5
+\e!.)x
+\&.)z
+.)b
+which will defer the processing of the index
+until the figure is output.
+This will guarantee
+that the page number in the index
+is correct.
+The same comments apply
+to
+blocks
+(with
+.b .(b
+and
+.b .)b )
+as well.
+.sh 1 "\*T and the Photosetter"
+.pp
+With a little care,
+you can prepare
+documents that
+will print nicely
+on either a regular terminal
+or when phototypeset
+using the \*T formatting program.
+.sh 2 "Fonts"
+.pp
+A
+.i font
+is a style of type.
+There are three fonts
+that are available simultaneously,
+Times Roman,
+Times Italic,
+and Times Bold,
+plus the special math font.
+The normal font is Roman.
+.pp
+There are ways of switching between fonts.
+The requests
+.b .r ,
+.b .i ,
+.b .b ,
+and
+.b .bi
+switch to Roman,
+italic,
+bold,
+and bold-italic fonts respectively.
+You can set a single word
+in some font
+by typing (for example):
+.(b
+\&.i word
+.)b
+which will set
+.i word
+in italics
+but does not affect the surrounding text.
+.pp
+Notice that if you are setting more than one word
+in whatever font,
+you must surround that word with double quote marks
+(`\|"\|')
+so that it will appear to the \*G processor as a single word.
+The quote marks will not appear in the formatted text.
+If you do want a quote mark to appear,
+you should quote the entire string
+(even if a single word),
+and use
+.i two
+quote marks where you want one to appear.
+For example,
+if you want to produce the text:
+.(b
+.i """Master Control\|"""
+.)b
+in italics, you must type:
+.(b
+\&.i """Master Control\e|"""
+.)b
+The
+.b \e|
+produces a very narrow space
+so that the
+.q l
+does not overlap the quote sign in \*G,
+like this:
+.(b
+.i """Master Control"""
+.)b
+.pp
+There are also some
+.q pseudo-fonts
+available.
+The input:
+.(b
+\&.(b
+\&.u underlined
+\&.bx "words in a box"
+\&.)b
+.)b
+generates
+.(b
+.u underlined
+.bx "words in a box"
+.)b
+Notice that pseudo font requests
+set only the single parameter in the pseudo font;
+ordinary font requests will begin setting all text
+in the special font
+if you do not provide a parameter.
+No more than one word
+should appear
+with these three font requests
+in the middle of lines.
+This is because
+of the way \*G justifies text.
+For example,
+if you were to issue the requests:
+.(b
+\&.u "some bold italics"
+and
+\&.bx "words in a box"
+.)b
+in the middle of a line
+\*G would produce
+.u "some bold italics"
+and
+.bx "words in a box" ,\p
+which I think you will agree does not look good.
+.pp
+The second parameter
+of all font requests
+is set in the original font.
+For example,
+the font request:
+.(b
+\&.b bold face
+.)b
+generates
+.q bold
+in bold font,
+but sets
+.q face
+in the font of the surrounding text,
+resulting in:
+.(b
+.b bold face.
+.)b
+To set the two words
+.b bold
+and
+.b face
+both in
+.b "bold face" ,
+type:
+.(b
+\&.b "bold face"
+.)b
+.pp
+You can mix fonts in a word by using the
+special sequence
+.b \ec
+at the end of a line
+to indicate
+.q "continue text processing" ;
+this allows input lines
+to be joined together
+without a space between them.
+For example, the input:
+.(b
+\&.u under \ec
+\&.i italics
+.)b
+generates
+.u under \c
+.i italics ,
+but if we had typed:
+.(b
+\&.u under
+\&.i italics
+.)b
+the result would have been
+.u under
+.i italics
+as two words.
+.sh 2 "Point Sizes"
+.pp
+The phototypesetter
+supports different sizes of type,
+measured in points.
+The default point size
+is 10 points
+for most text,
+8 points for footnotes.
+To change the pointsize,
+type:
+.(b
+\&.sz \c
+.i +N
+.)b
+where
+.i N
+is the size wanted in points.
+The
+.i "vertical spacing"
+(distance between the bottom of most letters
+(the
+.i baseline )
+between adjacent lines)
+is set to be proportional
+to the type size.
+.pp
+These pointsize changes are
+.i temporary !!!
+For example,
+to reset the pointsize of basic text to twelve point, use:
+.(b
+\&.nr pp 12
+\&.nr sp 12
+\&.nr tp 12
+.)b
+to reset the default pointsize of
+paragraphs,
+section headers,
+and titles respectively.
+If you only want to set the names of sections in a larger pointsize,
+use:
+.(b
+\&.nr sp 11
+.)b
+alone \*- this sets section titles
+(e.g.,
+.b "Point Sizes"
+above)
+in a larger font than the default.
+.pp
+A single word or phrase can be set in a smaller pointsize
+than the surrounding text
+using the
+.b .sm
+request.
+This is especially convenient for words that are all capitals,
+due to the optical illusion that makes them look even larger
+than they actually are.
+For example:
+.(b
+\&.sm UNIX
+.)b
+prints as
+.sm UNIX
+rather than
+UNIX.
+.pp
+Warning:
+changing point sizes
+on the phototypesetter
+is a slow mechanical operation.
+On laser printers it may require loading new fonts.
+Size changes
+should be considered carefully.
+.sh 2 "Quotes"
+.pp
+It is conventional when using
+the typesetter to
+use pairs of grave and acute accents
+to generate double quotes,
+rather than the
+double quote character
+(`\|"\|').
+This is because it looks better
+to use grave and acute accents;
+for example, compare
+"quote" to
+``quote''.
+.pp
+You may use the sequences
+.b \e*(lq
+and
+.b \e*(rq
+to stand for the left and right quote
+respectively.
+For example,
+use:
+.(b
+\e*(lqSome things aren\(aat true
+even if they did happen.\e*(rq
+.)b
+to generate the result:
+.(b
+.q "Some things aren't true even if they did happen."
+.)b
+As a shorthand,
+the special font request:
+.(b
+\&.q "quoted text"
+.)b
+will generate
+.q "quoted text" .
+Notice that you must surround
+the material to be quoted
+with double quote marks
+if it is more than one word.
+.sh 0
+.sp 1i
+.b Acknowledgments
+.pp
+I would like to thank
+Bob Epstein,
+Bill Joy,
+and Larry Rowe
+for having the courage
+to use the \-me macros
+to produce non-trivial papers
+during the development stages;
+Ricki Blau,
+Pamela Humphrey,
+and Jim Joyce
+for their help with the documentation phase;
+peter kessler
+for numerous complaints years after I was
+.q done
+with this project,
+most accompanied by fixes
+(hence forcing me to fix several small bugs);
+and the plethora of people who have contributed ideas
+and have given support for the project.
+.sp 1i
+This document was
+\*G'ed
+on \*(td
+and applies to the version of the \-me macros
+included with \*G version \*(MO.
diff --git a/doc/meref.me b/doc/meref.me
new file mode 100644
index 00000000..5a62ae11
--- /dev/null
+++ b/doc/meref.me
@@ -0,0 +1,2198 @@
+.\" Copyright (c) 1986 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms are permitted
+.\" provided that the above copyright notice and this paragraph are
+.\" duplicated in all such forms and that any documentation,
+.\" advertising materials, and other materials related to such
+.\" distribution and use acknowledge that the software was developed
+.\" by the University of California, Berkeley. The name of the
+.\" University may not be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\" @(#)ref.me 6.4 (Berkeley) 7/17/89
+.\"
+.\" Modified by jjc@jclark.com for groff.
+.\"UC 7
+.ll 6.5i
+.lt 6.5i
+.\"pn 0
+.ds MO @VERSION@
+.de TL \" *** title line
+.lp
+.di XX
+..
+.ie \n(.g \{\
+.de DE
+\?\h'|\\n(DIu'\c\?
+..
+.\}
+.el \{\
+.de DE
+\\\\h'|\\\\n(DIu'\\\\c
+..
+.\}
+.am DE
+.br
+.di
+.in +\\n(DIu
+.ti 0
+.cu 1000
+.XX
+.rm XX
+.cu 0
+..
+.ds G \s-1GROFF\s0
+.ds N \s-1NROFF\s0
+.ds T \s-1TROFF\s0
+.nr DI 1.5i
+.he '\-ME REFERENCE MANUAL''%'
+.de NR
+.b "\en\\$1" "\\$2"
+..
+.de ST
+.b "\e*\\$1" "\\$2"
+..
+.\"sc
+.\"eh 'USD:23-%''\-me Reference Manual'
+.\"oh '\-me Reference Manual''USD:23-%'
+.+c
+.ce 20
+.sz 14
+.b "\-ME REFERENCE MANUAL"
+.sz
+.sp
+.i "\*G Version \*(MO\(dg"
+.(f
+\(dgBased on Berkeley Release 2.31.
+.)f
+.sp 2
+.ul
+Eric P. Allman*
+.(f
+*Author's current address:
+Britton Lee, Inc.,
+1919 Addison Suite 105,
+Berkeley, California 94704.
+.)f
+.sp
+Project INGRES
+Electronics Research Laboratory
+University of California, Berkeley
+Berkeley, California 94720
+.sp 2
+.i "Modified for \*G by James Clark"
+.ce 0
+.sp 4
+.pp
+This document describes
+in extremely terse form
+the features
+of the
+.b \-me
+macro package
+for \*G.
+Some familiarity is assumed
+with
+\*G.
+Specifically,
+the reader should understand
+breaks,
+fonts,
+pointsizes,
+the use and definition of number registers
+and strings,
+how to define macros,
+and scaling factors for ens, points,
+.b v 's
+(vertical line spaces),
+etc.
+.pp
+For a more casual introduction
+to text processing
+using \*G,
+refer to the document
+.ul
+Writing Papers with \*G using \-me.
+.pp
+There are a number of macro parameters
+that may be adjusted.
+Fonts may be set to a font number only.
+Font 0 is no font change;
+the font of the surrounding text
+is used instead.
+Notice that font 0 is a
+.q pseudo-font ;
+that is,
+it is simulated by the macros.
+This means that although it is legal to set a font register
+to zero,
+it is not legal to use the escape character form,
+such as:
+.(b
+\ef0
+.)b
+.pp
+All distances
+are in basic units,
+so it is nearly always necessary
+to use a scaling factor.
+For example,
+the request
+to set the paragraph indent
+to eight one-en spaces is:
+.(b
+\&.nr pi 8n
+.)b
+and not
+.(b
+\&.nr pi 8
+.)b
+which would set the paragraph indent to eight basic units,
+or about 0.02 inch.
+Default parameter values are given in brackets
+in the remainder of this document.
+.pp
+Registers and strings
+of the form
+.b $ \c
+.i x
+may be used in expressions
+but should not be changed.
+Macros of the form
+.b $ \c
+.i x
+perform some function
+(as described)
+and may be redefined
+to change this function.
+This may be a sensitive operation;
+look at the body of the original macro
+before changing it.
+.pp
+All names in \-me
+follow a rigid naming convention.
+The user may define number registers,
+strings,
+and macros,
+provided that s/he
+uses single character upper case names
+or double character names
+consisting of letters and digits,
+with at least one upper case letter.
+In no case should special characters
+be used in user-defined names.
+Locally defined macros
+should all be of the form
+.b .* \c
+.i X ,
+where
+.i X
+is any letter
+(upper or lower case)
+or digit.
+.pp
+This documentation was \*G'ed
+on \*(td
+and applies to \*G version
+\*(MO
+of the \-me macros.
+.sh 1 "Paragraphing"
+.pp
+These macros are used
+to begin paragraphs.
+The standard paragraph macro
+is
+.b .pp ;
+the others are all variants
+to be used for special purposes.
+.pp
+After the first call to one of the paragraphing macros
+defined in this section
+or the
+.b .sh
+macro
+(defined in the next session),
+the effects of changing parameters
+which will have a global effect
+on the format of the page
+(notably page length and header and footer margins)
+are not well defined
+and should be avoided.
+.TL
+.b .lp
+.DE
+Begin left-justified paragraph.
+Centering and underlining
+are turned off if they were on,
+the font is set to
+.NR (pf
+[1]
+the type size
+is set to
+.NR (pp
+[10p],
+and a
+.NR (ps
+space is inserted
+before the paragraph
+[0.35v]
+The indent is reset
+to
+.NR ($i
+[0]
+plus
+.NR (po
+[0]
+unless the paragraph
+is inside a display.
+(see
+.b .ba ).
+At least
+the first two lines
+of the paragraph
+are kept together
+on a page.
+.TL
+.b .pp
+.DE
+Like
+.b .lp ,
+except that it puts
+.NR (pi
+[5n]
+units of indent.
+This is the standard paragraph macro.
+.TL
+.b .ip
+.i T
+.i I
+.DE
+Indented paragraph
+with hanging tag.
+The body of the following paragraph
+is indented
+.i I
+spaces
+(or
+.NR (ii
+[5n]
+spaces
+if
+.i I
+is not specified)
+more than a non-indented paragraph
+(such as with
+.b .pp )
+is.
+The title
+.i T
+is exdented (opposite of indented).
+The result is a paragraph
+with an even left edge
+and
+.i T
+printed in the margin.
+Any spaces in
+.i T
+must be unpaddable.
+If
+.i T
+will not fit in the space provided,
+.b .ip
+will start a new line.
+.TL
+.b .np
+.DE
+A variant of .ip which numbers paragraphs.
+Numbering is reset
+after a
+.b .lp ,
+.b .pp ,
+or
+.b .sh .
+The current paragraph number
+is in
+.NR ($p .
+.TL
+.b .bu
+.DE
+Like
+.b .np
+except that paragraphs are marked with bullets (\(bu).
+Leading space is eliminated to create compact lists.
+.sh 1 "Section Headings"
+.pp
+Numbered sections
+are similar to paragraphs
+except that a
+section number
+is automatically
+generated for each one.
+The section numbers are of the form
+.b 1.2.3 .
+The
+.i depth
+of the section
+is the count of numbers
+(separated by decimal points)
+in the section number.
+.pp
+Unnumbered section headings are similar,
+except that no number is attached
+to the heading.
+.TL
+.b .sh
+.i +N
+.i T
+.i "a b c d e f"
+.DE
+Begin numbered section
+of depth
+.i N .
+If
+.i N
+is missing
+the current depth
+(maintained in
+the number register
+.NR ($0 )
+is used.
+The values of
+the individual parts of the section number
+are maintained in
+.NR ($1
+through
+.NR ($6 .
+There is a
+.NR (ss
+[1v]
+space before the section.
+.i T
+is printed
+as a section title
+in font
+.NR (sf
+[8]
+and size
+.NR (sp
+[10p].
+The
+.q name
+of the section may be accessed via
+.ST ($n .
+If
+.NR (si
+is non-zero,
+the base indent
+is set to
+.NR (si
+times the section depth,
+and the section title
+is exdented.
+(See
+.b .ba .)
+Also,
+an additional indent of
+.NR (so
+[0]
+is added to the section title
+(but not to the body of the section).
+The font is then set
+to the paragraph font,
+so that more information may occur
+on the line
+with the section number
+and title.
+.b .sh
+insures that there is enough room
+to print the section head
+plus the beginning of a paragraph
+(about 3 lines total).
+If
+.i a
+through
+.i f
+are specified,
+the section number is set to that number
+rather than incremented automatically.
+If any of
+.i a
+through
+.i f
+are a hyphen
+that number is not reset.
+If
+.i T
+is a single underscore
+(\c
+.q _ )
+then the section depth and numbering is reset,
+but the base indent is not reset
+and nothing is printed out.
+This is useful to automatically
+coordinate section numbers with
+chapter numbers.
+.TL
+.b .sx
+.i +N
+.DE
+Go to section depth
+.i N
+[\c
+.b \-1 ],
+but do not print the number
+and title,
+and do not increment the section number
+at level
+.i N .
+This has the effect
+of starting a new paragraph
+at level
+.i N .
+.TL
+.b .uh
+.i T
+.DE
+Unnumbered section heading.
+The title
+.i T
+is printed
+with the same rules for spacing,
+font, etc.,
+as for
+.b .sh .
+.TL
+.b .$p
+.i T
+.i B
+.i N
+.DE
+Print section heading.
+May be redefined
+to get fancier headings.
+.i T
+is the title passed on the
+.b .sh
+or
+.b .uh
+line;
+.i B
+is the section number for this section,
+and
+.i N
+is the depth of this section.
+These parameters are not always present;
+in particular,
+.b .sh
+passes all three,
+.b .uh
+passes only the first,
+and
+.b .sx
+passes three,
+but the first two
+are null strings.
+Care should be taken if this macro
+is redefined;
+it is quite complex and subtle.
+.TL
+.b .$0
+.i T
+.i B
+.i N
+.DE
+This macro is called automatically
+after every call to
+.b .$p .
+It is normally undefined,
+but may be used
+to automatically put
+every section title
+into the table of contents
+or for some similar function.
+.i T
+is the section title
+for the section title which was just printed,
+.i B
+is the section number,
+and
+.i N
+is the section depth.
+.TL
+.b .$1
+\-
+.b .$6
+.DE
+Traps called just before printing that depth section.
+May be defined to
+(for example)
+give variable spacing
+before sections.
+These macros are called from
+.b .$p ,
+so if you redefine that macro
+you may lose this feature.
+.sh 1 "Headers and Footers"
+.ds TP \fI\(aal\|\(aam\^\(aar\^\(aa\fP
+.pp
+Headers and footers
+are put at the top and bottom
+of every page
+automatically.
+They are set in font
+.NR (tf
+[3]
+and size
+.NR (tp
+[10p].
+Each of the definitions
+apply as of the
+.i next
+page.
+Three-part titles
+must be quoted
+if there are two blanks adjacent
+anywhere in the title
+or more than eight blanks total.
+.pp
+The spacing
+of headers and footers
+are controlled by three number registers.
+.NR (hm
+[4v]
+is the distance from the top of the page
+to the top of the header,
+.NR (fm
+[3v]
+is the distance from the bottom of the page
+to the bottom of the footer,
+.NR (tm
+[7v]
+is the distance from the top of the page
+to the top of the text,
+and
+.NR (bm
+[6v]
+is the distance from the bottom of the page
+to the bottom of the text
+(nominal).
+The macros
+.b .m1 ,
+.b .m2 ,
+.b .m3 ,
+and
+.b .m4
+are also supplied for compatibility
+with
+\s-1ROFF\s0 documents.
+.TL
+.b .he
+\*(TP
+.DE
+Define three-part header,
+to be printed on the top
+of every page.
+.TL
+.b .fo
+\*(TP
+.DE
+Define footer,
+to be printed at the bottom
+of every page.
+.TL
+.b .eh
+\*(TP
+.DE
+Define header,
+to be printed at the top of every
+even-numbered page.
+.TL
+.b .oh
+\*(TP
+.DE
+Define header,
+to be printed at the top of every
+odd-numbered page.
+.TL
+.b .ef
+\*(TP
+.DE
+Define footer,
+to be printed at the bottom
+of every even-numbered page.
+.TL
+.b .of
+\*(TP
+.DE
+Define footer,
+to be printed at the bottom
+of every odd-numbered page.
+.TL
+.b .hx
+.DE
+Suppress headers and footers
+on the next page.
+.TL
+.b .m1
+.i +N
+.DE
+Set the space between the top of the page
+and the header
+[4v].
+.TL
+.b .m2
+.i +N
+.DE
+Set the space between the header
+and the first line of text
+[2v].
+.TL
+.b .m3
+.i +N
+.DE
+Set the space
+between the bottom of the text
+and the footer
+[2v].
+.TL
+.b .m4
+.i +N
+.DE
+Set the space
+between the footer
+and the bottom of the page
+[4v].
+.TL
+.b .ep
+.DE
+End this page,
+but do not begin the next page.
+Useful for forcing out footnotes,
+but other than
+that hardly every used.
+Must be followed by a
+.b .bp
+or the end of input.
+.TL
+.b .$h
+.DE
+Called at every page
+to print the header.
+May be redefined
+to provide fancy
+(e.g.,
+multi-line)
+headers,
+but doing so
+loses the function of the
+.b .he ,
+.b .fo ,
+.b .eh ,
+.b .oh ,
+.b .ef ,
+and
+.b .of
+requests,
+as well as the chapter-style title feature
+of
+.b .+c .
+.TL
+.b .$f
+.DE
+Print footer;
+same comments apply
+as in
+.b .$h .
+.TL
+.b .$H
+.DE
+A normally undefined macro
+which is called
+at the top of each page
+(after putting out
+the header,
+initial saved floating keeps,
+etc.);
+in other words,
+this macro is called immediately before
+printing text
+on a page.
+It can be used for column headings
+and the like.
+.sh 1 "Displays"
+.pp
+All displays except centered blocks
+and block quotes
+are preceded and followed
+by an extra
+.NR (bs
+[same as
+.NR (ps ]
+space.
+Quote spacing is stored in a separate register;
+centered blocks have no default initial or trailing space.
+The vertical spacing of all displays except quotes
+and centered blocks
+is stored in register
+.NR ($V
+instead of
+.NR ($v .
+.TL
+.b .(l
+.i m
+.i f
+.DE
+Begin list.
+Lists are single spaced,
+unfilled text.
+If
+.i f
+is
+.b F ,
+the list will be filled.
+If
+.i m
+[\c
+.b I ]
+is
+.b I
+the list is indented by
+.NR (bi
+[4m];
+if
+.b M
+the list is indented to the left margin;
+if
+.b L
+the list is left justified with respect to the text
+(different from
+.b M
+only if the base indent
+(stored in
+.NR ($i
+and set with
+.b .ba )
+is not zero);
+and if
+.b C
+the list is centered on a line-by-line basis.
+The list is set in font
+.NR (df
+[0].
+Must be matched by a
+.b .)l .
+This macro is almost like
+.b .(b
+except that no attempt is made
+to keep the display on one page.
+.TL
+.b .)l
+.DE
+End list.
+.TL
+.b .(q
+.DE
+Begin major quote.
+These are single spaced,
+filled,
+moved in from the text
+on both sides
+by
+.NR (qi
+[4n],
+preceded and followed
+by
+.NR (qs
+[same as
+.NR (bs ]
+space,
+and are set in point size
+.NR (qp
+[one point smaller than surrounding text].
+.TL
+.b .)q
+.DE
+End major quote.
+.TL
+.b .(b
+.i m
+.i f
+.DE
+Begin block.
+Blocks are a form of
+.i keep ,
+where the text of a keep
+is kept together on one page
+if possible
+(keeps are useful
+for tables and figures
+which should not be broken
+over a page).
+If the block will not fit
+on the current page
+a new page is begun,
+.i unless
+that would leave more than
+.NR (bt
+[0]
+white space
+at the bottom of the text.
+If
+.NR (bt
+is zero, the threshold feature
+is turned off.
+Blocks are not filled
+unless
+.i f
+is
+.b F ,
+when they are filled.
+The block will be left-justified
+if
+.i m
+is
+.b L ,
+indented by
+.NR (bi
+[4m]
+if
+.i m
+is
+.b I
+or absent,
+centered
+(line-for-line)
+if
+.i m
+is
+.b C ,
+and left justified to the margin
+(not to the base indent)
+if
+.i m
+is
+.b M .
+The block is set in font
+.NR (df
+[0].
+.TL
+.b .)b
+.DE
+End block.
+.TL
+.b .(z
+.i m
+.i f
+.DE
+Begin floating keep.
+Like
+.b .(b
+except that the keep is
+.i floated
+to the bottom of the page
+or the top of the next page.
+Therefore,
+its position relative to the text changes.
+The floating keep is preceded and followed
+by
+.NR (zs
+[1v]
+space.
+Also,
+it defaults to mode
+.b M .
+.TL
+.b .)z
+.DE
+End floating keep.
+.TL
+.b .(c
+.DE
+Begin centered block.
+The next keep
+is centered as a block,
+rather than on a line-by-line basis
+as with
+.b ".(b C" .
+This call may be nested
+inside keeps.
+.TL
+.b .)c
+.DE
+End centered block.
+.sh 1 Annotations
+.TL
+.b .(d
+.DE
+Begin delayed text.
+Everything in the next keep
+is saved for output
+later with
+.b .pd ,
+in a manner
+similar to footnotes.
+.TL
+.b .)d
+.i n
+.DE
+End delayed text.
+The delayed text number register
+.NR ($d
+and the associated string
+.ST #
+are incremented if
+.ST #
+has been referenced.
+.TL
+.b .pd
+.DE
+Print delayed text.
+Everything diverted via
+.b .(d
+is printed and truncated.
+This might be used
+at the end of each chapter.
+.TL
+.b .(f
+.DE
+Begin footnote.
+The text of the footnote
+is floated to the bottom
+of the page
+and set in font
+.NR (ff
+[1]
+and size
+.NR (fp
+[8p].
+Each entry
+is preceded by
+.NR (fs
+[0.2v]
+space,
+is indented
+.NR (fi
+[3n]
+on the first line,
+and is indented
+.NR (fu
+[0]
+from the right margin.
+Footnotes line up underneath
+two column output.
+If the text of the footnote
+will not all fit on one page
+it will be carried over
+to the next page.
+.TL
+.b .)f
+.i n
+.DE
+End footnote.
+The number register
+.NR ($f
+and the associated string
+.ST *
+are incremented
+if they have been referenced.
+.TL
+.b .$s
+.DE
+The macro to output the footnote separator.
+This macro may be redefined
+to give other size lines or other types
+of separators.
+Currently
+it draws a 1.5i line.
+.TL
+.b .(x
+.i x
+.DE
+Begin index entry.
+Index entries are saved in the index
+.i x
+[\c
+.b x ]
+until called up with
+.b .xp.
+Each entry is preceded
+by a
+.NR (xs
+[0.2v]
+space.
+Each entry is
+.q undented
+by
+.NR (xu
+[0.5i];
+this register tells how far the page number
+extends into the right margin.
+.TL
+.b .)x
+.i P
+.i A
+.DE
+End index entry.
+The index entry
+is finished with a row of dots
+with
+.i A
+[null]
+right justified on the last line
+(such as for an author's name),
+followed by P
+[\c
+.NR % ].
+If
+.i A
+is specified,
+.i P
+must be specified;
+.NR %
+can be used to print the current page number.
+If
+.i P
+is an underscore,
+no page number
+and no row of dots
+are printed.
+.TL
+.b .xp
+.i x
+.DE
+Print index
+.i x
+[\c
+.b x ].
+The index is formatted in the font, size, and so forth
+in effect at the time it is printed,
+rather than at the time it is collected.
+.sh 1 "Columned Output"
+.TL
+.b .2c
+.i +S
+.i N
+.DE
+Enter two-column mode.
+The column separation is set to
+.i +S
+[4n, 0.5i in ACM mode]
+(saved in
+.NR ($s ).
+The column width,
+calculated to fill the single column line length
+with both columns,
+is stored in
+.NR ($l .
+The current column
+is in
+.NR ($c .
+You can test register
+.NR ($m
+[1]
+to see if you are in single column
+or double column mode.
+Actually,
+the request enters
+.i N
+[2]
+column output.
+.TL
+.b .1c
+.DE
+Revert to single-column mode.
+.TL
+.b .bc
+.DE
+Begin column.
+This is like
+.b .bp
+except that it begins a new column
+on a new page
+only if necessary,
+rather than forcing a whole new page
+if there is another column left
+on the current page.
+.sh 1 "Fonts and Sizes"
+.TL
+.b .sz
+.i +P
+.DE
+The pointsize is set to
+.i P
+[10p],
+and the line spacing is set proportionally.
+The line spacing as a percentage of the pointsize expressed in units
+is stored in
+.NR ($v .
+The percentage used internally
+by displays and annotations
+is stored in
+.NR ($V
+(although this is not used by
+.b .sz ).
+This size is
+.i not
+sticky beyond many macros:
+in particular,
+.NR (pp
+(paragraph pointsize)
+modifies the pointsize every time a new paragraph is begun
+using the
+.b \&.pp ,
+.b \&.lp ,
+.b \&.ip ,
+.b \&.np ,
+or
+.b \&.bu
+macros.
+Also,
+.NR (fp
+(footnote pointsize),
+.NR (qp
+(quote pointsize),
+.NR (sp
+(section header pointsize),
+and
+.NR (tp
+(title pointsize)
+may modify the pointsize.
+.TL
+.b .r
+.i W
+.i X
+.DE
+Set
+.i W
+in roman font,
+appending
+.i X
+in the previous font.
+To append different font requests,
+use
+.i X
+=
+.b \ec .
+If no parameters,
+change to roman font.
+.TL
+.b .i
+.i W
+.i X
+.DE
+Set
+.i W
+in italics,
+appending
+.i X
+in the previous font.
+If no parameters,
+change to italic font.
+.TL
+.b .b
+.i W
+.i X
+.DE
+Set
+.i W
+in bold font
+and append
+.i X
+in the previous font.
+If no parameters,
+switch to bold font.
+.TL
+.b .u
+.i W
+.i X
+.DE
+Underline
+.i W
+and append
+.i X .
+This is a true underlining,
+as opposed to the
+.b .ul
+request,
+which changes to
+.q "underline font"
+(usually italics in \*G).
+It won't work right
+if
+.i W
+is spread or broken (including hyphenated).
+In other words,
+it is safe in nofill mode only.
+.TL
+.b .q
+.i W
+.i X
+.DE
+Quote
+.i W
+and append
+.i X .
+In \*G
+this surrounds
+.i W
+with
+.b \*(lq ,
+and
+.b \*(rq .
+.TL
+.b .bi
+.i W
+.i X
+.DE
+Set
+.i W
+in bold italics
+and append
+.i X .
+.TL
+.b .bx
+.i W
+.i X
+.DE
+Sets
+.i W
+in a box,
+with
+.i X
+appended.
+It won't work right
+if
+.i W
+is spread or broken (including hyphenated).
+In other words,
+it is safe in nofill mode only.
+.TL
+.b sm
+.i W
+.i X
+.DE
+Sets
+.i W
+in a smaller pointsize,
+with
+.i X
+appended.
+.sh 1 "Roff Support"
+.TL
+.b .ix
+.i +N
+.DE
+Indent,
+no break.
+Equivalent to
+.b \(aain
+.i N .
+.TL
+.b .bl
+.i N
+.DE
+Leave
+.i N
+contiguous white space,
+on the next page if not enough room
+on this page.
+Equivalent to a
+.b .sp
+.i N
+inside a block.
+.TL
+.b .pa
+.i +N
+.DE
+Equivalent to
+.b .bp .
+.TL
+.b .ro
+.DE
+Set page number
+in roman numerals.
+Equivalent to
+.b ".af % i" .
+.TL
+.b .ar
+.DE
+Set page number in Arabic.
+Equivalent to
+.b ".af % 1" .
+.TL
+.b .n1
+.DE
+Number lines in margin from one
+on each page.
+.TL
+.b .n2
+.i N
+.DE
+Number lines from
+.i N ,
+stop if
+.i N
+= 0.
+.TL
+.b .sk
+.DE
+Leave the next output page blank,
+except for headers and footers.
+This is used to leave space
+for a full-page diagram
+which is produced externally
+and pasted in later.
+To get a partial-page paste-in display,
+say
+.b .sv \ \c
+.i N ,
+where
+.i N
+is the amount of space
+to leave;
+this space will be output immediately
+if there is room,
+and will otherwise be output
+at the top of the next page.
+However, be warned:
+if
+.i N
+is greater than the amount of available space
+on an empty page,
+no space will ever be output.
+.sh 1 "Preprocessor Support"
+.TL
+.b .EQ
+.i m
+.i T
+.DE
+Begin equation.
+The equation is centered
+if
+.i m
+is
+.b C
+or omitted,
+indented
+.NR (bi
+[4m]
+if
+.i m
+is
+.b I ,
+and left justified if
+.i m
+is
+.b L .
+.i T
+is a title printed on the right margin
+next to the equation.
+See
+.i "Typesetting Mathematics \- User's Guide"
+by Brian W. Kernighan
+and Lorinda L. Cherry.
+.TL
+.b .EN
+.i c
+.DE
+End equation.
+If
+.i c
+is
+.b C
+the equation must be continued
+by immediately following
+with another
+.b .EQ ,
+the text of which
+can be centered
+along with this one.
+Otherwise,
+the equation is printed,
+always on one page,
+with
+.NR (es
+[0.5v]
+space
+above and below it.
+.TL
+.b .TS
+.i h
+.DE
+Table start.
+Tables are single spaced
+and kept on one page
+if possible.
+If you have a large table
+which will not fit on one page,
+use
+.i h
+=
+.b H
+and follow the header part
+(to be printed on every page of the table)
+with a
+.b .TH .
+See
+.i "Tbl \- A Program to Format Tables"
+by M. E. Lesk.
+.TL
+.b .TH
+.DE
+With
+.b ".TS H" ,
+ends the header portion of the table.
+.TL
+.b .TE
+.DE
+Table end.
+Note that this table
+does not float,
+in fact,
+it is not even guaranteed to stay on one page
+if you use requests such as
+.b .sp
+intermixed with the text
+of the table.
+If you want it to float
+(or if you use requests
+inside the table),
+surround the entire table
+(including the
+.b .TS
+and
+.b .TE
+requests)
+with the requests
+.b .(z
+and
+.b .)z .
+.TL
+.b .PS
+.i h
+.i w
+.DE
+Begin
+.i pic
+picture.
+.i H
+is the height and
+.i w
+is the width,
+both in basic units.
+.TL
+.b .PE
+.DE
+End picture.
+.TL
+.b .IS
+.DE
+Begin
+.i ideal
+picture.
+.TL
+.b .IE
+.DE
+End
+.i ideal
+picture.
+.TL
+.b .IF
+.DE
+End
+.i ideal
+picture (alternate form).
+.TL
+.b .GS
+.DE
+Begin
+.i gremlin
+picture.
+.TL
+.b .GE
+.DE
+End
+.i gremlin
+picture.
+.TL
+.b .GF
+.DE
+End
+.i gremlin
+picture (alternate form).
+.sh 1 "Miscellaneous"
+.TL
+.b .re
+.DE
+Reset tabs every 0.5i.
+.TL
+.b .ba
+.i +N
+.DE
+Set the base indent
+to
+.i +N
+[0]
+(saved in
+.NR ($i ).
+All paragraphs,
+sections,
+and displays
+come out indented by this amount.
+Titles and footnotes
+are unaffected.
+The
+.b .sh
+request performs a
+.b .ba
+request
+if
+.NR (si
+[0] is not zero,
+and sets the base indent to
+.NR (si \c
+.b * \c
+.NR ($0 .
+.TL
+.b .xl
+.i +N
+.DE
+Set the line length to
+.i N
+[6.0i].
+This differs
+from
+.b .ll
+because it only affects the current environment.
+.TL
+.b .ll
+.i +N
+.DE
+Set line length in all environments
+to
+.i N
+[6.0i].
+This should not be used
+after output has begun,
+and particularly not in two-column output.
+The current line length is stored in
+.NR ($l .
+.TL
+.b .hl
+.DE
+Draws a horizontal line
+the length of the page.
+This is useful
+inside floating keeps
+to differentiate
+between the text
+and the figure.
+.sh 1 "Standard Papers"
+.TL
+.b .tp
+.DE
+Begin title page.
+Spacing at the top of the page
+can occur,
+and headers and footers are suppressed.
+Also,
+the page number
+is not incremented
+for this page.
+.TL
+.b .++
+.i m
+.i H
+.DE
+This request defines the section of the paper
+which we are entering.
+The section type is defined by
+.i m .
+.b C
+means that we are entering the chapter portion
+of the paper,
+.b A
+means that we are entering the appendix portion
+of the paper,
+.b P
+means that the material following
+should be the preliminary portion
+(abstract, table of contents, etc.)
+portion of the paper,
+.b AB
+means that we are entering the abstract
+(numbered independently from 1
+in Arabic numerals),
+and
+.b B
+means that we are entering the bibliographic
+portion at the end of the paper.
+Also, the variants
+.b RC
+and
+.b RA
+are allowed,
+which specify renumbering of pages
+from one at the beginning of each
+chapter or appendix,
+respectively.
+The
+.i H
+parameter defines the new header.
+If there are any spaces in it,
+the entire header must be quoted.
+If you want the header to have the chapter number
+in it,
+Use the string
+.b "\e\e\e\en(ch" .
+For example, to number appendixes
+.b A.1
+etc.,
+type
+.b ".++ RA \(aa\(aa\(aa\e\e\e\en(ch.%\(aa" .
+Each section
+(chapter, appendix, etc.)
+should be preceded by the
+.b .+c
+request.
+It should be mentioned
+that it is easier when using
+\*T to put the front material
+at the end of the paper,
+so that the table of contents
+can be collected and put out;
+this material can then be physically
+moved to the beginning of the paper.
+.TL
+.b .+c
+.i T
+.DE
+Begin chapter with title
+.i T .
+The chapter number
+is maintained in
+.NR (ch .
+This register is incremented
+every time
+.b .+c
+is called with a parameter.
+The title and chapter number
+are printed by
+.b .$c .
+The header is moved to the footer
+on the first page
+of each chapter.
+If
+.i T
+is omitted,
+.b .$c
+is not called;
+this is useful for doing your own
+.q "title page"
+at the beginning of papers
+without a title page proper.
+.b .$c
+calls
+.b .$C
+as a hook so that chapter titles can be inserted
+into a table of contents automatically.
+The footnote numbering is reset to one.
+.TL
+.b .$c
+.i T
+.DE
+Print chapter number
+(from
+.NR (ch )
+and
+.i T .
+This macro can be redefined to your liking.
+It is defined by default
+to be acceptable
+for a PhD thesis
+at Berkeley.
+This macro calls
+.b $C ,
+which can be defined to make index entries,
+or whatever.
+.TL
+.b .$C
+.i K
+.i N
+.i T
+.DE
+This macro is called by
+.b .$c .
+It is normally undefined,
+but can be used to automatically insert
+index entries,
+or whatever.
+.i K
+is a keyword,
+either
+.q Chapter
+or
+.q Appendix
+(depending on the
+.b .++
+mode);
+.i N
+is the chapter or appendix number,
+and
+.i T
+is the chapter or appendix title.
+.sh 1 "Predefined Strings"
+.TL
+.ST *
+.DE
+Footnote number, actually
+.ST [ \c
+.NR ($f \c
+.ST ] .
+This macro is incremented
+after each call to
+.b .)f .
+.TL
+.ST #
+.DE
+Delayed text number.
+Actually
+[\c
+.NR ($d ].
+.TL
+.ST {
+.DE
+Superscript.
+This string gives upward movement
+and a change to a smaller point size.
+Extra space is left above the line
+to allow room for the superscript.
+.TL
+.ST }
+.DE
+Unsuperscript.
+Inverse to
+.ST { .
+For example,
+to produce a superscript
+you might type
+.b x \c
+.ST { \c
+.b 2 \c
+.ST } ,
+which will produce
+.b x\*{2\*} .
+.TL
+.ST <
+.DE
+Subscript.
+Extra space is left below the line
+to allow for the subscript.
+.TL
+.ST >
+.DE
+Inverse to
+.ST < .
+.TL
+.ST (dw
+.DE
+The day of the week,
+as a word.
+.TL
+.ST (mo
+.DE
+The month,
+as a word.
+.TL
+.ST (td
+.DE
+Today's date,
+directly printable.
+The date is of the form \*(td.
+Other forms of the date can be used
+by using
+.NR (dy
+(the day of the month;
+for example, \n(dy),
+.ST (mo
+(as noted above)
+or
+.NR (mo
+(the same,
+but as an ordinal number;
+for example, \*(mo is \n(mo),
+.NR (y4
+(the current year),
+and
+.NR (y2
+(the last two digits of the current year).
+.TL
+.ST (lq
+.DE
+Left quote marks.
+.TL
+.ST (rq
+.DE
+Right quote.
+.TL
+.ST \-
+.DE
+.ie \w'\(34'>0 \(34
+.el 3/4
+em dash.
+.sh 1 "Special Characters and Marks"
+.pp
+There are a number of special characters
+and diacritical marks
+(such as accents)
+available through \-me.
+.ta 15 +5 +6
+.nf
+Name Usage Example
+Acute accent \e*\(aa a\e*\(aa a\*'
+Grave accent \e*\(ga e\e*\(ga e\*`
+Umlaut \e*: u\e*: u\*:
+Tilde \e*~ n\e*~ n\*~
+Caret \e*^ e\e*^ e\*^
+Cedilla \e*, c\e*, c\*,
+Czech \e*v e\e*v e\*v
+Circle \e*o A\e*o A\*o
+There exists \e*(qe \*(qe
+For all \e*(qa \*(qa
+.fi
+.sp 1i
+.b Acknowledgments
+.pp
+I would like to thank
+Bob Epstein,
+Bill Joy,
+and Larry Rowe
+for having the courage
+to use the \-me macros
+to produce non-trivial papers
+during the development stages;
+Ricki Blau,
+Pamela Humphrey,
+and Jim Joyce
+for their help with the documentation phase;
+peter kessler
+for numerous complaints,
+most accompanied by fixes;
+and the plethora of people who have contributed ideas
+and have given support for the project.
+.bp
+.b Summary
+.pp
+This alphabetical list summarizes all macros, strings, and number registers
+available in the \-me macros.
+Selected
+.i troff
+commands, registers, and functions are included as well;
+those listed can generally be used with impunity.
+.pp
+The columns are the name of the
+command, macro, register, or string;
+the type of the object,
+and the description.
+Types are
+.b M
+for macro or builtin command
+(invoked with
+.b \&.
+or
+.b \&\'
+in the first input column),
+.b S
+for a string
+(invoked with
+.b \e*
+or
+.b \e*( ),
+.b R
+for a number register
+(invoked with
+.b \en
+or
+.b \en( ),
+and
+.b F
+for a
+.i troff
+builtin function
+(invoked by preceding it with a single backslash).
+.pp
+Lines marked with \(sc are
+.i troff
+internal codes.
+Lines marked with \(dg or \(dd
+may be defined by the user to get special functions;
+\(dd indicates that these are defined by default
+and changing them may have unexpected side effects.
+Lines marked with \(de
+are specific to
+.i ditroff
+(device-independent
+.i troff ).
+.de $H
+.ev 1
+.ta \w'\e(space)\(sc\ 'u +\w'TYPE 'u
+NAME TYPE DESCRIPTION
+.ev
+..
+.(l
+.$H
+\e(space) F\(sc unpaddable space
+\e" F\(sc comment (to end of line)
+\e*# S optional delayed text tag string
+\e$\fI\&N\fP F\(sc interpolate argument \fI\&N\fP
+\en($0 R section depth
+\&.$0 M\(dg invoked after section title printed
+\en($1 R first section number
+\&.$1 M\(dg invoked before printing depth 1 section
+\en($2 R second section number
+\&.$2 M\(dg invoked before printing depth 2 section
+\en($3 R third section number
+\&.$3 M\(dg invoked before printing depth 3 section
+\en($4 R fourth section number
+\&.$4 M\(dg invoked before printing depth 4 section
+\en($5 R fifth section number
+\&.$5 M\(dg invoked before printing depth 5 section
+\en($6 R sixth section number
+\&.$6 M\(dg invoked before printing depth 6 section
+\&.$C M\(dg called at beginning of chapter
+\&.$H M\(dg text header
+\en($V R\(dd relative vertical spacing in displays
+\en($c R current column number
+\&.$c M\(dd print chapter title
+\en($d R delayed text number
+\en($f R footnote number
+\&.$f M\(dd print footer
+\&.$h M\(dd print header
+\en($i R paragraph base indent
+\en($l R column width
+\en($m R number of columns in effect
+\e*($n S section name
+\en($p R numbered paragraph number
+\&.$p M\(dd print section heading (internal macro)
+\en($s R column indent
+\&.$s M\(dd footnote separator (from text)
+\en($v R\(dd relative vertical spacing in text
+\en% R\(sc current page number
+\e& F\(sc zero width character, useful for hiding controls
+\e(\fI\&xx\fP F\(sc interpolate special character \fI\&xx\fP
+\&.(b M begin block
+\&.(c M begin centered block
+\&.(d M begin delayed text
+\&.(f M begin footnote
+\&.(l M begin list
+\&.(q M begin quote
+\&.(x M begin index entry
+\&.(z M begin floating keep
+\&.)b M end block
+\&.)c M end centered block
+\&.)d M end delayed text
+\&.)f M end footnote
+\&.)l M end list
+\&.)q M end quote
+\&.)x M end index entry
+\&.)z M end floating keep
+\e*\fI\&x\fP F\(sc interpolate string \fI\&x\fP
+\e*(\fI\&xx\fP F\(sc interpolate string \fI\&xx\fP
+\e** S optional footnote tag string
+\&.++ M set paper section type
+\&.+c M begin chapter
+\e*, S cedilla
+\e\- F\(sc minus sign
+\e*\- S 3/4 em dash
+\e0 F\(sc unpaddable digit-width space
+\&.1c M revert to single column output
+\&.2c M begin two column output
+\e*: S umlat
+\e*< S begin subscript
+\e*> S end subscript
+\&.EN M end equation
+\&.EQ M begin equation
+\eL\'\fI\&d\fP\' F\(sc vertical line drawing function for distance \fI\&d\fP
+\&.GE M\(de end \fIgremlin\fP picture
+\&.GF M\(de end \fIgremlin\fP picture (with flyback)
+\&.GS M\(de start \fIgremlin\fP picture
+\&.IE M\(de end \fIideal\fP picture
+\&.IF M\(de end \fIideal\fP picture (with flyback)
+\&.IS M\(de start \fIideal\fP picture
+\&.PE M\(de end \fIpic\fP picture
+\&.PF M\(de end \fIpic\fP picture (with flyback)
+\&.PS M\(de start \fIpic\fP picture
+\&.TE M end table
+\&.TH M end header of table
+\&.TS M begin table
+\e*{ S begin superscript
+\en(\&.$ R\(sc number of arguments to macro
+\en(\&.i R\(sc current indent
+\en(\&.l R\(sc current line length
+\en(\&.s R\(sc current point size
+\e*(\&\' S acute accent
+\e*(\&\` S grave accent
+\e(\' F\(sc acute accent
+\e(\` F\(sc grave accent
+\e*} S end superscript
+\e^ F\(sc 1/12 em narrow space
+\e*^ S caret
+\&.ad M\(sc set text adjustment
+\&.af M\(sc assign format to register
+\&.am M\(sc append to macro
+\&.ar M set page numbers in Arabic
+\&.as M\(sc append to string
+\&.b M bold font
+\&.ba M set base indent
+\&.bc M begin new column
+\&.bi M bold italic
+\en(bi R display (block) indent
+\&.bl M blank lines (even at top of page)
+\en(bm R bottom title margin
+\&.bp M\(sc begin page
+\&.br M\(sc break (start new line)
+\en(bs R display (block) pre/post spacing
+\en(bt R block keep threshold
+\&.bx M boxed
+\ec F\(sc continue input
+\&.ce M\(sc center lines
+\en(ch R current chapter number
+\&.de M\(sc define macro
+\en(df R display font
+\&.ds M\(sc define string
+\en(dw R\(sc current day of week
+\e*(dw S current day of week
+\en(dy R\(sc day of month
+\ee F\(sc printable version of \e
+\&.ef M set footer (even numbered pages only)
+\&.eh M set header (even numbered pages only)
+\&.el M\(sc else part of conditional
+\&.ep M end page
+\en(es R equation pre/post space
+\ef\fI\&f\fP F\(sc inline font change to font \fI\&f\fP
+\ef(\fI\&ff\fP F\(sc inline font change to font \fI\&ff\fP
+\&.fc M\(sc set field characters
+\en(ff R footnote font
+\&.fi M\(sc fill output lines
+\en(fi R footnote indent (first line only)
+\en(fm R footer margin
+\&.fo M set footer
+\en(fp R footnote pointsize
+\en(fs R footnote prespace
+\en(fu R footnote undent (from right margin)
+\eh\'\fI\&d\fP\' F\(sc local horizontal motion for distance \fI\&d\fP
+\&.hc M\(sc set hyphenation character
+\&.he M set header
+\&.hl M draw horizontal line
+\en(hm R header margin
+\&.hx M suppress headers and footers on next page
+\&.hy M\(sc set hyphenation mode
+\&.i M italic font
+\&.ie M\(sc conditional with else
+\&.if M\(sc conditional
+\en(ii R indented paragraph indent
+\&.in M\(sc indent (transient, use .ba for pervasive)
+\&.ip M begin indented paragraph
+\&.ix M indent, no break
+\el\'\fI\&d\fP\' F\(sc horizontal line drawing function for distance \fI\&d\fP
+\&.lc M\(sc set leader repetition character
+\&.ll M set line length
+\&.lp M begin left justified paragraph
+\e*(lq S left quote marks
+\&.ls M\(sc set multi-line spacing
+\&.m1 M set space from top of page to header
+\&.m2 M set space from header to text
+\&.m3 M set space from text to footer
+\&.m4 M set space from footer to bottom of page
+\&.mc M\(sc insert margin character
+\&.mk M\(sc mark vertical position
+\en(mo R\(sc month of year
+\e*(mo S current month
+\en\fI\&x\fP F\(sc interpolate number register \fI\&x\fP
+\en(\fI\&xx\fP F\(sc interpolate number register \fI\&xx\fP
+\&.n1 M number lines in margin
+\&.n2 M number lines in margin
+\&.na M\(sc turn off text adjustment
+\&.ne M\(sc need vertical space
+\&.nf M\(sc don't fill output lines
+\&.nh M\(sc turn off hyphenation
+\&.np M begin numbered paragraph
+\&.nr M\(sc set number register
+\&.ns M\(sc no space mode
+\e*o S circle (e.g., for Norse A\*o)
+\&.of M set footer (odd numbered pages only)
+\&.oh M set header (odd numbered pages only)
+\&.pa M begin page
+\&.pd M print delayed text
+\en(pf R paragraph font
+\en(pi R paragraph indent
+\&.pl M\(sc set page length
+\&.pn M\(sc set next page number
+\&.po M\(sc page offset
+\en(po R simulated page offset
+\&.pp M begin paragraph
+\en(pp R paragraph pointsize
+\en(ps R paragraph prespace
+\&.q M quoted
+\e*(qa S for all
+\e*(qe S there exists
+\en(qi R quote indent (also shortens line)
+\en(qp R quote pointsize
+\en(qs R quote pre/post space
+\&.r M roman font
+\&.rb M real bold font
+\&.re M reset tabs
+\&.rm M\(sc remove macro or string
+\&.rn M\(sc rename macro or string
+\&.ro M set page numbers in roman
+\e*(rq S right quote marks
+\&.rr M\(sc remove register
+\&.rs M\(sc restore spacing
+\&.rt M\(sc return to vertical position
+\es\fI\&S\fP F\(sc inline size change to size \fI\&S\fP
+\en(sf R section title font
+\&.sh M begin numbered section
+\en(si R relative base indent per section depth
+\&.sk M skip next page
+\&.sm M set argument in a smaller pointsize
+\&.so M\(sc source input file
+\en(so R additional section title offset
+\&.sp M\(sc vertical space
+\en(sp R section title pointsize
+\en(ss R section prespace
+\&.sx M change section depth
+\&.sz M set pointsize and vertical spacing
+\&.ta M\(sc set tab stops
+\&.tc M\(sc set tab repetition character
+\e*(td S today's date
+\en(tf R title font
+\&.ti M\(sc temporary indent (next line only)
+\&.tl M\(sc three part title
+\en(tm R top title margin
+\&.tp M begin title page
+\en(tp R title pointsize
+\&.tr M\(sc translate
+\&.u M underlined
+\&.uh M unnumbered section
+\&.ul M\(sc underline next line
+\ev\'\fI\&d\fP\' F\(sc local vertical motion for distance \fI\&d\fP
+\e*v S inverted `v' for czeck ``e\*v''
+\ew\'\fI\&S\fP\' F\(sc return width of string \fI\&S\fP
+\&.xl M set line length (local)
+\&.xp M print index
+\en(xs R index entry prespace
+\en(xu R index undent (from right margin)
+\en(y2 R year (last two digits only)
+\en(y4 R year (all digits)
+\en(yr R\(sc year minus 1900
+\en(zs R floating keep pre/post space
+\e{ F\(sc begin conditional group
+\e| F\(sc 1/6 em narrow space
+\e} F\(sc end conditional group
+\e*~ S tilde
+.)l
+.rm $H
diff --git a/doc/pic.ms b/doc/pic.ms
new file mode 100644
index 00000000..2826eb37
--- /dev/null
+++ b/doc/pic.ms
@@ -0,0 +1,2434 @@
+.\" For tolerably obvious reason, this needs to be processed through PIC.
+.\" It also needs to be processed through TBL and EQN. Use "groff -p -e -t".
+.\" There is no hope that this will ever look right under nroff.
+.\"
+.\" Comments beginning with %% are cut lines so portions of this
+ \" document can be automatically extracted. %%TUTORIAL%% begins the
+.\" tutorial part; %%REFERENCE%% the reference part. %%POSTLUDE%% the
+ \" bibliography and end matter after the reference part.
+.\"
+.\" This document was written for free use and redistribution by
+.\" Eric S. Raymond <esr@thyrsus.com> in August 1995.
+.\"
+.\" $Id: pic.ms,v 1.1 2000/02/06 09:39:20 wlemb Exp $
+.\"
+.\" Set a proper TeX
+.ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X
+.el .ds tx TeX
+.\"
+.de CE\" Centered caption for figure. Assumes previous .KS
+.ce 1
+Figure \\n(H1-\\$1
+.sp 1
+.KE
+..
+.\" Definitions end here
+.TL
+Making Pictures With GNU PIC
+.AU
+Eric S. Raymond
+.AI
+<esr@snark.thyrsus.com>
+.AB
+The \fBpic\fP language is a \fBtroff\fP extension that makes it easy
+to create and alter box-and-arrow diagrams of the kind frequently used
+in technical papers and textbooks. This paper is both an introduction
+to and reference for \fIgpic\fP(1), the implementation distributed by
+the Free Software Foundation for use with \fIgroff\fP(1).
+.AE
+.\"%%TUTORIAL%%
+.NH 1
+Introduction to PIC
+.NH 2
+Why PIC?
+.PP
+The \fBpic\fP language provides an easy way to write procedural
+box-and-arrow diagrams to be included in \fBtroff\fP documents. The
+language is sufficiently flexible to be quite useful for state charts,
+Petri-net diagrams, flow charts, simple circuit schematics, jumper
+layouts, and other kinds of illustration involving repetitive uses of
+simple geometric forms and splines. Because these descriptions are
+procedural and object-based, they are both compact and easy to modify.
+.PP
+The \fIgpic\fP(1) implementation of \fBpic\fP is distributed by the
+Free Software Foundation for use with their \fIgroff\fP(1)
+implementation of \fBtroff\fP. Because both implementations are
+widely available in source form for free, they are good bets for
+writing very portable documentation.
+.NH 2
+PIC Versions
+.PP
+The original 1984 pre-\fIditroff\fP(1) version of \fBpic\fP is long
+obsolete. The rewritten 1991 version is still available as part of
+the Documenter's Work Bench module of System V.
+.PP
+Where differences between Documenter's Work Bench (1991) \fBpic\fP and GNU
+\fBpic\fP need to be described, original \fBpic\fP is referred to as
+"DWB pic". Details on the history of the program are given at the end
+of this document.
+.PP
+In this document, the \fIgpic\fP(1) extensions will be marked as such.
+.NH 1
+Invoking PIC
+.PP
+Every \fBpic\fP description is a little program, which gets compiled
+by \fIpic\fP(1) into \fIgtroff\fP(1) macros. Programs that process or
+display \fIgtroff\fP(1) output need not know or care that parts of the
+image began life as \fBpic\fP descriptions.
+.PP
+The \fIpic\fP(1) program tries to translate anything between \fB.PS\fP
+and \fB.PE\fP markers, and passes through everything else. The normal
+definitions of \fB.PS\fP and \fB.PE\fP in the \fIms\fP macro package
+and elsewhere have also the side-effect of centering the \fBpic\fP output
+on the page.
+.PP
+Other details of the \fI[gt]roff\fP(1) interface
+.NH 2
+PIC Error Messages
+.PP
+If you make a \fBpic\fP syntax error, \fIgpic\fP(1) will issue an
+error message in the standard \fIgcc\fP(1)-like syntax. A typical
+error message looks like this,
+.KS
+.DS
+.CW
+pic:pic.ms:<nnn>: parse error before `<token>'
+pic:pic.ms:<nnn>: giving up on this picture
+.DE
+.R
+.KE
+.LP
+where <nnn> is a line number, and <token> is a token near (usually
+just after) the error location.
+.NH 1
+Basic PIC Concepts
+.PP
+Pictures are described procedurally, as collections of objects
+connected by motions. Normally, \fBpic\fP tries to string together
+objects left-to-right in the sequence they are described, joining them
+at visually natural points. Here is an example illustrating the
+flow of data in \fBpic\fP processing:
+.KS
+.PS
+ellipse "document";
+arrow;
+box "\fIgpic\fP(1)"
+arrow;
+box width 1.2 "\fIgtbl\fP(1) or \fIgeqn\fP(1)" "(optional)" dashed;
+arrow;
+box "\fIgtroff\fP(1)";
+arrow;
+ellipse "PostScript"
+.PE
+.CE "1: Flow of \fBpic\fP data"
+.PP
+This was produced from the following \fBpic\fP program:
+.KS
+.DS
+.CW
+\&.PS
+\&ellipse "document";
+\&arrow;
+\&box "\\fIpic\\fP(1)"
+\&arrow;
+\&box width 1.2 "\\fIgtbl\\fP(1) or \\fIgeqn\\fP(1)" "(optional)" dashed;
+\&arrow;
+\&box "\\fIgtroff\\fP(1)";
+\&arrow;
+\&ellipse "PostScript"
+\&.PE
+.DE
+.R
+.KE
+.LP
+This little program illustrates several \fBpic\fP basics. Firstly, we
+see how to invoke three object types; ellipses, arrows, and boxes. We
+see how to declare text lines to go within an object (and that text
+can have font changes in it). We see how to change the line style of
+an object from solid to dashed. And we see that a box can be made
+wider than its default size to accommodate more text (we'll discuss
+this facility in detail in the next section).
+.PP
+We also get to see \fBpic\fP's simple syntax. Statements are ended by
+newlines or semicolons. String quotes are required around all text
+arguments, whether or not they contain spaces. In general, the order
+of command arguments and modifiers like "width 1.2" or "dashed" doesn't
+matter, except that the order of text arguments is significant.
+.PP
+Here are all but one of the basic \fBpic\fP objects at their default sizes:
+.KS
+.PS
+box "box";
+move;
+line "line" "";
+move;
+arrow "arrow" "";
+move;
+circle "circle";
+move;
+ellipse "ellipse";
+move;
+arc; down; move; "arc"
+.PE
+.CE "2: Basic \fBpic\fP objects"
+.PP
+The missing simple object type is a \fIspline\fP. There is also a way
+to collect objects into \fIblock composites\fP which allows you to
+treat the whole group as a single object (resembling a box) for many
+purposes. We'll describe both of these later on.
+.PP
+The box, ellipse, circle, and block composite objects are \fIclosed\fR;
+lines, arrows, arcs and splines are \fIopen\fP. This distinction
+will often be important in explaining command modifiers.
+.PP
+Figure \n[H1]-2 was produced by the following \fBpic\fP program,
+which introduces some more basic concepts:
+.KS
+.DS
+.CW
+\&.PS
+\&box "box";
+\&move;
+\&line "line" "";
+\&move;
+\&arrow "arrow" "";
+\&move;
+\&circle "circle";
+\&move;
+\&ellipse "ellipse";
+\&move;
+\&arc; down; move; "arc"
+\&.PE
+.DE
+.ft R
+.KE
+.PP
+The first thing to notice is the \fImove\fP command, which moves a
+default distance (1/2 inch) in the current movement direction.
+.PP
+Secondly, see how we can also decorate lines and arrows with text.
+The line and arrow commands each take two arguments here, specifying
+text to go above and below the object. If you wonder why one argument
+would not do, contemplate the output of \fBarrow "ow!"\fP:
+.KS
+.PS
+arrow "ow!"
+.PE
+.CE "3: Text centered on an arrow"
+.PP
+When a command takes one text string, \fBpic\fP tries to place it at
+the object's geometric center. As you add more strings, \fBpic\fP
+treats them as a vertical block to be centered. The program
+.KS
+.DS
+.CW
+line "1";
+line "1" "2";
+line "1" "2" "3";
+line "1" "2" "3" "4";
+line "1" "2" "3" "4" "5";
+.DE
+.ft R
+.KE
+.LP
+for example, gives you this:
+.KS
+.sp 2
+.PS
+line "1";
+line "1" "2";
+line "1" "2" "3";
+line "1" "2" "3" "4";
+line "1" "2" "3" "4" "5";
+.PE
+.sp 2
+.CE "4: Effects of multiple text arguments"
+.PP
+The last line of Figure 3.2's program, `\fBarc; down; move;
+"arc"\fP', describing the captioned arc, introduces several new ideas.
+Firstly, we see how to change the direction in which objects are
+joined. Had we written \fBarc; move; "arc"\fP,
+omitting \fBdown\fP the caption would have been joined to the top
+of the arc, like this:
+.KS
+.PS
+arc; move; "arc";
+.PE
+.CE "5: Result of \fBarc; move; \"arc\"\fP"
+.PP
+This is because drawing an arc changes the default direction to the
+one its exit end points at. To reinforce this point, consider:
+.KS
+.PS
+arc cw; move; "arc";
+.PE
+.CE "6: Result of \fBarc cw; move; \"arc\"\fP"
+.PP
+All we've done differently here is specify "cw" for a clockwise arc.
+Observe how it changes the default direction to down, rather than up.
+.PP
+Another good way to see this via with the following program:
+.KS
+.DS
+.CW
+line; arc; arc cw; line
+.DE
+.ft R
+.KE
+.LP
+which yields:
+.KS
+.PS
+line; arc; arc cw; line;
+.PE
+.CE "7: Result of \fBline; arc; arc cw; line\fP"
+.LP
+Notice that we did not have to specify "up" for the second arc to be
+joined to the end of the first.
+.PP
+Finally, observe that a string, alone, is treated as text to be
+surrounded by an invisible box of a size either specified by width
+and height attributes or by the defaults \fBtextwid\fR and
+\fBtextht\fR. Both are initially zero (because we don't know the
+default font size).
+.NH 1
+Sizes and Spacing
+.PP
+Sizes are specified in inches. If you don't like inches, it's
+possible to set a global style variable \fBscale\fP that changes the
+unit. Setting \fBscale = 2.54\fP will effectively change the internal
+unit to centimeters (all other size variable valuess will be scaled
+correspondingly).
+.NH 2
+Default Sizes of Objects
+.PP
+Here are the default sizes for \fBpic\fP objects:
+.RS
+.KS
+.TS
+tab(@), linesize(2);
+lb | lb
+l | l.
+.sp 2p
+Object@Default Size
+.sp 2p
+_
+.sp 2p
+box@0.75" wide by 0.5" high
+circle@0.5" diameter
+ellipse@0.75" wide by 0.5" high
+arc@0.5" radius
+line@0.5" long
+arrow@0.5" long
+.sp 5p
+_
+.TE
+.KE
+.RE
+.PP
+The simplest way to think about these defaults is that they make the
+other basic objects fit snugly into a default-sized box.
+.NH 2
+Objects Do Not Stretch!
+.PP
+Text is rendered in the current font with normal troff line spacing.
+Boxes, circles, and ellipses do \fInot\fP automatically resize to fit
+enclosed text. Thus, if you say \fBbox "text far too long"\fP
+you'll get this:
+.KS
+.PS
+box "this text is far too long for a default box"
+.PE
+.CE "1: Boxes do not automatically resize"
+.PP
+which is probably not the effect you want.
+.NH 2
+Resizing Boxes
+.PP
+To change the box size, you can specify a box width with the "width"
+modifier:
+.KS
+.PS
+box width 3 "this text is far too long for a default box"
+.PE
+.CE "2: Result of \fBbox width 3 \"text far too long\"\fP"
+.PP
+This modifier takes a dimension in inches. There is also a "height"
+modifier that will change a box's height. The \fBwidth\fP keyword may
+be abbreviated to \fBewid\fP; the \fBheight\fP keyword to
+\fBheight\fP.
+.NH 2
+Resizing Other Object Types
+.PP
+To change the size of a circle, give it a \fBrad\fP or \fBdiam\fP
+modifier; this changes the radius or diameter of the circle, according
+to the numeric argument that follows.
+.KS
+.PS
+{circle rad 0.1; move down 0.2 from last circle .s; "0.1"};
+move; circle rad 0.2 "0.2"; move; circle rad 0.3 "0.3";
+.PE
+.CE "3: Circles with increasing radii"
+.PP
+The \fBmove\fP command can also take a dimension, which just tells
+it how many inches to move in the current direction.
+.PP
+Ellipses are sized to fit in the rectangular box defined by their
+axes, and can be resized with \fBwidth\fP and \fBheight\fP like boxes.
+.PP
+You can also change the radius of curvature of an arc with \fBrad\fP
+(which specifies the radius of the circle of which the arc is a segnmment).
+Larger values yield flatter arcs.
+.KS
+.PS
+{arc rad 0.1; move down 0.3 from last arc .center; "0.1"};
+move;
+{arc rad 0.2; move down 0.4 from last arc .center; "0.2"};
+move;
+{arc rad 0.3; move down 0.5 from last arc .center; "0.3"};
+.PE
+.CE "4: \fBarc rad\fP with increasing radii"
+.PP
+Observe that because an arc is defined as a quarter circle, increasing
+the radius also increases the size of the arc's bounding box.
+.NH 2
+The `same' Keyword
+.PP
+In place of a dimension specification, you can use the keyword
+\fBsame\fR. This gives the object the same size as the previous one
+of its type. As an example, the program
+.KS
+.DS
+.CW
+\&.PS
+\&box; box wid 1 ht 1; box same; box
+\&.PE
+.R
+.DE
+.KE
+.LP
+gives you
+.KS
+.PS
+box; box wid 1 ht 1; box same; box
+.PE
+.CE "5: The \fBsame\fP keyword"
+
+.NH 1
+Generalized Lines and Splines
+.NH 2
+Diagonal Lines
+.PP
+It is possible to specify diagonal lines or arrows by adding multiple \fBup\fP,
+\fBdown\fP, \fBleft\fP, and \fBright\fP modifiers to the line object.
+Any of these can have a multiplier. To understand the effects, think
+of the drawing area as being gridded with standard-sized boxes.
+.KS
+.PS
+# Draw a demonstration up left arrow with grid box overlay
+define gridarrow
+{
+ [
+ {arrow up left $1;}
+ box wid 0.5 ht 0.5 dotted with .nw at last arrow .end;
+ for i = 2 to ($1 / 0.5) do
+ {
+ box wid 0.5 ht 0.5 dotted with .sw at last box .se;
+ }
+ move down from last arrow .center;
+ [
+ if ( $1 == boxht ) then { "\fBline up left\fP" } else { sprintf("\fBarrow up left %g\fP", $1) };
+ ]
+ ]
+ move right from last [] .e;
+}
+gridarrow(0.5);
+gridarrow(1);
+gridarrow(1.5);
+gridarrow(2);
+undef gridarrow
+.PE
+.CE "1: Diagonal arrows (dotted boxes show the implied 0.5-inch grid)"
+.NH 2
+Multi-Segment Line Objects
+.PP
+A "line" or "arrow" object may actually be a path consisting of any number of
+segments of varying lengths and directions. To describe a path,
+connect several line or arrow commands with the keyword \fBthen\fP.
+.KS
+.PS
+define zigzag { $1 right 1 then down .5 left 1 then right 1 }
+zigzag(line);
+.PE
+.CE "2: \fBline right 1 then down .5 left 1 then right 1\fP"
+.NH 2
+Spline Objects
+.PP
+If you start a path with the \fBspline\fP keyword, the path vertices
+are treated as control points for a spline curve fit.
+.KS
+.PS
+[zigzag(spline);]
+move down 0.2 from last [] .s;
+"The spline curve..."
+move right from last [] .e;
+[
+ zigzag(line dashed);
+ spline from start of last line right 1 then down .5 left 1 then right 1;
+ "1" at last spline .start + (-0.1, 0);
+ "2" at last spline .start + (1.1, 0);
+ "3" at last spline .end + (-1.1, 0);
+ "4" at last spline .end + (0.1, 0);
+]
+move down 0.2 from last [] .s;
+"...with tangents displayed"
+undef zigzag;
+.PE
+.CE "3: \fBspline right 1 then down .5 left 1 then right 1\fP"
+.PP
+You can describe many natural-looking but irregular curves this
+way. For example:
+.KS
+.PS
+[spline right then up then left then down ->;]
+move down 0.2 from last [] .s;
+["\fBspline right then up then left then down ->;\fP"]
+move right 3 from last [] .se;
+"\fBspline left then up right then down right ->;\fP"
+move up 0.2;
+[spline left then up right then down right ->;]
+.PE
+.CE "4: Two more spline examples"
+.PP
+Note the arrow decorations. Arrowheads can be applied naturally to
+any path-based object, line or spline. We'll see how in the next
+section.
+.NH 1
+Decorating Objects.
+.NH 2
+Dashed Objects
+.PP
+We've already seen that the modifier \fBdashed\fP can change the line
+style of an object from solid to dashed. GNU \fBgpic\fP permits you to
+dot or dash ellipses, circles, and arcs (and splines in \(*tx mode
+only); some versions of DWB may only permit dashing of lines and
+boxes. It's possible to change the dash interval by specifying a
+number after the modifier.
+.PP
+.KS
+.PS
+box dashed "default";
+move;
+box dashed 0.05 "0.05";
+move;
+box dashed 0.1 "0.1";
+move;
+box dashed 0.15 "0.15";
+move;
+box dashed 0.2 "0.2";
+.PE
+.CE "1: Dashed objects"
+.NH 2
+Dotted Objects
+.PP
+Another available qualifier is \fBdotted\fP. GNU \fBgpic\fP permits
+you to dot or dash ellipses, circles, and arcs (and splines in \(*tx
+mode only); some versions of DWB may only permit dashing of lines and
+boxes. It too can be suffixed with a number to specify the interval
+between dots:
+.KS
+.PS
+box dotted "default";
+move;
+box dotted 0.05 "0.05";
+move;
+box dotted 0.1 "0.1";
+move;
+box dotted 0.15 "0.15";
+move;
+box dotted 0.2 "0.2";
+.PE
+.CE "2: Dotted objects"
+.NH 2
+Rounding Box Corners
+.PP
+It is also possible, in GNU \fBgpic\fP only, to modify a box so it has
+rounded corners
+.KS
+.PS
+box rad 0.05 "rad 0.05";
+move;
+box rad 0.1 "rad 0.1";
+move;
+box rad 0.15 "rad=0.15";
+move;
+box rad 0.2 "rad=0.2";
+move;
+box rad 0.25 "rad=0.25";
+.PE
+.CE "3: \fBbox rad\fP with increasing radius values;"
+.PP
+Radius values higher than half the minimum box dimension are silently
+truncated to that value.
+.NH 2
+Arrowheads
+.PP
+Lines and arcs can be decorated as well. Any line or arc (and any
+spline as well) can be decorated with arrowheads by adding one or more
+as modifiers:
+.KS
+.PS
+line <- ->
+.PE
+.CE "4: Double-headed line made with \fBline <- ->\fP"
+.PP
+In fact, the \fBarrow\fP command is just shorthand for \fBline ->\fP. And
+there is a double-head modifier <->, so the figure above could have been made
+with \fCWline <->\fP.
+.PP
+Arrowheads have a \fBwidth\fP attribute, the distance across the rear;
+and a \fBheight\fP attribute, the length of the arrowhead along the shaft.
+.PP
+Arrowhead style is controlled by the style variable \fBarrowhead\fP.
+The DWB and GNU versions interpret it differently. DWB defaults to
+open arrowheads and an \fBarrowhead\fP value of 2; the Kernighan
+paper says a value of 7 will make solid arrowheads. GNU \fBgpic\fP
+defaults to solid arrowheads and an \fBarrowhead\fP value of 1; a
+value of 0 will produce open arrowheads.
+.NH 2
+Line Thickness
+.PP
+It's also possible to change the line thickness of an object (this is
+a GNU extension, DWB \fBpic\fP doesn't support it.).
+The default thickness of the lines used to draw objects is controlled by the
+.B linethick
+variable.
+This gives the thickness of lines in points.
+A negative value means use the default thickness:
+in \(*tx output mode, this means use a thickness of 8 milliinches;
+in \(*tx output mode with the
+.B -c
+option, this means use the line thickness specified by
+.B .ps
+lines; in troff output mode, this means use a thickness proportional
+to the pointsize. A zero value means draw the thinnest possible line
+supported by the output device. Initially it has a value of -1.
+There is also a \fBthickness\fP attribute (which can be abbreviated to
+\fBthick\fP). For example, \fBcircle thickness 1.5\fP would draw a
+circle using a line with a thickness of 1.5 points. The thickness of
+lines is not affected by the value of the
+.B scale
+variable, nor by any width or height given in the
+.B .PS
+line.
+.NH 2
+Invisible Objects
+.PP
+The modifier \fBinvis\fP makes an object entirely invisible. This
+used to be useful for positioning text in an invisible object that is
+properly joined to neighboring ones. Newer DWB versions and GNU
+\fBpic\fP treat standalone text in exactly this way.
+.NH 2
+Filled Objects
+.PP
+It is possible to fill boxes, circles, and ellipses. The
+modifier \fBfill[ed]\fP accomplishes this. You can suffix it with a fill
+value; the default is given by the stule variable \fBfillval\fP.
+.PP
+DWB \fBpic\fP and \fBgpic\fP have opposite conventions for fill values
+and different defaults. DWB \fBfillval\fP defaults to 0.3 and smaller
+values are darker; GNU \fBfillval\fP uses 0 for white and 1 for black.
+.KS
+.PS
+circle fill; move; circle fill 0.4; move; circle fill 0.2;
+.PE
+.CE "5: \fBcircle fill; move; circle fill 0.4; move; circle fill 0.9;\fB"
+.PP
+GNU \fBgpic\fP makes some additional guarantees. A fill value greater
+than 1 can also be used: this means fill with the shade of gray that
+is currently being used for text and lines. Normally this will be
+black, but output devices may provide a mechanism for changing this.
+The invisible attribute does not affect the filling of objects. Any
+text associated with a filled object will be added after the object
+has been filled, so that the text will not be obscured by the filling.
+.PP
+The closed-object modifier \fBsolid\fR is equivalent to \fBfill\fR
+with the darkest fill value (DWB \fBpic\fR had this capability but
+mentioned it only in a reference opinion).
+.NH 1
+More About Text Placement
+.PP
+By default, text is centered at the geometric center of the object it is
+associated with. The modifier \fBljust\fR causes the left end to be
+at the specified point (which means that the text lies to the right of
+the specified place!), The modifier \fBrjust\fP puts the right end at
+the place. The modifiers \fBabove\fP and \fBbelow\fP center the text
+one half line space in the given direction.
+.PP
+Text attributes can be combined:
+.KS
+.PS
+[line up "ljust text" ljust;]
+move 1.5;
+[line up "rjust text" rjust;]
+move;
+[arrow 1 "ljust above" ljust above;]
+move;
+[arrow 1 "rjust below" rjust below;]
+.PE
+.CE "1: Text attributes"
+.PP
+What actually happens is that n text strings are centered in a box
+that is \fBtextwid\fP wide by \fBtextht\fP high. Both these variables
+are initially zero (that is \fBpic\fR's way of not making assumptions
+about \fI[tg]roff\fP(1)'s default point size).
+.PP
+In GNU \fBgpic\fR, objects can have an
+.B aligned
+attribute.
+This will only work when the postprocessor is
+\fBgrops\fP.
+Any text associated with an object having the
+.B aligned
+attribute will be rotated about the center of the object
+so that it is aligned in the direction from the start point
+to the end point of the object.
+Note that this attribute will have no effect for objects whose start and
+end points are coincident.
+.NH 1
+More About Direction Changes
+.PP
+We've already seen how to change the direction in which objects are
+composed from rightwards to downwards. Here are some more
+illustrative examples:
+.KS
+.PS
+down;
+[
+ "\fBright; box; arrow; circle; arrow; ellipse\fP";
+ move 0.2;
+ [right; box; arrow; circle; arrow; ellipse;]
+]
+move down 0.3 from last [] .s;
+[
+ "\fBleft; box; arrow; circle; arrow; ellipse\fP"
+ move 0.2;
+ [left; box; arrow; circle; arrow; ellipse;]
+]
+# move down 0.3 from last [] .sw;
+# To re-join this illustrations, delete everything from here down to
+# the next #-comment, and uncomment the move line above
+.PE
+.CE "1: Effects of different motion directions (right and left)"
+.KS
+.PS
+# To re-join this illustrations, delete everything down to here, then
+# comment out the next `down' line.
+# Don't forget to re-number the figures following!
+down;
+[
+ "\fBdown; box; arrow; circle; arrow; ellipse;\fP"
+ move 0.2;
+ box; arrow; circle; arrow; ellipse;
+]
+move right 2 from last [] .e;
+[
+ up; box; arrow; circle; arrow; ellipse;
+ move 0.2;
+ "\fBup; box; arrow; circle; arrow; ellipse;\fP"
+]
+.PE
+.CE "2: Effects of different motion directions (up and down)"
+.PP
+Something that may appear surprising happens if you change directions
+in the obvious way:
+.KS
+.PS
+box; arrow; circle; down; arrow; ellipse
+.PE
+.CE "3: \fBbox; arrow; circle; down; arrow; ellipse\fP
+.LP
+You might have expected that program to yield this:
+.KS
+.PS
+box; arrow; circle; move to last circle .s; down; arrow; ellipse
+.PE
+.CE "4: More intuitive?
+.LP
+But, in fact, to get Figure \*[SN]3 you have to do this:
+.KS
+.DS
+.CW
+\&.PS
+box;
+arrow;
+circle;
+move to last circle .s;
+down;
+arrow;
+ellipse
+\&.PE
+.R
+.DE
+.KE
+Why is this? Because the exit point for the current direction is
+already set when you draw the object. The second arrow in Figure
+\*[SN]2 dropped downwards from the circle's attachment point for an
+object to be joined to the right.
+.PP
+The meaning of the command \fBmove to last circle .s\fP should be obvious.
+In order to see how it generalizes, we'll need to go into detail on two
+important topics; locations and object names.
+.NH 1
+Naming Objects
+.PP
+The most natural way to name locations in \fBpic\fP is relative to
+objects. In order to do this, you have to be able you have to be able
+to name objects. The \fBpic\fP language has rich facilities for this
+that try to emulate the syntax of English.
+.NH 2
+Naming Objects By Order Of Drawing
+.PP
+The simplest (and generally the most useful) way to name an object is
+with a \fBlast\fP clause. It needs to be followed by an object type
+name; \fBbox\fP, \fBcircle\fP, \fBellipse\fP, \fBline\fP, \fBarrow\fP,
+\fBspline\fP or \fB[]\fP (the last type refers to a \fIcomposite
+object\fP which we'll discuss later). So, for example, the \fBlast
+circle\fP clause in the program attached to Figure \*[SN]3 refers to the
+last circle drawn.
+.PP
+More generally, objects of a given type are implicitly numbered
+(starting from 1). You can refer to (say) the third ellipse in the
+current picture with \fB3rd ellipse\fP, or to the first box as \fB1st
+box\fP, or to the fifth line as \fB5th line\fP.
+.PP
+Objects are also numbered backwards by type from the last one of
+You can say \fB2nd last box\fP to get the second-to-last box, or
+\fB3rd last ellipse\fP to get the third-to-last box.
+.PP
+In places where \fIn\fBth\fP is allowed, \fB`\fIexpr\fB'th\fP is also allowed.
+Note that
+.B 'th
+is a single token: no space is allowed between the
+.B '
+and the \fBth\fP.
+For example,
+.IP
+.KS
+.R
+.DS
+for i = 1 to 4 do {
+ line from `i'th box.nw to `i+1'th box.se
+}
+.R
+.DE
+.KE
+.NH 2
+Naming Objects With Labels
+.PP
+You can also specify an object by referring to a label. A label is a
+word (which must begin with a capital letter) followed by a colon;
+you declare it by placing it immediately before the object drawing command.
+For example, the program
+.KS
+.DS
+.CW
+\&.PS
+A: box "first" "object"
+move;
+B: ellipse "second" "object"
+move;
+arrow left at A;
+\&.PE
+.R
+.DE
+.KE
+.LP
+declares labels \fBA\fP and \fBB\fP for its first and second objects.
+Here's what that looks like:
+.KS
+.PS
+A: box "first" "object"
+move;
+B: ellipse "second" "object"
+move;
+arrow left at A .l;
+.PE
+.CE "1: Example of label use"
+The \fBat\fP statement in the fourth line uses the label \fBA\fP (the
+behavior of \fBat\fP will be explained in the next section). We'll
+see later on that labels are most useful for referring to block composite
+objects.
+.PP
+Labels are not constants but variables (you can view colon as a sort
+of assignment). You can say something like \fBA: A + (1,0);\fP
+and the effect will be to reassign the label \fBA\fR to designate a
+position one inch to the right of its old value.
+.NH 1
+Describing locations
+.PP
+The location of points can be described in many different ways. All these
+forms are interchangeable as for as the \fBpic\fP language syntax is
+concerned; where you can use one, any of the others that would make
+semantic sense are allowed.
+.PP
+The special label \fBHere\fR always refers to the current position.
+.NH 2
+Absolute Coordinates
+.PP
+The simplest is absolute coordinates in inches; \fBpic\fP uses a
+Cartesian system with (0, 0) at the lower left corner of the virtual
+drawing surface for each picture (that is, X increases to the right
+and Y increases upwards). An absolute location may always be written in the
+conventional form as two comma-separated numbers surrounded by
+parentheses (and this is recommended for clarity). In contexts where
+it creates no ambiguity, the pair of X and Y coordinates suffices
+without punctuation.
+.PP
+It is a good idea to avoid absolute coordinates, however. They tend
+to make picture descriptions difficult to understand and modify.
+Instead, there are quite a number of ways to specify locations
+relative to \fBpic\fP objects and previous locations.
+.PP
+.NH 2
+Locations Relative to Objects
+.PP
+The symbol \fBhere\fP always refers to the position of the last object
+drawn or the destination of the last \fBmove\fP.
+.PP
+Alone and unqualified, a \fBlast circle\fP or any other way of
+specifying a closed-object or arc location refers as a position to the
+geometric center of the object. Unqualified, the name of a line or
+spline object refers to the position of the object start.
+.PP
+Also, \fBpic\fP objects have quite a few named locations
+associated with them. One of these is the object center, which can be
+indicated (redundantly) with the suffix \fB.center\fP (or just \fB.c\fP).
+Thus, \fBlast circle \&.center\fP is equivalent to \fBlast
+circle\fP.
+.NH 3
+Locations Relative to Closed Objects
+.PP
+Every closed object (box, circle, ellipse, or block composite) also
+has eight compass points associated with it;
+.KS
+.PS
+define dot {circle fill rad 0.02 at $1}
+
+define compass { [
+ ME: $1;
+ dot(ME.c); "\fB .c\fP" at ME .c ljust;
+ dot(ME.n); "\fB.n\fP" at ME .n above
+ dot(ME.ne); "\fB .ne\fP" at ME .ne above
+ dot(ME.e); "\fB .e\fP" at ME .e ljust
+ dot(ME.se); "\fB .se\fP" at ME .se below
+ dot(ME.s); "\fB.s\fP" at ME .s below
+ dot(ME.sw); "\fB.sw \fP" at ME .sw below
+ dot(ME.w); "\fB.w \fP" at ME .w rjust
+ dot(ME.nw); "\fB.nw \fP" at ME .nw above
+] }
+compass(box wid 1.5 ht 1);
+move right from last [] .e;
+compass(circle diam 1);
+move right from last [] .e;
+compass(ellipse wid 1.5 ht 1);
+.PE
+.CE "1: Compass points"
+.LP
+these are the locations where eight compass rays from the geometric center
+would intersect the figure. So when we say \fBlast circle .s\fP we are
+referring to the south compass point of the last circle drawn. The
+explanation of Figure 7.3's program is now complete.
+.PP
+(In case you dislike compass points, the names \fB.top\fP,
+\&\fB.bottom\fP, \fB.left\fP and \fB.right\fP are synonyms for \fB.n\fP,
+\&\fB.s\fP, \fB.e\fP, and \fB.w\fP respectively; they can even be
+abbreviated to \fB.t\fP, \fB.b\fP, \fB.l\fP and \fB.r\fP).
+.PP
+The names \fBcenter\fP, \fBtop\fP, \fBbottom\fP, \fBleft\fP and
+\fBright\fP can also be used (without the leading dot) in a prefix
+form marked by \fBof\fP; thus, \fPcenter of last circle\fB and
+\fBtop of 2nd last ellipse\fP are both valid object references.
+.PP
+Arc objects also have compass point; they are the compass points of
+the implied circle.
+.NH 3
+Locations Relative to Open Objects
+.PP
+Every open object (line, arrow, arc, or spline) has three named
+points; \fB.start\fP, \fB.center\fP, and \fB.end\fP. They can
+also be used without leading dots in the \fBof\fP prefix form.
+The center of an arc is the center of its circle, but the center of
+a line, path, or spline is halfway between its endpoints.
+.KS
+.PS
+define critical {
+ [ ME: $1;
+ dot(ME.c); ".center" rjust at ME.center + (-0.1, 0.1)
+ dot(ME.start); ".start" rjust at ME.start + (-0.1, 0.1)
+ dot(ME.end); ".end" rjust at ME.end + (-0.1, 0.1)
+ ]
+ move down 0.2 from last [] .s;
+}
+critical(line up right 1);
+move right from last [] .e;
+critical(arc rad 0.5 cw);
+move right from last [] .e;
+critical(line right 1 then down .5 left 1 then right 1);
+move right from last [] .e;
+critical(spline right 1 then up right then left then left 1);
+.PE
+.CE "2: Special points on open objects"
+.PP
+.NH 2
+Ways of Composing Positions
+.PP
+Once you have two positions to work with, there are several ways to
+combine them to specify new positions.
+.NH 3
+Vector Sums and Displacements
+.PP
+Any two positions may be added or subtracted to yield a new position.
+The result is the conventional vector sum or difference of coordinates.
+For example, \fBlast box .ne + (0.1, 0)\fP is a valid position. This
+example illustrates a common use, to define a position slightly offset
+from a named one (say, for captioning purposes).
+.NH 3
+Interpolation Between Positions
+.PP
+A position may be interpolated between any two positions. The syntax
+is `\fIfraction\fP \fBof the way between\fP \fIposition1\fP \fBand\fP
+\fIposition2\fP.' For example, you can say \fB1/3 of the way between
+here and last ellipse .ne\fP. The fraction may be in
+numerator/denominator form or may be an ordinary number (values are
+\&\fInot\fP restricted to [0,1]). As an alternative to this verbose
+syntax, you can say `\fIfraction\fP \fB<\fP\fIposition1\fP \fB,\fP
+\fIposition2\fP\fB>\fP.'; thus, the example could also be written
+\fB1/3\fP <here, last ellipse>\fP.
+.KS
+.PS
+arrow up right;
+P: 1/3 of the way between last arrow .start and last arrow .end;
+dot(P); move right 0.1; "P";
+.PE
+.CE "3: \fBP: 1/3 of the way between last arrow .start and last arrow .end\fP"
+.PP
+This facility can be used, for example, to double connections.
+.KS
+.PS
+A: box "yin"; move; B: box "yang";
+arrow right at 1/4 <A.e,A.ne>;
+arrow left at 1/4 <B.w,B.sw>;
+.PE
+.CE "4: Doubled arrows"
+.LP
+You can get Figure \n[H1]-4 from the following program:
+.KS
+.DS
+.CW
+\&.PS
+A: box "yin"; move;
+B: box "yang";
+arrow right at 1/4 <A.e,A.ne>;
+arrow left at 1/4 <B.w,B.sw>;
+\&.PE
+.R
+.DE
+.KE
+.LP
+Note the use of the short form for interpolating points.
+.NH 3
+Projections of Points
+.PP
+Given two positions \fIp\fP and \fIq\fP, the position
+\fB(\fP\fIp\fP\fB,\fP \fIq\fP\fB)\fP has the X coordinate of \fIp\fP
+and the Y coordinate of \fIq\fP. This can be helpful in placing an
+object at one of the corners of the virtual box defined by two other
+objects.
+.KS
+.PS
+box invis wid 2 height 1;
+dot(last box .ne); "\fB(B,A)\fB is here" ljust at last circle + (0.1, 0.1);
+dot(last box .se); "B" ljust at last circle + (0.1, -0.1)
+dot(last box .sw); "\fB(A,B)\fB is here" rjust at last circle + (-0.1, -0.1);
+dot(last box .nw); "A" ljust at last circle + (-0.1, 0.1)
+.PE
+.CE "5: Using (\fIx\fP, \fIy\fP) composition"
+.NH 2
+Using Locations
+.PP
+There are four ways to use locations; \fBat\fP, \fBfrom\fP, \fBto\fP,
+and \fBwith\fP. All three are object modifiers; that is, you use them
+as suffixes to a drawing command.
+.PP
+The \fBat\fP modifier says to draw a closed object or arc with its
+center at the following location, or to draw a line/spline/arrow
+starting at the following location.
+.PP
+The \fBto\fP modifier can be used alone to specify a move destination.
+The \fBfrom\fP modifier can be used alone in the same way as \fBat\fP.
+.PP
+The \fBfrom\fP and \fBto\fP modifiers can be used with a \fBline\fR or
+\fBarc\fR command to specify start and end points of the object. In
+conjunction with named locations, this offers a very flexible
+mechanism for connecting objects. For example, the following program
+.KS
+.DS
+.CW
+\&.PS
+box "from"
+move 0.75;
+ellipse "to"
+arc cw from 1/3 of the way \\
+ between last box .n and last box .ne to last ellipse .n;
+\&.PE
+.R
+.DE
+.KE
+.LP
+yields:
+.KS
+.PS
+box "from"
+move 0.75;
+ellipse "to"
+arc cw from 1/3 of the way between last box .n and last box .ne to last ellipse .n;
+.PE
+.CE "6: A tricky connection specified with English-like syntax"
+.PP
+The \fBwith\fP modifier allows you to identify a named attachment
+point of an object with another point. This is very useful for connecting
+objects in a natural way. For an example, consider these two programs:
+.KS
+.PS
+[
+ box wid 0.5 ht 0.5; box wid 0.75 ht 0.75;
+ move down from last box .s 0.1;
+ "\fBbox wid 0.5 ht 0.5; box wid 0.75 ht 0.75\fP"
+]
+move from last [].e 2
+[
+ box wid 0.5 ht 0.5; box wid 0.75 ht 0.75 with .sw at last box .se;
+ move down from last box .s 0.1;
+ "\fBbox wid 0.5 ht 0.5; box wid 0.75 ht 0.75 with .sw at last box .se;\fP"
+]
+.PE
+.CE "7: Using the \fBwith\fP modifier for attachments"
+.NH 2
+The chop modifier
+.PP
+When drawing lines between circles that don't intersect them at a
+compass point, it is useful to be able to shorten a line by the radius
+of the circle at either or both ends. Consider the following program:
+.KS
+.DS
+\&.PS
+circle "x"
+circle "y" at 1st circle - (0.4, 0.6)
+circle "z" at 1st circle + (0.4, -0.6)
+arrow from 1st circle to 2nd circle chop
+arrow from 2nd circle to 3rd circle chop
+arrow from 3rd circle to 1st circle chop
+\&.PE
+.DE
+.KE
+.LP
+It yields the following:
+.KS
+.PS
+circle "x"
+circle "y" at 1st circle - (0.4, 0.6)
+circle "z" at 1st circle + (0.4, -0.6)
+arrow from 1st circle to 2nd circle chop
+arrow from 2nd circle to 3rd circle chop
+arrow from 3rd circle to 1st circle chop
+.PE
+.CE "8: The \fBchop\fR modifier"
+.LP
+Notice that the \fBchop\fR attribute moves arrowheads rather than
+stepping on them. By default, the \fBchop\fR modifier shortens both
+ends of the line by \fBcirclerad\fR. By suffixing it with a number
+you can change the amount of chopping.
+.PP
+If you say \fBline ... chop \fIr1\fP chop \fIr2\fP\fR with \fIr1\fP
+and \fIr2\fP both numbers, you can vary the amount of chopping at both
+ends. You can use this in combination with trigonometric functions
+to write code that will deal with more complex intersections.
+.NH 1
+Object Groups
+.PP
+There are two different ways to group objects in \fBpic\fP; \fIbrace
+grouping\fP and \fIblock composites\fP.
+.NH 2
+Brace Grouping
+.PP
+The simpler method is simply to group a set of objects within curly
+bracket or brace characters. On exit from this grouping, the current
+position and direction are restored to their value when the opening
+brace was encountered.
+.NH 2
+Block Composites
+.PP
+A block composite object is created a series of commands enclosed by
+square brackets. The composite can be treated for most purposes like
+a single closed object, with the size and shape of its bounding box.
+Here is an example. The program fragment
+.KS
+.DS
+.CW
+\&A: [
+\& circle;
+\& line up 1 at last circle .n;
+\& line down 1 at last circle .s;
+\& line right 1 at last circle .e;
+\& line left 1 at last circle .w;
+\& box dashed with .nw at last circle .se + (0.2, -0.2);
+\& Caption: center of last box;
+\&]
+.R
+.DE
+.KE
+.LP
+yields the block in figure \n[H1]-1, which we show both with and
+without its attachment points. The block's location becomes the
+value of \fBA\fP.
+.KS
+.PS
+define junction {
+ circle;
+ line up 1 at last circle .n;
+ line down 1 at last circle .s;
+ line right 1 at last circle .e;
+ line left 1 at last circle .w;
+ box dashed with .nw at last circle .se + (0.2, -0.2);
+ Caption: center of last box;
+}
+[junction();]
+move;
+compass([junction()]);
+.PE
+.CE "1: A sample composite object"
+.LP
+To refer to one of the composite's attachment points, you can say
+(for example) \fBA .s\fP. For purposes of object naming, composites
+are a class. You could write \fBlast [] .s\fP as an equivalent
+refrence, usable anywhere a location is needed. This construction is
+very important for putting together large, multi-part diagrams.
+.PP
+Blocks are also a variable-scoping mechanism, like a \fIgroff\fP(1)
+environment. All variable assignments done inside a block are undone
+at the end of it. To get at values within a block, write a name of
+the block followed by a dot, followed by the variable or label you
+want. For example, we could refer the the center of the box in the
+above composite as \fBlast [] .Caption\fP or \fBA.Caption\fP.
+.PP
+This kind of reference to a label can be used in any way any other
+location can be. For example, if we added \fB"Hi!" at A.Caption\fP
+the result would look like this:
+.KS
+.PS
+A: [junction();]
+"Hi!" at A.Caption;
+.PE
+.CE "2: Adding a caption using interior labeling"
+.PP
+You can also use interior labels in either part of a \fBwith\fR
+modifier. This means that the example composite could be placed
+relative to its caption box by a command containing \fBwith A.Caption
+at\fP.
+.PP
+Blocks may be nested. This means you can use block attachment points
+to build up complex diagrams hierarchically, from the inside out.
+Note that \fBlast\fP and the other sequential naming mechanisms
+don't look inside blocks, so if you have a program that looks
+like
+.KS
+.DS
+.CW
+\&.PS
+P: [box "foo"; ellipse "bar"];
+Q: [
+ [box "baz"; ellipse "quxx"]
+ "random text";
+ ]
+arrow from 2nd last [];
+\&.PE
+.R
+.DE
+.KE
+.LP
+the arrow in the last line will be attached to object \fBP\fP, not
+object \fBQ\fP.
+.PP
+In DWB \fBpic\fP, only references one level deep into enclosed blocks
+were permitted. GNU \fBgpic\fP removes this restriction.
+.PP
+The combination of block variable scoping, assignability of labels and
+the macro facility that we'll describe later on can be used to
+simulate functions with local variables (just wrap the macro body in
+block braces).
+.NH 1
+Style Variables
+.PP
+There are a number of global style variables in \fBpic\fR that can be used to
+change its overall behavior. We've mentioned several of them in
+previous sections. They're all described here. For each variable,
+the default is given.
+.TS H
+tab(@), linesize(2);
+lb | lb | lb
+l | n | l.
+.sp 2p
+Style Variable@Default@What It Does
+.sp 2p
+_
+.sp 2p
+.TH
+boxht@0.5@Default height of a box
+boxwid@0.75@Default height of a box
+lineht@0.5@Default length of vertical line
+linewid@0.75@Default length of horizontal line
+arcrad @0.25@Default radius of an arc
+circlerad@0.25@Default radius of a circle
+ellipseht@0.5@Default height of an ellipse
+ellipsewid@0.75@Default width of an ellipse
+moveht@0.5@Default length of vertical move
+movewid@0.75@Default length of horizontal move
+textht@0@Default height of box enclosing a text object
+textwid@0@Default width of box enclosing a text object
+arrowht@0.1@Length of arrowhead along shaft
+arrowwid@0.05@Width of rear of arrowhead
+arrowhead@1@Enable/disable arrowhead filling
+dashwid@0.05@Interval for dashed lines
+maxpswid@11@Maximum width of picture
+maxpsht@8.5@Maximum height of picture
+scale@1@Unit scale factor
+fillval@0.5@Default fill value
+.sp 5p
+_
+.TE
+Any of these variables can be set with a simple assignment statement.
+For example:
+.KS
+.PS
+[boxht=1; boxwid=0.3; movewid=0.2; box; move; box; move; box; move; box;]
+.PE
+.CE "1: \fBboxht=1; boxwid=0.3; movewid=0.2; box; move; box; move; box; move; box;\fP"
+.PP
+In GNU \fBpic\fR, setting the \fBscale\fR variable re-scales all
+size-related state variables so that their values remain equivalent in
+the new units.
+.PP
+The command \fBreset\fP resets all style variables to their defaults.
+You can give it a comma-separated list of variable names as arguments,
+in which case it resets only those.
+.PP
+State variables retain their values across pictures until reset.
+.NH 1
+Expressions, Variables, and Assignment
+.PP
+A number is a valid expression, of course (all numbers are stored
+internally as floating-point). Decimal-point notation is acceptable;
+in GNU \fBgpic\fR, scientific notation in C's `e' format (like
+\f(CW5e-2\fP) is accepted.
+.PP
+Anywhere a number is expected, the language will also accept a
+variable. Variables may be the built-in style variable described in
+the last section, or new variables created by assignment.
+.PP
+DWB \fBpic\fP supports only the ordinary assignment via =, defines the
+variable in the current block if it is not already defined there, and
+then changes the value in the current block.
+GNU \fBgpic\fP supports an alternate form of assignment using :=. The
+.I variable
+(right side) must already be defined,
+and the value of
+.I variable
+will be changed only in the innermost block in which it is defined.
+.PP
+You can use the height, width, radius, and x and y coordinates of any
+object or corner in expressions If \fBA\fP is an object label or name,
+all the following are valid:
+.KS
+.DS
+.CW
+A.x # x coordinate of the center of A
+A.ne.y # y coordinate of the northeast corner of A
+A.wid # the width of A
+A.ht # and its height
+2nd last circle.rad # the radius of the 2nd last circle
+.R
+.DE
+.KE
+Note the second expression, showing how to extract a corner coordinate.
+.PP
+Basic arithmetic resembling those of C operators are available; +, *,
+-, /, and %. So is ^ for exponentiation. Grouping is permitted in
+the usual way using parentheses. GNU \fBgpic\fP allows logical
+operators to appear in expressions; ! (logical negation, not
+factorial), &&, ||, ==, !=, >=, <=, <, >.
+.PP
+Various built-in functions are supported: \fBsin(\fIx\fP)\fP,
+\fBcos(\fIx\fP)\fP, \fBlog(\fIx\fP)\fP, \fBexp(\fIx\fP)\fP,
+\fBsqrt(\fIx\fP)\fP, \fBmax(\fIx\fP,\fIy\fP)\fP,
+\fBatan2(\fIx\fP,\fIy\fP)\fP, \fBmin(\fIx\fP,\fIy\fP)\fP,
+\fBint(\fIx\fP\fB)\fP, and \fBrand()\fP, Both \fBexp\fP and \fBlog\fP are
+base 10; \fBint\fP does integer truncation; and \fBrand()\fP returns a
+random number in [0-1).
+.PP
+GNU \fBgpic\fP also documents a one-argument form or rand,
+\fBrand(\fIx\fP\fB)\fP, which returns a random number between 1 and
+\fIx\fP, but this is deprecated and may be removed in a future
+version.
+.PP
+The function \fBsprintf()\fP behaves like a C \fIsprintf\fP(3) that
+only takes %, %e, %f, and %g format strings.
+.NH 1
+Macros
+.PP
+You can define macros in \fBpic\fP. This is useful for diagrams with
+repetitive parts. In conjunction with the scope rules for block
+composites, it effectively gives you the ability to write functions.
+.PP
+The syntax is
+.DS
+.CW
+\fBdefine\fP \fIname\fP \fB{\fP \fIreplacement text \fB}\fP
+.R
+.DE
+.LP
+This defines \fIname\fR as a macro to be replaced by the replacement
+text (not including the braces). The macro may be called as
+.DS
+.CW
+\fIname\fB(\fIarg1, arg2, ... argn\fB)\fR
+.R
+.DE
+.LP
+The arguments (if any) will be substituted for tokens $1, $2 ... $n
+appearing in the replacement text.
+.PP
+As an example of macro use, consider the following:
+.KS
+.DS
+.CW
+\&.PS
+\&# Plot a single jumper in a $1 by $2 box, $3 is the on-off state
+\&define jumper { [
+\& shrinkfactor = 0.8;
+\& Outer: box invis wid 0.5 ht 1;
+\&
+\& # Count on end ] to reset these
+\& boxwid = Outer.wid * shrinkfactor / 2;
+\& boxht = Outer.ht * shrinkfactor / 2;
+\&
+\& box fill (!$1) with .s at center of Outer;
+\& box fill ($1) with .n at center of Outer;
+\&] }
+\&
+\&# Plot a block of six jumpers
+\&define jumperblock {
+\& jumper($1);
+\& jumper($2);
+\& jumper($3);
+\& jumper($4);
+\& jumper($5);
+\& jumper($6);
+\&
+\& jwidth = last [].Outer.wid;
+\& jheight = last [].Outer.ht;
+\&
+\& box with .nw at 6th last [].nw wid 6*jwidth ht jheight;
+\&
+\& # Use {} to avoid changing position from last box draw.
+\& # This is necessary so move in any direction will work as expected
+\& {"Jumpers in state $1$2$2$3$4$5$6" at last box .s + (0, -0.2);}
+\&}
+\&
+\&# Sample macro invocations
+\&jumperblock(1,1,0,0,1,0);
+\&move;
+\&jumperblock(1,0,1,0,1,1);
+.PE
+.R
+.DE
+.KE
+It yields the following:
+.KS
+.PS
+# Plot a single jumper in a $1 by $2 box, $3 is the on-off state
+define jumper { [
+ shrinkfactor = 0.8;
+ Outer: box invis wid 0.5 ht 1;
+
+ # Count on end ] to reset these
+ boxwid = Outer.wid * shrinkfactor / 2;
+ boxht = Outer.ht * shrinkfactor / 2;
+
+ box fill (!$1) with .s at center of Outer;
+ box fill ($1) with .n at center of Outer;
+] }
+
+# Plot a block of six jumpers
+define jumperblock {
+ jumper($1);
+ jumper($2);
+ jumper($3);
+ jumper($4);
+ jumper($5);
+ jumper($6);
+
+ jwidth = last [].Outer.wid;
+ jheight = last [].Outer.ht;
+
+ box with .nw at 6th last [].nw wid 6*jwidth ht jheight;
+
+ # Use {} to avoid changing position from last box draw.
+ # This is necessary so move in any direction will work as expected
+ {"Jumpers in state $1$2$2$3$4$5$6" at last box .s + (0, -0.2);}
+}
+
+# Sample macro invocations
+jumperblock(1,1,0,0,1,0);
+move;
+jumperblock(1,0,1,0,1,1);
+.PE
+.CE "1: Sample use of a macro"
+.LP
+This macro example illustrates how you can combine [], brace grouping,
+and variable assignment to write true functions.
+.PP
+One detail the example above does not illustrate is the fact that
+macro argument parsing is not token-oriented. If you call \fBjumper(
+1 )\fP, the value of $1 will be \fB" 1 "\fP. You could even call
+\fBjumper(big string)\fP to give $1 the value \fB"big string"\fP.
+.PP
+If you want to pass in a coordinate pair, you can avoid getting
+tripped up by the comma by wrapping the pair in parentheses.
+.PP
+Macros persist through pictures. To undefine a mcro, say \fBundef\fP
+\fIname\fR; for example,
+.DS
+\f(CWundef jumper\fP
+\f(CWundef jumperblock\fP
+.DE
+.LP
+would undefine the two macros in the jumper block example.
+.NH 1
+Import/Export Commands
+.PP
+Commands that import or export data between \fBpic\fR and its
+environment are described here.
+.NH 2
+File and Table Insertion
+.PP
+The statement
+.DS
+\f(CWcopy\fP \fIfilename\fR
+.DE
+inserts the contents of \fIfilename\fR in the \fBpic\fP input stream.
+Any .PS/.PE pair in the file will be ignored. This, you can use this
+to include pre-generated images.
+.PP
+A variant of this statement replicates the \fBcopy thru\fP feature of
+\fIgrap\fP(1). If you say
+.DS
+\f(CWcopy\fP \fIfilename\fR \f(CWthru\fP \fImacro\fP
+.DE
+.LP
+calls the \fImacro\fP (which may be either a name or replacement text)
+on the arguments obtained by breaking each line of the file into
+blank-separated fields. The macro may have up to 9 arguments. The
+replacement text may be delimited by braces or by a pair of instances
+of any character not appearing in the rest of the text.
+.PP
+If you write
+.DS
+\f(CWcopy thru\fP \fImacro\fP
+.DE
+.LP
+omitting the filename, lines to be parsed are taken from the input
+source up to the next .PE.
+.PP
+In either of the \fBcopy\fP commands, GNU \fBgpic\fP permits a
+trailing `\fBuntil\fP \fIword\fP' clause to be added which terminates
+the copy when the first word matches the argument (the default
+behavior is therefore equivalent to \fBuntil .PE\fP,
+.PP
+Accordingly, the command
+.RS
+.IP
+.ft CW
+.nf
+\&.PS
+copy thru % circle at ($1,$2) % until "END"
+1 2
+3 4
+5 6
+END
+box
+\&.PE
+.R
+.fi
+.RE
+.LP
+is equivalent to
+.RS
+.IP
+.ft CW
+.nf
+\&.PS
+circle at (1,2)
+circle at (3,4)
+circle at (5,6)
+box
+\&.PE
+.R
+.fi
+.RE
+.NH 2
+Debug Messages
+.PP
+The command \fBprint\fR accepts any number of comma-separated
+arguments, concatenates their output forms, and writes the result to
+standard error. Each argument must be an expression, a position, or
+a text string.
+.NH 2
+Escape to Post-Processor
+.PP
+If you write
+.DS
+\fBcommand\fR \fIarg\fR\|.\|.\|.
+.DE
+.LP
+\fBpic\fP concatenates the arguments and pass them through as a line
+to troff or \*(tx. Each
+.I arg
+must be an expression, a position, or text.
+This has a similar effect to a line beginning with
+.B .
+or
+\fB\e\fR,
+but allows the values of variables to be passed through.
+.NH 2
+Executing Shell Commands
+.PP
+The command
+.DS
+\f(CWsh { \fIanything...\fP }\fP
+.DE
+.LP
+macroexpands the text in braces, then executes it as a shell command.
+This could be used to generate images or data tables for later
+inclusion. The delimiters shown as {} here may also be two copies of
+any one character not present in the shell command text. In either
+case, the body may contain balanced {} pairs. Strings in the body
+may contain balanced or unbalanced braces in any case.
+.NH 1
+Control-flow constructs
+.PP
+The \fBpic\fP language provides conditionals and looping. For
+example,
+.KS
+.DS
+.CW
+pi = atan2(0, -1);
+for i = 0 to 2 * pi by 0.1 do {
+ "-" at (i/2, 0);
+ "." at (i/2, sin(i)/2);
+ ":" at (i/2, cos(i)/2);
+}
+.R
+.DE
+.KE
+.LP
+which yields this:
+.KS
+.PS
+pi = atan2(0, -1);
+for i = 0 to 2 * pi by 0.1 do {
+ "-" at (i/2, 0);
+ "." at (i/2, sin(i)/2);
+ ":" at (i/2, cos(i)/2);
+}
+.PE
+.CE "1: Plotting with a \fBfor\fP loop"
+.LP
+The syntax of the \fBfor\fP statement is:
+.DS
+\fBfor\fR \fIvariable\fR \fB=\fR \fIexpr1\fR \fBto\fR \fIexpr2\fR \
+[\fBby\fR [\fB*\fR]\fIexpr3\fR] \fBdo\fR \fIX\fR \fIbody\fR \fIX\fR
+.DE
+The semantics are as follows: Set
+.I variable
+to \fIexpr\fR1 .
+While the value of
+.I variable
+is less than or equal to
+\fIexpr2\fR,
+do
+.I body
+and increment
+.I variable
+by
+\fIexpr3\fR;
+if
+.B by
+is not given, increment
+.I variable
+by 1.
+If
+.I expr3
+is prefixed by
+.B *
+then
+.I variable
+will instead be multiplied by
+\fIexpr3\fR.
+.I X
+can be any character not occurring in
+\fIbody\fR; or the two Xs may be paired braces (as in the \fBsh\fR command).
+.PP
+The syntax of the \fBif\fP statement is as follows:
+.DS
+\fBif\fR \fIexpr\fR \fBthen\fR \fIX\fR \fIif-true\fR \fIX\fR \
+[\fBelse\fR \fIY\fR \fIif-false\fR \fIY\fR]
+.DE
+Its semantics are as follows: Evaluate
+\fIexpr\fR;
+if it is non-zero then do
+\fIif-true\fR,
+otherwise do
+\fIif-false\fR.
+.I X
+can be any character not occurring in
+\fIif-true\fR.
+.I Y
+can be any character not occurring in
+\fIif-false\fR.
+.PP
+Eithe or both of the X or Y pairs may instead be balanced pairs of
+braces ({ and }) as in the \fBsh\fR command. In either case, the
+\fIif-true\fR may contain balanced pairs of braces. None of these
+delimiters will be seen inside strings.
+.PP
+All the usual relational operators my be used in conditional expressions;
+! (logical negation, not factorial), &&, ||, ==, !=, >=, <=, <, >.
+.PP
+String comparison is also supported using == and !=. String
+comparisons may need to be parenthesized to avoid syntactic
+ambiguities.
+.NH 1
+Interface To [gt]roff
+.PP
+The output of \fBpic\fP is \fB[gt]roff\fP drawing commands. The GNU
+\fIgpic\fP(1) command warns that it relies on drawing extensions
+present in \fIgroff\fP(1) that are not present in \fItroff\fP(1).
+.NH 2
+Scaling Arguments
+.PP
+The DWB \fIpic\fP(1) program will accept one or two arguments to
+\&\fB.PS\fP, which is interpreted as a width and height in inches to
+which the results of \fIpic\fP(1) should be scaled (width and height
+scale independently). If there is only one argument, it is
+interpreted as a width to scale the picture to, and height will be
+scaled by the same proportion.
+.PP
+GNU \fBgpic\fP is less general; it will accept a single width to scale
+to, or a zero width and a maximum height to scale to. With
+two nonzero arguments, it will scale to the maximum height.
+.NH 2
+How Scaling is Handled
+.PP
+When \fBpic\fP processes a picture description on input, it passes .PS
+and .PE through to the postprocessor. The .PS gets decorated with two
+numeric arguments which are the X and Y dimensions of the picture in
+inches. The post-processor can use these to reserve space for the
+picture and center it.
+.PP
+The \fBmgs\fP macros, for example, include the following definitions:
+.KS
+.DS
+.CW
+\&.de PS
+\&.br
+\&.sp \\n[DD]u
+\&.ie \\n[.$]<2 .@error bad arguments to PS (not preprocessed with pic?)
+\&.el \{\
+\&. ds@need (u;\\$1)+1v
+\&. in +(u;\\n[.l]-\\n[.i]-\\$2/2>?0)
+\&.\}
+\&..
+\&.de PE
+\&.par@reset
+\&.sp \\n[DD]u+.5m
+\&..
+.R
+.DE
+.KE
+.LP
+Equivalent definition will be supplied by GNU \fIpic\fP(1) if you use
+the -mpic option; this should make it usable with macro pages other
+than \fIms\fR(1).
+.PP
+if .PF is used instead of .PE, the \fBtroff\fP position is restored to
+what it was at the picture start (Kernighan notes that the F stands
+for "flyback").
+.PP
+The invocation
+.DS
+\&\fB.PS <\fP\fIfile\fP
+.DE
+.LP
+causes the contents of \fIfile\fP to replace the .PS line. This
+feature is deprecated; use \fBcopy file\fR instead).
+.PP
+By default, input lines that begin with a period are passed to the
+postprocessor, embedded at the corresponding point in the output.
+Messing with horizontal or vertical spacing is an obvious recipe for
+bugs, but point size and font changes will usually be safe.
+.PP
+Point sizes and font changes are also safe within text strings, as
+long as they are undone before the end of string.
+.PP
+The state of \fB[gt]roff\fP's fill mode is preserved across pictures.
+.PP
+The Kernighan paper notes that there is a subtle problem with
+complicated equations inside \fBpic\fR pictures; they come out wrong if
+\fIeqn\fP(1) has to leave extra vertical space for the equation.
+If your equation involves more than subscripts and superscripts, you
+must add to the beginning of each equation the extra information
+\f(CWspace 0\fP. He gives the following example:
+.KS
+.DS
+.CW
+arrow
+box "$space 0 {H( omega )} over {1 - H( omega )}$"
+arrow
+.R
+.DE
+.KE
+.EQ
+delim @@
+.EN
+.KS
+.PS
+arrow
+box "@space 0 {H( omega )} over {1 - H( omega )}@"
+arrow
+.PE
+.CE "1: Equations within pictures"
+.NH 1
+Interface to TeX
+.PP
+.PP
+\*(tx mode is enabled by the
+.B \-t
+option.
+In \*(tx mode, pic will define a vbox called
+.B \egraph
+for each picture.
+You must yourself print that vbox using, for example, the command
+.RS
+.LP
+.B
+\ecenterline{\ebox\egraph}
+.RE
+.LP
+Actually, since the vbox has a height of zero this will produce
+slightly more vertical space above the picture than below it;
+.RS
+.LP
+.B
+\ecenterline{\eraise 1em\ebox\egraph}
+.RE
+.LP
+would avoid this.
+.PP
+You must use a \*(tx driver that supports the
+.B tpic
+specials, version 2.
+.PP
+Lines beginning with
+.B \e
+are passed through transparently; a
+.B %
+is added to the end of the line to avoid unwanted spaces.
+You can safely use this feature to change fonts or to
+change the value of \fI\ebaselineskip\fR.
+Anything else may well produce undesirable results; use at your own risk.
+Lines beginning with a period are not given any special treatment.
+.PP
+The \(*tx mode of \fIpic\fP(1) will \fInot\fP translate \fBtroff\fP
+font and size changes included in text strings!
+.NH 1
+Obsolete Commands
+.PP
+GNU \fIgpic\fP(1) has a command
+.DS
+\fBplot\fR \fIexpr\fR [\fB"\fItext\fB"\fR]
+.DE
+This is a text object which is constructed by using
+.I text
+as a format string for sprintf
+with an argument of
+\fIexpr\fP.
+If
+.I text
+is omitted a format string of "%g" is used.
+Attributes can be specified in the same way as for a normal text
+object.
+Be very careful that you specify an appropriate format string;
+\fBpic\fP does only very limited checking of the string.
+This is deprecated in favour of
+\fBsprintf\fP.
+.NH 1
+Some Larger Examples
+.PP
+Here are a few larger examples, with complete source code.
+.PP
+One of our earlier examples is generated in an instructive way using a
+for loop:
+.KS
+.DS
+.CW
+\&.PS
+\&# Draw a demonstration up left arrow with grid box overlay
+\&define gridarrow
+\&{
+\& [
+\& {arrow up left $1;}
+\& box wid 0.5 ht 0.5 dotted with .nw at last arrow .end;
+\& for i = 2 to ($1 / 0.5) do
+\& {
+\& box wid 0.5 ht 0.5 dotted with .sw at last box .se;
+\& }
+\& move down from last arrow .center;
+\& [
+\& if ( $1 == boxht ) then { "\\fBline up left\\fP" } else { sprintf("\\fBarrow up left %g\\fP", $1) };
+\& ]
+\& ]
+\& move right from last [] .e;
+\&}
+\&gridarrow(0.5);
+\&gridarrow(1);
+\&gridarrow(1.5);
+\&gridarrow(2);
+\&undef gridarrow
+\&.PE
+.R
+.DE
+.KE
+.KS
+.PS
+# Draw a demonstration up left arrow with grid box overlay
+define gridarrow
+{
+ [
+ {arrow up left $1;}
+ box wid 0.5 ht 0.5 dotted with .nw at last arrow .end;
+ for i = 2 to ($1 / 0.5) do
+ {
+ box wid 0.5 ht 0.5 dotted with .sw at last box .se;
+ }
+ move down from last arrow .center;
+ [
+ if ( $1 == boxht ) then { "\fBline up left\fP" } else { sprintf("\fBarrow up left %g\fP", $1) };
+ ]
+ ]
+ move right from last [] .e;
+}
+gridarrow(0.5);
+gridarrow(1);
+gridarrow(1.5);
+gridarrow(2);
+undef gridarrow
+.PE
+.CE "1: Diagonal arrows (dotted boxes show the implied 0.5-inch grid)"
+.PP
+Here's an example concocted to demonstrate layout of a large,
+multiple-part pattern:
+.KS
+.DS
+.CW
+\&.PS
+\&define filter {box ht 0.25 rad 0.125}
+\&lineht = 0.25;
+\&Top: [
+\& right;
+\& box "\\fBms\\fR" "sources";
+\& move;
+\& box "\\fBHTML\\fR" "sources";
+\& move;
+\& box "\\fBlinuxdoc-sgml\\fP" "sources" wid 1.5;
+\& move;
+\& box "\\fBTexinfo\\fP" "sources";
+\&
+\& line down from 1st box .s lineht;
+\& A: line down;
+\& line down from 2nd box .s; filter "\\fBhtml2ms";
+\& B: line down;
+\& line down from 3rd box .s; filter "\\fBformat\\fP";
+\& C: line down;
+\& line down from 4th box .s; filter "\\fBtexi2roff\\fP";
+\& D: line down;
+\&]
+\&move down 1 from last [] .s;
+\&Anchor: box wid 1 ht 0.75 "\\fBms\\fR" "intermediate" "form";
+\&arrow from Top.A.end to Anchor.nw;
+\&arrow from Top.B.end to 1/3 of the way between Anchor.nw and Anchor.ne;
+\&arrow from Top.C.end to 2/3 of the way between Anchor.nw and Anchor.ne;
+\&arrow from Top.D.end to Anchor.ne
+\&{
+\& # PostScript column
+\& move to Anchor .sw;
+\& line down left then down ->;
+\& filter "\\fBpic\\fP";
+\& arrow;
+\& filter "\\fBeqn\\fP";
+\& arrow;
+\& filter "\\fBtbl\\fP";
+\& arrow;
+\& filter "\\fBgroff\\fP";
+\& arrow;
+\& box "PostScript";
+\&
+\& # HTML column
+\& move to Anchor .se;
+\& line down right then down ->;
+\& A: filter dotted "\\fBpic2img\\fP";
+\& arrow;
+\& B: filter dotted "\\fBeqn2html\\fP";
+\& arrow;
+\& C: filter dotted "\\fBtbl2html\\fP";
+\& arrow;
+\& filter "\\fBms2html\\fP";
+\& arrow;
+\& box "HTML";
+\&
+\& # Nonexistence caption
+\& box dashed wid 1 at B + (2, 0) "These tools" "don't yet exist";
+\& line chop 0 chop 0.1 dashed from last box .nw to A.e ->;
+\& line chop 0 chop 0.1 dashed from last box .w to B.e ->;
+\& line chop 0 chop 0.1 dashed from last box .sw to C.e ->;
+\&}
+\&.PE
+.R
+.DE
+.KE
+.KS
+.PS
+define filter {box ht 0.25 rad 0.125}
+lineht = 0.25;
+Top: [
+ right;
+ box "\fBms\fR" "sources";
+ move;
+ box "\fBHTML\fR" "sources";
+ move;
+ box "\fBlinuxdoc-sgml\fP" "sources" wid 1.5;
+ move;
+ box "\fBTexinfo\fP" "sources";
+
+ line down from 1st box .s lineht;
+ A: line down;
+ line down from 2nd box .s; filter "\fBhtml2ms";
+ B: line down;
+ line down from 3rd box .s; filter "\fBformat\fP";
+ C: line down;
+ line down from 4th box .s; filter "\fBtexi2roff\fP";
+ D: line down;
+]
+move down 1 from last [] .s;
+Anchor: box wid 1 ht 0.75 "\fBms\fR" "intermediate" "form";
+arrow from Top.A.end to Anchor.nw;
+arrow from Top.B.end to 1/3 of the way between Anchor.nw and Anchor.ne;
+arrow from Top.C.end to 2/3 of the way between Anchor.nw and Anchor.ne;
+arrow from Top.D.end to Anchor.ne
+{
+ # PostScript column
+ move to Anchor .sw;
+ line down left then down ->;
+ filter "\fBpic\fP";
+ arrow;
+ filter "\fBeqn\fP";
+ arrow;
+ filter "\fBtbl\fP";
+ arrow;
+ filter "\fBgroff\fP";
+ arrow;
+ box "PostScript";
+
+ # HTML column
+ move to Anchor .se;
+ line down right then down ->;
+ A: filter dotted "\fBpic2img\fP";
+ arrow;
+ B: filter dotted "\fBeqn2html\fP";
+ arrow;
+ C: filter dotted "\fBtbl2html\fP";
+ arrow;
+ filter "\fBms2html\fP";
+ arrow;
+ box "HTML";
+
+ # Nonexistence caption
+ box dashed wid 1 at B + (2, 0) "These tools" "don't yet exist";
+ line chop 0 chop 0.1 dashed from last box .nw to A.e ->;
+ line chop 0 chop 0.1 dashed from last box .w to B.e ->;
+ line chop 0 chop 0.1 dashed from last box .sw to C.e ->;
+}
+.PE
+.CE "2: Hypothetical production flow for dual-mode publishing"
+.LP
+.\"%%REFERENCE%%
+.NH 1
+PIC Reference
+.PP
+This is an annotated grammar of PIC.
+.NH 2
+Lexical Items
+.PP
+In general, \fBpic\fP is a free-format, token-oriented language that
+ignores whitespace outside strings. But certain lines and contructs
+are specially interpreted at the lexical level:
+.PP
+A comment begins with # and continues to \en (comments may also follow
+text in a line). A line beginning with a period or backslash may be
+interpreted as text to be passed through to the post-processor,
+depending on command-line options. An end-of-line backslash is
+interpreted as a request to continue the line; the backslash and
+following newline are ignored.
+.LP
+Here are the grammar terminals:
+.IP <number>
+A decimal numeric constant. May contain a decimal point or be
+expressed in scientific notation in the style of \fIprintf\fP(3)'s %e
+escape. (All variables are represented internally in floating-point.)
+.IP <string>
+Any ASCII characters surrounded by a pair of double quotes. May
+contain a double quote if preceded by a backslash.
+.IP <variable>
+A lower-case alphabetic character, followed by any number of
+alphanumerics. (Values of variables are preserved across pictures.)
+.IP <label>
+An upper-case alphabetic character, followed by any number of
+alphanumerics.
+.NH 2
+Semi-Formal Grammar
+.PP
+Tokens not enclosed in <> are literals, except:
+.IP 1.
+\en is a newline
+.IP 2.
+three dots is a suffix meaning \&`replace with 0 or more repetitions
+of the preceding element.
+.IP 3.
+enclosure in square brackets has its usual meaning of `this clause is
+optional'.
+.IP 4.
+Square-bracket-enclosed portions within tokens are optional. Thus,
+\fBh[eigh]t\fR matches either `height' or `ht'.
+.LP
+If one of these special tokens has to be referred to literally, it is
+surrounded with single quotes.
+.PP
+The top-level \fBpic\fP object is a picture.
+.DS
+.CW
+<picture> ::= .PS [width [height]]\en
+ <statement> ...
+ .PE \en
+.R
+.DE
+.LP
+The \fIwidth\fP and \fIheight\fP arguments, if present, cause
+\fBpic\fR to attempt to scale the picture to the given dimensions in
+inches. In no case, however, will the X and Y dimensions of the
+picture exceed the values of the style variables \fBmaxpswid\fP,
+\fBmaxpsheight\fP (which default to the normal 8.5 by 11 page size)\fP.
+.LP
+If the ending .PS is replaced by .PF, the page vertical position is
+restored to its value at the time .PS was encountered. Another
+alternate form of invocation is \f(CW.PS <\fIfilename\fR, which
+replaces the .PS line with a file to be interpreted by \fBpic\fR (but
+this feature is deprecated).
+.LP
+The .PS, .PE, and .PF macros to perform centering and scaling are
+normally supplied by the post-processor.
+.DS
+.CW
+
+<statement> ::= <command> ;
+ <command> \en
+
+<command> ::= <primitive> <modifier>...
+ <label> : <command>
+ <label> : <position>
+ <variable> = <expr>
+ <direction>
+ { <command> ... }
+ '[' <command> ... ']'
+ for <var> = <expr> to <expr> [by <expr>] do { <command> ... }
+ if <expr> then { <command> ... } [else { <command> ... }]
+ copy <filename> [until <word>]
+ copy <filename> thru <macroname> [until <word>]
+ sh <balanced-text>
+ print <print-item>
+ reset [ <variable> ... ]
+.R
+.DE
+.LP
+The current position and direction are saved on entry to a { } and
+restored on exit from it.
+.LP
+Drawn objects within [ ] are treated as a single composite object with
+a rectangular shape (that of the bounding box of all the elements).
+Variable and label assignments within a block are local to the block.
+Current direction of motion is restored to the value at start of block
+upon exit. Position is \fInot\fR restored (unlike { }) instead, the
+current position becomes the exit position for the current direction
+on the block's bounding box.
+.DS
+.CW
+<primitive> ::= box \fR# Closed object -- rectangle\fP
+ circle \fR# Closed object -- circle\fP
+ ellipse \fR# Closed object -- ellipse\fP
+ arc \fR# Open object -- quarter-circle\fP
+ line \fR# Open object -- line\fP
+ arrow \fR# Open object -- line with arrowhead\fP
+ spline \fR# Open object -- spline curve\fP
+ move
+ <text> <text> ... \fR# Text within invisible box\fP
+
+<attribute> ::= h[eigh]t <expr> \fR# Set height of closed figure \fP
+ wid[th] <expr> \fR# Set width of closed figure \fP
+ rad[ius] <expr> \fR# Set radius of circle/arc \fP
+ diam[eter] <expr> \fR# Set diameter of circle/arc \fP
+ up [ <expr> ] \fR# Move up \fP
+ down [ <expr> ] \fR# Move down \fP
+ left [ <expr> ] \fR# Move left \fP
+ right [ <expr> ] \fR# Move right \fP
+ from <position> \fR# Set from position of open figure\fP
+ to <position> \fR# Set to position of open figure\fP
+ at <position> \fR# Set center of open figure\fP
+ with <corner> \fR# Fix corner at specified location\fP
+ by <expr> <expr> \fR# Set object's attachment point\fP
+ then \fR# Sequential segment composition\fP
+ dotted [ <expr> ] \fR# Set dotted line style\fP
+ dashed [ <expr> ] \fR# Set dashed line style\fP
+ chop [ <expr> ] \fR# Chop end(s) of segment\fP
+ -> \fR# Decorate with "to" arrow\fP
+ <- \fR# Decorate with "from" arrow\fP
+ <-> \fR# Decorate with both arrows\fP
+ invis \fR# Make primitive invisible\fP
+ solid \fR# Make closed figure solid\fP
+ fill <expr> \fR# Set fill density for figure\fP
+ same \fR# Copy size of previous object\fP
+ <text> <text> ... \fR# Text within object\fP
+ <expr> \fR# Motion in the current direction\fR
+.R
+.DE
+.LP
+Missing attributes are supplied from defaults; inappropriate ones are
+silently ignored. For lines, splines, and arcs, height and width
+refer to arrowhead size.
+.PP
+The \f(CWat\fP primitive sets the center of the current object. The
+\f(CWwith\fP attribute fixes the specified feature of the given object
+to a specified location.
+.PP
+The \f(CWsolid\fR primitive is not yet supported in GNU \fBgpic\fR.
+.PP
+The \f(CWby\fR primitive is not documented in the tutorial portion of
+the Kernighan paper, and should probably be considered unreliable.
+.PP
+The primitive \fBarrow\fR is a synonym for \fBline ->\fR.
+.DS
+.CW
+<text> ::= <string> [ <placement> ... ]
+ sprintf("format", <expr> ...) [ <placement> ... ]
+
+<placement> ::= center | ljust | rjust | above | below
+.R
+.DE
+.LP
+Text is normally an attribute of some object, in which case successive
+strings are vertically stacked and centered on the object's center by
+default. Standalone text is treated as though placed in an invisible
+box.
+.PP
+A text item consists of a string or sprintf-expression, optionally
+followed by positioning information. Text or format strings may
+contain {gtn}roff font changes, size changes, and local motions,
+provided those changes are undone before the end of the current item.
+.PP
+A position is an (x, y) coordinate pair. There are lots of different
+ways to specify positions:
+.DS
+.CW
+<position> ::= <expr> , <expr>
+ <place> {+-} <expr> , <expr>
+ <place> {+-} ( <expr> , <expr> )
+ ( <position> , <position> )
+ <expr> [of the way] between <position> and <position>
+ <expr> '<' <position> , <position> '>'
+ ( <position> )
+
+<place> ::= <label> [ <dot-corner> ]
+ <corner> of <label>
+ [0|1|2|3|4|5|6|7|8|9]th [last] <primitive> <dot-corner>
+ <expr>'th [last]<primitive> <dot-corner>
+ <corner> of [0|1|2|3|4|5|6|7|8|9]th [last] <primitive>
+ <corner> of <expr>'th [last] <primitive>
+ Here
+
+<dot-corner> ::= .n | .e | .w | .s | .ne | .nw | .se | .sw | .c | .start | .end
+
+<corner> ::= top | bot | left | right | start | end
+.R
+.DE
+.LP
+As Kernighan notes, "since barbarisms like \fB1th\fP and \fB3th\fP are
+barbaric, synonyms like \fB1st\fP and \fB3rd\fP are accepted as well".
+Objects of a given type are numbered from 1 upwards in order of
+declaration; the \fBlast\fP modifier counts backwards.
+.PP
+The "'th" form (which allows you to select a previous object with an
+expression, as opposed to a numeric literal) is bnot documented in DWB
+\fBpic\fR(1).
+.PP
+The following style variables control output:
+.TS H
+tab(@), linesize(2);
+lb | lb | lb
+l | n | l.
+.sp 2p
+Style Variable@Default@What It Does
+.sp 2p
+_
+.sp 2p
+.TH
+boxht@0.5@Default height of a box
+boxwid@0.75@Default height of a box
+lineht@0.5@Default length of vertical line
+linewid@0.75@Default length of horizontal line
+arcrad @0.25@Default radius of an arc
+circlerad@0.25@Default radius of a circle
+ellipseht@0.5@Default height of an ellipse
+ellipsewid@0.75@Default width of an ellipse
+moveht@0.5@Default length of vertical move
+movewid@0.75@Default length of horizontal move
+textht@0@Default height of box enclosing a text object
+textwid@0@Default width of box enclosing a text object
+arrowht@0.1@Length of arrowhead along shaft
+arrowwid@0.05@Width of rear of arrowhead
+arrowhead@1@Enable/disable arrowhead filling
+dashwid@0.05@Interval for dashed lines
+maxpswid@11@Maximum width of picture
+maxpsht@8.5@Maximum height of picture
+scale@1@Unit scale factor
+fillval@0.5@Default fill value
+.sp 5p
+_
+.TE
+Any of these can be set by assignment, or reset using the \fBreset\fP
+statement. Style variables assigned within [] blocks are restored to
+their beginning-of-block value on exit; top-level assignments persist
+across pictures. Dimensions are divided by \fBscale\fR on output.
+.PP
+All \fBpic\fP expressions are evaluated in floating point; units
+default to inches. Expressions have the following simple grammar,
+with semantics very similar to C expressions:
+.DS
+.CW
+<expr> ::= <expr> <op> <expr>
+ ! <expr>
+ ( <expr> )
+ - <expr>
+ <variable>
+ <number>
+ <place> .x
+ <place> .y
+ <place> .ht
+ <place> .wid
+ <place> .rad
+ sin(<expr>)
+ cos(<expr>)
+ log(<expr>)
+ exp(<expr>)
+ sqrt(<expr>)
+ max(<expr>, <expr>...)
+ atan2(<expr>, <expr>)
+ min(<expr>, <expr>...)
+ int(<expr>)
+ rand()
+
+<op> := + | - | * | / | % | ^ |
+ != | == | '<' | '>' | >= | <= |
+ '||' | &&
+.R
+.DE
+.LP
+Both \fBexp\fP and \fBlog\fP are base 10; \fBint\fP does integer
+truncation; and \fBrand()\fP returns a random number in [0-1).
+.PP
+There are \fBdefine\fP and \fBundef\fR statements which are not part
+of the grammar (they behave as pre-processor macros to the language).
+These may be used to define pseudo-functions.
+.DS
+.CW
+\fBdefine\fP \fIname\fP \fB{\fP \fIreplacement text \fB}\fP
+.R
+.DE
+.LP
+This defines \fIname\fR as a macro to be replaced by the replacement
+text (not including the braces). The macro may be called as
+.DS
+.CW
+\fIname\fB(\fIarg1, arg2, ... argn\fB)\fR
+.R
+.DE
+.LP
+The arguments (if any) will be substituted for tokens $1, $2 ... $n
+appearing in the replacement text. To undefine a mcro, say \fBundef\fP
+\fIname\fR, specifying the name to be undefined.
+.\"%%POSTLUDE%%
+.NH 1
+History and Acknowledgements
+.PP
+Original \fBpic\fP was written to go with Joseph Ossanna's original
+\&\fItroff\fP(1) by Brian Kernighan, and later re-written by Kernighan
+with substantial enhancements (apparently as part of the evolution of
+\&\fItroff\fP(1) into \&\fIditroff\fP(1) to generate
+device-independent output).
+.PP
+The language had been inspired by some earlier graphics languages
+including \fBideal\fP and \fBgrap\fP. Kernighan credits Chris van Wyk
+(the designer of \fBideal\fP) with many of the ideas that went into
+\fBpic\fP.
+.EQ
+delim $$
+.EN
+.PP
+The \fBpic\fP language was originally described by Brian Kernighan in
+Bell Labs Computing Science Technical Report #116 (you can obtain a
+PostScript copy of the revised version, [1], by sending a mail message to
+\&\fInetlib@research.att.com\fP with a body of \&`send 116 from
+research/cstr'.). There have been two revisions, in 1984 and 1991.
+.PP
+The document you are reading effectively subsumes Kernighan's
+description; it was written to fill in lacunae in the exposition and
+integrate in descriptions of the GNU \fIgpic\fP(1) features.
+.PP
+The GNU \fBgpic\fR implementation was written and is maintained by
+James Clark \fI<jjc@jclark.com>\fP.
+.NH 1
+Bibliography
+.IP 1.
+Kernighan, B. W. \fBPIC -- A Graphics Language for Typesetting
+(Revised User Manual)\fP Bell Labs Computing Science Technical Report
+#116, December 1991.
+.IP 2.
+Van Wyk, C.J. \fBA high-level language for specifying pictures\fP \fIACM
+Transactions On Graphics\fP 1,2 (1982) 163-182.
diff --git a/font/devX100-12/CB b/font/devX100-12/CB
new file mode 100644
index 00000000..3751184a
--- /dev/null
+++ b/font/devX100-12/CB
@@ -0,0 +1,306 @@
+name CB
+spacewidth 10
+charset
+--- 10,1 0 040
+! 10,11 0 041
+" 10,11 0 042
+# 10,11,1 0 043
+sh "
+$ 10,12,1 0 044
+Do "
+% 10,11 0 045
+& 10,9 0 046
+' 10,11 0 047
+( 10,11,2 0 050
+) 10,11,2 0 051
+* 10,11 0 052
++ 10,9 0 053
+, 10,2,3 0 054
+\- 10,6 0 055
+. 10,2 0 056
+/ 10,12,2 0 057
+sl "
+0 10,11 0 060
+1 10,11 0 061
+2 10,11 0 062
+3 10,11 0 063
+4 10,11 0 064
+5 10,11 0 065
+6 10,11 0 066
+7 10,11 0 067
+8 10,11 0 070
+9 10,11 0 071
+: 10,7 0 072
+; 10,7,3 0 073
+< 10,9 0 074
+= 10,7 0 075
+eq "
+> 10,9 0 076
+? 10,10 0 077
+@ 10,11,1 0 0100
+at "
+A 10,10 0 0101
+B 10,10 0 0102
+C 10,10 0 0103
+D 10,10 0 0104
+E 10,10 0 0105
+F 10,10 0 0106
+G 10,10 0 0107
+H 10,10 0 0110
+I 10,10 0 0111
+J 10,10 0 0112
+K 10,10 0 0113
+L 10,10 0 0114
+M 10,10 0 0115
+N 10,10 0 0116
+O 10,10 0 0117
+P 10,10 0 0120
+Q 10,10,2 0 0121
+R 10,10 0 0122
+S 10,10 0 0123
+T 10,10 0 0124
+U 10,10 0 0125
+V 10,10 0 0126
+W 10,10 0 0127
+X 10,10 0 0130
+Y 10,10 0 0131
+Z 10,10 0 0132
+[ 10,11,2 0 0133
+lB "
+\ 10,12,2 0 0134
+rs "
+] 10,11,2 0 0135
+rB "
+^ 10,11 0 0136
+a^ "
+ha "
+_ 10,0,3 0 0137
+` 10,11 0 0140
+oq "
+a 10,7 0 0141
+b 10,11 0 0142
+c 10,7 0 0143
+d 10,11 0 0144
+e 10,7 0 0145
+f 10,11 0 0146
+g 10,7,3 0 0147
+h 10,11 0 0150
+i 10,10 0 0151
+j 10,10,3 0 0152
+k 10,11 0 0153
+l 10,11 0 0154
+m 10,7 0 0155
+n 10,7 0 0156
+o 10,7 0 0157
+p 10,7,3 0 0160
+q 10,7,3 0 0161
+r 10,7 0 0162
+s 10,7 0 0163
+t 10,9 0 0164
+u 10,7 0 0165
+v 10,7 0 0166
+w 10,7 0 0167
+x 10,7 0 0170
+y 10,7,3 0 0171
+z 10,7 0 0172
+{ 10,11,2 0 0173
+lC "
+| 10,11,2 0 0174
+or "
+ba "
+} 10,11,2 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 10,7,3 0 0241
+¡ "
+ct 10,10 0 0242
+¢ "
+Po 10,10 0 0243
+£ "
+Cs 10,8 0 0244
+¤ "
+Ye 10,10 0 0245
+¥ "
+bb 10,11,2 0 0246
+¦ "
+sc 10,11,1 0 0247
+§ "
+ad 10,10 0 0250
+¨ "
+co 10,10 0 0251
+© "
+Of 10,10 0 0252
+ª "
+Fo 10,7 0 0253
+« "
+no 10,7 0 0254
+¬ "
+- 10,6 0 0255
+hy "
+­ "
+rg 10,10 0 0256
+® "
+a- 10,10 0 0257
+¯ "
+de 10,11 0 0260
+° "
++- 10,9 0 0261
+± "
+S2 10,11 0 0262
+² "
+S3 10,11 0 0263
+³ "
+aa 10,11 0 0264
+´ "
+µ 10,7,3 0 0265
+ps 10,11,1 0 0266
+¶ "
+md 10,6 0 0267
+· "
+ac 10,1,3 0 0270
+¸ "
+S1 10,11 0 0271
+¹ "
+Om 10,10 0 0272
+º "
+Fc 10,7 0 0273
+» "
+14 10,11 0 0274
+¼ "
+12 10,11 0 0275
+½ "
+34 10,11 0 0276
+¾ "
+r? 10,7,3 0 0277
+¿ "
+`A 10,14 0 0300
+À "
+'A 10,14 0 0301
+Á "
+^A 10,14 0 0302
+Â "
+~A 10,13 0 0303
+Ã "
+:A 10,13 0 0304
+Ä "
+oA 10,14 0 0305
+Å "
+AE 10,10 0 0306
+Æ "
+,C 10,10,3 0 0307
+Ç "
+`E 10,14 0 0310
+È "
+'E 10,14 0 0311
+É "
+^E 10,14 0 0312
+Ê "
+:E 10,13 0 0313
+Ë "
+`I 10,14 0 0314
+Ì "
+'I 10,14 0 0315
+Í "
+^I 10,14 0 0316
+Î "
+:I 10,13 0 0317
+Ï "
+-D 10,10 0 0320
+Ð "
+~N 10,13 0 0321
+Ñ "
+`O 10,14 0 0322
+Ò "
+'O 10,14 0 0323
+Ó "
+^O 10,14 0 0324
+Ô "
+~O 10,13 0 0325
+Õ "
+:O 10,13 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 10,11,1 0 0330
+Ø "
+`U 10,14 0 0331
+Ù "
+'U 10,14 0 0332
+Ú "
+^U 10,14 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 10,10 0 0336
+Þ "
+ss 10,11 0 0337
+ß "
+`a 10,11 0 0340
+à "
+'a 10,11 0 0341
+á "
+^a 10,11 0 0342
+â "
+~a 10,10 0 0343
+ã "
+:a 10,10 0 0344
+ä "
+oa 10,12 0 0345
+å "
+ae 10,7 0 0346
+æ "
+,c 10,7,3 0 0347
+ç "
+`e 10,11 0 0350
+è "
+'e 10,11 0 0351
+é "
+^e 10,11 0 0352
+ê "
+:e 10,10 0 0353
+ë "
+`i 10,11 0 0354
+ì "
+'i 10,11 0 0355
+í "
+^i 10,11 0 0356
+î "
+:i 10,10 0 0357
+ï "
+Sd 10,12 0 0360
+ð "
+~n 10,10 0 0361
+ñ "
+`o 10,11 0 0362
+ò "
+'o 10,11 0 0363
+ó "
+^o 10,11 0 0364
+ô "
+~o 10,10 0 0365
+õ "
+:o 10,10 0 0366
+ö "
+di 10,9 0 0367
+÷ "
+/o 10,8,1 0 0370
+ø "
+`u 10,11 0 0371
+ù "
+'u 10,11 0 0372
+ú "
+^u 10,11 0 0373
+û "
+:u 10,10 0 0374
+ü "
+'y 10,11,3 0 0375
+ý "
+Tp 10,11,3 0 0376
+þ "
+:y 10,10,3 0 0377
+ÿ "
diff --git a/font/devX100-12/CBI b/font/devX100-12/CBI
new file mode 100644
index 00000000..d7d0145a
--- /dev/null
+++ b/font/devX100-12/CBI
@@ -0,0 +1,306 @@
+name CBI
+spacewidth 10
+charset
+--- 10,1 0 040
+! 10,11 0 041
+" 10,11 0 042
+# 10,11,1 0 043
+sh "
+$ 10,12,1 0 044
+Do "
+% 10,11 0 045
+& 10,9 0 046
+' 10,11 0 047
+( 10,11,2 0 050
+) 10,11,2 0 051
+* 10,11 0 052
++ 10,9 0 053
+, 10,2,3 0 054
+\- 10,6 0 055
+. 10,2 0 056
+/ 10,12,2 0 057
+sl "
+0 10,11 0 060
+1 10,11 0 061
+2 10,11 0 062
+3 10,11 0 063
+4 10,11 0 064
+5 10,11 0 065
+6 10,11 0 066
+7 10,11 0 067
+8 10,11 0 070
+9 10,11 0 071
+: 10,7 0 072
+; 10,7,3 0 073
+< 10,9 0 074
+= 10,7 0 075
+eq "
+> 10,9 0 076
+? 10,10 0 077
+@ 10,11,1 0 0100
+at "
+A 10,10 0 0101
+B 10,10 0 0102
+C 10,10 0 0103
+D 10,10 0 0104
+E 10,10 0 0105
+F 10,10 0 0106
+G 10,10 0 0107
+H 10,10 0 0110
+I 10,10 0 0111
+J 10,10 0 0112
+K 10,10 0 0113
+L 10,10 0 0114
+M 10,10 0 0115
+N 10,10 0 0116
+O 10,10 0 0117
+P 10,10 0 0120
+Q 10,10,2 0 0121
+R 10,10 0 0122
+S 10,10 0 0123
+T 10,10 0 0124
+U 10,10 0 0125
+V 10,10 0 0126
+W 10,10 0 0127
+X 10,10 0 0130
+Y 10,10 0 0131
+Z 10,10 0 0132
+[ 10,11,2 0 0133
+lB "
+\ 10,12,2 0 0134
+rs "
+] 10,11,2 0 0135
+rB "
+^ 10,11 0 0136
+a^ "
+ha "
+_ 10,0,3 0 0137
+` 10,11 0 0140
+oq "
+a 10,7 0 0141
+b 10,11 0 0142
+c 10,7 0 0143
+d 10,11 0 0144
+e 10,7 0 0145
+f 10,11 0 0146
+g 10,7,3 0 0147
+h 10,11 0 0150
+i 10,10 0 0151
+j 10,10,3 0 0152
+k 10,11 0 0153
+l 10,11 0 0154
+m 10,7 0 0155
+n 10,7 0 0156
+o 10,7 0 0157
+p 10,7,3 0 0160
+q 10,7,3 0 0161
+r 10,7 0 0162
+s 10,7 0 0163
+t 10,9 0 0164
+u 10,7 0 0165
+v 10,7 0 0166
+w 10,7 0 0167
+x 10,7 0 0170
+y 10,7,3 0 0171
+z 10,7 0 0172
+{ 10,11,2 0 0173
+lC "
+| 10,11,2 0 0174
+or "
+ba "
+} 10,11,2 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 10,7,4 0 0241
+¡ "
+ct 10,10 0 0242
+¢ "
+Po 10,10 0 0243
+£ "
+Cs 10,8 0 0244
+¤ "
+Ye 10,10 0 0245
+¥ "
+bb 10,11,2 0 0246
+¦ "
+sc 10,11,1 0 0247
+§ "
+ad 10,10 0 0250
+¨ "
+co 10,10 0 0251
+© "
+Of 10,10 0 0252
+ª "
+Fo 10,7 0 0253
+« "
+no 10,7 0 0254
+¬ "
+- 10,6 0 0255
+hy "
+­ "
+rg 10,10 0 0256
+® "
+a- 10,9 0 0257
+¯ "
+de 10,11 0 0260
+° "
++- 10,10 0 0261
+± "
+S2 10,11 0 0262
+² "
+S3 10,11 0 0263
+³ "
+aa 10,11 0 0264
+´ "
+µ 10,7,3 0 0265
+ps 10,11,1 0 0266
+¶ "
+md 10,6 0 0267
+· "
+ac 10,0,3 0 0270
+¸ "
+S1 10,11 0 0271
+¹ "
+Om 10,10 0 0272
+º "
+Fc 10,7 0 0273
+» "
+14 10,11 0 0274
+¼ "
+12 10,11 0 0275
+½ "
+34 10,11 0 0276
+¾ "
+r? 10,7,4 0 0277
+¿ "
+`A 10,14 0 0300
+À "
+'A 10,14 0 0301
+Á "
+^A 10,14 0 0302
+Â "
+~A 10,13 0 0303
+Ã "
+:A 10,13 0 0304
+Ä "
+oA 10,14 0 0305
+Å "
+AE 10,10 0 0306
+Æ "
+,C 10,10,3 0 0307
+Ç "
+`E 10,14 0 0310
+È "
+'E 10,14 0 0311
+É "
+^E 10,14 0 0312
+Ê "
+:E 10,13 0 0313
+Ë "
+`I 10,14 0 0314
+Ì "
+'I 10,14 0 0315
+Í "
+^I 10,14 0 0316
+Î "
+:I 10,13 0 0317
+Ï "
+-D 10,10 0 0320
+Ð "
+~N 10,13 0 0321
+Ñ "
+`O 10,14 0 0322
+Ò "
+'O 10,14 0 0323
+Ó "
+^O 10,14 0 0324
+Ô "
+~O 10,13 0 0325
+Õ "
+:O 10,13 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 10,10 0 0330
+Ø "
+`U 10,14 0 0331
+Ù "
+'U 10,14 0 0332
+Ú "
+^U 10,14 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 10,10 0 0336
+Þ "
+ss 10,11 0 0337
+ß "
+`a 10,11 0 0340
+à "
+'a 10,11 0 0341
+á "
+^a 10,11 0 0342
+â "
+~a 10,10 0 0343
+ã "
+:a 10,10 0 0344
+ä "
+oa 10,11 0 0345
+å "
+ae 10,7 0 0346
+æ "
+,c 10,7,3 0 0347
+ç "
+`e 10,11 0 0350
+è "
+'e 10,11 0 0351
+é "
+^e 10,11 0 0352
+ê "
+:e 10,10 0 0353
+ë "
+`i 10,11 0 0354
+ì "
+'i 10,11 0 0355
+í "
+^i 10,11 0 0356
+î "
+:i 10,10 0 0357
+ï "
+Sd 10,12 0 0360
+ð "
+~n 10,10 0 0361
+ñ "
+`o 10,11 0 0362
+ò "
+'o 10,11 0 0363
+ó "
+^o 10,11 0 0364
+ô "
+~o 10,10 0 0365
+õ "
+:o 10,10 0 0366
+ö "
+di 10,9 0 0367
+÷ "
+/o 10,8,1 0 0370
+ø "
+`u 10,11 0 0371
+ù "
+'u 10,11 0 0372
+ú "
+^u 10,11 0 0373
+û "
+:u 10,10 0 0374
+ü "
+'y 10,11,3 0 0375
+ý "
+Tp 10,11,3 0 0376
+þ "
+:y 10,10,3 0 0377
+ÿ "
diff --git a/font/devX100-12/CI b/font/devX100-12/CI
new file mode 100644
index 00000000..804f71f7
--- /dev/null
+++ b/font/devX100-12/CI
@@ -0,0 +1,306 @@
+name CI
+spacewidth 10
+charset
+--- 10,1 0 040
+! 10,11 0 041
+" 10,11 0 042
+# 10,11,1 0 043
+sh "
+$ 10,12,1 0 044
+Do "
+% 10,11 0 045
+& 10,9 0 046
+' 10,11 0 047
+( 10,11,2 0 050
+) 10,11,2 0 051
+* 10,10 0 052
++ 10,9 0 053
+, 10,2,2 0 054
+\- 10,5 0 055
+. 10,2 0 056
+/ 10,11,2 0 057
+sl "
+0 10,11 0 060
+1 10,11 0 061
+2 10,11 0 062
+3 10,11 0 063
+4 10,11 0 064
+5 10,11 0 065
+6 10,11 0 066
+7 10,11 0 067
+8 10,11 0 070
+9 10,11 0 071
+: 10,7 0 072
+; 10,7,2 0 073
+< 10,9 0 074
+= 10,7 0 075
+eq "
+> 10,9 0 076
+? 10,10 0 077
+@ 10,11,1 0 0100
+at "
+A 10,10 0 0101
+B 10,10 0 0102
+C 10,10 0 0103
+D 10,10 0 0104
+E 10,10 0 0105
+F 10,10 0 0106
+G 10,10 0 0107
+H 10,10 0 0110
+I 10,10 0 0111
+J 10,10 0 0112
+K 10,10 0 0113
+L 10,10 0 0114
+M 10,10 0 0115
+N 10,10 0 0116
+O 10,10 0 0117
+P 10,10 0 0120
+Q 10,10,2 0 0121
+R 10,10 0 0122
+S 10,10 0 0123
+T 10,10 0 0124
+U 10,10 0 0125
+V 10,10 0 0126
+W 10,10 0 0127
+X 10,10 0 0130
+Y 10,10 0 0131
+Z 10,10 0 0132
+[ 10,11,2 0 0133
+lB "
+\ 10,11,2 0 0134
+rs "
+] 10,11,2 0 0135
+rB "
+^ 10,11 0 0136
+a^ "
+ha "
+_ 10,0,3 0 0137
+` 10,11 0 0140
+oq "
+a 10,7 0 0141
+b 10,10 0 0142
+c 10,7 0 0143
+d 10,10 0 0144
+e 10,7 0 0145
+f 10,10 0 0146
+g 10,7,3 0 0147
+h 10,10 0 0150
+i 10,11 0 0151
+j 10,11,3 0 0152
+k 10,10 0 0153
+l 10,10 0 0154
+m 10,7 0 0155
+n 10,7 0 0156
+o 10,7 0 0157
+p 10,7,3 0 0160
+q 10,7,3 0 0161
+r 10,7 0 0162
+s 10,7 0 0163
+t 10,9 0 0164
+u 10,7 0 0165
+v 10,7 0 0166
+w 10,7 0 0167
+x 10,7 0 0170
+y 10,7,3 0 0171
+z 10,7 0 0172
+{ 10,11,2 0 0173
+lC "
+| 10,10,2 0 0174
+or "
+ba "
+} 10,11,2 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 10,7,4 0 0241
+¡ "
+ct 10,10 0 0242
+¢ "
+Po 10,10 0 0243
+£ "
+Cs 10,8 0 0244
+¤ "
+Ye 10,10 0 0245
+¥ "
+bb 10,11,2 0 0246
+¦ "
+sc 10,11,1 0 0247
+§ "
+ad 10,10 0 0250
+¨ "
+co 10,10 0 0251
+© "
+Of 10,10 0 0252
+ª "
+Fo 10,7 0 0253
+« "
+no 10,6 0 0254
+¬ "
+- 10,5 0 0255
+hy "
+­ "
+rg 10,10 0 0256
+® "
+a- 10,10 0 0257
+¯ "
+de 10,11 0 0260
+° "
++- 10,9 0 0261
+± "
+S2 10,11 0 0262
+² "
+S3 10,11 0 0263
+³ "
+aa 10,11 0 0264
+´ "
+µ 10,7,3 0 0265
+ps 10,11,1 0 0266
+¶ "
+md 10,6 0 0267
+· "
+ac 10,0,3 0 0270
+¸ "
+S1 10,11 0 0271
+¹ "
+Om 10,10 0 0272
+º "
+Fc 10,7 0 0273
+» "
+14 10,11 0 0274
+¼ "
+12 10,11 0 0275
+½ "
+34 10,11 0 0276
+¾ "
+r? 10,7,3 0 0277
+¿ "
+`A 10,14 0 0300
+À "
+'A 10,14 0 0301
+Á "
+^A 10,14 0 0302
+Â "
+~A 10,13 0 0303
+Ã "
+:A 10,13 0 0304
+Ä "
+oA 10,14 0 0305
+Å "
+AE 10,10 0 0306
+Æ "
+,C 10,10,3 0 0307
+Ç "
+`E 10,14 0 0310
+È "
+'E 10,14 0 0311
+É "
+^E 10,14 0 0312
+Ê "
+:E 10,13 0 0313
+Ë "
+`I 10,14 0 0314
+Ì "
+'I 10,14 0 0315
+Í "
+^I 10,14 0 0316
+Î "
+:I 10,13 0 0317
+Ï "
+-D 10,10 0 0320
+Ð "
+~N 10,13 0 0321
+Ñ "
+`O 10,14 0 0322
+Ò "
+'O 10,14 0 0323
+Ó "
+^O 10,14 0 0324
+Ô "
+~O 10,13 0 0325
+Õ "
+:O 10,13 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 10,10 0 0330
+Ø "
+`U 10,14 0 0331
+Ù "
+'U 10,14 0 0332
+Ú "
+^U 10,14 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 10,10 0 0336
+Þ "
+ss 10,11 0 0337
+ß "
+`a 10,11 0 0340
+à "
+'a 10,11 0 0341
+á "
+^a 10,11 0 0342
+â "
+~a 10,10 0 0343
+ã "
+:a 10,10 0 0344
+ä "
+oa 10,11 0 0345
+å "
+ae 10,7 0 0346
+æ "
+,c 10,7,3 0 0347
+ç "
+`e 10,11 0 0350
+è "
+'e 10,11 0 0351
+é "
+^e 10,11 0 0352
+ê "
+:e 10,10 0 0353
+ë "
+`i 10,11 0 0354
+ì "
+'i 10,11 0 0355
+í "
+^i 10,11 0 0356
+î "
+:i 10,10 0 0357
+ï "
+Sd 10,11 0 0360
+ð "
+~n 10,10 0 0361
+ñ "
+`o 10,11 0 0362
+ò "
+'o 10,11 0 0363
+ó "
+^o 10,11 0 0364
+ô "
+~o 10,10 0 0365
+õ "
+:o 10,10 0 0366
+ö "
+di 10,8 0 0367
+÷ "
+/o 10,8,1 0 0370
+ø "
+`u 10,11 0 0371
+ù "
+'u 10,11 0 0372
+ú "
+^u 10,11 0 0373
+û "
+:u 10,10 0 0374
+ü "
+'y 10,11,3 0 0375
+ý "
+Tp 10,11,3 0 0376
+þ "
+:y 10,10,3 0 0377
+ÿ "
diff --git a/font/devX100-12/CR b/font/devX100-12/CR
new file mode 100644
index 00000000..140ec55d
--- /dev/null
+++ b/font/devX100-12/CR
@@ -0,0 +1,306 @@
+name CR
+spacewidth 10
+charset
+--- 10,1 0 040
+! 10,11 0 041
+" 10,11 0 042
+# 10,11,1 0 043
+sh "
+$ 10,12,1 0 044
+Do "
+% 10,11 0 045
+& 10,9 0 046
+' 10,11 0 047
+( 10,11,2 0 050
+) 10,11,2 0 051
+* 10,11 0 052
++ 10,9 0 053
+, 10,2,2 0 054
+\- 10,5 0 055
+. 10,2 0 056
+/ 10,11,2 0 057
+sl "
+0 10,11 0 060
+1 10,11 0 061
+2 10,11 0 062
+3 10,11 0 063
+4 10,11 0 064
+5 10,11 0 065
+6 10,11 0 066
+7 10,11 0 067
+8 10,11 0 070
+9 10,11 0 071
+: 10,7 0 072
+; 10,7,2 0 073
+< 10,9 0 074
+= 10,7 0 075
+eq "
+> 10,9 0 076
+? 10,10 0 077
+@ 10,11,1 0 0100
+at "
+A 10,10 0 0101
+B 10,10 0 0102
+C 10,10 0 0103
+D 10,10 0 0104
+E 10,10 0 0105
+F 10,10 0 0106
+G 10,10 0 0107
+H 10,10 0 0110
+I 10,10 0 0111
+J 10,10 0 0112
+K 10,10 0 0113
+L 10,10 0 0114
+M 10,10 0 0115
+N 10,10 0 0116
+O 10,10 0 0117
+P 10,10 0 0120
+Q 10,10,2 0 0121
+R 10,10 0 0122
+S 10,10 0 0123
+T 10,10 0 0124
+U 10,10 0 0125
+V 10,10 0 0126
+W 10,10 0 0127
+X 10,10 0 0130
+Y 10,10 0 0131
+Z 10,10 0 0132
+[ 10,11,2 0 0133
+lB "
+\ 10,11,2 0 0134
+rs "
+] 10,11,2 0 0135
+rB "
+^ 10,11 0 0136
+a^ "
+ha "
+_ 10,0,3 0 0137
+` 10,11 0 0140
+oq "
+a 10,7 0 0141
+b 10,10 0 0142
+c 10,7 0 0143
+d 10,10 0 0144
+e 10,7 0 0145
+f 10,10 0 0146
+g 10,7,3 0 0147
+h 10,10 0 0150
+i 10,10 0 0151
+j 10,10,3 0 0152
+k 10,10 0 0153
+l 10,10 0 0154
+m 10,7 0 0155
+n 10,7 0 0156
+o 10,7 0 0157
+p 10,7,3 0 0160
+q 10,7,3 0 0161
+r 10,7 0 0162
+s 10,7 0 0163
+t 10,9 0 0164
+u 10,7 0 0165
+v 10,7 0 0166
+w 10,7 0 0167
+x 10,7 0 0170
+y 10,7,3 0 0171
+z 10,7 0 0172
+{ 10,11,2 0 0173
+lC "
+| 10,10,2 0 0174
+or "
+ba "
+} 10,11,2 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 10,7,3 0 0241
+¡ "
+ct 10,10 0 0242
+¢ "
+Po 10,10 0 0243
+£ "
+Cs 10,8 0 0244
+¤ "
+Ye 10,10 0 0245
+¥ "
+bb 10,10,2 0 0246
+¦ "
+sc 10,11,1 0 0247
+§ "
+ad 10,10 0 0250
+¨ "
+co 10,10 0 0251
+© "
+Of 10,10 0 0252
+ª "
+Fo 10,7 0 0253
+« "
+no 10,6 0 0254
+¬ "
+- 10,5 0 0255
+hy "
+­ "
+rg 10,10 0 0256
+® "
+a- 10,9 0 0257
+¯ "
+de 10,11 0 0260
+° "
++- 10,9 0 0261
+± "
+S2 10,11 0 0262
+² "
+S3 10,11 0 0263
+³ "
+aa 10,11 0 0264
+´ "
+µ 10,7,3 0 0265
+ps 10,11,1 0 0266
+¶ "
+md 10,6 0 0267
+· "
+ac 10,1,3 0 0270
+¸ "
+S1 10,11 0 0271
+¹ "
+Om 10,10 0 0272
+º "
+Fc 10,7 0 0273
+» "
+14 10,11 0 0274
+¼ "
+12 10,11 0 0275
+½ "
+34 10,11 0 0276
+¾ "
+r? 10,7,3 0 0277
+¿ "
+`A 10,14 0 0300
+À "
+'A 10,14 0 0301
+Á "
+^A 10,14 0 0302
+Â "
+~A 10,13 0 0303
+Ã "
+:A 10,13 0 0304
+Ä "
+oA 10,14 0 0305
+Å "
+AE 10,10 0 0306
+Æ "
+,C 10,10,3 0 0307
+Ç "
+`E 10,14 0 0310
+È "
+'E 10,14 0 0311
+É "
+^E 10,14 0 0312
+Ê "
+:E 10,13 0 0313
+Ë "
+`I 10,14 0 0314
+Ì "
+'I 10,14 0 0315
+Í "
+^I 10,14 0 0316
+Î "
+:I 10,13 0 0317
+Ï "
+-D 10,10 0 0320
+Ð "
+~N 10,13 0 0321
+Ñ "
+`O 10,14 0 0322
+Ò "
+'O 10,14 0 0323
+Ó "
+^O 10,14 0 0324
+Ô "
+~O 10,13 0 0325
+Õ "
+:O 10,13 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 10,10 0 0330
+Ø "
+`U 10,14 0 0331
+Ù "
+'U 10,14 0 0332
+Ú "
+^U 10,14 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 10,10 0 0336
+Þ "
+ss 10,11 0 0337
+ß "
+`a 10,11 0 0340
+à "
+'a 10,11 0 0341
+á "
+^a 10,11 0 0342
+â "
+~a 10,10 0 0343
+ã "
+:a 10,10 0 0344
+ä "
+oa 10,12 0 0345
+å "
+ae 10,7 0 0346
+æ "
+,c 10,7,3 0 0347
+ç "
+`e 10,11 0 0350
+è "
+'e 10,11 0 0351
+é "
+^e 10,11 0 0352
+ê "
+:e 10,10 0 0353
+ë "
+`i 10,11 0 0354
+ì "
+'i 10,11 0 0355
+í "
+^i 10,11 0 0356
+î "
+:i 10,10 0 0357
+ï "
+Sd 10,11 0 0360
+ð "
+~n 10,10 0 0361
+ñ "
+`o 10,11 0 0362
+ò "
+'o 10,11 0 0363
+ó "
+^o 10,11 0 0364
+ô "
+~o 10,10 0 0365
+õ "
+:o 10,10 0 0366
+ö "
+di 10,8 0 0367
+÷ "
+/o 10,8,1 0 0370
+ø "
+`u 10,11 0 0371
+ù "
+'u 10,11 0 0372
+ú "
+^u 10,11 0 0373
+û "
+:u 10,10 0 0374
+ü "
+'y 10,11,3 0 0375
+ý "
+Tp 10,11,3 0 0376
+þ "
+:y 10,10,3 0 0377
+ÿ "
diff --git a/font/devX100-12/DESC b/font/devX100-12/DESC
new file mode 100644
index 00000000..ead70b97
--- /dev/null
+++ b/font/devX100-12/DESC
@@ -0,0 +1,9 @@
+styles R I B BI
+fonts 6 0 0 0 0 0 S
+sizes 8 10 12 14 18 24 0
+res 100
+X11
+hor 1
+vert 1
+unitwidth 12
+postpro gxditview
diff --git a/font/devX100-12/HB b/font/devX100-12/HB
new file mode 100644
index 00000000..e68615e1
--- /dev/null
+++ b/font/devX100-12/HB
@@ -0,0 +1,306 @@
+name HB
+spacewidth 5
+charset
+--- 5,1 0 040
+! 6,12 0 041
+" 8,12 0 042
+# 9,12 0 043
+sh "
+$ 9,13,1 0 044
+Do "
+% 14,12 0 045
+& 12,12 0 046
+' 5,12 0 047
+( 6,12,3 0 050
+) 6,12,3 0 051
+* 6,12 0 052
++ 10,8 0 053
+, 4,2,3 0 054
+\- 10,5 0 055
+. 4,2 0 056
+/ 5,12 0 057
+sl "
+0 9,12 0 060
+1 9,12 0 061
+2 9,12 0 062
+3 9,12 0 063
+4 9,12 0 064
+5 9,12 0 065
+6 9,12 0 066
+7 9,12 0 067
+8 9,12 0 070
+9 9,12 0 071
+: 5,8 0 072
+; 5,8,3 0 073
+< 10,8 0 074
+= 10,7 0 075
+eq "
+> 10,8 0 076
+? 10,12 0 077
+@ 16,12,2 0 0100
+at "
+A 12,12 0 0101
+B 12,12 0 0102
+C 12,12 0 0103
+D 12,12 0 0104
+E 11,12 0 0105
+F 10,12 0 0106
+G 13,12 0 0107
+H 12,12 0 0110
+I 4,12 0 0111
+J 9,12 0 0112
+K 12,12 0 0113
+L 10,12 0 0114
+M 13,12 0 0115
+N 12,12 0 0116
+O 13,12 0 0117
+P 11,12 0 0120
+Q 13,12,1 0 0121
+R 12,12 0 0122
+S 11,12 0 0123
+T 10,12 0 0124
+U 12,12 0 0125
+V 11,12 0 0126
+W 15,12 0 0127
+X 11,12 0 0130
+Y 11,12 0 0131
+Z 10,12 0 0132
+[ 6,12,3 0 0133
+lB "
+\ 5,12 0 0134
+rs "
+] 6,12,3 0 0135
+rB "
+^ 10,12 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 5,12 0 0140
+oq "
+a 9,9 0 0141
+b 10,12 0 0142
+c 9,9 0 0143
+d 10,12 0 0144
+e 9,9 0 0145
+f 5,12 0 0146
+g 10,9,4 0 0147
+h 10,12 0 0150
+i 4,12 0 0151
+j 5,12,4 0 0152
+k 9,12 0 0153
+l 5,12 0 0154
+m 14,9 0 0155
+n 10,9 0 0156
+o 10,9 0 0157
+p 10,9,4 0 0160
+q 10,9,4 0 0161
+r 6,9 0 0162
+s 9,9 0 0163
+t 6,11 0 0164
+u 10,9 0 0165
+v 9,9 0 0166
+w 13,9 0 0167
+x 9,9 0 0170
+y 9,9,4 0 0171
+z 8,9 0 0172
+{ 6,12,3 0 0173
+lC "
+| 4,12,4 0 0174
+or "
+ba "
+} 6,12,3 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 6,9,3 0 0241
+¡ "
+ct 9,10,1 0 0242
+¢ "
+Po 9,12 0 0243
+£ "
+Cs 9,9 0 0244
+¤ "
+Ye 9,12 0 0245
+¥ "
+bb 5,12,4 0 0246
+¦ "
+sc 9,12,3 0 0247
+§ "
+ad 6,12 0 0250
+¨ "
+co 12,12 0 0251
+© "
+Of 6,12 0 0252
+ª "
+Fo 9,8 0 0253
+« "
+no 10,7 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,12 0 0256
+® "
+a- 6,11 0 0257
+¯ "
+de 7,12 0 0260
+° "
++- 10,11 0 0261
+± "
+S2 6,12 0 0262
+² "
+S3 6,12 0 0263
+³ "
+aa 6,13 0 0264
+´ "
+µ 10,9,3 0 0265
+ps 9,12,3 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 6,0,4 0 0270
+¸ "
+S1 6,12 0 0271
+¹ "
+Om 6,12 0 0272
+º "
+Fc 9,8 0 0273
+» "
+14 14,12 0 0274
+¼ "
+12 14,12 0 0275
+½ "
+34 14,12 0 0276
+¾ "
+r? 10,9,3 0 0277
+¿ "
+`A 12,16 0 0300
+À "
+'A 12,16 0 0301
+Á "
+^A 12,16 0 0302
+Â "
+~A 12,15 0 0303
+Ã "
+:A 12,15 0 0304
+Ä "
+oA 12,16 0 0305
+Å "
+AE 16,12 0 0306
+Æ "
+,C 12,12,4 0 0307
+Ç "
+`E 11,16 0 0310
+È "
+'E 11,16 0 0311
+É "
+^E 11,16 0 0312
+Ê "
+:E 11,15 0 0313
+Ë "
+`I 4,16 0 0314
+Ì "
+'I 4,16 0 0315
+Í "
+^I 4,16 0 0316
+Î "
+:I 4,15 0 0317
+Ï "
+-D 12,12 0 0320
+Ð "
+~N 12,15 0 0321
+Ñ "
+`O 13,16 0 0322
+Ò "
+'O 13,16 0 0323
+Ó "
+^O 13,16 0 0324
+Ô "
+~O 13,15 0 0325
+Õ "
+:O 13,15 0 0326
+Ö "
+mu 10,9 0 0327
+× "
+/O 13,12 0 0330
+Ø "
+`U 12,16 0 0331
+Ù "
+'U 12,16 0 0332
+Ú "
+^U 12,16 0 0333
+Û "
+:U 12,15 0 0334
+Ü "
+'Y 11,16 0 0335
+Ý "
+TP 11,12 0 0336
+Þ "
+ss 10,12 0 0337
+ß "
+`a 9,13 0 0340
+à "
+'a 9,13 0 0341
+á "
+^a 9,13 0 0342
+â "
+~a 9,12 0 0343
+ã "
+:a 9,12 0 0344
+ä "
+oa 9,13 0 0345
+å "
+ae 15,9 0 0346
+æ "
+,c 9,9,4 0 0347
+ç "
+`e 9,13 0 0350
+è "
+'e 9,13 0 0351
+é "
+^e 9,13 0 0352
+ê "
+:e 9,12 0 0353
+ë "
+`i 4,13 0 0354
+ì "
+'i 4,13 0 0355
+í "
+^i 4,13 0 0356
+î "
+:i 4,12 0 0357
+ï "
+Sd 10,12 0 0360
+ð "
+~n 10,12 0 0361
+ñ "
+`o 10,13 0 0362
+ò "
+'o 10,13 0 0363
+ó "
+^o 10,13 0 0364
+ô "
+~o 10,12 0 0365
+õ "
+:o 10,12 0 0366
+ö "
+di 10,8 0 0367
+÷ "
+/o 10,9 0 0370
+ø "
+`u 10,13 0 0371
+ù "
+'u 10,13 0 0372
+ú "
+^u 10,13 0 0373
+û "
+:u 10,12 0 0374
+ü "
+'y 9,13,4 0 0375
+ý "
+Tp 10,12,4 0 0376
+þ "
+:y 9,12,4 0 0377
+ÿ "
diff --git a/font/devX100-12/HBI b/font/devX100-12/HBI
new file mode 100644
index 00000000..6723ddff
--- /dev/null
+++ b/font/devX100-12/HBI
@@ -0,0 +1,306 @@
+name HBI
+spacewidth 5
+charset
+--- 5,1 0 040
+! 6,12 0 041
+" 8,12 0 042
+# 9,12 0 043
+sh "
+$ 9,13,1 0 044
+Do "
+% 14,12 0 045
+& 12,12 0 046
+' 5,12 0 047
+( 6,12,3 0 050
+) 6,12,3 0 051
+* 6,12 0 052
++ 10,8 0 053
+, 4,2,3 0 054
+\- 10,5 0 055
+. 4,2 0 056
+/ 5,12 0 057
+sl "
+0 10,12 0 060
+1 9,12 0 061
+2 10,12 0 062
+3 9,12 0 063
+4 9,12 0 064
+5 9,12 0 065
+6 9,12 0 066
+7 9,12 0 067
+8 9,12 0 070
+9 9,12 0 071
+: 5,8 0 072
+; 5,8,3 0 073
+< 10,8 0 074
+= 10,7 0 075
+eq "
+> 10,8 0 076
+? 10,12 0 077
+@ 16,12,2 0 0100
+at "
+A 12,12 0 0101
+B 12,12 0 0102
+C 12,12 0 0103
+D 12,12 0 0104
+E 11,12 0 0105
+F 10,12 0 0106
+G 13,12 0 0107
+H 12,12 0 0110
+I 4,12 0 0111
+J 9,12 0 0112
+K 12,12 0 0113
+L 10,12 0 0114
+M 13,12 0 0115
+N 12,12 0 0116
+O 13,12 0 0117
+P 11,12 0 0120
+Q 13,12,1 0 0121
+R 12,12 0 0122
+S 11,12 0 0123
+T 10,12 0 0124
+U 12,12 0 0125
+V 11,12 0 0126
+W 15,12 0 0127
+X 11,12 0 0130
+Y 11,12 0 0131
+Z 10,12 0 0132
+[ 6,12,3 0 0133
+lB "
+\ 5,12 0 0134
+rs "
+] 6,12,3 0 0135
+rB "
+^ 10,12 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 5,12 0 0140
+oq "
+a 9,9 0 0141
+b 10,12 0 0142
+c 9,9 0 0143
+d 10,12 0 0144
+e 9,9 0 0145
+f 5,12 0 0146
+g 10,9,4 0 0147
+h 10,12 0 0150
+i 4,12 0 0151
+j 5,12,4 0 0152
+k 9,12 0 0153
+l 5,12 0 0154
+m 14,9 0 0155
+n 10,9 0 0156
+o 10,9 0 0157
+p 10,9,4 0 0160
+q 10,9,4 0 0161
+r 6,9 0 0162
+s 9,9 0 0163
+t 6,12 0 0164
+u 10,9 0 0165
+v 9,9 0 0166
+w 13,9 0 0167
+x 9,9 0 0170
+y 9,9,4 0 0171
+z 8,9 0 0172
+{ 6,12,3 0 0173
+lC "
+| 3,12,4 0 0174
+or "
+ba "
+} 6,12,3 0 0175
+rC "
+~ 10,5 0 0176
+a~ "
+ap "
+ti "
+r! 6,9,3 0 0241
+¡ "
+ct 9,10,1 0 0242
+¢ "
+Po 9,12 0 0243
+£ "
+Cs 9,9 0 0244
+¤ "
+Ye 9,12 0 0245
+¥ "
+bb 5,12,4 0 0246
+¦ "
+sc 9,12,3 0 0247
+§ "
+ad 6,12 0 0250
+¨ "
+co 12,12 0 0251
+© "
+Of 6,12 0 0252
+ª "
+Fo 9,8 0 0253
+« "
+no 10,7 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,12 0 0256
+® "
+a- 6,11 0 0257
+¯ "
+de 7,12 0 0260
+° "
++- 10,11 0 0261
+± "
+S2 6,12 0 0262
+² "
+S3 6,12 0 0263
+³ "
+aa 6,13 0 0264
+´ "
+µ 10,9,4 0 0265
+ps 9,12,3 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 6,0,4 0 0270
+¸ "
+S1 6,12 0 0271
+¹ "
+Om 6,12 0 0272
+º "
+Fc 9,8 0 0273
+» "
+14 14,12 0 0274
+¼ "
+12 14,12 0 0275
+½ "
+34 14,12 0 0276
+¾ "
+r? 10,9,3 0 0277
+¿ "
+`A 12,16 0 0300
+À "
+'A 12,16 0 0301
+Á "
+^A 12,16 0 0302
+Â "
+~A 12,15 0 0303
+Ã "
+:A 12,15 0 0304
+Ä "
+oA 12,15 0 0305
+Å "
+AE 17,12 0 0306
+Æ "
+,C 12,12,4 0 0307
+Ç "
+`E 11,16 0 0310
+È "
+'E 11,16 0 0311
+É "
+^E 11,16 0 0312
+Ê "
+:E 11,15 0 0313
+Ë "
+`I 4,16 0 0314
+Ì "
+'I 4,16 0 0315
+Í "
+^I 4,16 0 0316
+Î "
+:I 4,15 0 0317
+Ï "
+-D 12,12 0 0320
+Ð "
+~N 12,15 0 0321
+Ñ "
+`O 13,16 0 0322
+Ò "
+'O 13,16 0 0323
+Ó "
+^O 13,16 0 0324
+Ô "
+~O 13,15 0 0325
+Õ "
+:O 13,15 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 13,12 0 0330
+Ø "
+`U 12,16 0 0331
+Ù "
+'U 12,16 0 0332
+Ú "
+^U 12,16 0 0333
+Û "
+:U 12,15 0 0334
+Ü "
+'Y 11,16 0 0335
+Ý "
+TP 11,12 0 0336
+Þ "
+ss 10,12 0 0337
+ß "
+`a 9,13 0 0340
+à "
+'a 9,13 0 0341
+á "
+^a 9,13 0 0342
+â "
+~a 9,12 0 0343
+ã "
+:a 9,12 0 0344
+ä "
+oa 9,13 0 0345
+å "
+ae 15,9 0 0346
+æ "
+,c 9,9,4 0 0347
+ç "
+`e 9,13 0 0350
+è "
+'e 9,13 0 0351
+é "
+^e 9,13 0 0352
+ê "
+:e 9,12 0 0353
+ë "
+`i 4,13 0 0354
+ì "
+'i 4,13 0 0355
+í "
+^i 4,13 0 0356
+î "
+:i 4,12 0 0357
+ï "
+Sd 10,13 0 0360
+ð "
+~n 10,12 0 0361
+ñ "
+`o 10,13 0 0362
+ò "
+'o 10,13 0 0363
+ó "
+^o 10,13 0 0364
+ô "
+~o 10,12 0 0365
+õ "
+:o 10,12 0 0366
+ö "
+di 10,8 0 0367
+÷ "
+/o 10,9 0 0370
+ø "
+`u 10,13 0 0371
+ù "
+'u 10,13 0 0372
+ú "
+^u 10,13 0 0373
+û "
+:u 10,12 0 0374
+ü "
+'y 9,13,4 0 0375
+ý "
+Tp 10,12,4 0 0376
+þ "
+:y 9,12,4 0 0377
+ÿ "
diff --git a/font/devX100-12/HI b/font/devX100-12/HI
new file mode 100644
index 00000000..f002cd63
--- /dev/null
+++ b/font/devX100-12/HI
@@ -0,0 +1,306 @@
+name HI
+spacewidth 5
+charset
+--- 5,1 0 040
+! 5,12 0 041
+" 6,12 0 042
+# 9,12 0 043
+sh "
+$ 9,13,1 0 044
+Do "
+% 14,12 0 045
+& 11,12 0 046
+' 4,12 0 047
+( 6,12,3 0 050
+) 6,12,3 0 051
+* 6,12 0 052
++ 10,9 0 053
+, 4,2,2 0 054
+\- 10,5 0 055
+. 4,2 0 056
+/ 5,12 0 057
+sl "
+0 9,12 0 060
+1 9,12 0 061
+2 9,12 0 062
+3 9,12 0 063
+4 9,12 0 064
+5 9,12 0 065
+6 9,12 0 066
+7 9,12 0 067
+8 9,12 0 070
+9 9,12 0 071
+: 4,9 0 072
+; 4,9,2 0 073
+< 10,9 0 074
+= 10,6 0 075
+eq "
+> 10,9 0 076
+? 9,12 0 077
+@ 17,12,1 0 0100
+at "
+A 11,12 0 0101
+B 11,12 0 0102
+C 12,12 0 0103
+D 12,12 0 0104
+E 11,12 0 0105
+F 10,12 0 0106
+G 13,12 0 0107
+H 12,12 0 0110
+I 4,12 0 0111
+J 8,12 0 0112
+K 11,12 0 0113
+L 9,12 0 0114
+M 13,12 0 0115
+N 12,12 0 0116
+O 13,12 0 0117
+P 11,12 0 0120
+Q 13,12,1 0 0121
+R 12,12 0 0122
+S 11,12 0 0123
+T 10,12 0 0124
+U 12,12 0 0125
+V 11,12 0 0126
+W 16,12 0 0127
+X 11,12 0 0130
+Y 11,12 0 0131
+Z 10,12 0 0132
+[ 5,12,3 0 0133
+lB "
+\ 5,12 0 0134
+rs "
+] 5,12,3 0 0135
+rB "
+^ 8,12 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 4,12 0 0140
+oq "
+a 9,9 0 0141
+b 9,12 0 0142
+c 8,9 0 0143
+d 9,12 0 0144
+e 9,9 0 0145
+f 5,12 0 0146
+g 9,9,4 0 0147
+h 9,12 0 0150
+i 3,12 0 0151
+j 4,12,4 0 0152
+k 8,12 0 0153
+l 4,12 0 0154
+m 14,9 0 0155
+n 9,9 0 0156
+o 9,9 0 0157
+p 9,9,4 0 0160
+q 9,9,4 0 0161
+r 5,9 0 0162
+s 8,9 0 0163
+t 5,11 0 0164
+u 9,9 0 0165
+v 8,9 0 0166
+w 12,9 0 0167
+x 8,9 0 0170
+y 8,9,4 0 0171
+z 8,9 0 0172
+{ 6,12,3 0 0173
+lC "
+| 3,12,4 0 0174
+or "
+ba "
+} 6,12,3 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 6,9,3 0 0241
+¡ "
+ct 9,10,1 0 0242
+¢ "
+Po 9,12 0 0243
+£ "
+Cs 9,10 0 0244
+¤ "
+Ye 9,12 0 0245
+¥ "
+bb 4,12,4 0 0246
+¦ "
+sc 9,12,3 0 0247
+§ "
+ad 5,12 0 0250
+¨ "
+co 12,12 0 0251
+© "
+Of 6,12 0 0252
+ª "
+Fo 9,8 0 0253
+« "
+no 10,6 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,12 0 0256
+® "
+a- 6,11 0 0257
+¯ "
+de 7,12 0 0260
+° "
++- 10,11 0 0261
+± "
+S2 6,12 0 0262
+² "
+S3 6,12 0 0263
+³ "
+aa 6,13 0 0264
+´ "
+µ 9,9,4 0 0265
+ps 9,12,3 0 0266
+¶ "
+md 5,7 0 0267
+· "
+ac 6,0,4 0 0270
+¸ "
+S1 6,12 0 0271
+¹ "
+Om 6,12 0 0272
+º "
+Fc 9,8 0 0273
+» "
+14 14,12 0 0274
+¼ "
+12 14,13 0 0275
+½ "
+34 14,12 0 0276
+¾ "
+r? 10,9,3 0 0277
+¿ "
+`A 11,16 0 0300
+À "
+'A 11,16 0 0301
+Á "
+^A 11,16 0 0302
+Â "
+~A 11,15 0 0303
+Ã "
+:A 11,15 0 0304
+Ä "
+oA 11,15 0 0305
+Å "
+AE 16,12 0 0306
+Æ "
+,C 12,12,3 0 0307
+Ç "
+`E 11,16 0 0310
+È "
+'E 11,16 0 0311
+É "
+^E 11,16 0 0312
+Ê "
+:E 11,15 0 0313
+Ë "
+`I 4,16 0 0314
+Ì "
+'I 4,16 0 0315
+Í "
+^I 4,16 0 0316
+Î "
+:I 4,15 0 0317
+Ï "
+-D 12,12 0 0320
+Ð "
+~N 12,15 0 0321
+Ñ "
+`O 13,16 0 0322
+Ò "
+'O 13,16 0 0323
+Ó "
+^O 13,16 0 0324
+Ô "
+~O 13,15 0 0325
+Õ "
+:O 13,15 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 13,12 0 0330
+Ø "
+`U 12,16 0 0331
+Ù "
+'U 12,16 0 0332
+Ú "
+^U 12,16 0 0333
+Û "
+:U 12,15 0 0334
+Ü "
+'Y 11,16 0 0335
+Ý "
+TP 11,12 0 0336
+Þ "
+ss 10,12 0 0337
+ß "
+`a 9,13 0 0340
+à "
+'a 9,13 0 0341
+á "
+^a 9,13 0 0342
+â "
+~a 9,12 0 0343
+ã "
+:a 9,12 0 0344
+ä "
+oa 9,13 0 0345
+å "
+ae 15,9 0 0346
+æ "
+,c 8,9,3 0 0347
+ç "
+`e 9,13 0 0350
+è "
+'e 9,13 0 0351
+é "
+^e 9,13 0 0352
+ê "
+:e 9,12 0 0353
+ë "
+`i 4,13 0 0354
+ì "
+'i 4,13 0 0355
+í "
+^i 4,13 0 0356
+î "
+:i 4,12 0 0357
+ï "
+Sd 9,12 0 0360
+ð "
+~n 9,12 0 0361
+ñ "
+`o 9,13 0 0362
+ò "
+'o 9,13 0 0363
+ó "
+^o 9,13 0 0364
+ô "
+~o 9,12 0 0365
+õ "
+:o 9,12 0 0366
+ö "
+di 10,9 0 0367
+÷ "
+/o 10,9 0 0370
+ø "
+`u 9,13 0 0371
+ù "
+'u 9,13 0 0372
+ú "
+^u 9,13 0 0373
+û "
+:u 9,12 0 0374
+ü "
+'y 8,13,4 0 0375
+ý "
+Tp 9,12,4 0 0376
+þ "
+:y 8,12,4 0 0377
+ÿ "
diff --git a/font/devX100-12/HR b/font/devX100-12/HR
new file mode 100644
index 00000000..d2b296f6
--- /dev/null
+++ b/font/devX100-12/HR
@@ -0,0 +1,306 @@
+name HR
+spacewidth 5
+charset
+--- 5,1 0 040
+! 5,12 0 041
+" 6,12 0 042
+# 9,11 0 043
+sh "
+$ 9,13,2 0 044
+Do "
+% 14,12 0 045
+& 11,12 0 046
+' 4,12 0 047
+( 6,12,4 0 050
+) 6,12,4 0 051
+* 6,12 0 052
++ 10,9 0 053
+, 4,2,2 0 054
+\- 10,5 0 055
+. 4,2 0 056
+/ 5,12 0 057
+sl "
+0 9,12 0 060
+1 9,12 0 061
+2 9,12 0 062
+3 9,12 0 063
+4 9,12 0 064
+5 9,12 0 065
+6 9,12 0 066
+7 9,12 0 067
+8 9,12 0 070
+9 9,12 0 071
+: 4,9 0 072
+; 4,9,2 0 073
+< 10,9 0 074
+= 10,6 0 075
+eq "
+> 10,9 0 076
+? 9,12 0 077
+@ 17,12,2 0 0100
+at "
+A 11,12 0 0101
+B 11,12 0 0102
+C 12,12 0 0103
+D 12,12 0 0104
+E 11,12 0 0105
+F 10,12 0 0106
+G 13,12 0 0107
+H 12,12 0 0110
+I 4,12 0 0111
+J 8,12 0 0112
+K 11,12 0 0113
+L 9,12 0 0114
+M 13,12 0 0115
+N 12,12 0 0116
+O 13,12 0 0117
+P 11,12 0 0120
+Q 13,12,1 0 0121
+R 12,12 0 0122
+S 11,12 0 0123
+T 10,12 0 0124
+U 12,12 0 0125
+V 11,12 0 0126
+W 15,12 0 0127
+X 11,12 0 0130
+Y 11,12 0 0131
+Z 10,12 0 0132
+[ 5,12,3 0 0133
+lB "
+\ 5,12 0 0134
+rs "
+] 5,12,3 0 0135
+rB "
+^ 8,12 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 4,12 0 0140
+oq "
+a 9,9 0 0141
+b 9,12 0 0142
+c 8,9 0 0143
+d 9,12 0 0144
+e 9,9 0 0145
+f 5,12 0 0146
+g 9,9,4 0 0147
+h 9,12 0 0150
+i 3,12 0 0151
+j 4,12,4 0 0152
+k 8,12 0 0153
+l 3,12 0 0154
+m 14,9 0 0155
+n 9,9 0 0156
+o 9,9 0 0157
+p 9,9,4 0 0160
+q 9,9,4 0 0161
+r 5,9 0 0162
+s 8,9 0 0163
+t 5,11 0 0164
+u 9,9 0 0165
+v 8,9 0 0166
+w 12,9 0 0167
+x 8,9 0 0170
+y 8,9,3 0 0171
+z 8,9 0 0172
+{ 6,12,4 0 0173
+lC "
+| 4,12,4 0 0174
+or "
+ba "
+} 6,12,4 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 6,9,3 0 0241
+¡ "
+ct 9,11,2 0 0242
+¢ "
+Po 9,12 0 0243
+£ "
+Cs 9,10 0 0244
+¤ "
+Ye 9,12 0 0245
+¥ "
+bb 4,12,4 0 0246
+¦ "
+sc 9,12,3 0 0247
+§ "
+ad 5,12 0 0250
+¨ "
+co 12,12 0 0251
+© "
+Of 6,12 0 0252
+ª "
+Fo 9,8 0 0253
+« "
+no 10,6 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,12 0 0256
+® "
+a- 6,11 0 0257
+¯ "
+de 7,12 0 0260
+° "
++- 10,11 0 0261
+± "
+S2 6,12 0 0262
+² "
+S3 6,12 0 0263
+³ "
+aa 6,13 0 0264
+´ "
+µ 9,9,4 0 0265
+ps 9,12,3 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 6,0,4 0 0270
+¸ "
+S1 6,12 0 0271
+¹ "
+Om 6,12 0 0272
+º "
+Fc 9,8 0 0273
+» "
+14 14,12 0 0274
+¼ "
+12 14,13 0 0275
+½ "
+34 14,12 0 0276
+¾ "
+r? 10,9,3 0 0277
+¿ "
+`A 11,16 0 0300
+À "
+'A 11,16 0 0301
+Á "
+^A 11,16 0 0302
+Â "
+~A 11,15 0 0303
+Ã "
+:A 11,15 0 0304
+Ä "
+oA 11,15 0 0305
+Å "
+AE 16,12 0 0306
+Æ "
+,C 12,12,4 0 0307
+Ç "
+`E 11,16 0 0310
+È "
+'E 11,16 0 0311
+É "
+^E 11,16 0 0312
+Ê "
+:E 11,15 0 0313
+Ë "
+`I 4,16 0 0314
+Ì "
+'I 4,16 0 0315
+Í "
+^I 4,16 0 0316
+Î "
+:I 4,15 0 0317
+Ï "
+-D 12,12 0 0320
+Ð "
+~N 12,15 0 0321
+Ñ "
+`O 13,16 0 0322
+Ò "
+'O 13,16 0 0323
+Ó "
+^O 13,16 0 0324
+Ô "
+~O 13,15 0 0325
+Õ "
+:O 13,15 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 13,13,1 0 0330
+Ø "
+`U 12,16 0 0331
+Ù "
+'U 12,16 0 0332
+Ú "
+^U 12,16 0 0333
+Û "
+:U 12,15 0 0334
+Ü "
+'Y 11,16 0 0335
+Ý "
+TP 11,12 0 0336
+Þ "
+ss 10,12 0 0337
+ß "
+`a 9,13 0 0340
+à "
+'a 9,13 0 0341
+á "
+^a 9,13 0 0342
+â "
+~a 9,12 0 0343
+ã "
+:a 9,12 0 0344
+ä "
+oa 9,13 0 0345
+å "
+ae 15,9 0 0346
+æ "
+,c 8,9,4 0 0347
+ç "
+`e 9,13 0 0350
+è "
+'e 9,13 0 0351
+é "
+^e 9,13 0 0352
+ê "
+:e 9,12 0 0353
+ë "
+`i 4,13 0 0354
+ì "
+'i 4,13 0 0355
+í "
+^i 4,13 0 0356
+î "
+:i 4,12 0 0357
+ï "
+Sd 9,12 0 0360
+ð "
+~n 9,12 0 0361
+ñ "
+`o 9,13 0 0362
+ò "
+'o 9,13 0 0363
+ó "
+^o 9,13 0 0364
+ô "
+~o 9,12 0 0365
+õ "
+:o 9,12 0 0366
+ö "
+di 10,9 0 0367
+÷ "
+/o 10,10 0 0370
+ø "
+`u 9,13 0 0371
+ù "
+'u 9,13 0 0372
+ú "
+^u 9,13 0 0373
+û "
+:u 9,12 0 0374
+ü "
+'y 8,13,3 0 0375
+ý "
+Tp 9,12,4 0 0376
+þ "
+:y 8,12,3 0 0377
+ÿ "
diff --git a/font/devX100-12/Makefile.sub b/font/devX100-12/Makefile.sub
new file mode 100644
index 00000000..d0747579
--- /dev/null
+++ b/font/devX100-12/Makefile.sub
@@ -0,0 +1,2 @@
+DEV=X100-12
+DEVFILES=DESC TR TI TB TBI CR CI CB CBI HR HI HB HBI NR NI NB NBI S
diff --git a/font/devX100-12/NB b/font/devX100-12/NB
new file mode 100644
index 00000000..f997df59
--- /dev/null
+++ b/font/devX100-12/NB
@@ -0,0 +1,306 @@
+name NB
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,12 0 041
+" 6,12 0 042
+# 10,12 0 043
+sh "
+$ 10,14,1 0 044
+Do "
+% 14,12 0 045
+& 14,12 0 046
+' 4,12 0 047
+( 6,12,2 0 050
+) 6,12,2 0 051
+* 8,12 0 052
++ 10,8 0 053
+, 5,3,3 0 054
+\- 10,5 0 055
+. 5,3 0 056
+/ 5,12 0 057
+sl "
+0 10,12 0 060
+1 9,12 0 061
+2 9,12 0 062
+3 10,12 0 063
+4 9,12 0 064
+5 10,12 0 065
+6 9,12 0 066
+7 9,12 0 067
+8 9,12 0 070
+9 10,12 0 071
+: 5,8 0 072
+; 5,8,3 0 073
+< 10,9 0 074
+= 10,7 0 075
+eq "
+> 10,9 0 076
+? 8,12 0 077
+@ 12,12,1 0 0100
+at "
+A 13,12 0 0101
+B 13,12 0 0102
+C 13,12 0 0103
+D 14,12 0 0104
+E 12,12 0 0105
+F 12,12 0 0106
+G 14,12 0 0107
+H 15,12 0 0110
+I 7,12 0 0111
+J 11,12 0 0112
+K 13,12 0 0113
+L 12,12 0 0114
+M 16,12 0 0115
+N 14,12 0 0116
+O 14,12 0 0117
+P 13,12 0 0120
+Q 14,12,3 0 0121
+R 14,12 0 0122
+S 11,12 0 0123
+T 12,12 0 0124
+U 14,12 0 0125
+V 13,12 0 0126
+W 16,12 0 0127
+X 12,12 0 0130
+Y 12,12 0 0131
+Z 11,12 0 0132
+[ 6,12,2 0 0133
+lB "
+\ 10,12 0 0134
+rs "
+] 7,12,2 0 0135
+rB "
+^ 10,12 0 0136
+a^ "
+ha "
+_ 8,0,2 0 0137
+` 4,12 0 0140
+oq "
+a 10,8 0 0141
+b 11,12 0 0142
+c 9,8 0 0143
+d 11,12 0 0144
+e 10,8 0 0145
+f 7,12 0 0146
+g 10,9,3 0 0147
+h 11,12 0 0150
+i 6,12 0 0151
+j 6,12,3 0 0152
+k 11,12 0 0153
+l 6,12 0 0154
+m 16,8 0 0155
+n 11,8 0 0156
+o 11,8 0 0157
+p 11,8,3 0 0160
+q 10,8,3 0 0161
+r 9,8 0 0162
+s 8,8 0 0163
+t 7,11 0 0164
+u 11,8 0 0165
+v 10,8 0 0166
+w 15,8 0 0167
+x 10,8 0 0170
+y 10,8,3 0 0171
+z 9,8 0 0172
+{ 6,12,2 0 0173
+lC "
+| 10,12 0 0174
+or "
+ba "
+} 6,12,2 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 5,9,3 0 0241
+¡ "
+ct 10,10,2 0 0242
+¢ "
+Po 10,12 0 0243
+£ "
+Cs 10,10 0 0244
+¤ "
+Ye 10,12 0 0245
+¥ "
+bb 10,12 0 0246
+¦ "
+sc 9,12,3 0 0247
+§ "
+ad 6,11 0 0250
+¨ "
+co 12,12 0 0251
+© "
+Of 6,12 0 0252
+ª "
+Fo 8,7 0 0253
+« "
+no 10,7 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,12 0 0256
+® "
+a- 6,11 0 0257
+¯ "
+de 7,12 0 0260
+° "
++- 10,9 0 0261
+± "
+S2 6,12 0 0262
+² "
+S3 6,12 0 0263
+³ "
+aa 6,12 0 0264
+´ "
+µ 11,8,3 0 0265
+ps 12,12 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 6,1,3 0 0270
+¸ "
+S1 6,12 0 0271
+¹ "
+Om 6,12 0 0272
+º "
+Fc 8,7 0 0273
+» "
+14 14,12 0 0274
+¼ "
+12 14,12 0 0275
+½ "
+34 14,12 0 0276
+¾ "
+r? 8,9,3 0 0277
+¿ "
+`A 13,16 0 0300
+À "
+'A 13,16 0 0301
+Á "
+^A 13,16 0 0302
+Â "
+~A 13,15 0 0303
+Ã "
+:A 13,15 0 0304
+Ä "
+oA 13,16 0 0305
+Å "
+AE 16,12 0 0306
+Æ "
+,C 13,12,3 0 0307
+Ç "
+`E 12,16 0 0310
+È "
+'E 12,16 0 0311
+É "
+^E 12,16 0 0312
+Ê "
+:E 12,15 0 0313
+Ë "
+`I 7,16 0 0314
+Ì "
+'I 7,16 0 0315
+Í "
+^I 7,16 0 0316
+Î "
+:I 7,15 0 0317
+Ï "
+-D 14,12 0 0320
+Ð "
+~N 14,15 0 0321
+Ñ "
+`O 14,16 0 0322
+Ò "
+'O 14,16 0 0323
+Ó "
+^O 14,16 0 0324
+Ô "
+~O 14,15 0 0325
+Õ "
+:O 14,15 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 14,13,1 0 0330
+Ø "
+`U 14,16 0 0331
+Ù "
+'U 14,16 0 0332
+Ú "
+^U 14,16 0 0333
+Û "
+:U 14,15 0 0334
+Ü "
+'Y 12,16 0 0335
+Ý "
+TP 13,12 0 0336
+Þ "
+ss 10,12 0 0337
+ß "
+`a 10,12 0 0340
+à "
+'a 10,12 0 0341
+á "
+^a 10,12 0 0342
+â "
+~a 10,11 0 0343
+ã "
+:a 10,11 0 0344
+ä "
+oa 10,12 0 0345
+å "
+ae 15,8 0 0346
+æ "
+,c 9,8,3 0 0347
+ç "
+`e 10,12 0 0350
+è "
+'e 10,12 0 0351
+é "
+^e 10,12 0 0352
+ê "
+:e 10,11 0 0353
+ë "
+`i 6,12 0 0354
+ì "
+'i 6,12 0 0355
+í "
+^i 6,12 0 0356
+î "
+:i 6,11 0 0357
+ï "
+Sd 11,13 0 0360
+ð "
+~n 11,11 0 0361
+ñ "
+`o 11,12 0 0362
+ò "
+'o 11,12 0 0363
+ó "
+^o 11,12 0 0364
+ô "
+~o 11,11 0 0365
+õ "
+:o 11,11 0 0366
+ö "
+di 10,8 0 0367
+÷ "
+/o 10,10,2 0 0370
+ø "
+`u 11,12 0 0371
+ù "
+'u 11,12 0 0372
+ú "
+^u 11,12 0 0373
+û "
+:u 11,11 0 0374
+ü "
+'y 10,12,3 0 0375
+ý "
+Tp 11,12,3 0 0376
+þ "
+:y 10,11,3 0 0377
+ÿ "
diff --git a/font/devX100-12/NBI b/font/devX100-12/NBI
new file mode 100644
index 00000000..38c32819
--- /dev/null
+++ b/font/devX100-12/NBI
@@ -0,0 +1,306 @@
+name NBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 6,12 0 041
+" 7,12 0 042
+# 10,12 0 043
+sh "
+$ 9,14,1 0 044
+Do "
+% 15,12 0 045
+& 15,12 0 046
+' 4,12 0 047
+( 7,12,2 0 050
+) 7,12,2 0 051
+* 8,12 0 052
++ 10,8 0 053
+, 5,3,3 0 054
+\- 10,5 0 055
+. 5,3 0 056
+/ 5,12 0 057
+sl "
+0 9,12 0 060
+1 9,12 0 061
+2 9,12 0 062
+3 9,12 0 063
+4 9,12 0 064
+5 10,12 0 065
+6 10,12 0 066
+7 9,12 0 067
+8 9,12 0 070
+9 9,12 0 071
+: 5,8 0 072
+; 5,8,3 0 073
+< 10,8 0 074
+= 10,7 0 075
+eq "
+> 10,8 0 076
+? 8,12 0 077
+@ 12,12 0 0100
+at "
+A 12,12 0 0101
+B 13,12 0 0102
+C 13,12 0 0103
+D 14,12 0 0104
+E 12,12 0 0105
+F 12,12 0 0106
+G 14,12 0 0107
+H 14,12 0 0110
+I 7,12 0 0111
+J 11,12 0 0112
+K 13,12 0 0113
+L 12,12 0 0114
+M 16,12 0 0115
+N 14,12 0 0116
+O 14,12 0 0117
+P 12,12 0 0120
+Q 14,12,3 0 0121
+R 14,12 0 0122
+S 11,12 0 0123
+T 12,12 0 0124
+U 14,12 0 0125
+V 12,12 0 0126
+W 16,12 0 0127
+X 12,12 0 0130
+Y 12,12 0 0131
+Z 12,12 0 0132
+[ 7,12,2 0 0133
+lB "
+\ 10,12 0 0134
+rs "
+] 7,12,2 0 0135
+rB "
+^ 10,12 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 4,12 0 0140
+oq "
+a 11,8 0 0141
+b 10,12 0 0142
+c 9,8 0 0143
+d 11,12 0 0144
+e 9,8 0 0145
+f 6,12,3 0 0146
+g 10,9,3 0 0147
+h 11,12 0 0150
+i 6,12 0 0151
+j 6,12,3 0 0152
+k 11,12 0 0153
+l 6,12 0 0154
+m 15,8 0 0155
+n 11,8 0 0156
+o 10,8 0 0157
+p 11,8,3 0 0160
+q 10,8,3 0 0161
+r 9,8 0 0162
+s 8,8 0 0163
+t 7,11 0 0164
+u 11,8 0 0165
+v 9,8 0 0166
+w 14,8 0 0167
+x 9,8 0 0170
+y 9,8,3 0 0171
+z 9,8 0 0172
+{ 7,12,2 0 0173
+lC "
+| 10,12 0 0174
+or "
+ba "
+} 7,12,2 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 6,9,3 0 0241
+¡ "
+ct 10,10,2 0 0242
+¢ "
+Po 10,12 0 0243
+£ "
+Cs 10,10 0 0244
+¤ "
+Ye 10,12 0 0245
+¥ "
+bb 10,12 0 0246
+¦ "
+sc 9,12,3 0 0247
+§ "
+ad 6,11 0 0250
+¨ "
+co 12,12 0 0251
+© "
+Of 7,12 0 0252
+ª "
+Fo 8,7 0 0253
+« "
+no 10,7 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,12 0 0256
+® "
+a- 6,11 0 0257
+¯ "
+de 7,12 0 0260
+° "
++- 10,8 0 0261
+± "
+S2 6,12 0 0262
+² "
+S3 6,12 0 0263
+³ "
+aa 6,12 0 0264
+´ "
+µ 11,8,3 0 0265
+ps 11,12 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 5,1,3 0 0270
+¸ "
+S1 6,12 0 0271
+¹ "
+Om 6,12 0 0272
+º "
+Fc 8,7 0 0273
+» "
+14 14,12 0 0274
+¼ "
+12 14,12 0 0275
+½ "
+34 14,12 0 0276
+¾ "
+r? 8,9,3 0 0277
+¿ "
+`A 12,16 0 0300
+À "
+'A 12,16 0 0301
+Á "
+^A 12,16 0 0302
+Â "
+~A 12,15 0 0303
+Ã "
+:A 12,15 0 0304
+Ä "
+oA 12,16 0 0305
+Å "
+AE 15,12 0 0306
+Æ "
+,C 13,12,3 0 0307
+Ç "
+`E 12,16 0 0310
+È "
+'E 12,16 0 0311
+É "
+^E 12,16 0 0312
+Ê "
+:E 12,15 0 0313
+Ë "
+`I 7,16 0 0314
+Ì "
+'I 7,16 0 0315
+Í "
+^I 7,16 0 0316
+Î "
+:I 7,15 0 0317
+Ï "
+-D 14,12 0 0320
+Ð "
+~N 14,15 0 0321
+Ñ "
+`O 14,16 0 0322
+Ò "
+'O 14,16 0 0323
+Ó "
+^O 14,16 0 0324
+Ô "
+~O 14,15 0 0325
+Õ "
+:O 14,15 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 14,13,1 0 0330
+Ø "
+`U 14,16 0 0331
+Ù "
+'U 14,16 0 0332
+Ú "
+^U 14,16 0 0333
+Û "
+:U 14,15 0 0334
+Ü "
+'Y 12,16 0 0335
+Ý "
+TP 12,12 0 0336
+Þ "
+ss 10,12,3 0 0337
+ß "
+`a 11,12 0 0340
+à "
+'a 11,12 0 0341
+á "
+^a 11,12 0 0342
+â "
+~a 11,11 0 0343
+ã "
+:a 11,11 0 0344
+ä "
+oa 11,13 0 0345
+å "
+ae 14,8 0 0346
+æ "
+,c 9,8,3 0 0347
+ç "
+`e 9,12 0 0350
+è "
+'e 9,12 0 0351
+é "
+^e 9,12 0 0352
+ê "
+:e 9,11 0 0353
+ë "
+`i 6,12 0 0354
+ì "
+'i 6,12 0 0355
+í "
+^i 6,12 0 0356
+î "
+:i 6,11 0 0357
+ï "
+Sd 10,13 0 0360
+ð "
+~n 11,11 0 0361
+ñ "
+`o 10,12 0 0362
+ò "
+'o 10,12 0 0363
+ó "
+^o 10,12 0 0364
+ô "
+~o 10,11 0 0365
+õ "
+:o 10,11 0 0366
+ö "
+di 10,8 0 0367
+÷ "
+/o 10,10,2 0 0370
+ø "
+`u 11,12 0 0371
+ù "
+'u 11,12 0 0372
+ú "
+^u 11,12 0 0373
+û "
+:u 11,11 0 0374
+ü "
+'y 9,12,3 0 0375
+ý "
+Tp 11,11,3 0 0376
+þ "
+:y 9,11,3 0 0377
+ÿ "
diff --git a/font/devX100-12/NI b/font/devX100-12/NI
new file mode 100644
index 00000000..7a34f2af
--- /dev/null
+++ b/font/devX100-12/NI
@@ -0,0 +1,306 @@
+name NI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 6,12 0 041
+" 7,12 0 042
+# 9,12 0 043
+sh "
+$ 9,14,1 0 044
+Do "
+% 14,12 0 045
+& 14,12 0 046
+' 3,12 0 047
+( 6,12,2 0 050
+) 5,12,2 0 051
+* 8,12 0 052
++ 10,9 0 053
+, 4,2,3 0 054
+\- 10,5 0 055
+. 4,2 0 056
+/ 10,12,2 0 057
+sl "
+0 9,12 0 060
+1 9,12 0 061
+2 9,12 0 062
+3 9,12 0 063
+4 9,12 0 064
+5 9,12 0 065
+6 9,12 0 066
+7 9,12 0 067
+8 9,12 0 070
+9 9,12 0 071
+: 5,8 0 072
+; 5,8,3 0 073
+< 10,9 0 074
+= 10,6 0 075
+eq "
+> 10,9 0 076
+? 7,12 0 077
+@ 12,12 0 0100
+at "
+A 12,12 0 0101
+B 12,12 0 0102
+C 12,12 0 0103
+D 13,12 0 0104
+E 12,12 0 0105
+F 11,12 0 0106
+G 13,12 0 0107
+H 14,12 0 0110
+I 7,12 0 0111
+J 10,12 0 0112
+K 12,12 0 0113
+L 11,12 0 0114
+M 16,12 0 0115
+N 13,12 0 0116
+O 13,12 0 0117
+P 11,12 0 0120
+Q 13,12,3 0 0121
+R 13,12 0 0122
+S 11,12 0 0123
+T 11,12 0 0124
+U 13,12 0 0125
+V 11,12 0 0126
+W 15,12 0 0127
+X 12,12 0 0130
+Y 11,12 0 0131
+Z 11,12 0 0132
+[ 6,12,2 0 0133
+lB "
+\ 10,12 0 0134
+rs "
+] 6,12,2 0 0135
+rB "
+^ 10,12 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 3,12 0 0140
+oq "
+a 10,8 0 0141
+b 9,12 0 0142
+c 8,8 0 0143
+d 10,12 0 0144
+e 7,8 0 0145
+f 5,12,3 0 0146
+g 9,9,3 0 0147
+h 10,12 0 0150
+i 6,12 0 0151
+j 5,12,3 0 0152
+k 9,12 0 0153
+l 6,12 0 0154
+m 15,8 0 0155
+n 10,8 0 0156
+o 8,8 0 0157
+p 9,8,3 0 0160
+q 9,8,3 0 0161
+r 7,8 0 0162
+s 7,8 0 0163
+t 6,11 0 0164
+u 10,8 0 0165
+v 8,8 0 0166
+w 13,8 0 0167
+x 8,8 0 0170
+y 8,8,3 0 0171
+z 8,8 0 0172
+{ 6,12,2 0 0173
+lC "
+| 10,12 0 0174
+or "
+ba "
+} 6,12,2 0 0175
+rC "
+~ 10,5 0 0176
+a~ "
+ap "
+ti "
+r! 6,9,3 0 0241
+¡ "
+ct 9,10,2 0 0242
+¢ "
+Po 9,12 0 0243
+£ "
+Cs 9,10 0 0244
+¤ "
+Ye 9,12 0 0245
+¥ "
+bb 10,12 0 0246
+¦ "
+sc 8,12,3 0 0247
+§ "
+ad 6,11 0 0250
+¨ "
+co 12,12 0 0251
+© "
+Of 7,12 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 10,6 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 12,12 0 0256
+® "
+a- 5,10 0 0257
+¯ "
+de 7,12 0 0260
+° "
++- 10,9 0 0261
+± "
+S2 6,12 0 0262
+² "
+S3 6,12 0 0263
+³ "
+aa 5,12 0 0264
+´ "
+µ 10,8,3 0 0265
+ps 11,12 0 0266
+¶ "
+md 5,5 0 0267
+· "
+ac 5,1,3 0 0270
+¸ "
+S1 6,12 0 0271
+¹ "
+Om 6,12 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 14,12 0 0274
+¼ "
+12 14,12 0 0275
+½ "
+34 14,12 0 0276
+¾ "
+r? 7,9,3 0 0277
+¿ "
+`A 12,16 0 0300
+À "
+'A 12,16 0 0301
+Á "
+^A 12,16 0 0302
+Â "
+~A 12,15 0 0303
+Ã "
+:A 12,15 0 0304
+Ä "
+oA 12,16 0 0305
+Å "
+AE 14,12 0 0306
+Æ "
+,C 12,12,3 0 0307
+Ç "
+`E 12,16 0 0310
+È "
+'E 12,16 0 0311
+É "
+^E 12,16 0 0312
+Ê "
+:E 12,15 0 0313
+Ë "
+`I 7,16 0 0314
+Ì "
+'I 7,16 0 0315
+Í "
+^I 7,16 0 0316
+Î "
+:I 7,15 0 0317
+Ï "
+-D 13,12 0 0320
+Ð "
+~N 13,15 0 0321
+Ñ "
+`O 13,16 0 0322
+Ò "
+'O 13,16 0 0323
+Ó "
+^O 13,16 0 0324
+Ô "
+~O 13,15 0 0325
+Õ "
+:O 13,15 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 13,13,1 0 0330
+Ø "
+`U 13,16 0 0331
+Ù "
+'U 13,16 0 0332
+Ú "
+^U 13,16 0 0333
+Û "
+:U 13,15 0 0334
+Ü "
+'Y 11,16 0 0335
+Ý "
+TP 11,12 0 0336
+Þ "
+ss 9,12,3 0 0337
+ß "
+`a 10,12 0 0340
+à "
+'a 10,12 0 0341
+á "
+^a 10,12 0 0342
+â "
+~a 10,11 0 0343
+ã "
+:a 10,11 0 0344
+ä "
+oa 10,13 0 0345
+å "
+ae 12,8 0 0346
+æ "
+,c 8,8,3 0 0347
+ç "
+`e 7,12 0 0350
+è "
+'e 7,12 0 0351
+é "
+^e 7,12 0 0352
+ê "
+:e 7,11 0 0353
+ë "
+`i 6,12 0 0354
+ì "
+'i 6,12 0 0355
+í "
+^i 6,12 0 0356
+î "
+:i 6,11 0 0357
+ï "
+Sd 8,13 0 0360
+ð "
+~n 10,11 0 0361
+ñ "
+`o 8,12 0 0362
+ò "
+'o 8,12 0 0363
+ó "
+^o 8,12 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 10,8 0 0367
+÷ "
+/o 8,10,2 0 0370
+ø "
+`u 10,12 0 0371
+ù "
+'u 10,12 0 0372
+ú "
+^u 10,12 0 0373
+û "
+:u 10,11 0 0374
+ü "
+'y 8,12,3 0 0375
+ý "
+Tp 9,11,3 0 0376
+þ "
+:y 8,11,3 0 0377
+ÿ "
diff --git a/font/devX100-12/NR b/font/devX100-12/NR
new file mode 100644
index 00000000..0a9a0cfa
--- /dev/null
+++ b/font/devX100-12/NR
@@ -0,0 +1,306 @@
+name NR
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,12 0 041
+" 6,12 0 042
+# 9,12 0 043
+sh "
+$ 9,13,2 0 044
+Do "
+% 14,12 0 045
+& 13,12 0 046
+' 3,12 0 047
+( 6,12,2 0 050
+) 6,12,2 0 051
+* 8,12 0 052
++ 10,9 0 053
+, 4,2,3 0 054
+\- 10,5 0 055
+. 4,2 0 056
+/ 5,12 0 057
+sl "
+0 9,12 0 060
+1 9,12 0 061
+2 9,12 0 062
+3 9,12 0 063
+4 9,12 0 064
+5 9,12 0 065
+6 9,12 0 066
+7 9,12 0 067
+8 9,12 0 070
+9 9,12 0 071
+: 4,8 0 072
+; 4,8,3 0 073
+< 10,8 0 074
+= 10,6 0 075
+eq "
+> 10,8 0 076
+? 7,12 0 077
+@ 12,12,1 0 0100
+at "
+A 12,12 0 0101
+B 12,12 0 0102
+C 12,12 0 0103
+D 13,12 0 0104
+E 12,12 0 0105
+F 11,12 0 0106
+G 13,12 0 0107
+H 14,12 0 0110
+I 7,12 0 0111
+J 9,12 0 0112
+K 13,12 0 0113
+L 11,12 0 0114
+M 16,12 0 0115
+N 13,12 0 0116
+O 13,12 0 0117
+P 11,12 0 0120
+Q 13,12,3 0 0121
+R 12,12 0 0122
+S 10,12 0 0123
+T 11,12 0 0124
+U 13,12 0 0125
+V 12,12 0 0126
+W 16,12 0 0127
+X 11,12 0 0130
+Y 12,12 0 0131
+Z 10,12 0 0132
+[ 6,12,2 0 0133
+lB "
+\ 10,12 0 0134
+rs "
+] 6,12,2 0 0135
+rB "
+^ 10,12 0 0136
+a^ "
+ha "
+_ 8,0,2 0 0137
+` 3,12 0 0140
+oq "
+a 9,8 0 0141
+b 9,12 0 0142
+c 7,8 0 0143
+d 10,12 0 0144
+e 8,8 0 0145
+f 6,12 0 0146
+g 9,8,3 0 0147
+h 10,12 0 0150
+i 5,12 0 0151
+j 5,12,3 0 0152
+k 10,12 0 0153
+l 5,12 0 0154
+m 15,8 0 0155
+n 10,8 0 0156
+o 8,8 0 0157
+p 9,8,3 0 0160
+q 9,8,3 0 0161
+r 7,8 0 0162
+s 8,8 0 0163
+t 7,11 0 0164
+u 10,8 0 0165
+v 9,8 0 0166
+w 13,8 0 0167
+x 9,8 0 0170
+y 9,8,3 0 0171
+z 8,8 0 0172
+{ 6,12,2 0 0173
+lC "
+| 10,12 0 0174
+or "
+ba "
+} 6,12,2 0 0175
+rC "
+~ 10,5 0 0176
+a~ "
+ap "
+ti "
+r! 5,9,3 0 0241
+¡ "
+ct 9,10,2 0 0242
+¢ "
+Po 9,12 0 0243
+£ "
+Cs 9,10 0 0244
+¤ "
+Ye 9,12 0 0245
+¥ "
+bb 10,12 0 0246
+¦ "
+sc 8,12,3 0 0247
+§ "
+ad 5,11 0 0250
+¨ "
+co 12,12 0 0251
+© "
+Of 6,12 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 10,6 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 12,12 0 0256
+® "
+a- 5,10 0 0257
+¯ "
+de 7,12 0 0260
+° "
++- 10,9 0 0261
+± "
+S2 6,12 0 0262
+² "
+S3 6,12 0 0263
+³ "
+aa 5,12 0 0264
+´ "
+µ 10,8,3 0 0265
+ps 10,12,3 0 0266
+¶ "
+md 5,5 0 0267
+· "
+ac 5,1,3 0 0270
+¸ "
+S1 6,12 0 0271
+¹ "
+Om 5,12 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 14,12 0 0274
+¼ "
+12 13,12 0 0275
+½ "
+34 14,12 0 0276
+¾ "
+r? 7,9,3 0 0277
+¿ "
+`A 12,16 0 0300
+À "
+'A 12,16 0 0301
+Á "
+^A 12,16 0 0302
+Â "
+~A 12,15 0 0303
+Ã "
+:A 12,15 0 0304
+Ä "
+oA 12,16 0 0305
+Å "
+AE 17,12 0 0306
+Æ "
+,C 12,12,3 0 0307
+Ç "
+`E 12,16 0 0310
+È "
+'E 12,16 0 0311
+É "
+^E 12,16 0 0312
+Ê "
+:E 12,15 0 0313
+Ë "
+`I 7,16 0 0314
+Ì "
+'I 7,16 0 0315
+Í "
+^I 7,16 0 0316
+Î "
+:I 7,15 0 0317
+Ï "
+-D 13,12 0 0320
+Ð "
+~N 13,15 0 0321
+Ñ "
+`O 13,16 0 0322
+Ò "
+'O 13,16 0 0323
+Ó "
+^O 13,16 0 0324
+Ô "
+~O 13,15 0 0325
+Õ "
+:O 13,15 0 0326
+Ö "
+mu 10,8 0 0327
+× "
+/O 13,13,1 0 0330
+Ø "
+`U 13,16 0 0331
+Ù "
+'U 13,16 0 0332
+Ú "
+^U 13,16 0 0333
+Û "
+:U 13,15 0 0334
+Ü "
+'Y 12,16 0 0335
+Ý "
+TP 11,12 0 0336
+Þ "
+ss 10,12 0 0337
+ß "
+`a 9,12 0 0340
+à "
+'a 9,12 0 0341
+á "
+^a 9,12 0 0342
+â "
+~a 9,11 0 0343
+ã "
+:a 9,11 0 0344
+ä "
+oa 9,13 0 0345
+å "
+ae 13,8 0 0346
+æ "
+,c 7,8,3 0 0347
+ç "
+`e 8,12 0 0350
+è "
+'e 8,12 0 0351
+é "
+^e 8,12 0 0352
+ê "
+:e 8,11 0 0353
+ë "
+`i 5,12 0 0354
+ì "
+'i 5,12 0 0355
+í "
+^i 5,12 0 0356
+î "
+:i 5,11 0 0357
+ï "
+Sd 8,13 0 0360
+ð "
+~n 10,11 0 0361
+ñ "
+`o 8,12 0 0362
+ò "
+'o 8,12 0 0363
+ó "
+^o 8,12 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 10,8 0 0367
+÷ "
+/o 8,9,1 0 0370
+ø "
+`u 10,12 0 0371
+ù "
+'u 10,12 0 0372
+ú "
+^u 10,12 0 0373
+û "
+:u 10,11 0 0374
+ü "
+'y 9,12,3 0 0375
+ý "
+Tp 9,11,3 0 0376
+þ "
+:y 9,11,3 0 0377
+ÿ "
diff --git a/font/devX100-12/S b/font/devX100-12/S
new file mode 100644
index 00000000..453c295e
--- /dev/null
+++ b/font/devX100-12/S
@@ -0,0 +1,226 @@
+name S
+special
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+fa 11,12 0 042
+# 8,11 0 043
+sh "
+te 9,12 0 044
+% 13,11,1 0 045
+& 13,11 0 046
+st 7,8 0 047
+( 5,12,2 0 050
+) 5,12,2 0 051
+** 8,8 0 052
++ 9,9 0 053
+pl "
+, 4,3,2 0 054
+\- 9,5 0 055
+mi "
+. 4,3 0 056
+/ 5,11 0 057
+sl "
+0 8,12 0 060
+1 8,12 0 061
+2 8,12 0 062
+3 8,12 0 063
+4 8,12 0 064
+5 8,12 0 065
+6 8,12 0 066
+7 8,12 0 067
+8 8,12 0 070
+9 8,12 0 071
+: 4,8 0 072
+; 4,8,2 0 073
+< 9,9 0 074
+= 9,6 0 075
+eq "
+> 9,9 0 076
+? 7,11 0 077
+=~ 9,8 0 0100
+*A 12,11 0 0101
+*B 11,11 0 0102
+*X 12,11 0 0103
+*D 10,11 0 0104
+*E 10,11 0 0105
+*F 12,11 0 0106
+*G 10,11 0 0107
+*Y 12,11 0 0110
+*I 6,11 0 0111
++h 10,12 0 0112
+*K 12,11 0 0113
+*L 11,11 0 0114
+*M 14,11 0 0115
+*N 11,11 0 0116
+*O 12,11 0 0117
+*P 12,11 0 0120
+*H 12,11 0 0121
+*R 9,11 0 0122
+*S 10,11 0 0123
+*T 10,11 0 0124
+--- 11,11 0 0125
+ts 8,8,4 0 0126
+*W 12,12 0 0127
+*C 11,11 0 0130
+*Q 13,11 0 0131
+*Z 10,11 0 0132
+[ 6,12,2 0 0133
+lB "
+tf 14,8 0 0134
+3d "
+] 5,12,2 0 0135
+rB "
+pp 11,11 0 0136
+_ 8,0,4 0 0137
+radicalex 8,13 0 0140
+*a 11,9 0 0141
+*b 9,13,4 0 0142
+*x 9,9,3 0 0143
+*d 8,12 0 0144
+*e 7,9 0 0145
+*f 9,11,3 0 0146
+*g 7,9,4 0 0147
+*y 10,9,3 0 0150
+*i 5,9 0 0151
++f 10,9,3 0 0152
+*k 9,9 0 0153
+*l 9,13 0 0154
+*m 9,9,4 0 0155
+µ "
+*n 8,9 0 0156
+*o 9,9 0 0157
+*p 9,9 0 0160
+*h 9,12 0 0161
+*r 9,9,4 0 0162
+*s 10,9 0 0163
+*t 7,9 0 0164
+*u 9,9 0 0165
++p 11,10 0 0166
+*w 11,9 0 0167
+*c 8,13,4 0 0170
+*q 11,9,4 0 0171
+*z 8,13,4 0 0172
+lC 8,12,2 0 0173
+{ "
+ba 3,11,3 0 0174
+or "
+| "
+rC 8,12,2 0 0175
+} "
+ap 9,5 0 0176
+*U 10,11 0 0241
+fm 4,12 0 0242
+<= 9,11 0 0243
+f/ 3,11 0 0244
+if 12,7 0 0245
+Fn 8,12,3 0 0246
+CL 12,9,1 0 0247
+DI 12,9 0 0250
+HE 12,9 0 0251
+SP 12,9,1 0 0252
+<> 17,9 0 0253
+<- 16,9 0 0254
+ua 10,13,2 0 0255
+arrowverttp "
+-> 16,9 0 0256
+da 10,13,2 0 0257
+arrowvertbt "
+de 6,11 0 0260
+° "
++- 9,11 0 0261
+± "
+sd 7,12 0 0262
+>= 9,11 0 0263
+mu 9,9 0 0264
+× "
+pt 11,7 0 0265
+pd 8,13,1 0 0266
+bu 8,8 0 0267
+di 9,8 0 0270
+÷ "
+!= 9,9,1 0 0271
+== 9,8 0 0272
+~= 9,7 0 0273
+~~ "
+--- 16,3 0 0274
+arrowvertex 10,13,4 0 0275
+an 16,5 0 0276
+CR 10,10,1 0 0277
+Ah 13,11 0 0300
+Im 11,13,1 0 0301
+Re 13,13 0 0302
+wp 16,9,4 0 0303
+c* 12,11 0 0304
+c+ 12,11 0 0305
+es 13,12 0 0306
+ca 12,9 0 0307
+cu 12,9 0 0310
+sp 11,8 0 0311
+ip 11,7,3 0 0312
+--- 11,9,1 0 0313
+sb 11,8 0 0314
+ib 11,8,2 0 0315
+mo 11,7 0 0316
+nm 11,8,1 0 0317
+/_ 12,11 0 0320
+gr 11,12 0 0321
+rg 13,11 0 0322
+co 13,11 0 0323
+tm 14,11 0 0324
+--- 13,13,2 0 0325
+sr 9,13,3 0 0326
+md 4,5 0 0327
+no 12,5 0 0330
+¬ "
+AN 10,8 0 0331
+OR 10,8 0 0332
+hA 17,9 0 0333
+lA 16,9 0 0334
+uA 10,13,2 0 0335
+rA 16,9 0 0336
+dA 10,13,2 0 0337
+lz 8,12 0 0340
+la 5,13,2 0 0341
+--- 13,11 0 0342
+--- 13,11 0 0343
+--- 13,11 0 0344
+--- 11,13,2 0 0345
+parenlefttp 6,13,4 0 0346
+parenleftex 6,13,4 0 0347
+parenleftbt 6,13,4 0 0350
+bracketlefttp 6,13,4 0 0351
+lc "
+bracketleftex 6,13,4 0 0352
+bracketleftbt 6,13,4 0 0353
+lf "
+bracelefttp 8,13,4 0 0354
+lt "
+braceleftmid 8,13,4 0 0355
+lk "
+braceleftbt 8,13,4 0 0356
+lb "
+bracerightex 8,13,4 0 0357
+braceleftex "
+bv "
+--- 13,13 0 0360
+ra 5,13,2 0 0361
+is 5,13,4 0 0362
+--- 11,13,4 0 0363
+--- 11,13,4 0 0364
+--- 11,13,4 0 0365
+parenrighttp 7,13,4 0 0366
+parenrightex 6,13,4 0 0367
+parenrightbt 6,13,4 0 0370
+bracketrighttp 6,13,4 0 0371
+rc "
+bracketrightex 6,13,4 0 0372
+bracketrightbt 6,13,4 0 0373
+rf "
+bracerighttp 8,13,4 0 0374
+rt "
+bracerightmid 8,13,4 0 0375
+rk "
+bracerightbt 8,13,4 0 0376
+rb "
diff --git a/font/devX100-12/TB b/font/devX100-12/TB
new file mode 100644
index 00000000..83073d52
--- /dev/null
+++ b/font/devX100-12/TB
@@ -0,0 +1,306 @@
+name TB
+spacewidth 4
+charset
+--- 4,1 0 040
+! 6,11 0 041
+" 9,11 0 042
+# 8,11 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 16,12 0 045
+& 14,11 0 046
+' 6,11 0 047
+( 6,11,3 0 050
+) 6,11,3 0 051
+* 8,11 0 052
++ 9,8 0 053
+, 4,2,3 0 054
+\- 9,5 0 055
+. 4,2 0 056
+/ 5,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 5,7 0 072
+; 5,7,3 0 073
+< 9,8 0 074
+= 9,7 0 075
+eq "
+> 9,8 0 076
+? 8,11 0 077
+@ 16,11,2 0 0100
+at "
+A 12,11 0 0101
+B 11,11 0 0102
+C 12,11 0 0103
+D 12,11 0 0104
+E 11,11 0 0105
+F 10,11 0 0106
+G 13,11 0 0107
+H 13,11 0 0110
+I 6,11 0 0111
+J 8,11,2 0 0112
+K 13,11 0 0113
+L 11,11 0 0114
+M 15,11 0 0115
+N 12,11 0 0116
+O 13,11 0 0117
+P 10,11 0 0120
+Q 13,11,3 0 0121
+R 12,11 0 0122
+S 9,11 0 0123
+T 11,11 0 0124
+U 12,11 0 0125
+V 12,11 0 0126
+W 16,11 0 0127
+X 12,11 0 0130
+Y 12,11 0 0131
+Z 11,11 0 0132
+[ 6,11,3 0 0133
+lB "
+\ 5,11 0 0134
+rs "
+] 6,11,3 0 0135
+rB "
+^ 9,11 0 0136
+a^ "
+ha "
+_ 8,0,4 0 0137
+` 6,11 0 0140
+oq "
+a 8,8 0 0141
+b 9,11 0 0142
+c 7,8 0 0143
+d 9,11 0 0144
+e 7,8 0 0145
+f 6,11 0 0146
+g 8,8,4 0 0147
+h 9,11 0 0150
+i 5,11 0 0151
+j 5,11,4 0 0152
+k 9,11 0 0153
+l 5,11 0 0154
+m 14,8 0 0155
+n 9,8 0 0156
+o 8,8 0 0157
+p 9,8,4 0 0160
+q 9,8,4 0 0161
+r 7,8 0 0162
+s 6,8 0 0163
+t 6,11 0 0164
+u 9,8 0 0165
+v 8,8 0 0166
+w 12,8 0 0167
+x 8,8 0 0170
+y 8,8,4 0 0171
+z 7,8 0 0172
+{ 7,11,3 0 0173
+lC "
+| 4,11,3 0 0174
+or "
+ba "
+} 7,11,3 0 0175
+rC "
+~ 9,8 0 0176
+a~ "
+ap "
+ti "
+r! 6,8,4 0 0241
+¡ "
+ct 8,10,2 0 0242
+¢ "
+Po 8,11 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 8,11 0 0245
+¥ "
+bb 4,12,3 0 0246
+¦ "
+sc 8,11,4 0 0247
+§ "
+ad 6,11 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 5,11 0 0252
+ª "
+Fo 8,7 0 0253
+« "
+no 9,7 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 6,10 0 0257
+¯ "
+de 7,11 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 6,12 0 0264
+´ "
+µ 9,8,3 0 0265
+ps 9,11,4 0 0266
+¶ "
+md 4,6 0 0267
+· "
+ac 6,0,4 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 6,11 0 0272
+º "
+Fc 8,7 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 8,8,3 0 0277
+¿ "
+`A 12,15 0 0300
+À "
+'A 12,15 0 0301
+Á "
+^A 12,15 0 0302
+Â "
+~A 12,14 0 0303
+Ã "
+:A 12,14 0 0304
+Ä "
+oA 12,16 0 0305
+Å "
+AE 16,11 0 0306
+Æ "
+,C 12,11,4 0 0307
+Ç "
+`E 11,15 0 0310
+È "
+'E 11,15 0 0311
+É "
+^E 11,15 0 0312
+Ê "
+:E 11,14 0 0313
+Ë "
+`I 6,15 0 0314
+Ì "
+'I 6,15 0 0315
+Í "
+^I 6,15 0 0316
+Î "
+:I 6,14 0 0317
+Ï "
+-D 12,11 0 0320
+Ð "
+~N 12,14 0 0321
+Ñ "
+`O 13,15 0 0322
+Ò "
+'O 13,15 0 0323
+Ó "
+^O 13,15 0 0324
+Ô "
+~O 13,15 0 0325
+Õ "
+:O 13,14 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 13,12,1 0 0330
+Ø "
+`U 12,15 0 0331
+Ù "
+'U 12,15 0 0332
+Ú "
+^U 12,15 0 0333
+Û "
+:U 12,14 0 0334
+Ü "
+'Y 12,15 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 9,11 0 0337
+ß "
+`a 8,12 0 0340
+à "
+'a 8,12 0 0341
+á "
+^a 8,12 0 0342
+â "
+~a 8,11 0 0343
+ã "
+:a 8,11 0 0344
+ä "
+oa 8,13 0 0345
+å "
+ae 12,8 0 0346
+æ "
+,c 7,8,4 0 0347
+ç "
+`e 7,12 0 0350
+è "
+'e 7,12 0 0351
+é "
+^e 7,12 0 0352
+ê "
+:e 7,11 0 0353
+ë "
+`i 5,12 0 0354
+ì "
+'i 5,12 0 0355
+í "
+^i 5,12 0 0356
+î "
+:i 5,11 0 0357
+ï "
+Sd 8,11 0 0360
+ð "
+~n 9,11 0 0361
+ñ "
+`o 8,12 0 0362
+ò "
+'o 8,12 0 0363
+ó "
+^o 8,12 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 8,9,1 0 0370
+ø "
+`u 9,12 0 0371
+ù "
+'u 9,12 0 0372
+ú "
+^u 9,12 0 0373
+û "
+:u 9,11 0 0374
+ü "
+'y 8,12,4 0 0375
+ý "
+Tp 9,11,4 0 0376
+þ "
+:y 8,11,4 0 0377
+ÿ "
diff --git a/font/devX100-12/TBI b/font/devX100-12/TBI
new file mode 100644
index 00000000..71ca7136
--- /dev/null
+++ b/font/devX100-12/TBI
@@ -0,0 +1,306 @@
+name TBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 6,11 0 041
+" 9,11 0 042
+# 8,11 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11 0 045
+& 13,11 0 046
+' 6,11 0 047
+( 6,11,3 0 050
+) 6,11,3 0 051
+* 8,11 0 052
++ 10,9 0 053
+, 4,2,3 0 054
+\- 10,6 0 055
+. 4,2 0 056
+/ 5,12 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 5,7 0 072
+; 5,7,3 0 073
+< 10,8 0 074
+= 10,7 0 075
+eq "
+> 10,8 0 076
+? 8,11 0 077
+@ 14,11,2 0 0100
+at "
+A 11,11 0 0101
+B 11,11 0 0102
+C 11,11 0 0103
+D 12,11 0 0104
+E 11,11 0 0105
+F 11,11 0 0106
+G 12,11 0 0107
+H 13,11 0 0110
+I 6,11 0 0111
+J 8,11,2 0 0112
+K 11,11 0 0113
+L 10,11 0 0114
+M 15,11 0 0115
+N 12,11 0 0116
+O 12,11 0 0117
+P 10,11 0 0120
+Q 12,11,4 0 0121
+R 11,11 0 0122
+S 9,11 0 0123
+T 10,11 0 0124
+U 12,11 0 0125
+V 11,11 0 0126
+W 15,11 0 0127
+X 11,11 0 0130
+Y 10,11 0 0131
+Z 10,11 0 0132
+[ 6,12,3 0 0133
+lB "
+\ 5,12 0 0134
+rs "
+] 6,12,3 0 0135
+rB "
+^ 10,11 0 0136
+a^ "
+ha "
+_ 8,0,2 0 0137
+` 6,11 0 0140
+oq "
+a 8,8 0 0141
+b 8,11 0 0142
+c 7,8 0 0143
+d 8,11 0 0144
+e 7,8 0 0145
+f 6,11,3 0 0146
+g 8,8,3 0 0147
+h 9,11 0 0150
+i 5,11 0 0151
+j 5,11,3 0 0152
+k 8,11 0 0153
+l 5,11 0 0154
+m 13,8 0 0155
+n 9,8 0 0156
+o 8,8 0 0157
+p 8,8,3 0 0160
+q 8,8,3 0 0161
+r 6,8 0 0162
+s 6,8 0 0163
+t 5,10 0 0164
+u 9,8 0 0165
+v 7,8 0 0166
+w 11,8 0 0167
+x 8,8 0 0170
+y 7,8,3 0 0171
+z 6,8,1 0 0172
+{ 6,12,3 0 0173
+lC "
+| 4,12 0 0174
+or "
+ba "
+} 6,12,3 0 0175
+rC "
+~ 10,6 0 0176
+a~ "
+ap "
+ti "
+r! 6,8,4 0 0241
+¡ "
+ct 8,10,2 0 0242
+¢ "
+Po 8,11 0 0243
+£ "
+Cs 8,9 0 0244
+¤ "
+Ye 8,11 0 0245
+¥ "
+bb 4,12 0 0246
+¦ "
+sc 8,11,3 0 0247
+§ "
+ad 6,11 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 4,11 0 0252
+ª "
+Fo 8,7 0 0253
+« "
+no 10,5 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 6,10 0 0257
+¯ "
+de 7,11 0 0260
+° "
++- 10,10 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 6,12 0 0264
+´ "
+µ 9,8,3 0 0265
+ps 8,11,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 6,1,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 5,11 0 0272
+º "
+Fc 8,7 0 0273
+» "
+14 13,11 0 0274
+¼ "
+12 13,11 0 0275
+½ "
+34 13,11 0 0276
+¾ "
+r? 8,8,4 0 0277
+¿ "
+`A 11,15 0 0300
+À "
+'A 11,15 0 0301
+Á "
+^A 11,15 0 0302
+Â "
+~A 11,14 0 0303
+Ã "
+:A 11,14 0 0304
+Ä "
+oA 11,15 0 0305
+Å "
+AE 15,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 11,15 0 0310
+È "
+'E 11,15 0 0311
+É "
+^E 11,15 0 0312
+Ê "
+:E 11,14 0 0313
+Ë "
+`I 6,15 0 0314
+Ì "
+'I 6,15 0 0315
+Í "
+^I 6,15 0 0316
+Î "
+:I 6,14 0 0317
+Ï "
+-D 12,11 0 0320
+Ð "
+~N 12,14 0 0321
+Ñ "
+`O 12,15 0 0322
+Ò "
+'O 12,15 0 0323
+Ó "
+^O 12,15 0 0324
+Ô "
+~O 12,14 0 0325
+Õ "
+:O 12,14 0 0326
+Ö "
+mu 10,9 0 0327
+× "
+/O 12,12,2 0 0330
+Ø "
+`U 12,15 0 0331
+Ù "
+'U 12,15 0 0332
+Ú "
+^U 12,15 0 0333
+Û "
+:U 12,14 0 0334
+Ü "
+'Y 10,15 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 8,12,3 0 0337
+ß "
+`a 8,12 0 0340
+à "
+'a 8,12 0 0341
+á "
+^a 8,12 0 0342
+â "
+~a 8,11 0 0343
+ã "
+:a 8,11 0 0344
+ä "
+oa 8,12 0 0345
+å "
+ae 12,8 0 0346
+æ "
+,c 7,8,3 0 0347
+ç "
+`e 7,12 0 0350
+è "
+'e 7,12 0 0351
+é "
+^e 7,12 0 0352
+ê "
+:e 7,11 0 0353
+ë "
+`i 5,12 0 0354
+ì "
+'i 5,12 0 0355
+í "
+^i 5,12 0 0356
+î "
+:i 5,11 0 0357
+ï "
+Sd 8,11 0 0360
+ð "
+~n 9,11 0 0361
+ñ "
+`o 8,12 0 0362
+ò "
+'o 8,12 0 0363
+ó "
+^o 8,12 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 10,9 0 0367
+÷ "
+/o 8,10,2 0 0370
+ø "
+`u 9,12 0 0371
+ù "
+'u 9,12 0 0372
+ú "
+^u 9,12 0 0373
+û "
+:u 9,11 0 0374
+ü "
+'y 7,12,3 0 0375
+ý "
+Tp 8,11,3 0 0376
+þ "
+:y 7,11,3 0 0377
+ÿ "
diff --git a/font/devX100-12/TI b/font/devX100-12/TI
new file mode 100644
index 00000000..fad269f9
--- /dev/null
+++ b/font/devX100-12/TI
@@ -0,0 +1,306 @@
+name TI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 6,11 0 041
+" 7,10 0 042
+# 8,11 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11 0 045
+& 13,11 0 046
+' 6,10 0 047
+( 6,11,3 0 050
+) 6,11,3 0 051
+* 8,11 0 052
++ 11,9 0 053
+, 4,2,2 0 054
+\- 11,5 0 055
+. 4,2 0 056
+/ 5,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 5,7 0 072
+; 5,7,2 0 073
+< 11,9 0 074
+= 11,6 0 075
+eq "
+> 11,9 0 076
+? 8,11 0 077
+@ 15,11,3 0 0100
+at "
+A 10,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 12,11 0 0104
+E 10,11 0 0105
+F 10,11 0 0106
+G 12,11 0 0107
+H 12,11 0 0110
+I 6,11 0 0111
+J 7,11 0 0112
+K 11,11 0 0113
+L 9,11 0 0114
+M 14,11 0 0115
+N 11,11 0 0116
+O 12,11 0 0117
+P 10,11 0 0120
+Q 12,11,3 0 0121
+R 10,11 0 0122
+S 8,11 0 0123
+T 9,11 0 0124
+U 12,11 0 0125
+V 10,11 0 0126
+W 14,11 0 0127
+X 10,11 0 0130
+Y 9,11 0 0131
+Z 9,11 0 0132
+[ 6,11,3 0 0133
+lB "
+\ 5,11 0 0134
+rs "
+] 6,11,3 0 0135
+rB "
+^ 7,11 0 0136
+a^ "
+ha "
+_ 8,0,4 0 0137
+` 6,10 0 0140
+oq "
+a 8,8 0 0141
+b 8,11 0 0142
+c 7,8 0 0143
+d 8,11 0 0144
+e 7,8 0 0145
+f 5,11,4 0 0146
+g 8,8,4 0 0147
+h 8,11 0 0150
+i 5,11 0 0151
+j 5,11,4 0 0152
+k 7,11 0 0153
+l 5,11 0 0154
+m 12,8 0 0155
+n 8,8 0 0156
+o 8,8 0 0157
+p 8,8,4 0 0160
+q 8,8,4 0 0161
+r 6,8 0 0162
+s 6,8 0 0163
+t 5,10 0 0164
+u 8,8 0 0165
+v 7,8 0 0166
+w 11,8 0 0167
+x 7,8 0 0170
+y 7,8,4 0 0171
+z 6,8 0 0172
+{ 7,11,3 0 0173
+lC "
+| 5,11,3 0 0174
+or "
+ba "
+} 7,11,3 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 6,8,3 0 0241
+¡ "
+ct 8,9,1 0 0242
+¢ "
+Po 8,11 0 0243
+£ "
+Cs 8,9 0 0244
+¤ "
+Ye 8,11 0 0245
+¥ "
+bb 5,11,3 0 0246
+¦ "
+sc 8,12,1 0 0247
+§ "
+ad 6,11 0 0250
+¨ "
+co 13,11 0 0251
+© "
+Of 5,11 0 0252
+ª "
+Fo 8,6 0 0253
+« "
+no 11,6 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 13,11 0 0256
+® "
+a- 6,10 0 0257
+¯ "
+de 7,11 0 0260
+° "
++- 11,11 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 6,12 0 0264
+´ "
+µ 8,8,4 0 0265
+ps 9,11,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 6,1,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 5,11 0 0272
+º "
+Fc 8,6 0 0273
+» "
+14 13,11 0 0274
+¼ "
+12 13,11 0 0275
+½ "
+34 13,11 0 0276
+¾ "
+r? 8,8,3 0 0277
+¿ "
+`A 10,15 0 0300
+À "
+'A 10,15 0 0301
+Á "
+^A 10,15 0 0302
+Â "
+~A 10,14 0 0303
+Ã "
+:A 10,14 0 0304
+Ä "
+oA 10,15 0 0305
+Å "
+AE 15,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 10,15 0 0310
+È "
+'E 10,15 0 0311
+É "
+^E 10,15 0 0312
+Ê "
+:E 10,14 0 0313
+Ë "
+`I 6,15 0 0314
+Ì "
+'I 6,15 0 0315
+Í "
+^I 6,15 0 0316
+Î "
+:I 6,14 0 0317
+Ï "
+-D 12,11 0 0320
+Ð "
+~N 11,14 0 0321
+Ñ "
+`O 12,15 0 0322
+Ò "
+'O 12,15 0 0323
+Ó "
+^O 12,15 0 0324
+Ô "
+~O 12,14 0 0325
+Õ "
+:O 12,14 0 0326
+Ö "
+mu 11,9 0 0327
+× "
+/O 12,12,1 0 0330
+Ø "
+`U 12,15 0 0331
+Ù "
+'U 12,15 0 0332
+Ú "
+^U 12,15 0 0333
+Û "
+:U 12,14 0 0334
+Ü "
+'Y 9,15 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 8,11,4 0 0337
+ß "
+`a 8,12 0 0340
+à "
+'a 8,12 0 0341
+á "
+^a 8,12 0 0342
+â "
+~a 8,11 0 0343
+ã "
+:a 8,11 0 0344
+ä "
+oa 8,13 0 0345
+å "
+ae 11,8 0 0346
+æ "
+,c 7,8,3 0 0347
+ç "
+`e 7,12 0 0350
+è "
+'e 7,12 0 0351
+é "
+^e 7,12 0 0352
+ê "
+:e 7,11 0 0353
+ë "
+`i 5,12 0 0354
+ì "
+'i 5,12 0 0355
+í "
+^i 5,12 0 0356
+î "
+:i 5,11 0 0357
+ï "
+Sd 8,12 0 0360
+ð "
+~n 8,11 0 0361
+ñ "
+`o 8,12 0 0362
+ò "
+'o 8,12 0 0363
+ó "
+^o 8,12 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 11,8 0 0367
+÷ "
+/o 8,9,1 0 0370
+ø "
+`u 8,12 0 0371
+ù "
+'u 8,12 0 0372
+ú "
+^u 8,12 0 0373
+û "
+:u 8,11 0 0374
+ü "
+'y 7,12,4 0 0375
+ý "
+Tp 8,11,4 0 0376
+þ "
+:y 7,11,4 0 0377
+ÿ "
diff --git a/font/devX100-12/TR b/font/devX100-12/TR
new file mode 100644
index 00000000..6db573e8
--- /dev/null
+++ b/font/devX100-12/TR
@@ -0,0 +1,306 @@
+name TR
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+" 7,11 0 042
+# 8,11 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 14,11 0 045
+& 13,11 0 046
+' 5,11 0 047
+( 5,11,3 0 050
+) 5,11,3 0 051
+* 8,11 0 052
++ 9,8 0 053
+, 4,2,1 0 054
+\- 9,5 0 055
+. 4,2 0 056
+/ 5,11,2 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,8 0 072
+; 4,8,1 0 073
+< 9,9 0 074
+= 9,6 0 075
+eq "
+> 9,9 0 076
+? 7,11 0 077
+@ 15,11,3 0 0100
+at "
+A 12,11 0 0101
+B 11,11 0 0102
+C 11,11 0 0103
+D 12,11 0 0104
+E 10,11 0 0105
+F 9,11 0 0106
+G 12,11 0 0107
+H 12,11 0 0110
+I 5,11 0 0111
+J 6,11 0 0112
+K 12,11 0 0113
+L 10,11 0 0114
+M 15,11 0 0115
+N 12,11 0 0116
+O 12,11 0 0117
+P 9,11 0 0120
+Q 12,11,3 0 0121
+R 11,11 0 0122
+S 9,11 0 0123
+T 10,11 0 0124
+U 12,11 0 0125
+V 12,11 0 0126
+W 16,11 0 0127
+X 12,11 0 0130
+Y 12,11 0 0131
+Z 10,11 0 0132
+[ 5,11,3 0 0133
+lB "
+\ 5,11 0 0134
+rs "
+] 5,11,3 0 0135
+rB "
+^ 8,11 0 0136
+a^ "
+ha "
+_ 8,0,2 0 0137
+` 5,11 0 0140
+oq "
+a 7,8 0 0141
+b 8,11 0 0142
+c 7,8 0 0143
+d 8,11 0 0144
+e 7,8 0 0145
+f 6,11 0 0146
+g 8,8,4 0 0147
+h 8,11 0 0150
+i 5,11 0 0151
+j 4,11,4 0 0152
+k 8,11 0 0153
+l 5,11 0 0154
+m 13,8 0 0155
+n 8,8 0 0156
+o 8,8 0 0157
+p 8,8,4 0 0160
+q 8,8,4 0 0161
+r 6,8 0 0162
+s 6,8 0 0163
+t 5,10 0 0164
+u 8,8 0 0165
+v 8,8 0 0166
+w 12,8 0 0167
+x 8,8 0 0170
+y 8,8,4 0 0171
+z 7,8 0 0172
+{ 8,11,3 0 0173
+lC "
+| 3,11 0 0174
+or "
+ba "
+} 8,11,3 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 5,8,3 0 0241
+¡ "
+ct 8,10,2 0 0242
+¢ "
+Po 8,11 0 0243
+£ "
+Cs 8,10 0 0244
+¤ "
+Ye 8,11 0 0245
+¥ "
+bb 3,11 0 0246
+¦ "
+sc 8,11,3 0 0247
+§ "
+ad 6,11 0 0250
+¨ "
+co 13,11 0 0251
+© "
+Of 5,11 0 0252
+ª "
+Fo 8,7 0 0253
+« "
+no 9,5 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 13,11 0 0256
+® "
+a- 6,10 0 0257
+¯ "
+de 7,11 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 6,11 0 0264
+´ "
+µ 8,8,3 0 0265
+ps 8,11,4 0 0266
+¶ "
+md 4,6 0 0267
+· "
+ac 6,0,4 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 5,11 0 0272
+º "
+Fc 8,7 0 0273
+» "
+14 13,11 0 0274
+¼ "
+12 13,11 0 0275
+½ "
+34 13,11 0 0276
+¾ "
+r? 7,8,3 0 0277
+¿ "
+`A 12,15 0 0300
+À "
+'A 12,15 0 0301
+Á "
+^A 12,15 0 0302
+Â "
+~A 12,14 0 0303
+Ã "
+:A 12,14 0 0304
+Ä "
+oA 12,14 0 0305
+Å "
+AE 15,11 0 0306
+Æ "
+,C 11,11,4 0 0307
+Ç "
+`E 10,15 0 0310
+È "
+'E 10,15 0 0311
+É "
+^E 10,15 0 0312
+Ê "
+:E 10,14 0 0313
+Ë "
+`I 5,15 0 0314
+Ì "
+'I 5,15 0 0315
+Í "
+^I 5,15 0 0316
+Î "
+:I 5,14 0 0317
+Ï "
+-D 12,11 0 0320
+Ð "
+~N 12,14 0 0321
+Ñ "
+`O 12,15 0 0322
+Ò "
+'O 12,15 0 0323
+Ó "
+^O 12,15 0 0324
+Ô "
+~O 12,14 0 0325
+Õ "
+:O 12,14 0 0326
+Ö "
+mu 9,7 0 0327
+× "
+/O 12,12,1 0 0330
+Ø "
+`U 12,15 0 0331
+Ù "
+'U 12,15 0 0332
+Ú "
+^U 12,15 0 0333
+Û "
+:U 12,14 0 0334
+Ü "
+'Y 12,15 0 0335
+Ý "
+TP 9,11 0 0336
+Þ "
+ss 8,11 0 0337
+ß "
+`a 7,12 0 0340
+à "
+'a 7,12 0 0341
+á "
+^a 7,12 0 0342
+â "
+~a 7,11 0 0343
+ã "
+:a 7,11 0 0344
+ä "
+oa 7,12 0 0345
+å "
+ae 11,8 0 0346
+æ "
+,c 7,8,4 0 0347
+ç "
+`e 7,12 0 0350
+è "
+'e 7,12 0 0351
+é "
+^e 7,12 0 0352
+ê "
+:e 7,11 0 0353
+ë "
+`i 5,12 0 0354
+ì "
+'i 5,12 0 0355
+í "
+^i 5,12 0 0356
+î "
+:i 5,11 0 0357
+ï "
+Sd 8,11 0 0360
+ð "
+~n 8,11 0 0361
+ñ "
+`o 8,12 0 0362
+ò "
+'o 8,12 0 0363
+ó "
+^o 8,12 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 9,9 0 0367
+÷ "
+/o 8,10,2 0 0370
+ø "
+`u 8,12 0 0371
+ù "
+'u 8,12 0 0372
+ú "
+^u 8,12 0 0373
+û "
+:u 8,11 0 0374
+ü "
+'y 8,12,4 0 0375
+ý "
+Tp 8,11,4 0 0376
+þ "
+:y 8,11,4 0 0377
+ÿ "
diff --git a/font/devX100/CB b/font/devX100/CB
new file mode 100644
index 00000000..7239ed1e
--- /dev/null
+++ b/font/devX100/CB
@@ -0,0 +1,306 @@
+name CB
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,9 0 041
+" 9,10 0 042
+# 9,10,1 0 043
+sh "
+$ 9,11,1 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046
+' 9,10 0 047
+( 9,9,2 0 050
+) 9,9,2 0 051
+* 9,9 0 052
++ 9,8 0 053
+, 9,2,2 0 054
+\- 9,5 0 055
+. 9,2 0 056
+/ 9,10,2 0 057
+sl "
+0 9,10 0 060
+1 9,10 0 061
+2 9,10 0 062
+3 9,10 0 063
+4 9,10 0 064
+5 9,10 0 065
+6 9,10 0 066
+7 9,10 0 067
+8 9,10 0 070
+9 9,10 0 071
+: 9,7 0 072
+; 9,7,2 0 073
+< 9,8 0 074
+= 9,6 0 075
+eq "
+> 9,8 0 076
+? 9,9 0 077
+@ 9,9 0 0100
+at "
+A 9,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 9,9 0 0111
+J 9,9 0 0112
+K 9,9 0 0113
+L 9,9 0 0114
+M 9,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 9,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 9,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 9,9 0 0126
+W 9,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 9,9,2 0 0133
+lB "
+\ 9,10,2 0 0134
+rs "
+] 9,9,2 0 0135
+rB "
+^ 9,9 0 0136
+a^ "
+ha "
+_ 9,0,2 0 0137
+` 9,10 0 0140
+oq "
+a 9,7 0 0141
+b 9,10 0 0142
+c 9,7 0 0143
+d 9,10 0 0144
+e 9,7 0 0145
+f 9,10 0 0146
+g 9,7,3 0 0147
+h 9,10 0 0150
+i 9,10 0 0151
+j 9,10,3 0 0152
+k 9,10 0 0153
+l 9,10 0 0154
+m 9,7 0 0155
+n 9,7 0 0156
+o 9,7 0 0157
+p 9,7,3 0 0160
+q 9,7,3 0 0161
+r 9,7 0 0162
+s 9,7 0 0163
+t 9,9 0 0164
+u 9,7 0 0165
+v 9,7 0 0166
+w 9,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 9,9,2 0 0173
+lC "
+| 9,9,2 0 0174
+or "
+ba "
+} 9,9,2 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 9,7,2 0 0241
+¡ "
+ct 9,9,1 0 0242
+¢ "
+Po 9,9 0 0243
+£ "
+Cs 9,7 0 0244
+¤ "
+Ye 9,9 0 0245
+¥ "
+bb 9,9,2 0 0246
+¦ "
+sc 9,10,1 0 0247
+§ "
+ad 9,10 0 0250
+¨ "
+co 9,9 0 0251
+© "
+Of 9,9 0 0252
+ª "
+Fo 9,6 0 0253
+« "
+no 9,5 0 0254
+¬ "
+- 9,5 0 0255
+hy "
+­ "
+rg 9,9 0 0256
+® "
+a- 9,9 0 0257
+¯ "
+de 9,9 0 0260
+° "
++- 9,8 0 0261
+± "
+S2 9,10 0 0262
+² "
+S3 9,10 0 0263
+³ "
+aa 9,9 0 0264
+´ "
+µ 9,7,3 0 0265
+ps 9,10,1 0 0266
+¶ "
+md 9,5 0 0267
+· "
+ac 9,1,3 0 0270
+¸ "
+S1 9,10 0 0271
+¹ "
+Om 9,9 0 0272
+º "
+Fc 9,6 0 0273
+» "
+14 9,10 0 0274
+¼ "
+12 9,10 0 0275
+½ "
+34 9,10 0 0276
+¾ "
+r? 9,7,2 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,12 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 9,9 0 0306
+Æ "
+,C 9,9,4 0 0307
+Ç "
+`E 9,12 0 0310
+È "
+'E 9,12 0 0311
+É "
+^E 9,12 0 0312
+Ê "
+:E 9,12 0 0313
+Ë "
+`I 9,12 0 0314
+Ì "
+'I 9,12 0 0315
+Í "
+^I 9,12 0 0316
+Î "
+:I 9,12 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,12 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 9,10 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,12 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 9,9 0 0336
+Þ "
+ss 9,9 0 0337
+ß "
+`a 9,10 0 0340
+à "
+'a 9,10 0 0341
+á "
+^a 9,10 0 0342
+â "
+~a 9,10 0 0343
+ã "
+:a 9,10 0 0344
+ä "
+oa 9,10 0 0345
+å "
+ae 9,7 0 0346
+æ "
+,c 9,7,4 0 0347
+ç "
+`e 9,10 0 0350
+è "
+'e 9,10 0 0351
+é "
+^e 9,10 0 0352
+ê "
+:e 9,10 0 0353
+ë "
+`i 9,10 0 0354
+ì "
+'i 9,10 0 0355
+í "
+^i 9,10 0 0356
+î "
+:i 9,10 0 0357
+ï "
+Sd 9,10 0 0360
+ð "
+~n 9,10 0 0361
+ñ "
+`o 9,10 0 0362
+ò "
+'o 9,10 0 0363
+ó "
+^o 9,10 0 0364
+ô "
+~o 9,10 0 0365
+õ "
+:o 9,10 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 9,7 0 0370
+ø "
+`u 9,10 0 0371
+ù "
+'u 9,10 0 0372
+ú "
+^u 9,10 0 0373
+û "
+:u 9,10 0 0374
+ü "
+'y 9,10,3 0 0375
+ý "
+Tp 9,9,3 0 0376
+þ "
+:y 9,10,3 0 0377
+ÿ "
diff --git a/font/devX100/CBI b/font/devX100/CBI
new file mode 100644
index 00000000..384f91d7
--- /dev/null
+++ b/font/devX100/CBI
@@ -0,0 +1,306 @@
+name CBI
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,10 0 041
+" 9,9 0 042
+# 9,11,1 0 043
+sh "
+$ 9,11,1 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046
+' 9,9 0 047
+( 9,9,2 0 050
+) 9,9,2 0 051
+* 9,10 0 052
++ 9,8 0 053
+, 9,2,2 0 054
+\- 9,5 0 055
+. 9,2 0 056
+/ 9,10,2 0 057
+sl "
+0 9,10 0 060
+1 9,10 0 061
+2 9,10 0 062
+3 9,10 0 063
+4 9,10 0 064
+5 9,10 0 065
+6 9,10 0 066
+7 9,10 0 067
+8 9,10 0 070
+9 9,10 0 071
+: 9,7 0 072
+; 9,7,2 0 073
+< 9,8 0 074
+= 9,6 0 075
+eq "
+> 9,8 0 076
+? 9,9 0 077
+@ 9,9 0 0100
+at "
+A 9,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 9,9 0 0111
+J 9,9 0 0112
+K 9,9 0 0113
+L 9,9 0 0114
+M 9,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 9,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 9,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 9,9 0 0126
+W 9,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 9,9,2 0 0133
+lB "
+\ 9,10,2 0 0134
+rs "
+] 9,9,2 0 0135
+rB "
+^ 9,9 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 9,9 0 0140
+oq "
+a 9,7 0 0141
+b 9,10 0 0142
+c 9,7 0 0143
+d 9,10 0 0144
+e 9,7 0 0145
+f 9,10 0 0146
+g 9,7,3 0 0147
+h 9,10 0 0150
+i 9,10 0 0151
+j 9,10,3 0 0152
+k 9,10 0 0153
+l 9,10 0 0154
+m 9,7 0 0155
+n 9,7 0 0156
+o 9,7 0 0157
+p 9,7,3 0 0160
+q 9,7,3 0 0161
+r 9,7 0 0162
+s 9,7 0 0163
+t 9,9 0 0164
+u 9,7 0 0165
+v 9,7 0 0166
+w 9,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 9,9,2 0 0173
+lC "
+| 9,9,2 0 0174
+or "
+ba "
+} 9,9,2 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 9,7,3 0 0241
+¡ "
+ct 9,9,1 0 0242
+¢ "
+Po 9,9 0 0243
+£ "
+Cs 9,7 0 0244
+¤ "
+Ye 9,9 0 0245
+¥ "
+bb 9,10,2 0 0246
+¦ "
+sc 9,10,1 0 0247
+§ "
+ad 9,10 0 0250
+¨ "
+co 9,9 0 0251
+© "
+Of 9,9 0 0252
+ª "
+Fo 9,6 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 9,5 0 0255
+hy "
+­ "
+rg 9,9 0 0256
+® "
+a- 9,9 0 0257
+¯ "
+de 9,10 0 0260
+° "
++- 9,8 0 0261
+± "
+S2 9,10 0 0262
+² "
+S3 9,10 0 0263
+³ "
+aa 9,10 0 0264
+´ "
+µ 9,7,3 0 0265
+ps 9,10,1 0 0266
+¶ "
+md 9,5 0 0267
+· "
+ac 9,1,3 0 0270
+¸ "
+S1 9,10 0 0271
+¹ "
+Om 9,9 0 0272
+º "
+Fc 9,6 0 0273
+» "
+14 9,10 0 0274
+¼ "
+12 9,10 0 0275
+½ "
+34 9,10 0 0276
+¾ "
+r? 9,7,2 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,12 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 9,9 0 0306
+Æ "
+,C 9,9,4 0 0307
+Ç "
+`E 9,12 0 0310
+È "
+'E 9,12 0 0311
+É "
+^E 9,12 0 0312
+Ê "
+:E 9,12 0 0313
+Ë "
+`I 9,12 0 0314
+Ì "
+'I 9,12 0 0315
+Í "
+^I 9,12 0 0316
+Î "
+:I 9,12 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,12 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 9,9 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,12 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 9,9 0 0336
+Þ "
+ss 9,9 0 0337
+ß "
+`a 9,10 0 0340
+à "
+'a 9,10 0 0341
+á "
+^a 9,10 0 0342
+â "
+~a 9,10 0 0343
+ã "
+:a 9,10 0 0344
+ä "
+oa 9,10 0 0345
+å "
+ae 9,7 0 0346
+æ "
+,c 9,7,4 0 0347
+ç "
+`e 9,10 0 0350
+è "
+'e 9,10 0 0351
+é "
+^e 9,10 0 0352
+ê "
+:e 9,10 0 0353
+ë "
+`i 9,10 0 0354
+ì "
+'i 9,10 0 0355
+í "
+^i 9,10 0 0356
+î "
+:i 9,10 0 0357
+ï "
+Sd 9,10 0 0360
+ð "
+~n 9,10 0 0361
+ñ "
+`o 9,10 0 0362
+ò "
+'o 9,10 0 0363
+ó "
+^o 9,10 0 0364
+ô "
+~o 9,10 0 0365
+õ "
+:o 9,10 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 9,8 0 0370
+ø "
+`u 9,10 0 0371
+ù "
+'u 9,10 0 0372
+ú "
+^u 9,10 0 0373
+û "
+:u 9,10 0 0374
+ü "
+'y 9,10,3 0 0375
+ý "
+Tp 9,9,3 0 0376
+þ "
+:y 9,10,3 0 0377
+ÿ "
diff --git a/font/devX100/CI b/font/devX100/CI
new file mode 100644
index 00000000..07fd0a68
--- /dev/null
+++ b/font/devX100/CI
@@ -0,0 +1,306 @@
+name CI
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,9 0 041
+" 9,10 0 042
+# 9,10,1 0 043
+sh "
+$ 9,10,1 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046
+' 9,10 0 047
+( 9,10,3 0 050
+) 9,10,3 0 051
+* 9,9 0 052
++ 9,8 0 053
+, 9,2,2 0 054
+\- 9,5 0 055
+. 9,2 0 056
+/ 9,10,2 0 057
+sl "
+0 9,10 0 060
+1 9,10 0 061
+2 9,10 0 062
+3 9,10 0 063
+4 9,10 0 064
+5 9,10 0 065
+6 9,10 0 066
+7 9,10 0 067
+8 9,10 0 070
+9 9,10 0 071
+: 9,7 0 072
+; 9,7,2 0 073
+< 9,8 0 074
+= 9,6 0 075
+eq "
+> 9,8 0 076
+? 9,9 0 077
+@ 9,9 0 0100
+at "
+A 9,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 9,9 0 0111
+J 9,9 0 0112
+K 9,9 0 0113
+L 9,9 0 0114
+M 9,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 9,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 9,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 9,9 0 0126
+W 9,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 9,10,3 0 0133
+lB "
+\ 9,10,2 0 0134
+rs "
+] 9,10,3 0 0135
+rB "
+^ 9,9 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 9,10 0 0140
+oq "
+a 9,7 0 0141
+b 9,10 0 0142
+c 9,7 0 0143
+d 9,10 0 0144
+e 9,7 0 0145
+f 9,10 0 0146
+g 9,7,3 0 0147
+h 9,10 0 0150
+i 9,10 0 0151
+j 9,10,3 0 0152
+k 9,10 0 0153
+l 9,10 0 0154
+m 9,7 0 0155
+n 9,7 0 0156
+o 9,7 0 0157
+p 9,7,3 0 0160
+q 9,7,3 0 0161
+r 9,7 0 0162
+s 9,7 0 0163
+t 9,9 0 0164
+u 9,7 0 0165
+v 9,7 0 0166
+w 9,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 9,10,3 0 0173
+lC "
+| 9,9,2 0 0174
+or "
+ba "
+} 9,10,3 0 0175
+rC "
+~ 9,5 0 0176
+a~ "
+ap "
+ti "
+r! 9,7,2 0 0241
+¡ "
+ct 9,10 0 0242
+¢ "
+Po 9,9 0 0243
+£ "
+Cs 9,7 0 0244
+¤ "
+Ye 9,9 0 0245
+¥ "
+bb 9,9,2 0 0246
+¦ "
+sc 9,9,1 0 0247
+§ "
+ad 9,9 0 0250
+¨ "
+co 9,9 0 0251
+© "
+Of 9,9 0 0252
+ª "
+Fo 9,7 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 9,5 0 0255
+hy "
+­ "
+rg 9,9 0 0256
+® "
+a- 9,9 0 0257
+¯ "
+de 9,10 0 0260
+° "
++- 9,8 0 0261
+± "
+S2 9,10 0 0262
+² "
+S3 9,10 0 0263
+³ "
+aa 9,9 0 0264
+´ "
+µ 9,7,3 0 0265
+ps 9,9,1 0 0266
+¶ "
+md 9,5 0 0267
+· "
+ac 9,1,3 0 0270
+¸ "
+S1 9,10 0 0271
+¹ "
+Om 9,9 0 0272
+º "
+Fc 9,7 0 0273
+» "
+14 9,10 0 0274
+¼ "
+12 9,10 0 0275
+½ "
+34 9,10 0 0276
+¾ "
+r? 9,7,2 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,11 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 9,9 0 0306
+Æ "
+,C 9,9,3 0 0307
+Ç "
+`E 9,12 0 0310
+È "
+'E 9,12 0 0311
+É "
+^E 9,12 0 0312
+Ê "
+:E 9,11 0 0313
+Ë "
+`I 9,12 0 0314
+Ì "
+'I 9,12 0 0315
+Í "
+^I 9,12 0 0316
+Î "
+:I 9,11 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,11 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 9,9 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,11 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 9,9 0 0336
+Þ "
+ss 9,9 0 0337
+ß "
+`a 9,10 0 0340
+à "
+'a 9,10 0 0341
+á "
+^a 9,10 0 0342
+â "
+~a 9,10 0 0343
+ã "
+:a 9,9 0 0344
+ä "
+oa 9,11 0 0345
+å "
+ae 9,7 0 0346
+æ "
+,c 9,7,3 0 0347
+ç "
+`e 9,10 0 0350
+è "
+'e 9,10 0 0351
+é "
+^e 9,10 0 0352
+ê "
+:e 9,9 0 0353
+ë "
+`i 9,10 0 0354
+ì "
+'i 9,10 0 0355
+í "
+^i 9,10 0 0356
+î "
+:i 9,9 0 0357
+ï "
+Sd 9,10 0 0360
+ð "
+~n 9,10 0 0361
+ñ "
+`o 9,10 0 0362
+ò "
+'o 9,10 0 0363
+ó "
+^o 9,10 0 0364
+ô "
+~o 9,10 0 0365
+õ "
+:o 9,9 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 9,7 0 0370
+ø "
+`u 9,10 0 0371
+ù "
+'u 9,10 0 0372
+ú "
+^u 9,10 0 0373
+û "
+:u 9,9 0 0374
+ü "
+'y 9,10,3 0 0375
+ý "
+Tp 9,9,3 0 0376
+þ "
+:y 9,9,3 0 0377
+ÿ "
diff --git a/font/devX100/CR b/font/devX100/CR
new file mode 100644
index 00000000..e425fa60
--- /dev/null
+++ b/font/devX100/CR
@@ -0,0 +1,306 @@
+name CR
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,9 0 041
+" 9,10 0 042
+# 9,9,1 0 043
+sh "
+$ 9,11,2 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046
+' 9,10 0 047
+( 9,10,2 0 050
+) 9,10,2 0 051
+* 9,9 0 052
++ 9,8 0 053
+, 9,2,2 0 054
+\- 9,5 0 055
+. 9,2 0 056
+/ 9,10,1 0 057
+sl "
+0 9,10 0 060
+1 9,10 0 061
+2 9,10 0 062
+3 9,10 0 063
+4 9,10 0 064
+5 9,10 0 065
+6 9,10 0 066
+7 9,10 0 067
+8 9,10 0 070
+9 9,10 0 071
+: 9,7 0 072
+; 9,7,2 0 073
+< 9,8 0 074
+= 9,6 0 075
+eq "
+> 9,8 0 076
+? 9,9 0 077
+@ 9,9,1 0 0100
+at "
+A 9,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 9,9 0 0111
+J 9,9 0 0112
+K 9,9 0 0113
+L 9,9 0 0114
+M 9,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 9,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 9,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 9,9 0 0126
+W 9,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 9,10,2 0 0133
+lB "
+\ 9,10,1 0 0134
+rs "
+] 9,10,2 0 0135
+rB "
+^ 9,9 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 9,10 0 0140
+oq "
+a 9,7 0 0141
+b 9,10 0 0142
+c 9,7 0 0143
+d 9,10 0 0144
+e 9,7 0 0145
+f 9,10 0 0146
+g 9,7,3 0 0147
+h 9,10 0 0150
+i 9,10 0 0151
+j 9,10,3 0 0152
+k 9,10 0 0153
+l 9,10 0 0154
+m 9,7 0 0155
+n 9,7 0 0156
+o 9,7 0 0157
+p 9,7,3 0 0160
+q 9,7,3 0 0161
+r 9,7 0 0162
+s 9,7 0 0163
+t 9,9 0 0164
+u 9,7 0 0165
+v 9,7 0 0166
+w 9,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 9,10,2 0 0173
+lC "
+| 9,9,2 0 0174
+or "
+ba "
+} 9,10,2 0 0175
+rC "
+~ 9,5 0 0176
+a~ "
+ap "
+ti "
+r! 9,7,2 0 0241
+¡ "
+ct 9,9 0 0242
+¢ "
+Po 9,9 0 0243
+£ "
+Cs 9,7 0 0244
+¤ "
+Ye 9,9 0 0245
+¥ "
+bb 9,9,2 0 0246
+¦ "
+sc 9,9,1 0 0247
+§ "
+ad 9,9 0 0250
+¨ "
+co 9,9 0 0251
+© "
+Of 9,9 0 0252
+ª "
+Fo 9,7 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 9,5 0 0255
+hy "
+­ "
+rg 9,9 0 0256
+® "
+a- 9,9 0 0257
+¯ "
+de 9,10 0 0260
+° "
++- 9,8 0 0261
+± "
+S2 9,10 0 0262
+² "
+S3 9,10 0 0263
+³ "
+aa 9,10 0 0264
+´ "
+µ 9,7,3 0 0265
+ps 9,9,1 0 0266
+¶ "
+md 9,5 0 0267
+· "
+ac 9,0,3 0 0270
+¸ "
+S1 9,10 0 0271
+¹ "
+Om 9,9 0 0272
+º "
+Fc 9,7 0 0273
+» "
+14 9,10 0 0274
+¼ "
+12 9,10 0 0275
+½ "
+34 9,10 0 0276
+¾ "
+r? 9,7,2 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,11 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 9,9 0 0306
+Æ "
+,C 9,9,3 0 0307
+Ç "
+`E 9,12 0 0310
+È "
+'E 9,12 0 0311
+É "
+^E 9,12 0 0312
+Ê "
+:E 9,11 0 0313
+Ë "
+`I 9,12 0 0314
+Ì "
+'I 9,12 0 0315
+Í "
+^I 9,12 0 0316
+Î "
+:I 9,11 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,11 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 9,9 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,11 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 9,9 0 0336
+Þ "
+ss 9,9 0 0337
+ß "
+`a 9,10 0 0340
+à "
+'a 9,10 0 0341
+á "
+^a 9,10 0 0342
+â "
+~a 9,10 0 0343
+ã "
+:a 9,9 0 0344
+ä "
+oa 9,10 0 0345
+å "
+ae 9,7 0 0346
+æ "
+,c 9,7,3 0 0347
+ç "
+`e 9,10 0 0350
+è "
+'e 9,10 0 0351
+é "
+^e 9,10 0 0352
+ê "
+:e 9,9 0 0353
+ë "
+`i 9,10 0 0354
+ì "
+'i 9,10 0 0355
+í "
+^i 9,10 0 0356
+î "
+:i 9,9 0 0357
+ï "
+Sd 9,12 0 0360
+ð "
+~n 9,10 0 0361
+ñ "
+`o 9,10 0 0362
+ò "
+'o 9,10 0 0363
+ó "
+^o 9,10 0 0364
+ô "
+~o 9,10 0 0365
+õ "
+:o 9,9 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 9,7 0 0370
+ø "
+`u 9,10 0 0371
+ù "
+'u 9,10 0 0372
+ú "
+^u 9,10 0 0373
+û "
+:u 9,9 0 0374
+ü "
+'y 9,10,3 0 0375
+ý "
+Tp 9,9,3 0 0376
+þ "
+:y 9,9,3 0 0377
+ÿ "
diff --git a/font/devX100/DESC b/font/devX100/DESC
new file mode 100644
index 00000000..7f63535e
--- /dev/null
+++ b/font/devX100/DESC
@@ -0,0 +1,9 @@
+styles R I B BI
+fonts 6 0 0 0 0 0 S
+sizes 8 10 12 14 18 24 0
+res 100
+X11
+hor 1
+vert 1
+unitwidth 10
+postpro gxditview
diff --git a/font/devX100/HB b/font/devX100/HB
new file mode 100644
index 00000000..d877fd65
--- /dev/null
+++ b/font/devX100/HB
@@ -0,0 +1,306 @@
+name HB
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,11 0 041
+" 7,11 0 042
+# 9,10 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 13,11 0 045
+& 11,10 0 046
+' 5,11 0 047
+( 5,11,3 0 050
+) 5,11,3 0 051
+* 6,11 0 052
++ 9,8 0 053
+, 4,2,1 0 054
+\- 9,5 0 055
+. 4,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 5,8 0 072
+; 5,8,1 0 073
+< 8,7 0 074
+= 9,6 0 075
+eq "
+> 8,7 0 076
+? 9,11 0 077
+@ 14,11,1 0 0100
+at "
+A 10,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 11,11 0 0104
+E 9,11 0 0105
+F 9,11 0 0106
+G 11,11 0 0107
+H 10,11 0 0110
+I 4,11 0 0111
+J 8,11 0 0112
+K 10,11 0 0113
+L 8,11 0 0114
+M 13,11 0 0115
+N 11,11 0 0116
+O 12,11 0 0117
+P 10,11 0 0120
+Q 12,11 0 0121
+R 11,11 0 0122
+S 10,11 0 0123
+T 8,11 0 0124
+U 11,11 0 0125
+V 10,11 0 0126
+W 14,11 0 0127
+X 9,11 0 0130
+Y 10,11 0 0131
+Z 9,11 0 0132
+[ 5,11,3 0 0133
+lB "
+\ 4,11 0 0134
+rs "
+] 5,11,3 0 0135
+rB "
+^ 8,11 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 5,11 0 0140
+oq "
+a 8,8 0 0141
+b 9,11 0 0142
+c 8,8 0 0143
+d 9,11 0 0144
+e 8,8 0 0145
+f 4,11 0 0146
+g 9,8,3 0 0147
+h 9,11 0 0150
+i 4,11 0 0151
+j 4,11,3 0 0152
+k 8,11 0 0153
+l 4,11 0 0154
+m 12,8 0 0155
+n 9,8 0 0156
+o 9,8 0 0157
+p 9,8,3 0 0160
+q 9,8,3 0 0161
+r 6,8 0 0162
+s 8,8 0 0163
+t 5,10 0 0164
+u 9,8 0 0165
+v 8,8 0 0166
+w 10,8 0 0167
+x 7,8 0 0170
+y 8,8,3 0 0171
+z 6,8 0 0172
+{ 6,11,3 0 0173
+lC "
+| 4,11,3 0 0174
+or "
+ba "
+} 6,11,3 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241
+¡ "
+ct 8,9,1 0 0242
+¢ "
+Po 8,11 0 0243
+£ "
+Cs 8,9 0 0244
+¤ "
+Ye 9,11 0 0245
+¥ "
+bb 4,11,3 0 0246
+¦ "
+sc 8,11,3 0 0247
+§ "
+ad 5,11 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 6,11 0 0252
+ª "
+Fo 9,7 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 4,5 0 0255
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 5,10 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 9,8,3 0 0265
+ps 8,11,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 4,11 0 0271
+¹ "
+Om 6,11 0 0272
+º "
+Fc 9,7 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 9,8,3 0 0277
+¿ "
+`A 10,14 0 0300
+À "
+'A 10,14 0 0301
+Á "
+^A 10,14 0 0302
+Â "
+~A 10,14 0 0303
+Ã "
+:A 10,14 0 0304
+Ä "
+oA 10,14 0 0305
+Å "
+AE 15,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,14 0 0313
+Ë "
+`I 4,14 0 0314
+Ì "
+'I 4,14 0 0315
+Í "
+^I 4,14 0 0316
+Î "
+:I 4,14 0 0317
+Ï "
+-D 11,11 0 0320
+Ð "
+~N 11,14 0 0321
+Ñ "
+`O 12,14 0 0322
+Ò "
+'O 12,14 0 0323
+Ó "
+^O 12,14 0 0324
+Ô "
+~O 12,14 0 0325
+Õ "
+:O 12,14 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 12,11 0 0330
+Ø "
+`U 11,14 0 0331
+Ù "
+'U 11,14 0 0332
+Ú "
+^U 11,14 0 0333
+Û "
+:U 11,14 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 8,11 0 0337
+ß "
+`a 8,11 0 0340
+à "
+'a 8,11 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,11 0 0343
+ã "
+:a 8,11 0 0344
+ä "
+oa 8,11 0 0345
+å "
+ae 13,8 0 0346
+æ "
+,c 9,8,3 0 0347
+ç "
+`e 8,11 0 0350
+è "
+'e 8,11 0 0351
+é "
+^e 8,11 0 0352
+ê "
+:e 8,11 0 0353
+ë "
+`i 4,11 0 0354
+ì "
+'i 4,11 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,11 0 0357
+ï "
+Sd 9,11 0 0360
+ð "
+~n 9,11 0 0361
+ñ "
+`o 9,11 0 0362
+ò "
+'o 9,11 0 0363
+ó "
+^o 9,11 0 0364
+ô "
+~o 9,11 0 0365
+õ "
+:o 9,11 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 9,8 0 0370
+ø "
+`u 9,11 0 0371
+ù "
+'u 9,11 0 0372
+ú "
+^u 9,11 0 0373
+û "
+:u 9,11 0 0374
+ü "
+'y 8,11,3 0 0375
+ý "
+Tp 9,11,3 0 0376
+þ "
+:y 8,11,3 0 0377
+ÿ "
diff --git a/font/devX100/HBI b/font/devX100/HBI
new file mode 100644
index 00000000..1cf0e56e
--- /dev/null
+++ b/font/devX100/HBI
@@ -0,0 +1,306 @@
+name HBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+" 7,11 0 042
+# 10,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11 0 045
+& 11,10 0 046
+' 5,11 0 047
+( 5,11,3 0 050
+) 6,11,3 0 051
+* 6,11 0 052
++ 9,8 0 053
+, 4,2,2 0 054
+\- 9,5 0 055
+. 4,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 5,8 0 072
+; 5,8,2 0 073
+< 8,7 0 074
+= 9,6 0 075
+eq "
+> 9,7 0 076
+? 9,11 0 077
+@ 14,11,2 0 0100
+at "
+A 9,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 11,11 0 0104
+E 9,11 0 0105
+F 8,11 0 0106
+G 11,11 0 0107
+H 10,11 0 0110
+I 4,11 0 0111
+J 8,11 0 0112
+K 10,11 0 0113
+L 8,11 0 0114
+M 13,11 0 0115
+N 11,11 0 0116
+O 12,11 0 0117
+P 10,11 0 0120
+Q 12,11 0 0121
+R 10,11 0 0122
+S 10,11 0 0123
+T 8,11 0 0124
+U 11,11 0 0125
+V 10,11 0 0126
+W 14,11 0 0127
+X 9,11 0 0130
+Y 10,11 0 0131
+Z 9,11 0 0132
+[ 5,11,3 0 0133
+lB "
+\ 6,11 0 0134
+rs "
+] 5,11,3 0 0135
+rB "
+^ 8,11 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 5,11 0 0140
+oq "
+a 8,8 0 0141
+b 9,11 0 0142
+c 8,8 0 0143
+d 9,11 0 0144
+e 8,8 0 0145
+f 5,11 0 0146
+g 9,8,3 0 0147
+h 9,11 0 0150
+i 4,11 0 0151
+j 4,11,3 0 0152
+k 8,11 0 0153
+l 4,11 0 0154
+m 12,8 0 0155
+n 9,8 0 0156
+o 8,8 0 0157
+p 9,8,3 0 0160
+q 9,8,3 0 0161
+r 6,8 0 0162
+s 8,8 0 0163
+t 5,10 0 0164
+u 9,8 0 0165
+v 8,8 0 0166
+w 11,8 0 0167
+x 7,8 0 0170
+y 7,8,3 0 0171
+z 6,8 0 0172
+{ 6,11,3 0 0173
+lC "
+| 4,11,3 0 0174
+or "
+ba "
+} 6,11,3 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 5,8,3 0 0241
+¡ "
+ct 8,9,1 0 0242
+¢ "
+Po 9,11 0 0243
+£ "
+Cs 9,8 0 0244
+¤ "
+Ye 9,11 0 0245
+¥ "
+bb 4,11,3 0 0246
+¦ "
+sc 9,11,3 0 0247
+§ "
+ad 5,11 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 6,11 0 0252
+ª "
+Fo 11,7 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 5,11 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 9,8,3 0 0265
+ps 8,11,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,1,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 6,11 0 0272
+º "
+Fc 11,7 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 13,11 0 0276
+¾ "
+r? 8,8,3 0 0277
+¿ "
+`A 9,14 0 0300
+À "
+'A 9,14 0 0301
+Á "
+^A 9,14 0 0302
+Â "
+~A 9,14 0 0303
+Ã "
+:A 9,14 0 0304
+Ä "
+oA 9,14 0 0305
+Å "
+AE 14,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,14 0 0313
+Ë "
+`I 4,14 0 0314
+Ì "
+'I 4,14 0 0315
+Í "
+^I 4,14 0 0316
+Î "
+:I 4,14 0 0317
+Ï "
+-D 11,11 0 0320
+Ð "
+~N 11,14 0 0321
+Ñ "
+`O 12,14 0 0322
+Ò "
+'O 12,14 0 0323
+Ó "
+^O 12,14 0 0324
+Ô "
+~O 12,14 0 0325
+Õ "
+:O 12,14 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 12,11 0 0330
+Ø "
+`U 11,14 0 0331
+Ù "
+'U 11,14 0 0332
+Ú "
+^U 11,14 0 0333
+Û "
+:U 11,14 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 9,11 0 0337
+ß "
+`a 8,11 0 0340
+à "
+'a 8,11 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,11 0 0343
+ã "
+:a 8,11 0 0344
+ä "
+oa 8,11 0 0345
+å "
+ae 13,8 0 0346
+æ "
+,c 8,8,3 0 0347
+ç "
+`e 8,11 0 0350
+è "
+'e 8,11 0 0351
+é "
+^e 8,11 0 0352
+ê "
+:e 8,11 0 0353
+ë "
+`i 4,11 0 0354
+ì "
+'i 4,11 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,11 0 0357
+ï "
+Sd 8,11 0 0360
+ð "
+~n 9,11 0 0361
+ñ "
+`o 8,11 0 0362
+ò "
+'o 8,11 0 0363
+ó "
+^o 8,11 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 8,8 0 0370
+ø "
+`u 9,11 0 0371
+ù "
+'u 9,11 0 0372
+ú "
+^u 9,11 0 0373
+û "
+:u 9,11 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 9,11,3 0 0376
+þ "
+:y 7,11,3 0 0377
+ÿ "
diff --git a/font/devX100/HI b/font/devX100/HI
new file mode 100644
index 00000000..7908492d
--- /dev/null
+++ b/font/devX100/HI
@@ -0,0 +1,306 @@
+name HI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,11 0 041
+" 5,11 0 042
+# 9,10 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 12,11 0 045
+& 10,10 0 046
+' 3,11 0 047
+( 5,11,3 0 050
+) 5,11,3 0 051
+* 8,11 0 052
++ 9,8 0 053
+, 3,2,2 0 054
+\- 9,5 0 055
+. 3,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,8 0 072
+; 4,8,2 0 073
+< 9,7 0 074
+= 9,6 0 075
+eq "
+> 9,7 0 076
+? 8,11 0 077
+@ 13,11,1 0 0100
+at "
+A 11,11 0 0101
+B 10,11 0 0102
+C 10,11 0 0103
+D 10,11 0 0104
+E 9,11 0 0105
+F 9,11 0 0106
+G 11,11 0 0107
+H 11,11 0 0110
+I 5,11 0 0111
+J 9,11 0 0112
+K 10,11 0 0113
+L 8,11 0 0114
+M 14,11 0 0115
+N 11,11 0 0116
+O 11,11 0 0117
+P 9,11 0 0120
+Q 11,11 0 0121
+R 10,11 0 0122
+S 9,11 0 0123
+T 8,11 0 0124
+U 11,11 0 0125
+V 11,11 0 0126
+W 14,11 0 0127
+X 10,11 0 0130
+Y 9,11 0 0131
+Z 9,11 0 0132
+[ 5,11,3 0 0133
+lB "
+\ 6,11 0 0134
+rs "
+] 5,11,3 0 0135
+rB "
+^ 7,11 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 3,11 0 0140
+oq "
+a 8,8 0 0141
+b 8,11 0 0142
+c 7,8 0 0143
+d 8,11 0 0144
+e 8,8 0 0145
+f 4,11 0 0146
+g 8,8,3 0 0147
+h 8,11 0 0150
+i 4,11 0 0151
+j 3,11,3 0 0152
+k 7,11 0 0153
+l 3,11 0 0154
+m 11,8 0 0155
+n 8,8 0 0156
+o 8,8 0 0157
+p 8,8,3 0 0160
+q 8,8,3 0 0161
+r 5,8 0 0162
+s 7,8 0 0163
+t 4,10 0 0164
+u 8,8 0 0165
+v 7,8 0 0166
+w 10,8 0 0167
+x 7,8 0 0170
+y 7,8,3 0 0171
+z 7,8 0 0172
+{ 5,11,3 0 0173
+lC "
+| 4,11,3 0 0174
+or "
+ba "
+} 5,11,3 0 0175
+rC "
+~ 8,6 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241
+¡ "
+ct 8,9,1 0 0242
+¢ "
+Po 9,11 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 9,11 0 0245
+¥ "
+bb 4,11,3 0 0246
+¦ "
+sc 8,11,3 0 0247
+§ "
+ad 5,10 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 5,11 0 0252
+ª "
+Fo 8,6 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 4,10 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 4,11 0 0264
+´ "
+µ 8,8,3 0 0265
+ps 8,11,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 3,0,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 5,11 0 0272
+º "
+Fc 8,6 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 8,8,3 0 0277
+¿ "
+`A 11,14 0 0300
+À "
+'A 11,14 0 0301
+Á "
+^A 11,14 0 0302
+Â "
+~A 11,14 0 0303
+Ã "
+:A 11,13 0 0304
+Ä "
+oA 11,14 0 0305
+Å "
+AE 15,11 0 0306
+Æ "
+,C 10,11,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,13 0 0313
+Ë "
+`I 5,14 0 0314
+Ì "
+'I 5,14 0 0315
+Í "
+^I 5,14 0 0316
+Î "
+:I 5,13 0 0317
+Ï "
+-D 10,11 0 0320
+Ð "
+~N 11,14 0 0321
+Ñ "
+`O 11,14 0 0322
+Ò "
+'O 11,14 0 0323
+Ó "
+^O 11,14 0 0324
+Ô "
+~O 11,14 0 0325
+Õ "
+:O 11,13 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 11,11 0 0330
+Ø "
+`U 11,14 0 0331
+Ù "
+'U 11,14 0 0332
+Ú "
+^U 11,14 0 0333
+Û "
+:U 11,13 0 0334
+Ü "
+'Y 9,14 0 0335
+Ý "
+TP 9,11 0 0336
+Þ "
+ss 8,11 0 0337
+ß "
+`a 8,11 0 0340
+à "
+'a 8,11 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,11 0 0343
+ã "
+:a 8,11 0 0344
+ä "
+oa 8,11 0 0345
+å "
+ae 12,8 0 0346
+æ "
+,c 7,8,3 0 0347
+ç "
+`e 8,11 0 0350
+è "
+'e 8,11 0 0351
+é "
+^e 8,11 0 0352
+ê "
+:e 8,11 0 0353
+ë "
+`i 3,11 0 0354
+ì "
+'i 3,11 0 0355
+í "
+^i 3,11 0 0356
+î "
+:i 3,11 0 0357
+ï "
+Sd 8,11 0 0360
+ð "
+~n 8,11 0 0361
+ñ "
+`o 8,11 0 0362
+ò "
+'o 8,11 0 0363
+ó "
+^o 8,11 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 8,9,1 0 0370
+ø "
+`u 8,11 0 0371
+ù "
+'u 8,11 0 0372
+ú "
+^u 8,11 0 0373
+û "
+:u 8,11 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 8,11,3 0 0376
+þ "
+:y 7,11,3 0 0377
+ÿ "
diff --git a/font/devX100/HR b/font/devX100/HR
new file mode 100644
index 00000000..c2f6af39
--- /dev/null
+++ b/font/devX100/HR
@@ -0,0 +1,306 @@
+name HR
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,11 0 041
+" 5,11 0 042
+# 8,10 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 12,11 0 045
+& 10,10 0 046
+' 3,11 0 047
+( 5,11,3 0 050
+) 5,11,3 0 051
+* 7,11 0 052
++ 9,8 0 053
+, 3,2,2 0 054
+\- 9,5 0 055
+. 3,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 3,8 0 072
+; 4,8,2 0 073
+< 8,7 0 074
+= 9,6 0 075
+eq "
+> 8,7 0 076
+? 8,11 0 077
+@ 13,11,1 0 0100
+at "
+A 9,11 0 0101
+B 9,11 0 0102
+C 10,11 0 0103
+D 10,11 0 0104
+E 9,11 0 0105
+F 8,11 0 0106
+G 11,11 0 0107
+H 10,11 0 0110
+I 4,11 0 0111
+J 7,11 0 0112
+K 9,11 0 0113
+L 8,11 0 0114
+M 12,11 0 0115
+N 10,11 0 0116
+O 11,11 0 0117
+P 9,11 0 0120
+Q 11,11 0 0121
+R 10,11 0 0122
+S 9,11 0 0123
+T 9,11 0 0124
+U 10,11 0 0125
+V 9,11 0 0126
+W 13,11 0 0127
+X 9,11 0 0130
+Y 9,11 0 0131
+Z 9,11 0 0132
+[ 4,11,3 0 0133
+lB "
+\ 4,11 0 0134
+rs "
+] 4,11,3 0 0135
+rB "
+^ 7,11 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 3,11 0 0140
+oq "
+a 8,8 0 0141
+b 7,11 0 0142
+c 7,8 0 0143
+d 8,11 0 0144
+e 8,8 0 0145
+f 4,11 0 0146
+g 8,8,3 0 0147
+h 8,11 0 0150
+i 3,11 0 0151
+j 3,11,3 0 0152
+k 7,11 0 0153
+l 3,11 0 0154
+m 11,8 0 0155
+n 8,8 0 0156
+o 8,8 0 0157
+p 8,8,3 0 0160
+q 8,8,3 0 0161
+r 5,8 0 0162
+s 7,8 0 0163
+t 4,10 0 0164
+u 7,8 0 0165
+v 7,8 0 0166
+w 10,8 0 0167
+x 7,8 0 0170
+y 7,8,3 0 0171
+z 7,8 0 0172
+{ 5,11,3 0 0173
+lC "
+| 3,11,3 0 0174
+or "
+ba "
+} 5,11,3 0 0175
+rC "
+~ 8,6 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241
+¡ "
+ct 8,9,1 0 0242
+¢ "
+Po 8,11 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 7,11 0 0245
+¥ "
+bb 3,11,3 0 0246
+¦ "
+sc 8,11,3 0 0247
+§ "
+ad 5,10 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 6,11 0 0252
+ª "
+Fo 8,7 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 4,5 0 0255
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 4,10 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 8,8,3 0 0265
+ps 8,11,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 6,11 0 0272
+º "
+Fc 8,7 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 8,8,3 0 0277
+¿ "
+`A 9,14 0 0300
+À "
+'A 9,14 0 0301
+Á "
+^A 9,14 0 0302
+Â "
+~A 9,13 0 0303
+Ã "
+:A 9,14 0 0304
+Ä "
+oA 9,14 0 0305
+Å "
+AE 14,11 0 0306
+Æ "
+,C 10,11,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,13 0 0313
+Ë "
+`I 4,14 0 0314
+Ì "
+'I 4,14 0 0315
+Í "
+^I 4,14 0 0316
+Î "
+:I 4,13 0 0317
+Ï "
+-D 10,11 0 0320
+Ð "
+~N 10,14 0 0321
+Ñ "
+`O 11,14 0 0322
+Ò "
+'O 11,14 0 0323
+Ó "
+^O 11,14 0 0324
+Ô "
+~O 11,14 0 0325
+Õ "
+:O 11,13 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 11,11 0 0330
+Ø "
+`U 10,14 0 0331
+Ù "
+'U 10,14 0 0332
+Ú "
+^U 10,14 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 9,14 0 0335
+Ý "
+TP 9,11 0 0336
+Þ "
+ss 7,11 0 0337
+ß "
+`a 8,11 0 0340
+à "
+'a 8,11 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,11 0 0343
+ã "
+:a 8,11 0 0344
+ä "
+oa 8,12 0 0345
+å "
+ae 13,8 0 0346
+æ "
+,c 8,8,3 0 0347
+ç "
+`e 8,11 0 0350
+è "
+'e 8,11 0 0351
+é "
+^e 8,11 0 0352
+ê "
+:e 8,11 0 0353
+ë "
+`i 3,11 0 0354
+ì "
+'i 3,11 0 0355
+í "
+^i 3,11 0 0356
+î "
+:i 3,11 0 0357
+ï "
+Sd 8,11 0 0360
+ð "
+~n 8,11 0 0361
+ñ "
+`o 8,11 0 0362
+ò "
+'o 8,11 0 0363
+ó "
+^o 8,11 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 8,8 0 0370
+ø "
+`u 8,11 0 0371
+ù "
+'u 8,11 0 0372
+ú "
+^u 8,11 0 0373
+û "
+:u 8,11 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 8,11,3 0 0376
+þ "
+:y 7,10,3 0 0377
+ÿ "
diff --git a/font/devX100/Makefile.sub b/font/devX100/Makefile.sub
new file mode 100644
index 00000000..4d40f0fd
--- /dev/null
+++ b/font/devX100/Makefile.sub
@@ -0,0 +1,2 @@
+DEV=X100
+DEVFILES=DESC TR TI TB TBI CR CI CB CBI HR HI HB HBI NR NI NB NBI S
diff --git a/font/devX100/NB b/font/devX100/NB
new file mode 100644
index 00000000..d47fdb2e
--- /dev/null
+++ b/font/devX100/NB
@@ -0,0 +1,306 @@
+name NB
+spacewidth 11
+charset
+--- 11,1 0 040
+! 4,11 0 041
+" 5,11 0 042
+# 8,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11 0 045
+& 13,11 0 046
+' 4,11 0 047
+( 5,11,2 0 050
+) 5,11,2 0 051
+* 6,11 0 052
++ 8,8 0 053
+, 4,3,2 0 054
+\- 8,5 0 055
+. 4,3 0 056
+/ 5,11 0 057
+sl "
+0 8,11 0 060
+1 6,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 8,8 0 074
+= 8,6 0 075
+eq "
+> 8,8 0 076
+? 7,11 0 077
+@ 14,11 0 0100
+at "
+A 11,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 12,11 0 0104
+E 10,11 0 0105
+F 10,11 0 0106
+G 12,11 0 0107
+H 12,11 0 0110
+I 7,11 0 0111
+J 9,11 0 0112
+K 12,11 0 0113
+L 10,11 0 0114
+M 14,11 0 0115
+N 12,11 0 0116
+O 12,11 0 0117
+P 10,11 0 0120
+Q 12,11,3 0 0121
+R 12,11 0 0122
+S 10,11 0 0123
+T 11,11 0 0124
+U 12,11 0 0125
+V 11,11 0 0126
+W 14,11 0 0127
+X 12,11 0 0130
+Y 11,11 0 0131
+Z 9,11 0 0132
+[ 5,11,2 0 0133
+lB "
+\ 7,11 0 0134
+rs "
+] 5,11,2 0 0135
+rB "
+^ 8,11 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 4,11 0 0140
+oq "
+a 9,7 0 0141
+b 10,11 0 0142
+c 8,7 0 0143
+d 10,11 0 0144
+e 9,7 0 0145
+f 6,11 0 0146
+g 8,8,3 0 0147
+h 10,11 0 0150
+i 5,10 0 0151
+j 5,10,3 0 0152
+k 9,11 0 0153
+l 5,11 0 0154
+m 15,7 0 0155
+n 10,7 0 0156
+o 9,7 0 0157
+p 10,7,3 0 0160
+q 9,7,3 0 0161
+r 7,7 0 0162
+s 7,7 0 0163
+t 6,10 0 0164
+u 10,7 0 0165
+v 7,7 0 0166
+w 12,7 0 0167
+x 9,7 0 0170
+y 7,7,3 0 0171
+z 7,7 0 0172
+{ 6,11,2 0 0173
+lC "
+| 8,11 0 0174
+or "
+ba "
+} 6,11,2 0 0175
+rC "
+~ 8,6 0 0176
+a~ "
+ap "
+ti "
+r! 5,8,3 0 0241
+¡ "
+ct 8,8,1 0 0242
+¢ "
+Po 9,11 0 0243
+£ "
+Cs 9,10 0 0244
+¤ "
+Ye 11,11 0 0245
+¥ "
+bb 8,11 0 0246
+¦ "
+sc 7,11,2 0 0247
+§ "
+ad 7,10 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 6,11 0 0252
+ª "
+Fo 8,6 0 0253
+« "
+no 8,6 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 7,9 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 8,8 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 6,11 0 0264
+´ "
+µ 10,7,3 0 0265
+ps 10,11 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 6,11 0 0272
+º "
+Fc 8,6 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 7,8,3 0 0277
+¿ "
+`A 11,15 0 0300
+À "
+'A 11,15 0 0301
+Á "
+^A 11,15 0 0302
+Â "
+~A 11,14 0 0303
+Ã "
+:A 11,14 0 0304
+Ä "
+oA 11,15 0 0305
+Å "
+AE 15,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 10,15 0 0310
+È "
+'E 10,15 0 0311
+É "
+^E 10,15 0 0312
+Ê "
+:E 10,14 0 0313
+Ë "
+`I 7,15 0 0314
+Ì "
+'I 7,15 0 0315
+Í "
+^I 7,15 0 0316
+Î "
+:I 7,14 0 0317
+Ï "
+-D 12,11 0 0320
+Ð "
+~N 12,14 0 0321
+Ñ "
+`O 12,15 0 0322
+Ò "
+'O 12,15 0 0323
+Ó "
+^O 12,15 0 0324
+Ô "
+~O 12,14 0 0325
+Õ "
+:O 12,14 0 0326
+Ö "
+mu 8,8 0 0327
+× "
+/O 12,11 0 0330
+Ø "
+`U 12,15 0 0331
+Ù "
+'U 12,15 0 0332
+Ú "
+^U 12,15 0 0333
+Û "
+:U 12,14 0 0334
+Ü "
+'Y 11,14 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 9,11 0 0337
+ß "
+`a 9,11 0 0340
+à "
+'a 9,11 0 0341
+á "
+^a 9,11 0 0342
+â "
+~a 9,10 0 0343
+ã "
+:a 9,10 0 0344
+ä "
+oa 9,11 0 0345
+å "
+ae 14,7 0 0346
+æ "
+,c 8,7,3 0 0347
+ç "
+`e 9,11 0 0350
+è "
+'e 9,11 0 0351
+é "
+^e 9,11 0 0352
+ê "
+:e 9,10 0 0353
+ë "
+`i 5,11 0 0354
+ì "
+'i 5,11 0 0355
+í "
+^i 5,11 0 0356
+î "
+:i 5,10 0 0357
+ï "
+Sd 9,11 0 0360
+ð "
+~n 10,10 0 0361
+ñ "
+`o 9,11 0 0362
+ò "
+'o 9,11 0 0363
+ó "
+^o 9,11 0 0364
+ô "
+~o 9,10 0 0365
+õ "
+:o 9,10 0 0366
+ö "
+di 8,8 0 0367
+÷ "
+/o 9,8,1 0 0370
+ø "
+`u 10,11 0 0371
+ù "
+'u 10,11 0 0372
+ú "
+^u 10,11 0 0373
+û "
+:u 10,10 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 10,11,3 0 0376
+þ "
+:y 7,10,3 0 0377
+ÿ "
diff --git a/font/devX100/NBI b/font/devX100/NBI
new file mode 100644
index 00000000..c46b945a
--- /dev/null
+++ b/font/devX100/NBI
@@ -0,0 +1,306 @@
+name NBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+" 6,11 0 042
+# 8,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11,1 0 045
+& 13,11 0 046
+' 4,11 0 047
+( 5,11,2 0 050
+) 6,11,2 0 051
+* 7,11 0 052
++ 8,8 0 053
+, 4,2,3 0 054
+\- 8,5 0 055
+. 4,2 0 056
+/ 5,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,7 0 072
+; 5,7,3 0 073
+< 9,9 0 074
+= 9,7 0 075
+eq "
+> 9,9 0 076
+? 7,11 0 077
+@ 13,11 0 0100
+at "
+A 11,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 12,11 0 0104
+E 10,11 0 0105
+F 10,11 0 0106
+G 11,11 0 0107
+H 12,11 0 0110
+I 6,11 0 0111
+J 8,11 0 0112
+K 12,11 0 0113
+L 10,11 0 0114
+M 15,11 0 0115
+N 13,11 0 0116
+O 12,11 0 0117
+P 11,11 0 0120
+Q 12,11,2 0 0121
+R 12,11 0 0122
+S 10,11 0 0123
+T 11,11 0 0124
+U 12,11 0 0125
+V 11,11 0 0126
+W 15,11 0 0127
+X 11,11 0 0130
+Y 9,11 0 0131
+Z 10,11 0 0132
+[ 7,11,2 0 0133
+lB "
+\ 9,11 0 0134
+rs "
+] 7,11,2 0 0135
+rB "
+^ 8,11 0 0136
+a^ "
+ha "
+_ 9,0,2 0 0137
+` 4,11 0 0140
+oq "
+a 10,7 0 0141
+b 8,11 0 0142
+c 8,7 0 0143
+d 10,11 0 0144
+e 8,7 0 0145
+f 5,11,3 0 0146
+g 8,9,3 0 0147
+h 10,11 0 0150
+i 5,10 0 0151
+j 4,10,3 0 0152
+k 9,11 0 0153
+l 5,11 0 0154
+m 15,7 0 0155
+n 10,7 0 0156
+o 8,7 0 0157
+p 8,7,3 0 0160
+q 9,7,3 0 0161
+r 7,7 0 0162
+s 8,7 0 0163
+t 5,9 0 0164
+u 10,7 0 0165
+v 8,7 0 0166
+w 13,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 6,11,2 0 0173
+lC "
+| 9,11 0 0174
+or "
+ba "
+} 6,11,2 0 0175
+rC "
+~ 11,6 0 0176
+a~ "
+ap "
+ti "
+r! 5,8,3 0 0241
+¡ "
+ct 8,8,1 0 0242
+¢ "
+Po 10,11 0 0243
+£ "
+Cs 8,9 0 0244
+¤ "
+Ye 10,11 0 0245
+¥ "
+bb 8,11 0 0246
+¦ "
+sc 9,11,2 0 0247
+§ "
+ad 6,10 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 8,11 0 0252
+ª "
+Fo 10,7 0 0253
+« "
+no 9,7 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 6,9 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 8,8 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 10,7,3 0 0265
+ps 9,11 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 8,11 0 0272
+º "
+Fc 10,7 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 7,8,3 0 0277
+¿ "
+`A 11,15 0 0300
+À "
+'A 11,15 0 0301
+Á "
+^A 11,15 0 0302
+Â "
+~A 11,14 0 0303
+Ã "
+:A 11,14 0 0304
+Ä "
+oA 11,15 0 0305
+Å "
+AE 14,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 10,15 0 0310
+È "
+'E 10,15 0 0311
+É "
+^E 10,15 0 0312
+Ê "
+:E 10,14 0 0313
+Ë "
+`I 6,15 0 0314
+Ì "
+'I 6,15 0 0315
+Í "
+^I 6,15 0 0316
+Î "
+:I 6,14 0 0317
+Ï "
+-D 12,11 0 0320
+Ð "
+~N 13,14 0 0321
+Ñ "
+`O 12,15 0 0322
+Ò "
+'O 12,15 0 0323
+Ó "
+^O 12,15 0 0324
+Ô "
+~O 12,14 0 0325
+Õ "
+:O 12,14 0 0326
+Ö "
+mu 8,8 0 0327
+× "
+/O 12,11 0 0330
+Ø "
+`U 12,15 0 0331
+Ù "
+'U 12,15 0 0332
+Ú "
+^U 12,15 0 0333
+Û "
+:U 12,14 0 0334
+Ü "
+'Y 9,15 0 0335
+Ý "
+TP 11,11 0 0336
+Þ "
+ss 10,11,3 0 0337
+ß "
+`a 10,11 0 0340
+à "
+'a 10,11 0 0341
+á "
+^a 10,11 0 0342
+â "
+~a 10,10 0 0343
+ã "
+:a 10,10 0 0344
+ä "
+oa 10,11 0 0345
+å "
+ae 13,7 0 0346
+æ "
+,c 8,7,3 0 0347
+ç "
+`e 8,11 0 0350
+è "
+'e 8,11 0 0351
+é "
+^e 8,11 0 0352
+ê "
+:e 8,10 0 0353
+ë "
+`i 5,11 0 0354
+ì "
+'i 5,11 0 0355
+í "
+^i 5,11 0 0356
+î "
+:i 5,10 0 0357
+ï "
+Sd 8,11 0 0360
+ð "
+~n 10,10 0 0361
+ñ "
+`o 8,11 0 0362
+ò "
+'o 8,11 0 0363
+ó "
+^o 8,11 0 0364
+ô "
+~o 8,10 0 0365
+õ "
+:o 8,10 0 0366
+ö "
+di 8,8 0 0367
+÷ "
+/o 8,7 0 0370
+ø "
+`u 10,11 0 0371
+ù "
+'u 10,11 0 0372
+ú "
+^u 10,11 0 0373
+û "
+:u 10,10 0 0374
+ü "
+'y 9,11,3 0 0375
+ý "
+Tp 8,11,3 0 0376
+þ "
+:y 9,10,3 0 0377
+ÿ "
diff --git a/font/devX100/NI b/font/devX100/NI
new file mode 100644
index 00000000..3216f64a
--- /dev/null
+++ b/font/devX100/NI
@@ -0,0 +1,306 @@
+name NI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+" 6,11 0 042
+# 11,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 12,11,1 0 045
+& 11,11 0 046
+' 4,11 0 047
+( 5,11,2 0 050
+) 5,11,2 0 051
+* 6,11 0 052
++ 8,8 0 053
+, 4,2,2 0 054
+\- 9,5 0 055
+. 4,2 0 056
+/ 9,11,3 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 9,8 0 074
+= 8,6 0 075
+eq "
+> 9,8 0 076
+? 6,11 0 077
+@ 12,11 0 0100
+at "
+A 11,11 0 0101
+B 9,11 0 0102
+C 10,11 0 0103
+D 11,11 0 0104
+E 9,11 0 0105
+F 8,11 0 0106
+G 10,11 0 0107
+H 11,11 0 0110
+I 7,11 0 0111
+J 8,11 0 0112
+K 10,11 0 0113
+L 9,11 0 0114
+M 14,11 0 0115
+N 12,11 0 0116
+O 10,11 0 0117
+P 10,11 0 0120
+Q 10,11,2 0 0121
+R 11,11 0 0122
+S 10,11 0 0123
+T 10,11 0 0124
+U 12,11 0 0125
+V 10,11 0 0126
+W 13,11 0 0127
+X 10,11 0 0130
+Y 9,11 0 0131
+Z 10,11 0 0132
+[ 6,11,2 0 0133
+lB "
+\ 8,11 0 0134
+rs "
+] 6,11,2 0 0135
+rB "
+^ 6,11 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 4,11 0 0140
+oq "
+a 9,7 0 0141
+b 7,11 0 0142
+c 6,7 0 0143
+d 9,11 0 0144
+e 6,7 0 0145
+f 5,11,3 0 0146
+g 7,8,3 0 0147
+h 9,11 0 0150
+i 4,11 0 0151
+j 4,11,3 0 0152
+k 8,11 0 0153
+l 4,11 0 0154
+m 14,7 0 0155
+n 9,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 8,7,3 0 0161
+r 7,7 0 0162
+s 7,7 0 0163
+t 5,9 0 0164
+u 9,7 0 0165
+v 7,7 0 0166
+w 11,7 0 0167
+x 8,7 0 0170
+y 7,7,3 0 0171
+z 8,7 0 0172
+{ 6,11,2 0 0173
+lC "
+| 9,11 0 0174
+or "
+ba "
+} 6,11,2 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241
+¡ "
+ct 8,9,2 0 0242
+¢ "
+Po 9,11 0 0243
+£ "
+Cs 8,9 0 0244
+¤ "
+Ye 9,11 0 0245
+¥ "
+bb 8,11 0 0246
+¦ "
+sc 7,11,2 0 0247
+§ "
+ad 7,10 0 0250
+¨ "
+co 13,11 0 0251
+© "
+Of 6,11 0 0252
+ª "
+Fo 8,7 0 0253
+« "
+no 8,6 0 0254
+¬ "
+- 5,5 0 0255
+hy "
+­ "
+rg 13,11 0 0256
+® "
+a- 6,9 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 8,8 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 4,11 0 0264
+´ "
+µ 9,7,3 0 0265
+ps 9,11 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 6,11 0 0272
+º "
+Fc 8,7 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 6,8,3 0 0277
+¿ "
+`A 11,14 0 0300
+À "
+'A 11,14 0 0301
+Á "
+^A 11,14 0 0302
+Â "
+~A 11,14 0 0303
+Ã "
+:A 11,14 0 0304
+Ä "
+oA 11,14 0 0305
+Å "
+AE 14,11 0 0306
+Æ "
+,C 10,11,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,14 0 0313
+Ë "
+`I 7,14 0 0314
+Ì "
+'I 7,14 0 0315
+Í "
+^I 7,14 0 0316
+Î "
+:I 7,14 0 0317
+Ï "
+-D 11,11 0 0320
+Ð "
+~N 12,14 0 0321
+Ñ "
+`O 10,14 0 0322
+Ò "
+'O 10,14 0 0323
+Ó "
+^O 10,14 0 0324
+Ô "
+~O 10,14 0 0325
+Õ "
+:O 10,14 0 0326
+Ö "
+mu 8,8 0 0327
+× "
+/O 10,11 0 0330
+Ø "
+`U 12,14 0 0331
+Ù "
+'U 12,14 0 0332
+Ú "
+^U 12,14 0 0333
+Û "
+:U 12,14 0 0334
+Ü "
+'Y 9,14 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 8,11,3 0 0337
+ß "
+`a 9,11 0 0340
+à "
+'a 9,11 0 0341
+á "
+^a 9,11 0 0342
+â "
+~a 9,10 0 0343
+ã "
+:a 9,10 0 0344
+ä "
+oa 9,11 0 0345
+å "
+ae 10,7 0 0346
+æ "
+,c 6,7,3 0 0347
+ç "
+`e 6,11 0 0350
+è "
+'e 6,11 0 0351
+é "
+^e 6,11 0 0352
+ê "
+:e 6,10 0 0353
+ë "
+`i 4,11 0 0354
+ì "
+'i 4,11 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,10 0 0357
+ï "
+Sd 7,11 0 0360
+ð "
+~n 9,10 0 0361
+ñ "
+`o 7,11 0 0362
+ò "
+'o 7,11 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,10 0 0366
+ö "
+di 8,8 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 9,11 0 0371
+ù "
+'u 9,11 0 0372
+ú "
+^u 9,11 0 0373
+û "
+:u 9,10 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 7,11,3 0 0376
+þ "
+:y 7,10,3 0 0377
+ÿ "
diff --git a/font/devX100/NR b/font/devX100/NR
new file mode 100644
index 00000000..8e6717ee
--- /dev/null
+++ b/font/devX100/NR
@@ -0,0 +1,306 @@
+name NR
+spacewidth 4
+charset
+--- 4,1 0 040
+! 3,11 0 041
+" 5,11 0 042
+# 8,11 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 12,11 0 045
+& 13,11 0 046
+' 4,11 0 047
+( 5,11,2 0 050
+) 6,11,2 0 051
+* 7,11 0 052
++ 9,7 0 053
+, 4,2,2 0 054
+\- 9,4 0 055
+. 4,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 10,7 0 074
+= 9,6 0 075
+eq "
+> 10,7 0 076
+? 6,11 0 077
+@ 13,11 0 0100
+at "
+A 10,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 11,11 0 0104
+E 10,11 0 0105
+F 10,11 0 0106
+G 11,11 0 0107
+H 12,11 0 0110
+I 6,11 0 0111
+J 7,11 0 0112
+K 11,11 0 0113
+L 10,11 0 0114
+M 16,11 0 0115
+N 13,11 0 0116
+O 11,11 0 0117
+P 10,11 0 0120
+Q 11,11,2 0 0121
+R 11,11 0 0122
+S 8,11 0 0123
+T 10,11 0 0124
+U 13,11 0 0125
+V 10,11 0 0126
+W 16,11 0 0127
+X 13,11 0 0130
+Y 10,11 0 0131
+Z 9,11 0 0132
+[ 4,11,2 0 0133
+lB "
+\ 8,11 0 0134
+rs "
+] 4,11,2 0 0135
+rB "
+^ 7,11 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 4,11 0 0140
+oq "
+a 8,7 0 0141
+b 7,11 0 0142
+c 7,7 0 0143
+d 8,11 0 0144
+e 7,7 0 0145
+f 5,11 0 0146
+g 8,7,3 0 0147
+h 9,11 0 0150
+i 4,10 0 0151
+j 4,10,3 0 0152
+k 9,11 0 0153
+l 4,11 0 0154
+m 14,7 0 0155
+n 9,7 0 0156
+o 7,7 0 0157
+p 8,7,3 0 0160
+q 7,7,3 0 0161
+r 7,7 0 0162
+s 6,7 0 0163
+t 5,9 0 0164
+u 9,7 0 0165
+v 8,7 0 0166
+w 12,7 0 0167
+x 8,7 0 0170
+y 8,7,3 0 0171
+z 7,7 0 0172
+{ 4,11,2 0 0173
+lC "
+| 9,11 0 0174
+or "
+ba "
+} 5,11,2 0 0175
+rC "
+~ 9,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241
+¡ "
+ct 8,9,2 0 0242
+¢ "
+Po 8,11 0 0243
+£ "
+Cs 8,9 0 0244
+¤ "
+Ye 8,11 0 0245
+¥ "
+bb 9,11 0 0246
+¦ "
+sc 7,11,2 0 0247
+§ "
+ad 6,10 0 0250
+¨ "
+co 14,11 0 0251
+© "
+Of 6,11 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 9,5 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 14,11 0 0256
+® "
+a- 5,9 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 9,7 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 9,7,3 0 0265
+ps 9,11,2 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,1,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 5,11 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 6,8,3 0 0277
+¿ "
+`A 10,14 0 0300
+À "
+'A 10,14 0 0301
+Á "
+^A 10,14 0 0302
+Â "
+~A 10,14 0 0303
+Ã "
+:A 10,13 0 0304
+Ä "
+oA 10,14 0 0305
+Å "
+AE 15,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 10,14 0 0310
+È "
+'E 10,14 0 0311
+É "
+^E 10,14 0 0312
+Ê "
+:E 10,14 0 0313
+Ë "
+`I 6,14 0 0314
+Ì "
+'I 6,14 0 0315
+Í "
+^I 6,14 0 0316
+Î "
+:I 6,14 0 0317
+Ï "
+-D 11,11 0 0320
+Ð "
+~N 13,14 0 0321
+Ñ "
+`O 11,14 0 0322
+Ò "
+'O 11,14 0 0323
+Ó "
+^O 11,14 0 0324
+Ô "
+~O 11,14 0 0325
+Õ "
+:O 11,14 0 0326
+Ö "
+mu 9,7 0 0327
+× "
+/O 11,11 0 0330
+Ø "
+`U 13,14 0 0331
+Ù "
+'U 13,14 0 0332
+Ú "
+^U 13,14 0 0333
+Û "
+:U 13,14 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 8,11 0 0337
+ß "
+`a 8,11 0 0340
+à "
+'a 8,11 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,10 0 0343
+ã "
+:a 8,10 0 0344
+ä "
+oa 8,11 0 0345
+å "
+ae 12,7 0 0346
+æ "
+,c 7,7,3 0 0347
+ç "
+`e 7,11 0 0350
+è "
+'e 7,11 0 0351
+é "
+^e 7,11 0 0352
+ê "
+:e 7,10 0 0353
+ë "
+`i 4,11 0 0354
+ì "
+'i 4,11 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,10 0 0357
+ï "
+Sd 7,11 0 0360
+ð "
+~n 9,10 0 0361
+ñ "
+`o 7,11 0 0362
+ò "
+'o 7,11 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,10 0 0366
+ö "
+di 9,7 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 9,11 0 0371
+ù "
+'u 9,11 0 0372
+ú "
+^u 9,11 0 0373
+û "
+:u 9,10 0 0374
+ü "
+'y 8,11,3 0 0375
+ý "
+Tp 8,11,3 0 0376
+þ "
+:y 8,10,3 0 0377
+ÿ "
diff --git a/font/devX100/S b/font/devX100/S
new file mode 100644
index 00000000..59af889e
--- /dev/null
+++ b/font/devX100/S
@@ -0,0 +1,226 @@
+name S
+special
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,10 0 041
+fa 9,10 0 042
+# 7,10 0 043
+sh "
+te 8,10 0 044
+% 12,10 0 045
+& 11,10 0 046
+st 6,7 0 047
+( 5,10,3 0 050
+) 5,10,3 0 051
+** 7,8 0 052
++ 8,7 0 053
+pl "
+, 3,2,2 0 054
+\- 8,4 0 055
+mi "
+. 3,2 0 056
+/ 4,10 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 8,7 0 074
+= 8,5 0 075
+eq "
+> 8,7 0 076
+? 6,10 0 077
+=~ 8,7 0 0100
+*A 11,10 0 0101
+*B 9,10 0 0102
+*X 11,10 0 0103
+*D 9,10 0 0104
+*E 9,10 0 0105
+*F 11,10 0 0106
+*G 9,10 0 0107
+*Y 11,10 0 0110
+*I 5,10 0 0111
++h 9,10 0 0112
+*K 10,10 0 0113
+*L 10,10 0 0114
+*M 13,10 0 0115
+*N 11,10 0 0116
+*O 10,10 0 0117
+*P 11,10 0 0120
+*H 10,10 0 0121
+*R 8,10 0 0122
+*S 9,10 0 0123
+*T 9,10 0 0124
+--- 9,10 0 0125
+ts 7,7,3 0 0126
+*W 11,10 0 0127
+*C 9,10 0 0130
+*Q 11,10 0 0131
+*Z 9,10 0 0132
+[ 5,10,3 0 0133
+lB "
+tf 10,7 0 0134
+3d "
+] 5,10,3 0 0135
+rB "
+pp 10,10 0 0136
+_ 7,0,3 0 0137
+radicalex 7,12 0 0140
+*a 9,7 0 0141
+*b 8,11,3 0 0142
+*x 8,7,3 0 0143
+*d 7,11 0 0144
+*e 6,7 0 0145
+*f 9,10,3 0 0146
+*g 6,7,3 0 0147
+*y 8,7,3 0 0150
+*i 5,7 0 0151
++f 9,7,3 0 0152
+*k 8,7 0 0153
+*l 8,10 0 0154
+*m 8,7,2 0 0155
+µ "
+*n 8,7 0 0156
+*o 8,7 0 0157
+*p 8,7 0 0160
+*h 7,10 0 0161
+*r 8,7,3 0 0162
+*s 8,7 0 0163
+*t 6,7 0 0164
+*u 8,7 0 0165
++p 11,8 0 0166
+*w 11,7 0 0167
+*c 7,12,3 0 0170
+*q 9,7,3 0 0171
+*z 7,11,3 0 0172
+lC 7,10,3 0 0173
+{ "
+ba 3,10,3 0 0174
+or "
+| "
+rC 7,10,3 0 0175
+} "
+ap 8,5 0 0176
+*U 9,10 0 0241
+fm 4,10 0 0242
+<= 8,9 0 0243
+f/ 4,10 0 0244
+if 10,6 0 0245
+Fn 7,10,3 0 0246
+CL 11,7 0 0247
+DI 11,7 0 0250
+HE 11,7 0 0251
+SP 11,7 0 0252
+<> 15,7 0 0253
+<- 14,7 0 0254
+ua 9,12,3 0 0255
+arrowverttp "
+-> 14,7 0 0256
+da 9,12,3 0 0257
+arrowvertbt "
+de 6,10 0 0260
+° "
++- 8,9 0 0261
+± "
+sd 6,10 0 0262
+>= 8,9 0 0263
+mu 8,7 0 0264
+× "
+pt 10,6 0 0265
+pd 7,11 0 0266
+bu 7,6 0 0267
+di 8,7 0 0270
+÷ "
+!= 8,7 0 0271
+== 8,6 0 0272
+~= 8,7 0 0273
+~~ "
+--- 15,2 0 0274
+arrowvertex 9,12,3 0 0275
+an 15,4 0 0276
+CR 10,9 0 0277
+Ah 12,10 0 0300
+Im 10,11,1 0 0301
+Re 12,11 0 0302
+wp 12,9,3 0 0303
+c* 11,9 0 0304
+c+ 11,9 0 0305
+es 12,11 0 0306
+ca 10,7 0 0307
+cu 10,7 0 0310
+sp 10,7 0 0311
+ip 10,7,2 0 0312
+--- 10,8,1 0 0313
+sb 10,7 0 0314
+ib 10,7,2 0 0315
+mo 10,7 0 0316
+nm 10,8,1 0 0317
+/_ 11,10 0 0320
+gr 10,11 0 0321
+rg 12,10 0 0322
+co 12,10 0 0323
+tm 11,10 0 0324
+--- 12,11,1 0 0325
+sr 8,12 0 0326
+md 4,5 0 0327
+no 10,5 0 0330
+¬ "
+AN 9,7 0 0331
+OR 9,7 0 0332
+hA 15,7 0 0333
+lA 14,7 0 0334
+uA 9,12 0 0335
+rA 14,7 0 0336
+dA 9,12 0 0337
+lz 7,11 0 0340
+la 5,12,3 0 0341
+--- 12,10 0 0342
+--- 12,10 0 0343
+--- 11,10 0 0344
+--- 10,11,1 0 0345
+parenlefttp 6,12,3 0 0346
+parenleftex 6,12,3 0 0347
+parenleftbt 6,12,3 0 0350
+bracketlefttp 6,12,3 0 0351
+lc "
+bracketleftex 6,12,3 0 0352
+bracketleftbt 6,12,3 0 0353
+lf "
+bracelefttp 7,12,3 0 0354
+lt "
+braceleftmid 7,12,3 0 0355
+lk "
+braceleftbt 7,12,3 0 0356
+lb "
+bracerightex 7,12,3 0 0357
+braceleftex "
+bv "
+--- 12,12 0 0360
+ra 5,12,3 0 0361
+is 4,12,1 0 0362
+--- 10,12,3 0 0363
+--- 10,12,3 0 0364
+--- 10,12,3 0 0365
+parenrighttp 6,12,3 0 0366
+parenrightex 6,12,3 0 0367
+parenrightbt 6,12,3 0 0370
+bracketrighttp 6,12,3 0 0371
+rc "
+bracketrightex 6,12,3 0 0372
+bracketrightbt 6,12,3 0 0373
+rf "
+bracerighttp 7,12,3 0 0374
+rt "
+bracerightmid 7,12,3 0 0375
+rk "
+bracerightbt 7,12,3 0 0376
+rb "
diff --git a/font/devX100/TB b/font/devX100/TB
new file mode 100644
index 00000000..ebafbac7
--- /dev/null
+++ b/font/devX100/TB
@@ -0,0 +1,306 @@
+name TB
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,10 0 041
+" 7,10 0 042
+# 7,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 14,10 0 045
+& 12,10 0 046
+' 4,10 0 047
+( 5,10,3 0 050
+) 5,10,3 0 051
+* 7,10 0 052
++ 8,7 0 053
+, 3,2,2 0 054
+\- 9,4 0 055
+. 3,2 0 056
+/ 4,10 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 8,7 0 074
+= 8,5 0 075
+eq "
+> 8,7 0 076
+? 7,10 0 077
+@ 14,10,2 0 0100
+at "
+A 10,10 0 0101
+B 9,10 0 0102
+C 10,10 0 0103
+D 10,10 0 0104
+E 9,10 0 0105
+F 8,10 0 0106
+G 11,10 0 0107
+H 11,10 0 0110
+I 5,10 0 0111
+J 7,10,1 0 0112
+K 11,10 0 0113
+L 9,10 0 0114
+M 13,10 0 0115
+N 10,10 0 0116
+O 11,10 0 0117
+P 9,10 0 0120
+Q 11,10,3 0 0121
+R 10,10 0 0122
+S 8,10 0 0123
+T 9,10 0 0124
+U 10,10 0 0125
+V 10,10 0 0126
+W 14,10 0 0127
+X 10,10 0 0130
+Y 10,10 0 0131
+Z 9,10 0 0132
+[ 5,10,3 0 0133
+lB "
+\ 4,10 0 0134
+rs "
+] 5,10,3 0 0135
+rB "
+^ 8,10 0 0136
+a^ "
+ha "
+_ 7,0,3 0 0137
+` 4,10 0 0140
+oq "
+a 7,7 0 0141
+b 8,10 0 0142
+c 6,7 0 0143
+d 7,10 0 0144
+e 6,7 0 0145
+f 5,10 0 0146
+g 7,7,3 0 0147
+h 8,10 0 0150
+i 4,10 0 0151
+j 4,10,3 0 0152
+k 8,10 0 0153
+l 4,10 0 0154
+m 12,7 0 0155
+n 8,7 0 0156
+o 7,7 0 0157
+p 8,7,3 0 0160
+q 7,7,3 0 0161
+r 6,7 0 0162
+s 6,7 0 0163
+t 5,9 0 0164
+u 7,7 0 0165
+v 7,7 0 0166
+w 10,7 0 0167
+x 7,7 0 0170
+y 7,7,3 0 0171
+z 6,7 0 0172
+{ 7,10,3 0 0173
+lC "
+| 3,10,2 0 0174
+or "
+ba "
+} 7,10,3 0 0175
+rC "
+~ 8,7 0 0176
+a~ "
+ap "
+ti "
+r! 4,7,3 0 0241
+¡ "
+ct 7,9,2 0 0242
+¢ "
+Po 8,10 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 8,10 0 0245
+¥ "
+bb 3,10,2 0 0246
+¦ "
+sc 7,10,2 0 0247
+§ "
+ad 5,10 0 0250
+¨ "
+co 12,10 0 0251
+© "
+Of 5,10 0 0252
+ª "
+Fo 9,6 0 0253
+« "
+no 9,5 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 12,10 0 0256
+® "
+a- 5,9 0 0257
+¯ "
+de 6,10 0 0260
+° "
++- 8,9 0 0261
+± "
+S2 4,10 0 0262
+² "
+S3 4,10 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 8,10,3 0 0266
+¶ "
+md 4,6 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 4,10 0 0271
+¹ "
+Om 5,10 0 0272
+º "
+Fc 9,6 0 0273
+» "
+14 10,10 0 0274
+¼ "
+12 10,10 0 0275
+½ "
+34 10,10 0 0276
+¾ "
+r? 7,7,3 0 0277
+¿ "
+`A 10,14 0 0300
+À "
+'A 10,14 0 0301
+Á "
+^A 10,14 0 0302
+Â "
+~A 10,13 0 0303
+Ã "
+:A 10,13 0 0304
+Ä "
+oA 10,14 0 0305
+Å "
+AE 14,10 0 0306
+Æ "
+,C 10,10,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,13 0 0313
+Ë "
+`I 5,14 0 0314
+Ì "
+'I 5,14 0 0315
+Í "
+^I 5,14 0 0316
+Î "
+:I 5,13 0 0317
+Ï "
+-D 11,10 0 0320
+Ð "
+~N 10,13 0 0321
+Ñ "
+`O 11,14 0 0322
+Ò "
+'O 11,14 0 0323
+Ó "
+^O 11,14 0 0324
+Ô "
+~O 11,13 0 0325
+Õ "
+:O 11,13 0 0326
+Ö "
+mu 8,7 0 0327
+× "
+/O 11,11,1 0 0330
+Ø "
+`U 10,14 0 0331
+Ù "
+'U 10,14 0 0332
+Ú "
+^U 10,14 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 9,10 0 0336
+Þ "
+ss 8,10 0 0337
+ß "
+`a 7,11 0 0340
+à "
+'a 7,11 0 0341
+á "
+^a 7,11 0 0342
+â "
+~a 7,10 0 0343
+ã "
+:a 7,10 0 0344
+ä "
+oa 7,11 0 0345
+å "
+ae 11,7 0 0346
+æ "
+,c 7,7,3 0 0347
+ç "
+`e 7,11 0 0350
+è "
+'e 7,11 0 0351
+é "
+^e 7,11 0 0352
+ê "
+:e 7,10 0 0353
+ë "
+`i 4,11 0 0354
+ì "
+'i 4,11 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,10 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 8,10 0 0361
+ñ "
+`o 7,11 0 0362
+ò "
+'o 7,11 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,10 0 0366
+ö "
+di 8,7 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 7,11 0 0371
+ù "
+'u 7,11 0 0372
+ú "
+^u 7,11 0 0373
+û "
+:u 7,10 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 8,10,3 0 0376
+þ "
+:y 7,10,3 0 0377
+ÿ "
diff --git a/font/devX100/TBI b/font/devX100/TBI
new file mode 100644
index 00000000..2297b4b2
--- /dev/null
+++ b/font/devX100/TBI
@@ -0,0 +1,306 @@
+name TBI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 7,10 0 041
+" 7,10 0 042
+# 8,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 14,10 0 045
+& 10,10 0 046
+' 5,10 0 047
+( 6,10,3 0 050
+) 6,10,3 0 051
+* 7,10 0 052
++ 9,7 0 053
+, 4,2,2 0 054
+\- 9,4 0 055
+. 3,2 0 056
+/ 6,10 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 5,7 0 072
+; 4,7,2 0 073
+< 8,6 0 074
+= 10,5 0 075
+eq "
+> 8,6 0 076
+? 8,10 0 077
+@ 15,10,2 0 0100
+at "
+A 9,10 0 0101
+B 9,10 0 0102
+C 9,10 0 0103
+D 10,10 0 0104
+E 10,10 0 0105
+F 9,10 0 0106
+G 10,10 0 0107
+H 11,10 0 0110
+I 5,10 0 0111
+J 7,10,1 0 0112
+K 11,10 0 0113
+L 9,10 0 0114
+M 13,10 0 0115
+N 11,10 0 0116
+O 10,10 0 0117
+P 9,10 0 0120
+Q 10,10,3 0 0121
+R 10,10 0 0122
+S 8,10 0 0123
+T 10,10 0 0124
+U 10,10 0 0125
+V 10,10 0 0126
+W 13,10 0 0127
+X 9,10 0 0130
+Y 8,10 0 0131
+Z 8,10 0 0132
+[ 6,10,3 0 0133
+lB "
+\ 6,10 0 0134
+rs "
+] 5,10,3 0 0135
+rB "
+^ 8,10 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 5,10 0 0140
+oq "
+a 8,7 0 0141
+b 7,10 0 0142
+c 6,7 0 0143
+d 7,10 0 0144
+e 7,7 0 0145
+f 5,10,3 0 0146
+g 6,7,3 0 0147
+h 8,10 0 0150
+i 4,10 0 0151
+j 4,10,3 0 0152
+k 7,10 0 0153
+l 4,10 0 0154
+m 11,7 0 0155
+n 8,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 6,7 0 0162
+s 6,7 0 0163
+t 4,9 0 0164
+u 7,7 0 0165
+v 6,7 0 0166
+w 9,7 0 0167
+x 6,7 0 0170
+y 6,7,3 0 0171
+z 6,7 0 0172
+{ 7,10,3 0 0173
+lC "
+| 4,10 0 0174
+or "
+ba "
+} 7,10,3 0 0175
+rC "
+~ 10,5 0 0176
+a~ "
+ap "
+ti "
+r! 7,7,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 7,10 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 7,10 0 0245
+¥ "
+bb 4,10 0 0246
+¦ "
+sc 8,10,3 0 0247
+§ "
+ad 6,9 0 0250
+¨ "
+co 12,10 0 0251
+© "
+Of 6,10 0 0252
+ª "
+Fo 8,6 0 0253
+« "
+no 9,5 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 12,10 0 0256
+® "
+a- 6,9 0 0257
+¯ "
+de 6,10 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 4,10 0 0262
+² "
+S3 4,10 0 0263
+³ "
+aa 6,10 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 8,10,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 4,10 0 0271
+¹ "
+Om 6,10 0 0272
+º "
+Fc 8,6 0 0273
+» "
+14 10,10 0 0274
+¼ "
+12 10,10 0 0275
+½ "
+34 10,10 0 0276
+¾ "
+r? 8,7,3 0 0277
+¿ "
+`A 9,13 0 0300
+À "
+'A 9,13 0 0301
+Á "
+^A 9,13 0 0302
+Â "
+~A 9,13 0 0303
+Ã "
+:A 9,13 0 0304
+Ä "
+oA 9,13 0 0305
+Å "
+AE 14,10 0 0306
+Æ "
+,C 9,10,3 0 0307
+Ç "
+`E 10,13 0 0310
+È "
+'E 10,13 0 0311
+É "
+^E 10,13 0 0312
+Ê "
+:E 10,13 0 0313
+Ë "
+`I 5,13 0 0314
+Ì "
+'I 5,13 0 0315
+Í "
+^I 5,13 0 0316
+Î "
+:I 5,13 0 0317
+Ï "
+-D 10,10 0 0320
+Ð "
+~N 11,13 0 0321
+Ñ "
+`O 10,13 0 0322
+Ò "
+'O 10,13 0 0323
+Ó "
+^O 10,13 0 0324
+Ô "
+~O 10,13 0 0325
+Õ "
+:O 10,13 0 0326
+Ö "
+mu 9,7 0 0327
+× "
+/O 10,11,1 0 0330
+Ø "
+`U 10,13 0 0331
+Ù "
+'U 10,13 0 0332
+Ú "
+^U 10,13 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 8,13 0 0335
+Ý "
+TP 9,10 0 0336
+Þ "
+ss 7,10,3 0 0337
+ß "
+`a 8,10 0 0340
+à "
+'a 8,10 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,10 0 0343
+ã "
+:a 8,10 0 0344
+ä "
+oa 8,11 0 0345
+å "
+ae 11,7 0 0346
+æ "
+,c 6,7,3 0 0347
+ç "
+`e 7,10 0 0350
+è "
+'e 7,10 0 0351
+é "
+^e 7,11 0 0352
+ê "
+:e 7,10 0 0353
+ë "
+`i 4,10 0 0354
+ì "
+'i 4,10 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,10 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 8,10 0 0361
+ñ "
+`o 7,10 0 0362
+ò "
+'o 7,10 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,10 0 0366
+ö "
+di 9,7 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 7,10 0 0371
+ù "
+'u 7,10 0 0372
+ú "
+^u 7,11 0 0373
+û "
+:u 7,10 0 0374
+ü "
+'y 6,10,2 0 0375
+ý "
+Tp 7,10,3 0 0376
+þ "
+:y 6,10,2 0 0377
+ÿ "
diff --git a/font/devX100/TI b/font/devX100/TI
new file mode 100644
index 00000000..80a2f1c4
--- /dev/null
+++ b/font/devX100/TI
@@ -0,0 +1,306 @@
+name TI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 5,10 0 041
+" 6,10 0 042
+# 7,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 12,10 0 045
+& 11,10 0 046
+' 5,10 0 047
+( 5,10,3 0 050
+) 5,10,3 0 051
+* 7,10 0 052
++ 10,7 0 053
+, 4,2,1 0 054
+\- 9,4 0 055
+. 3,2 0 056
+/ 4,10 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 4,7 0 072
+; 4,7,1 0 073
+< 10,7,1 0 074
+= 10,5 0 075
+eq "
+> 10,7,1 0 076
+? 7,10 0 077
+@ 13,10,3 0 0100
+at "
+A 9,10 0 0101
+B 8,10 0 0102
+C 9,10 0 0103
+D 10,10 0 0104
+E 9,10 0 0105
+F 9,10 0 0106
+G 10,10 0 0107
+H 10,10 0 0110
+I 5,10 0 0111
+J 6,10 0 0112
+K 10,10 0 0113
+L 8,10 0 0114
+M 12,10 0 0115
+N 11,10 0 0116
+O 10,10 0 0117
+P 9,10 0 0120
+Q 10,10,3 0 0121
+R 9,10 0 0122
+S 7,10 0 0123
+T 8,10 0 0124
+U 10,10 0 0125
+V 9,10 0 0126
+W 11,10 0 0127
+X 9,10 0 0130
+Y 8,10 0 0131
+Z 8,10 0 0132
+[ 6,10,3 0 0133
+lB "
+\ 4,10 0 0134
+rs "
+] 6,10,3 0 0135
+rB "
+^ 6,10 0 0136
+a^ "
+ha "
+_ 7,0,4 0 0137
+` 5,10 0 0140
+oq "
+a 7,7 0 0141
+b 7,10 0 0142
+c 6,7 0 0143
+d 7,10 0 0144
+e 7,7 0 0145
+f 5,10,3 0 0146
+g 6,7,3 0 0147
+h 7,10 0 0150
+i 4,10 0 0151
+j 4,10,3 0 0152
+k 7,10 0 0153
+l 4,10 0 0154
+m 10,7 0 0155
+n 7,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 5,7 0 0162
+s 6,7 0 0163
+t 5,9 0 0164
+u 7,7 0 0165
+v 6,7 0 0166
+w 9,7 0 0167
+x 7,7 0 0170
+y 7,7,3 0 0171
+z 6,7 0 0172
+{ 6,10,3 0 0173
+lC "
+| 4,10,3 0 0174
+or "
+ba "
+} 6,10,3 0 0175
+rC "
+~ 8,5 0 0176
+a~ "
+ap "
+ti "
+r! 6,7,3 0 0241
+¡ "
+ct 7,9,2 0 0242
+¢ "
+Po 7,10 0 0243
+£ "
+Cs 7,8 0 0244
+¤ "
+Ye 7,10 0 0245
+¥ "
+bb 4,10,3 0 0246
+¦ "
+sc 7,11,2 0 0247
+§ "
+ad 5,10 0 0250
+¨ "
+co 12,10 0 0251
+© "
+Of 5,10 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 12,10 0 0256
+® "
+a- 5,10 0 0257
+¯ "
+de 6,10 0 0260
+° "
++- 10,9 0 0261
+± "
+S2 4,10 0 0262
+² "
+S3 4,10 0 0263
+³ "
+aa 4,10 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 8,10,3 0 0266
+¶ "
+md 4,4 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 4,10 0 0271
+¹ "
+Om 5,10 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 10,10 0 0274
+¼ "
+12 10,10 0 0275
+½ "
+34 10,10 0 0276
+¾ "
+r? 7,7,3 0 0277
+¿ "
+`A 9,13 0 0300
+À "
+'A 9,13 0 0301
+Á "
+^A 9,13 0 0302
+Â "
+~A 9,13 0 0303
+Ã "
+:A 9,12 0 0304
+Ä "
+oA 9,13 0 0305
+Å "
+AE 13,10 0 0306
+Æ "
+,C 9,10,3 0 0307
+Ç "
+`E 9,13 0 0310
+È "
+'E 9,13 0 0311
+É "
+^E 9,13 0 0312
+Ê "
+:E 9,12 0 0313
+Ë "
+`I 5,13 0 0314
+Ì "
+'I 5,13 0 0315
+Í "
+^I 5,13 0 0316
+Î "
+:I 5,12 0 0317
+Ï "
+-D 10,10 0 0320
+Ð "
+~N 11,13 0 0321
+Ñ "
+`O 10,13 0 0322
+Ò "
+'O 10,13 0 0323
+Ó "
+^O 10,13 0 0324
+Ô "
+~O 10,13 0 0325
+Õ "
+:O 10,12 0 0326
+Ö "
+mu 10,7 0 0327
+× "
+/O 10,11,1 0 0330
+Ø "
+`U 10,13 0 0331
+Ù "
+'U 10,13 0 0332
+Ú "
+^U 10,13 0 0333
+Û "
+:U 10,12 0 0334
+Ü "
+'Y 8,13 0 0335
+Ý "
+TP 9,10 0 0336
+Þ "
+ss 7,10,3 0 0337
+ß "
+`a 7,10 0 0340
+à "
+'a 7,10 0 0341
+á "
+^a 7,11 0 0342
+â "
+~a 7,10 0 0343
+ã "
+:a 7,9 0 0344
+ä "
+oa 7,10 0 0345
+å "
+ae 10,7 0 0346
+æ "
+,c 6,7,3 0 0347
+ç "
+`e 7,10 0 0350
+è "
+'e 7,10 0 0351
+é "
+^e 7,11 0 0352
+ê "
+:e 7,9 0 0353
+ë "
+`i 4,10 0 0354
+ì "
+'i 4,10 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,9 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 7,10 0 0361
+ñ "
+`o 7,10 0 0362
+ò "
+'o 7,10 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,9 0 0366
+ö "
+di 10,7 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 7,10 0 0371
+ù "
+'u 7,10 0 0372
+ú "
+^u 7,11 0 0373
+û "
+:u 7,9 0 0374
+ü "
+'y 7,10,3 0 0375
+ý "
+Tp 7,10,3 0 0376
+þ "
+:y 7,9,3 0 0377
+ÿ "
diff --git a/font/devX100/TR b/font/devX100/TR
new file mode 100644
index 00000000..eafc811b
--- /dev/null
+++ b/font/devX100/TR
@@ -0,0 +1,306 @@
+name TR
+spacewidth 3
+charset
+--- 3,1 0 040
+! 5,10 0 041
+" 6,10 0 042
+# 7,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 12,10 0 045
+& 11,10 0 046
+' 4,10 0 047
+( 5,10,3 0 050
+) 5,10,3 0 051
+* 7,10 0 052
++ 8,7 0 053
+, 4,1,2 0 054
+\- 9,4 0 055
+. 4,1 0 056
+/ 4,10,2 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 8,7 0 074
+= 8,5 0 075
+eq "
+> 8,7 0 076
+? 6,10 0 077
+@ 13,10,2 0 0100
+at "
+A 11,10 0 0101
+B 9,10 0 0102
+C 10,10 0 0103
+D 10,10 0 0104
+E 9,10 0 0105
+F 8,10 0 0106
+G 11,10 0 0107
+H 10,10 0 0110
+I 5,10 0 0111
+J 6,10 0 0112
+K 10,10 0 0113
+L 9,10 0 0114
+M 13,10 0 0115
+N 11,10 0 0116
+O 10,10 0 0117
+P 8,10 0 0120
+Q 10,10,3 0 0121
+R 9,10 0 0122
+S 8,10 0 0123
+T 9,10 0 0124
+U 10,10 0 0125
+V 9,10 0 0126
+W 13,10 0 0127
+X 10,10 0 0130
+Y 9,10 0 0131
+Z 8,10 0 0132
+[ 5,10,3 0 0133
+lB "
+\ 4,10 0 0134
+rs "
+] 5,10,3 0 0135
+rB "
+^ 7,10 0 0136
+a^ "
+ha "
+_ 7,0,3 0 0137
+` 4,10 0 0140
+oq "
+a 7,7 0 0141
+b 7,10 0 0142
+c 7,7 0 0143
+d 7,10 0 0144
+e 7,7 0 0145
+f 4,10 0 0146
+g 7,7,3 0 0147
+h 7,10 0 0150
+i 3,10 0 0151
+j 4,10,3 0 0152
+k 7,10 0 0153
+l 3,10 0 0154
+m 11,7 0 0155
+n 7,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 5,7 0 0162
+s 6,7 0 0163
+t 4,8 0 0164
+u 7,7 0 0165
+v 7,7 0 0166
+w 11,7 0 0167
+x 7,7 0 0170
+y 7,7,3 0 0171
+z 6,7 0 0172
+{ 7,10,3 0 0173
+lC "
+| 3,10 0 0174
+or "
+ba "
+} 7,10,3 0 0175
+rC "
+~ 8,5 0 0176
+a~ "
+ap "
+ti "
+r! 5,7,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 8,10 0 0243
+£ "
+Cs 7,8 0 0244
+¤ "
+Ye 7,10 0 0245
+¥ "
+bb 3,10 0 0246
+¦ "
+sc 7,10,3 0 0247
+§ "
+ad 5,10 0 0250
+¨ "
+co 12,10 0 0251
+© "
+Of 4,10 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 12,10 0 0256
+® "
+a- 4,9 0 0257
+¯ "
+de 6,10 0 0260
+° "
++- 8,7 0 0261
+± "
+S2 4,10 0 0262
+² "
+S3 4,10 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 7,10,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 4,10 0 0271
+¹ "
+Om 5,10 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 10,10 0 0274
+¼ "
+12 10,10 0 0275
+½ "
+34 10,10 0 0276
+¾ "
+r? 6,7,3 0 0277
+¿ "
+`A 11,14 0 0300
+À "
+'A 11,14 0 0301
+Á "
+^A 11,14 0 0302
+Â "
+~A 11,14 0 0303
+Ã "
+:A 11,13 0 0304
+Ä "
+oA 11,14 0 0305
+Å "
+AE 13,10 0 0306
+Æ "
+,C 10,10,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,13 0 0313
+Ë "
+`I 5,14 0 0314
+Ì "
+'I 5,14 0 0315
+Í "
+^I 5,14 0 0316
+Î "
+:I 5,13 0 0317
+Ï "
+-D 10,10 0 0320
+Ð "
+~N 11,14 0 0321
+Ñ "
+`O 10,14 0 0322
+Ò "
+'O 10,14 0 0323
+Ó "
+^O 10,14 0 0324
+Ô "
+~O 10,14 0 0325
+Õ "
+:O 10,13 0 0326
+Ö "
+mu 8,7 0 0327
+× "
+/O 10,11,1 0 0330
+Ø "
+`U 10,14 0 0331
+Ù "
+'U 10,14 0 0332
+Ú "
+^U 10,14 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 9,14 0 0335
+Ý "
+TP 8,10 0 0336
+Þ "
+ss 7,10 0 0337
+ß "
+`a 7,11 0 0340
+à "
+'a 7,11 0 0341
+á "
+^a 7,11 0 0342
+â "
+~a 7,11 0 0343
+ã "
+:a 7,10 0 0344
+ä "
+oa 7,11 0 0345
+å "
+ae 11,7 0 0346
+æ "
+,c 7,7,3 0 0347
+ç "
+`e 7,11 0 0350
+è "
+'e 7,11 0 0351
+é "
+^e 7,11 0 0352
+ê "
+:e 7,10 0 0353
+ë "
+`i 3,11 0 0354
+ì "
+'i 3,11 0 0355
+í "
+^i 3,11 0 0356
+î "
+:i 3,10 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 7,11 0 0361
+ñ "
+`o 7,11 0 0362
+ò "
+'o 7,11 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,11 0 0365
+õ "
+:o 7,10 0 0366
+ö "
+di 8,7 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 7,11 0 0371
+ù "
+'u 7,11 0 0372
+ú "
+^u 7,11 0 0373
+û "
+:u 7,10 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 7,10,3 0 0376
+þ "
+:y 7,10,3 0 0377
+ÿ "
diff --git a/font/devX75-12/CB b/font/devX75-12/CB
new file mode 100644
index 00000000..a5d1baff
--- /dev/null
+++ b/font/devX75-12/CB
@@ -0,0 +1,306 @@
+name CB
+spacewidth 7
+charset
+--- 7,1 0 040
+! 7,9 0 041
+" 7,8 0 042
+# 7,8 0 043
+sh "
+$ 7,10,2 0 044
+Do "
+% 7,8 0 045
+& 7,8 0 046
+' 7,8 0 047
+( 7,9,2 0 050
+) 7,9,2 0 051
+* 7,9 0 052
++ 7,6 0 053
+, 7,2,1 0 054
+\- 7,4 0 055
+. 7,2 0 056
+/ 7,8,2 0 057
+sl "
+0 7,9 0 060
+1 7,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 7,6 0 072
+; 7,6,1 0 073
+< 7,7 0 074
+= 7,5 0 075
+eq "
+> 7,7 0 076
+? 7,8 0 077
+@ 7,8 0 0100
+at "
+A 7,8 0 0101
+B 7,8 0 0102
+C 7,8 0 0103
+D 7,8 0 0104
+E 7,8 0 0105
+F 7,8 0 0106
+G 7,8 0 0107
+H 7,8 0 0110
+I 7,8 0 0111
+J 7,8 0 0112
+K 7,8 0 0113
+L 7,8 0 0114
+M 7,8 0 0115
+N 7,8 0 0116
+O 7,8 0 0117
+P 7,8 0 0120
+Q 7,8,2 0 0121
+R 7,8 0 0122
+S 7,8 0 0123
+T 7,8 0 0124
+U 7,8 0 0125
+V 7,8 0 0126
+W 7,8 0 0127
+X 7,8 0 0130
+Y 7,8 0 0131
+Z 7,8 0 0132
+[ 7,9,2 0 0133
+lB "
+\ 7,8,2 0 0134
+rs "
+] 7,9,2 0 0135
+rB "
+^ 7,8 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 7,8 0 0140
+oq "
+a 7,6 0 0141
+b 7,9 0 0142
+c 7,6 0 0143
+d 7,9 0 0144
+e 7,6 0 0145
+f 7,9 0 0146
+g 7,6,3 0 0147
+h 7,9 0 0150
+i 7,9 0 0151
+j 7,9,3 0 0152
+k 7,9 0 0153
+l 7,9 0 0154
+m 7,6 0 0155
+n 7,6 0 0156
+o 7,6 0 0157
+p 7,6,3 0 0160
+q 7,6,3 0 0161
+r 7,6 0 0162
+s 7,6 0 0163
+t 7,8 0 0164
+u 7,6 0 0165
+v 7,6 0 0166
+w 7,6 0 0167
+x 7,6 0 0170
+y 7,6,3 0 0171
+z 7,6 0 0172
+{ 7,9,2 0 0173
+lC "
+| 7,8,2 0 0174
+or "
+ba "
+} 7,9,2 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 7,6,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 7,8 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 7,8 0 0245
+¥ "
+bb 7,8,2 0 0246
+¦ "
+sc 7,9,1 0 0247
+§ "
+ad 7,9 0 0250
+¨ "
+co 7,8 0 0251
+© "
+Of 7,9 0 0252
+ª "
+Fo 7,5 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 7,4 0 0255
+hy "
+­ "
+rg 7,8 0 0256
+® "
+a- 7,8 0 0257
+¯ "
+de 7,8 0 0260
+° "
++- 7,6 0 0261
+± "
+S2 7,8 0 0262
+² "
+S3 7,8 0 0263
+³ "
+aa 7,9 0 0264
+´ "
+µ 7,6,3 0 0265
+ps 7,9,1 0 0266
+¶ "
+md 7,5 0 0267
+· "
+ac 7,0,3 0 0270
+¸ "
+S1 7,8 0 0271
+¹ "
+Om 7,9 0 0272
+º "
+Fc 7,5 0 0273
+» "
+14 7,9,1 0 0274
+¼ "
+12 7,9,1 0 0275
+½ "
+34 7,9,1 0 0276
+¾ "
+r? 7,6,3 0 0277
+¿ "
+`A 7,11 0 0300
+À "
+'A 7,11 0 0301
+Á "
+^A 7,11 0 0302
+Â "
+~A 7,11 0 0303
+Ã "
+:A 7,10 0 0304
+Ä "
+oA 7,11 0 0305
+Å "
+AE 7,8 0 0306
+Æ "
+,C 7,8,3 0 0307
+Ç "
+`E 7,11 0 0310
+È "
+'E 7,11 0 0311
+É "
+^E 7,11 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 7,11 0 0314
+Ì "
+'I 7,11 0 0315
+Í "
+^I 7,11 0 0316
+Î "
+:I 7,10 0 0317
+Ï "
+-D 7,8 0 0320
+Ð "
+~N 7,11 0 0321
+Ñ "
+`O 7,11 0 0322
+Ò "
+'O 7,11 0 0323
+Ó "
+^O 7,11 0 0324
+Ô "
+~O 7,11 0 0325
+Õ "
+:O 7,10 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 7,8 0 0330
+Ø "
+`U 7,11 0 0331
+Ù "
+'U 7,11 0 0332
+Ú "
+^U 7,11 0 0333
+Û "
+:U 7,10 0 0334
+Ü "
+'Y 7,11 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 7,9 0 0337
+ß "
+`a 7,9 0 0340
+à "
+'a 7,9 0 0341
+á "
+^a 7,9 0 0342
+â "
+~a 7,9 0 0343
+ã "
+:a 7,8 0 0344
+ä "
+oa 7,10 0 0345
+å "
+ae 7,6 0 0346
+æ "
+,c 7,6,3 0 0347
+ç "
+`e 7,9 0 0350
+è "
+'e 7,9 0 0351
+é "
+^e 7,9 0 0352
+ê "
+:e 7,8 0 0353
+ë "
+`i 7,9 0 0354
+ì "
+'i 7,9 0 0355
+í "
+^i 7,9 0 0356
+î "
+:i 7,8 0 0357
+ï "
+Sd 7,9 0 0360
+ð "
+~n 7,9 0 0361
+ñ "
+`o 7,9 0 0362
+ò "
+'o 7,9 0 0363
+ó "
+^o 7,9 0 0364
+ô "
+~o 7,9 0 0365
+õ "
+:o 7,8 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 7,7,1 0 0370
+ø "
+`u 7,9 0 0371
+ù "
+'u 7,9 0 0372
+ú "
+^u 7,9 0 0373
+û "
+:u 7,8 0 0374
+ü "
+'y 7,9,3 0 0375
+ý "
+Tp 7,8,3 0 0376
+þ "
+:y 7,8,3 0 0377
+ÿ "
diff --git a/font/devX75-12/CBI b/font/devX75-12/CBI
new file mode 100644
index 00000000..764eaf77
--- /dev/null
+++ b/font/devX75-12/CBI
@@ -0,0 +1,306 @@
+name CBI
+spacewidth 7
+charset
+--- 7,1 0 040
+! 7,9 0 041
+" 7,8 0 042
+# 7,9 0 043
+sh "
+$ 7,10,2 0 044
+Do "
+% 7,8 0 045
+& 7,8 0 046
+' 7,8 0 047
+( 7,9,2 0 050
+) 7,9,2 0 051
+* 7,8 0 052
++ 7,6 0 053
+, 7,2,1 0 054
+\- 7,4 0 055
+. 7,2 0 056
+/ 7,9,1 0 057
+sl "
+0 7,9 0 060
+1 7,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 7,6 0 072
+; 7,6,1 0 073
+< 7,6 0 074
+= 7,5 0 075
+eq "
+> 7,6 0 076
+? 7,8 0 077
+@ 7,8,1 0 0100
+at "
+A 7,8 0 0101
+B 7,8 0 0102
+C 7,8 0 0103
+D 7,8 0 0104
+E 7,8 0 0105
+F 7,8 0 0106
+G 7,8 0 0107
+H 7,8 0 0110
+I 7,8 0 0111
+J 7,8 0 0112
+K 7,8 0 0113
+L 7,8 0 0114
+M 7,8 0 0115
+N 7,8 0 0116
+O 7,8 0 0117
+P 7,8 0 0120
+Q 7,8,2 0 0121
+R 7,8 0 0122
+S 7,8 0 0123
+T 7,8 0 0124
+U 7,8 0 0125
+V 7,8 0 0126
+W 7,8 0 0127
+X 7,8 0 0130
+Y 7,8 0 0131
+Z 7,8 0 0132
+[ 7,9,2 0 0133
+lB "
+\ 7,9,1 0 0134
+rs "
+] 7,9,2 0 0135
+rB "
+^ 7,8 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 7,8 0 0140
+oq "
+a 7,6 0 0141
+b 7,9 0 0142
+c 7,6 0 0143
+d 7,9 0 0144
+e 7,6 0 0145
+f 7,9 0 0146
+g 7,6,3 0 0147
+h 7,9 0 0150
+i 7,9 0 0151
+j 7,9,3 0 0152
+k 7,9 0 0153
+l 7,9 0 0154
+m 7,6 0 0155
+n 7,6 0 0156
+o 7,6 0 0157
+p 7,6,3 0 0160
+q 7,6,3 0 0161
+r 7,6 0 0162
+s 7,6 0 0163
+t 7,8 0 0164
+u 7,6 0 0165
+v 7,6 0 0166
+w 7,6 0 0167
+x 7,6 0 0170
+y 7,6,3 0 0171
+z 7,6 0 0172
+{ 7,9,2 0 0173
+lC "
+| 7,8,1 0 0174
+or "
+ba "
+} 7,9,2 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 7,6,2 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 7,8 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 7,8 0 0245
+¥ "
+bb 7,8,1 0 0246
+¦ "
+sc 7,9,1 0 0247
+§ "
+ad 7,9 0 0250
+¨ "
+co 7,8 0 0251
+© "
+Of 7,8 0 0252
+ª "
+Fo 7,5 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 7,4 0 0255
+hy "
+­ "
+rg 7,8 0 0256
+® "
+a- 7,8 0 0257
+¯ "
+de 7,8 0 0260
+° "
++- 7,6 0 0261
+± "
+S2 7,8 0 0262
+² "
+S3 7,8 0 0263
+³ "
+aa 7,9 0 0264
+´ "
+µ 7,6,3 0 0265
+ps 7,9,1 0 0266
+¶ "
+md 7,5 0 0267
+· "
+ac 7,0,3 0 0270
+¸ "
+S1 7,8 0 0271
+¹ "
+Om 7,8 0 0272
+º "
+Fc 7,5 0 0273
+» "
+14 7,9 0 0274
+¼ "
+12 7,9 0 0275
+½ "
+34 7,9 0 0276
+¾ "
+r? 7,6,2 0 0277
+¿ "
+`A 7,11 0 0300
+À "
+'A 7,11 0 0301
+Á "
+^A 7,11 0 0302
+Â "
+~A 7,11 0 0303
+Ã "
+:A 7,10 0 0304
+Ä "
+oA 7,11 0 0305
+Å "
+AE 7,8 0 0306
+Æ "
+,C 7,8,3 0 0307
+Ç "
+`E 7,11 0 0310
+È "
+'E 7,11 0 0311
+É "
+^E 7,11 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 7,11 0 0314
+Ì "
+'I 7,11 0 0315
+Í "
+^I 7,11 0 0316
+Î "
+:I 7,10 0 0317
+Ï "
+-D 7,8 0 0320
+Ð "
+~N 7,11 0 0321
+Ñ "
+`O 7,11 0 0322
+Ò "
+'O 7,11 0 0323
+Ó "
+^O 7,11 0 0324
+Ô "
+~O 7,11 0 0325
+Õ "
+:O 7,10 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 7,8 0 0330
+Ø "
+`U 7,11 0 0331
+Ù "
+'U 7,11 0 0332
+Ú "
+^U 7,11 0 0333
+Û "
+:U 7,10 0 0334
+Ü "
+'Y 7,11 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 7,8 0 0337
+ß "
+`a 7,9 0 0340
+à "
+'a 7,9 0 0341
+á "
+^a 7,9 0 0342
+â "
+~a 7,9 0 0343
+ã "
+:a 7,8 0 0344
+ä "
+oa 7,10 0 0345
+å "
+ae 7,6 0 0346
+æ "
+,c 7,6,3 0 0347
+ç "
+`e 7,9 0 0350
+è "
+'e 7,9 0 0351
+é "
+^e 7,9 0 0352
+ê "
+:e 7,8 0 0353
+ë "
+`i 7,9 0 0354
+ì "
+'i 7,9 0 0355
+í "
+^i 7,9 0 0356
+î "
+:i 7,8 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 7,9 0 0361
+ñ "
+`o 7,9 0 0362
+ò "
+'o 7,9 0 0363
+ó "
+^o 7,9 0 0364
+ô "
+~o 7,9 0 0365
+õ "
+:o 7,8 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 7,7,1 0 0370
+ø "
+`u 7,9 0 0371
+ù "
+'u 7,9 0 0372
+ú "
+^u 7,9 0 0373
+û "
+:u 7,8 0 0374
+ü "
+'y 7,9,3 0 0375
+ý "
+Tp 7,8,3 0 0376
+þ "
+:y 7,8,3 0 0377
+ÿ "
diff --git a/font/devX75-12/CI b/font/devX75-12/CI
new file mode 100644
index 00000000..acc9ec86
--- /dev/null
+++ b/font/devX75-12/CI
@@ -0,0 +1,306 @@
+name CI
+spacewidth 7
+charset
+--- 7,1 0 040
+! 7,8 0 041
+" 7,8 0 042
+# 7,8 0 043
+sh "
+$ 7,10,1 0 044
+Do "
+% 7,8 0 045
+& 7,8 0 046
+' 7,8 0 047
+( 7,9,2 0 050
+) 7,9,2 0 051
+* 7,8 0 052
++ 7,6 0 053
+, 7,2,1 0 054
+\- 7,4 0 055
+. 7,1 0 056
+/ 7,8,1 0 057
+sl "
+0 7,9 0 060
+1 7,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 7,5 0 072
+; 7,5,1 0 073
+< 7,7 0 074
+= 7,5 0 075
+eq "
+> 7,7 0 076
+? 7,8 0 077
+@ 7,8 0 0100
+at "
+A 7,8 0 0101
+B 7,8 0 0102
+C 7,8 0 0103
+D 7,8 0 0104
+E 7,8 0 0105
+F 7,8 0 0106
+G 7,8 0 0107
+H 7,8 0 0110
+I 7,8 0 0111
+J 7,8 0 0112
+K 7,8 0 0113
+L 7,8 0 0114
+M 7,8 0 0115
+N 7,8 0 0116
+O 7,8 0 0117
+P 7,8 0 0120
+Q 7,8,2 0 0121
+R 7,8 0 0122
+S 7,8 0 0123
+T 7,8 0 0124
+U 7,8 0 0125
+V 7,8 0 0126
+W 7,8 0 0127
+X 7,8 0 0130
+Y 7,8 0 0131
+Z 7,8 0 0132
+[ 7,9,2 0 0133
+lB "
+\ 7,8,1 0 0134
+rs "
+] 7,9,2 0 0135
+rB "
+^ 7,8 0 0136
+a^ "
+ha "
+_ 7,0,3 0 0137
+` 7,8 0 0140
+oq "
+a 7,6 0 0141
+b 7,9 0 0142
+c 7,6 0 0143
+d 7,9 0 0144
+e 7,6 0 0145
+f 7,9 0 0146
+g 7,6,3 0 0147
+h 7,9 0 0150
+i 7,9 0 0151
+j 7,9,3 0 0152
+k 7,9 0 0153
+l 7,9 0 0154
+m 7,6 0 0155
+n 7,6 0 0156
+o 7,6 0 0157
+p 7,6,3 0 0160
+q 7,6,3 0 0161
+r 7,6 0 0162
+s 7,6 0 0163
+t 7,8 0 0164
+u 7,6 0 0165
+v 7,6 0 0166
+w 7,6 0 0167
+x 7,6 0 0170
+y 7,6,3 0 0171
+z 7,6 0 0172
+{ 7,9,2 0 0173
+lC "
+| 7,8,1 0 0174
+or "
+ba "
+} 7,9,2 0 0175
+rC "
+~ 7,4 0 0176
+a~ "
+ap "
+ti "
+r! 7,6,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 7,8 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 7,8 0 0245
+¥ "
+bb 7,8,2 0 0246
+¦ "
+sc 7,9,1 0 0247
+§ "
+ad 7,8 0 0250
+¨ "
+co 7,8 0 0251
+© "
+Of 7,8 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 7,4 0 0255
+hy "
+­ "
+rg 7,8 0 0256
+® "
+a- 7,8 0 0257
+¯ "
+de 7,8 0 0260
+° "
++- 7,6 0 0261
+± "
+S2 7,8 0 0262
+² "
+S3 7,8 0 0263
+³ "
+aa 7,9 0 0264
+´ "
+µ 7,6,3 0 0265
+ps 7,9,1 0 0266
+¶ "
+md 7,4 0 0267
+· "
+ac 7,0,3 0 0270
+¸ "
+S1 7,8 0 0271
+¹ "
+Om 7,8 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 7,9,1 0 0274
+¼ "
+12 7,9,1 0 0275
+½ "
+34 7,9,1 0 0276
+¾ "
+r? 7,6,2 0 0277
+¿ "
+`A 7,11 0 0300
+À "
+'A 7,11 0 0301
+Á "
+^A 7,11 0 0302
+Â "
+~A 7,11 0 0303
+Ã "
+:A 7,10 0 0304
+Ä "
+oA 7,11 0 0305
+Å "
+AE 7,8 0 0306
+Æ "
+,C 7,8,3 0 0307
+Ç "
+`E 7,11 0 0310
+È "
+'E 7,11 0 0311
+É "
+^E 7,11 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 7,11 0 0314
+Ì "
+'I 7,11 0 0315
+Í "
+^I 7,11 0 0316
+Î "
+:I 7,10 0 0317
+Ï "
+-D 7,8 0 0320
+Ð "
+~N 7,11 0 0321
+Ñ "
+`O 7,11 0 0322
+Ò "
+'O 7,11 0 0323
+Ó "
+^O 7,11 0 0324
+Ô "
+~O 7,11 0 0325
+Õ "
+:O 7,10 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 7,8 0 0330
+Ø "
+`U 7,11 0 0331
+Ù "
+'U 7,11 0 0332
+Ú "
+^U 7,11 0 0333
+Û "
+:U 7,10 0 0334
+Ü "
+'Y 7,11 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 7,9 0 0337
+ß "
+`a 7,9 0 0340
+à "
+'a 7,9 0 0341
+á "
+^a 7,9 0 0342
+â "
+~a 7,9 0 0343
+ã "
+:a 7,8 0 0344
+ä "
+oa 7,10 0 0345
+å "
+ae 7,6 0 0346
+æ "
+,c 7,6,3 0 0347
+ç "
+`e 7,9 0 0350
+è "
+'e 7,9 0 0351
+é "
+^e 7,9 0 0352
+ê "
+:e 7,8 0 0353
+ë "
+`i 7,9 0 0354
+ì "
+'i 7,9 0 0355
+í "
+^i 7,9 0 0356
+î "
+:i 7,8 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 7,9 0 0361
+ñ "
+`o 7,9 0 0362
+ò "
+'o 7,9 0 0363
+ó "
+^o 7,9 0 0364
+ô "
+~o 7,9 0 0365
+õ "
+:o 7,8 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 7,7,1 0 0370
+ø "
+`u 7,9 0 0371
+ù "
+'u 7,9 0 0372
+ú "
+^u 7,9 0 0373
+û "
+:u 7,8 0 0374
+ü "
+'y 7,9,3 0 0375
+ý "
+Tp 7,9,3 0 0376
+þ "
+:y 7,8,3 0 0377
+ÿ "
diff --git a/font/devX75-12/CR b/font/devX75-12/CR
new file mode 100644
index 00000000..666e837b
--- /dev/null
+++ b/font/devX75-12/CR
@@ -0,0 +1,306 @@
+name CR
+spacewidth 7
+charset
+--- 7,1 0 040
+! 7,9 0 041
+" 7,8 0 042
+# 7,8 0 043
+sh "
+$ 7,9,1 0 044
+Do "
+% 7,8 0 045
+& 7,8 0 046
+' 7,8 0 047
+( 7,9,2 0 050
+) 7,9,2 0 051
+* 7,8 0 052
++ 7,6 0 053
+, 7,2,1 0 054
+\- 7,4 0 055
+. 7,1 0 056
+/ 7,9,1 0 057
+sl "
+0 7,9 0 060
+1 7,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 7,5 0 072
+; 7,5,1 0 073
+< 7,7 0 074
+= 7,5 0 075
+eq "
+> 7,7 0 076
+? 7,8 0 077
+@ 7,8 0 0100
+at "
+A 7,8 0 0101
+B 7,8 0 0102
+C 7,8 0 0103
+D 7,8 0 0104
+E 7,8 0 0105
+F 7,8 0 0106
+G 7,8 0 0107
+H 7,8 0 0110
+I 7,8 0 0111
+J 7,8 0 0112
+K 7,8 0 0113
+L 7,8 0 0114
+M 7,8 0 0115
+N 7,8 0 0116
+O 7,8 0 0117
+P 7,8 0 0120
+Q 7,8,1 0 0121
+R 7,8 0 0122
+S 7,8 0 0123
+T 7,8 0 0124
+U 7,8 0 0125
+V 7,8 0 0126
+W 7,8 0 0127
+X 7,8 0 0130
+Y 7,8 0 0131
+Z 7,8 0 0132
+[ 7,9,2 0 0133
+lB "
+\ 7,9,1 0 0134
+rs "
+] 7,9,2 0 0135
+rB "
+^ 7,8 0 0136
+a^ "
+ha "
+_ 7,0,3 0 0137
+` 7,8 0 0140
+oq "
+a 7,6 0 0141
+b 7,9 0 0142
+c 7,6 0 0143
+d 7,9 0 0144
+e 7,6 0 0145
+f 7,9 0 0146
+g 7,6,3 0 0147
+h 7,9 0 0150
+i 7,9 0 0151
+j 7,9,3 0 0152
+k 7,9 0 0153
+l 7,9 0 0154
+m 7,6 0 0155
+n 7,6 0 0156
+o 7,6 0 0157
+p 7,6,3 0 0160
+q 7,6,3 0 0161
+r 7,6 0 0162
+s 7,6 0 0163
+t 7,8 0 0164
+u 7,6 0 0165
+v 7,6 0 0166
+w 7,6 0 0167
+x 7,6 0 0170
+y 7,6,3 0 0171
+z 7,6 0 0172
+{ 7,8,2 0 0173
+lC "
+| 7,8,2 0 0174
+or "
+ba "
+} 7,8,2 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 7,6,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 7,8 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 7,8 0 0245
+¥ "
+bb 7,8,2 0 0246
+¦ "
+sc 7,9,1 0 0247
+§ "
+ad 7,8 0 0250
+¨ "
+co 7,8 0 0251
+© "
+Of 7,8 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 7,4 0 0255
+hy "
+­ "
+rg 7,8 0 0256
+® "
+a- 7,8 0 0257
+¯ "
+de 7,8 0 0260
+° "
++- 7,6 0 0261
+± "
+S2 7,8 0 0262
+² "
+S3 7,8 0 0263
+³ "
+aa 7,9 0 0264
+´ "
+µ 7,6,3 0 0265
+ps 7,9,1 0 0266
+¶ "
+md 7,4 0 0267
+· "
+ac 7,0,3 0 0270
+¸ "
+S1 7,8 0 0271
+¹ "
+Om 7,8 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 7,9,1 0 0274
+¼ "
+12 7,9,1 0 0275
+½ "
+34 7,9,1 0 0276
+¾ "
+r? 7,6,2 0 0277
+¿ "
+`A 7,11 0 0300
+À "
+'A 7,11 0 0301
+Á "
+^A 7,11 0 0302
+Â "
+~A 7,11 0 0303
+Ã "
+:A 7,10 0 0304
+Ä "
+oA 7,11 0 0305
+Å "
+AE 7,8 0 0306
+Æ "
+,C 7,8,3 0 0307
+Ç "
+`E 7,11 0 0310
+È "
+'E 7,11 0 0311
+É "
+^E 7,11 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 7,11 0 0314
+Ì "
+'I 7,11 0 0315
+Í "
+^I 7,11 0 0316
+Î "
+:I 7,10 0 0317
+Ï "
+-D 7,8 0 0320
+Ð "
+~N 7,11 0 0321
+Ñ "
+`O 7,11 0 0322
+Ò "
+'O 7,11 0 0323
+Ó "
+^O 7,11 0 0324
+Ô "
+~O 7,11 0 0325
+Õ "
+:O 7,10 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 7,9,1 0 0330
+Ø "
+`U 7,11 0 0331
+Ù "
+'U 7,11 0 0332
+Ú "
+^U 7,11 0 0333
+Û "
+:U 7,10 0 0334
+Ü "
+'Y 7,11 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 7,9 0 0337
+ß "
+`a 7,9 0 0340
+à "
+'a 7,9 0 0341
+á "
+^a 7,9 0 0342
+â "
+~a 7,9 0 0343
+ã "
+:a 7,8 0 0344
+ä "
+oa 7,9 0 0345
+å "
+ae 7,6 0 0346
+æ "
+,c 7,6,3 0 0347
+ç "
+`e 7,9 0 0350
+è "
+'e 7,9 0 0351
+é "
+^e 7,9 0 0352
+ê "
+:e 7,8 0 0353
+ë "
+`i 7,9 0 0354
+ì "
+'i 7,9 0 0355
+í "
+^i 7,9 0 0356
+î "
+:i 7,8 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 7,9 0 0361
+ñ "
+`o 7,9 0 0362
+ò "
+'o 7,9 0 0363
+ó "
+^o 7,9 0 0364
+ô "
+~o 7,9 0 0365
+õ "
+:o 7,8 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 7,7,1 0 0370
+ø "
+`u 7,9 0 0371
+ù "
+'u 7,9 0 0372
+ú "
+^u 7,9 0 0373
+û "
+:u 7,8 0 0374
+ü "
+'y 7,9,3 0 0375
+ý "
+Tp 7,9,3 0 0376
+þ "
+:y 7,8,3 0 0377
+ÿ "
diff --git a/font/devX75-12/DESC b/font/devX75-12/DESC
new file mode 100644
index 00000000..4793e599
--- /dev/null
+++ b/font/devX75-12/DESC
@@ -0,0 +1,9 @@
+styles R I B BI
+fonts 6 0 0 0 0 0 S
+sizes 8 10 12 14 18 24 0
+res 75
+X11
+hor 1
+vert 1
+unitwidth 12
+postpro gxditview
diff --git a/font/devX75-12/HB b/font/devX75-12/HB
new file mode 100644
index 00000000..b8cbb6ef
--- /dev/null
+++ b/font/devX75-12/HB
@@ -0,0 +1,306 @@
+name HB
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,9 0 041
+" 5,9 0 042
+# 8,8 0 043
+sh "
+$ 7,9,2 0 044
+Do "
+% 12,9 0 045
+& 9,9 0 046
+' 4,9 0 047
+( 6,9,3 0 050
+) 6,9,3 0 051
+* 6,9 0 052
++ 7,6 0 053
+, 4,2,2 0 054
+\- 8,4 0 055
+. 4,2 0 056
+/ 4,9 0 057
+sl "
+0 7,9 0 060
+1 7,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 7,6 0 074
+= 7,5 0 075
+eq "
+> 7,6 0 076
+? 8,9 0 077
+@ 12,9,1 0 0100
+at "
+A 8,9 0 0101
+B 9,9 0 0102
+C 8,9 0 0103
+D 9,9 0 0104
+E 8,9 0 0105
+F 7,9 0 0106
+G 10,9 0 0107
+H 9,9 0 0110
+I 4,9 0 0111
+J 7,9 0 0112
+K 9,9 0 0113
+L 7,9 0 0114
+M 11,9 0 0115
+N 9,9 0 0116
+O 10,9 0 0117
+P 8,9 0 0120
+Q 10,9 0 0121
+R 9,9 0 0122
+S 9,9 0 0123
+T 8,9 0 0124
+U 9,9 0 0125
+V 8,9 0 0126
+W 10,9 0 0127
+X 8,9 0 0130
+Y 8,9 0 0131
+Z 7,9 0 0132
+[ 4,9,3 0 0133
+lB "
+\ 4,9 0 0134
+rs "
+] 4,9,3 0 0135
+rB "
+^ 7,9 0 0136
+a^ "
+ha "
+_ 7,0,3 0 0137
+` 4,9 0 0140
+oq "
+a 7,7 0 0141
+b 7,9 0 0142
+c 7,7 0 0143
+d 7,9 0 0144
+e 7,7 0 0145
+f 5,9 0 0146
+g 7,7,3 0 0147
+h 7,9 0 0150
+i 3,9 0 0151
+j 3,9,3 0 0152
+k 7,9 0 0153
+l 3,9 0 0154
+m 11,7 0 0155
+n 7,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 5,7 0 0162
+s 7,7 0 0163
+t 5,9 0 0164
+u 7,7 0 0165
+v 8,7 0 0166
+w 11,7 0 0167
+x 7,7 0 0170
+y 8,7,3 0 0171
+z 6,7 0 0172
+{ 5,9,3 0 0173
+lC "
+| 4,9,3 0 0174
+or "
+ba "
+} 5,9,3 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,7,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 7,9 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 7,9 0 0245
+¥ "
+bb 4,9,2 0 0246
+¦ "
+sc 7,9,3 0 0247
+§ "
+ad 5,9 0 0250
+¨ "
+co 11,9 0 0251
+© "
+Of 6,9 0 0252
+ª "
+Fo 8,6 0 0253
+« "
+no 8,6 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 4,9 0 0257
+¯ "
+de 5,8 0 0260
+° "
++- 7,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 4,10 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 7,9,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 4,1,3 0 0270
+¸ "
+S1 4,9 0 0271
+¹ "
+Om 6,9 0 0272
+º "
+Fc 8,6 0 0273
+» "
+14 10,9 0 0274
+¼ "
+12 10,9 0 0275
+½ "
+34 10,9 0 0276
+¾ "
+r? 8,7,3 0 0277
+¿ "
+`A 8,12 0 0300
+À "
+'A 8,12 0 0301
+Á "
+^A 8,12 0 0302
+Â "
+~A 8,12 0 0303
+Ã "
+:A 8,11 0 0304
+Ä "
+oA 8,12 0 0305
+Å "
+AE 13,9 0 0306
+Æ "
+,C 8,9,3 0 0307
+Ç "
+`E 8,12 0 0310
+È "
+'E 8,12 0 0311
+É "
+^E 8,12 0 0312
+Ê "
+:E 8,11 0 0313
+Ë "
+`I 4,12 0 0314
+Ì "
+'I 4,12 0 0315
+Í "
+^I 4,12 0 0316
+Î "
+:I 4,11 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 10,12 0 0322
+Ò "
+'O 10,12 0 0323
+Ó "
+^O 10,12 0 0324
+Ô "
+~O 10,12 0 0325
+Õ "
+:O 10,11 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 10,9,1 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,11 0 0334
+Ü "
+'Y 8,12 0 0335
+Ý "
+TP 8,9 0 0336
+Þ "
+ss 8,9 0 0337
+ß "
+`a 7,10 0 0340
+à "
+'a 7,10 0 0341
+á "
+^a 7,10 0 0342
+â "
+~a 7,10 0 0343
+ã "
+:a 7,9 0 0344
+ä "
+oa 7,11 0 0345
+å "
+ae 11,7 0 0346
+æ "
+,c 7,7,3 0 0347
+ç "
+`e 7,10 0 0350
+è "
+'e 7,10 0 0351
+é "
+^e 7,10 0 0352
+ê "
+:e 7,9 0 0353
+ë "
+`i 3,10 0 0354
+ì "
+'i 3,10 0 0355
+í "
+^i 3,10 0 0356
+î "
+:i 3,9 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 7,10 0 0361
+ñ "
+`o 7,10 0 0362
+ò "
+'o 7,10 0 0363
+ó "
+^o 7,10 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,9 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 7,7 0 0370
+ø "
+`u 7,10 0 0371
+ù "
+'u 7,10 0 0372
+ú "
+^u 7,10 0 0373
+û "
+:u 7,9 0 0374
+ü "
+'y 8,10,3 0 0375
+ý "
+Tp 7,9,3 0 0376
+þ "
+:y 8,9,3 0 0377
+ÿ "
diff --git a/font/devX75-12/HBI b/font/devX75-12/HBI
new file mode 100644
index 00000000..3014c902
--- /dev/null
+++ b/font/devX75-12/HBI
@@ -0,0 +1,306 @@
+name HBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,9 0 041
+" 6,9 0 042
+# 7,8 0 043
+sh "
+$ 7,9,1 0 044
+Do "
+% 13,9 0 045
+& 9,9 0 046
+' 4,9 0 047
+( 5,9,3 0 050
+) 5,9,3 0 051
+* 6,9 0 052
++ 8,6 0 053
+, 3,2,2 0 054
+\- 8,4 0 055
+. 3,2 0 056
+/ 5,9 0 057
+sl "
+0 7,9 0 060
+1 7,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 7,6 0 074
+= 7,5 0 075
+eq "
+> 7,6 0 076
+? 8,9 0 077
+@ 11,9,1 0 0100
+at "
+A 8,9 0 0101
+B 9,9 0 0102
+C 8,9 0 0103
+D 9,9 0 0104
+E 8,9 0 0105
+F 7,9 0 0106
+G 9,9 0 0107
+H 10,9 0 0110
+I 5,9 0 0111
+J 7,9 0 0112
+K 9,9 0 0113
+L 7,9 0 0114
+M 12,9 0 0115
+N 10,9 0 0116
+O 9,9 0 0117
+P 8,9 0 0120
+Q 9,9 0 0121
+R 9,9 0 0122
+S 8,9 0 0123
+T 7,9 0 0124
+U 8,9 0 0125
+V 9,9 0 0126
+W 10,9 0 0127
+X 9,9 0 0130
+Y 7,9 0 0131
+Z 7,9 0 0132
+[ 4,9,3 0 0133
+lB "
+\ 5,9 0 0134
+rs "
+] 4,9,3 0 0135
+rB "
+^ 6,9 0 0136
+a^ "
+ha "
+_ 7,0,3 0 0137
+` 4,9 0 0140
+oq "
+a 6,7 0 0141
+b 7,9 0 0142
+c 7,7 0 0143
+d 7,9 0 0144
+e 7,7 0 0145
+f 5,9 0 0146
+g 7,7,3 0 0147
+h 7,9 0 0150
+i 3,9 0 0151
+j 3,9,3 0 0152
+k 7,9 0 0153
+l 3,9 0 0154
+m 11,7 0 0155
+n 7,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 5,7 0 0162
+s 7,7 0 0163
+t 5,9 0 0164
+u 7,7 0 0165
+v 7,7 0 0166
+w 10,7 0 0167
+x 7,7 0 0170
+y 7,7,3 0 0171
+z 6,7 0 0172
+{ 5,9,3 0 0173
+lC "
+| 4,9,3 0 0174
+or "
+ba "
+} 5,9,3 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,7,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 7,9 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 7,9 0 0245
+¥ "
+bb 4,9,2 0 0246
+¦ "
+sc 7,9,3 0 0247
+§ "
+ad 5,9 0 0250
+¨ "
+co 11,9 0 0251
+© "
+Of 6,9 0 0252
+ª "
+Fo 10,6 0 0253
+« "
+no 8,5 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 4,9 0 0257
+¯ "
+de 5,8 0 0260
+° "
++- 8,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 4,9 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 7,9,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 4,1,3 0 0270
+¸ "
+S1 4,9 0 0271
+¹ "
+Om 6,9 0 0272
+º "
+Fc 10,6 0 0273
+» "
+14 10,9 0 0274
+¼ "
+12 10,9 0 0275
+½ "
+34 10,9 0 0276
+¾ "
+r? 7,7,2 0 0277
+¿ "
+`A 8,12 0 0300
+À "
+'A 8,12 0 0301
+Á "
+^A 8,12 0 0302
+Â "
+~A 8,12 0 0303
+Ã "
+:A 8,11 0 0304
+Ä "
+oA 8,12 0 0305
+Å "
+AE 11,9 0 0306
+Æ "
+,C 8,9,3 0 0307
+Ç "
+`E 8,12 0 0310
+È "
+'E 8,12 0 0311
+É "
+^E 8,12 0 0312
+Ê "
+:E 8,11 0 0313
+Ë "
+`I 5,12 0 0314
+Ì "
+'I 5,12 0 0315
+Í "
+^I 5,12 0 0316
+Î "
+:I 5,11 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 10,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,11 0 0326
+Ö "
+mu 8,6 0 0327
+× "
+/O 9,9 0 0330
+Ø "
+`U 8,12 0 0331
+Ù "
+'U 8,12 0 0332
+Ú "
+^U 8,12 0 0333
+Û "
+:U 8,11 0 0334
+Ü "
+'Y 7,12 0 0335
+Ý "
+TP 8,9 0 0336
+Þ "
+ss 7,9 0 0337
+ß "
+`a 6,10 0 0340
+à "
+'a 6,10 0 0341
+á "
+^a 6,10 0 0342
+â "
+~a 6,10 0 0343
+ã "
+:a 6,9 0 0344
+ä "
+oa 6,10 0 0345
+å "
+ae 10,7 0 0346
+æ "
+,c 7,7,3 0 0347
+ç "
+`e 7,10 0 0350
+è "
+'e 7,10 0 0351
+é "
+^e 7,10 0 0352
+ê "
+:e 7,9 0 0353
+ë "
+`i 3,10 0 0354
+ì "
+'i 3,10 0 0355
+í "
+^i 3,10 0 0356
+î "
+:i 3,9 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 7,10 0 0361
+ñ "
+`o 7,10 0 0362
+ò "
+'o 7,10 0 0363
+ó "
+^o 7,10 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,9 0 0366
+ö "
+di 8,6 0 0367
+÷ "
+/o 7,8 0 0370
+ø "
+`u 7,10 0 0371
+ù "
+'u 7,10 0 0372
+ú "
+^u 7,10 0 0373
+û "
+:u 7,9 0 0374
+ü "
+'y 7,10,3 0 0375
+ý "
+Tp 7,9,3 0 0376
+þ "
+:y 7,9,3 0 0377
+ÿ "
diff --git a/font/devX75-12/HI b/font/devX75-12/HI
new file mode 100644
index 00000000..587e1451
--- /dev/null
+++ b/font/devX75-12/HI
@@ -0,0 +1,306 @@
+name HI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 3,9 0 041
+" 5,9 0 042
+# 7,8 0 043
+sh "
+$ 7,9,1 0 044
+Do "
+% 11,9 0 045
+& 9,9 0 046
+' 3,9 0 047
+( 4,9,3 0 050
+) 4,9,3 0 051
+* 5,9 0 052
++ 7,6 0 053
+, 3,1,2 0 054
+\- 8,4 0 055
+. 3,1 0 056
+/ 4,9 0 057
+sl "
+0 7,9 0 060
+1 7,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 3,6 0 072
+; 3,6,2 0 073
+< 8,6 0 074
+= 7,5 0 075
+eq "
+> 8,6 0 076
+? 7,9 0 077
+@ 12,9,1 0 0100
+at "
+A 9,9 0 0101
+B 8,9 0 0102
+C 8,9 0 0103
+D 9,9 0 0104
+E 8,9 0 0105
+F 8,9 0 0106
+G 8,9 0 0107
+H 10,9 0 0110
+I 4,9 0 0111
+J 8,9 0 0112
+K 8,9 0 0113
+L 7,9 0 0114
+M 12,9 0 0115
+N 10,9 0 0116
+O 9,9 0 0117
+P 8,9 0 0120
+Q 9,9 0 0121
+R 8,9 0 0122
+S 8,9 0 0123
+T 7,9 0 0124
+U 9,9 0 0125
+V 8,9 0 0126
+W 11,9 0 0127
+X 9,9 0 0130
+Y 8,9 0 0131
+Z 9,9 0 0132
+[ 4,9,3 0 0133
+lB "
+\ 4,9 0 0134
+rs "
+] 4,9,3 0 0135
+rB "
+^ 6,8 0 0136
+a^ "
+ha "
+_ 7,0,3 0 0137
+` 3,9 0 0140
+oq "
+a 7,7 0 0141
+b 7,9 0 0142
+c 6,7 0 0143
+d 7,9 0 0144
+e 6,7 0 0145
+f 3,9 0 0146
+g 7,7,3 0 0147
+h 7,9 0 0150
+i 3,9 0 0151
+j 3,9,3 0 0152
+k 6,9 0 0153
+l 3,9 0 0154
+m 9,7 0 0155
+n 7,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 4,7 0 0162
+s 6,7 0 0163
+t 4,9 0 0164
+u 7,7 0 0165
+v 6,7 0 0166
+w 9,7 0 0167
+x 6,7 0 0170
+y 6,7,3 0 0171
+z 6,7 0 0172
+{ 5,9,3 0 0173
+lC "
+| 4,9,3 0 0174
+or "
+ba "
+} 5,9,3 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,3 0 0241
+¡ "
+ct 8,8,1 0 0242
+¢ "
+Po 8,9 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 7,9 0 0245
+¥ "
+bb 4,9,2 0 0246
+¦ "
+sc 7,9,3 0 0247
+§ "
+ad 3,9 0 0250
+¨ "
+co 11,9 0 0251
+© "
+Of 5,9 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 8,6 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 4,9 0 0257
+¯ "
+de 5,8 0 0260
+° "
++- 7,7 0 0261
+± "
+S2 4,8 0 0262
+² "
+S3 4,8 0 0263
+³ "
+aa 2,10 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 8,9,3 0 0266
+¶ "
+md 3,4 0 0267
+· "
+ac 3,1,3 0 0270
+¸ "
+S1 4,8 0 0271
+¹ "
+Om 5,9 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 10,9 0 0274
+¼ "
+12 10,9 0 0275
+½ "
+34 10,9 0 0276
+¾ "
+r? 7,6,3 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,11 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 11,9 0 0306
+Æ "
+,C 8,9,3 0 0307
+Ç "
+`E 8,12 0 0310
+È "
+'E 8,12 0 0311
+É "
+^E 8,12 0 0312
+Ê "
+:E 8,11 0 0313
+Ë "
+`I 4,12 0 0314
+Ì "
+'I 4,12 0 0315
+Í "
+^I 4,12 0 0316
+Î "
+:I 4,11 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 10,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,11 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 10,9 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,11 0 0334
+Ü "
+'Y 8,12 0 0335
+Ý "
+TP 8,9 0 0336
+Þ "
+ss 7,9 0 0337
+ß "
+`a 7,10 0 0340
+à "
+'a 7,10 0 0341
+á "
+^a 7,10 0 0342
+â "
+~a 7,10 0 0343
+ã "
+:a 7,9 0 0344
+ä "
+oa 7,10 0 0345
+å "
+ae 11,7 0 0346
+æ "
+,c 6,7,3 0 0347
+ç "
+`e 6,10 0 0350
+è "
+'e 6,10 0 0351
+é "
+^e 6,10 0 0352
+ê "
+:e 6,9 0 0353
+ë "
+`i 3,10 0 0354
+ì "
+'i 3,10 0 0355
+í "
+^i 3,10 0 0356
+î "
+:i 3,9 0 0357
+ï "
+Sd 7,11 0 0360
+ð "
+~n 7,10 0 0361
+ñ "
+`o 7,10 0 0362
+ò "
+'o 7,10 0 0363
+ó "
+^o 7,10 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,9 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 7,7 0 0370
+ø "
+`u 7,10 0 0371
+ù "
+'u 7,10 0 0372
+ú "
+^u 7,10 0 0373
+û "
+:u 7,9 0 0374
+ü "
+'y 6,10,3 0 0375
+ý "
+Tp 7,9,3 0 0376
+þ "
+:y 7,9,3 0 0377
+ÿ "
diff --git a/font/devX75-12/HR b/font/devX75-12/HR
new file mode 100644
index 00000000..86958ed6
--- /dev/null
+++ b/font/devX75-12/HR
@@ -0,0 +1,306 @@
+name HR
+spacewidth 4
+charset
+--- 4,1 0 040
+! 3,9 0 041
+" 5,9 0 042
+# 7,8 0 043
+sh "
+$ 6,9,2 0 044
+Do "
+% 11,9 0 045
+& 9,9 0 046
+' 3,9 0 047
+( 4,9,3 0 050
+) 4,9,3 0 051
+* 5,9 0 052
++ 7,6 0 053
+, 4,1,2 0 054
+\- 8,4 0 055
+. 3,1 0 056
+/ 4,9 0 057
+sl "
+0 7,9 0 060
+1 7,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 3,6 0 072
+; 3,6,2 0 073
+< 7,6 0 074
+= 7,5 0 075
+eq "
+> 7,6 0 076
+? 7,9 0 077
+@ 12,9,1 0 0100
+at "
+A 9,9 0 0101
+B 8,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 8,9 0 0105
+F 8,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 3,9 0 0111
+J 7,9 0 0112
+K 8,9 0 0113
+L 7,9 0 0114
+M 11,9 0 0115
+N 9,9 0 0116
+O 10,9 0 0117
+P 8,9 0 0120
+Q 10,9 0 0121
+R 8,9 0 0122
+S 8,9 0 0123
+T 7,9 0 0124
+U 8,9 0 0125
+V 9,9 0 0126
+W 11,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 3,9,3 0 0133
+lB "
+\ 4,9 0 0134
+rs "
+] 3,9,3 0 0135
+rB "
+^ 6,8 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 3,9 0 0140
+oq "
+a 7,7 0 0141
+b 7,9 0 0142
+c 7,7 0 0143
+d 7,9 0 0144
+e 7,7 0 0145
+f 3,9 0 0146
+g 7,7,3 0 0147
+h 7,9 0 0150
+i 3,9 0 0151
+j 3,9,3 0 0152
+k 6,9 0 0153
+l 3,9 0 0154
+m 9,7 0 0155
+n 7,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 4,7 0 0162
+s 6,7 0 0163
+t 4,9 0 0164
+u 7,7 0 0165
+v 7,7 0 0166
+w 9,7 0 0167
+x 6,7 0 0170
+y 7,7,3 0 0171
+z 6,7 0 0172
+{ 4,9,3 0 0173
+lC "
+| 3,9,3 0 0174
+or "
+ba "
+} 4,9,3 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 3,7,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 7,9 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 7,9 0 0245
+¥ "
+bb 3,9,2 0 0246
+¦ "
+sc 6,9,3 0 0247
+§ "
+ad 3,9 0 0250
+¨ "
+co 11,9 0 0251
+© "
+Of 5,9 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 8,6 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 4,9 0 0257
+¯ "
+de 5,8 0 0260
+° "
++- 7,7 0 0261
+± "
+S2 4,8 0 0262
+² "
+S3 4,8 0 0263
+³ "
+aa 2,10 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 7,9,3 0 0266
+¶ "
+md 3,4 0 0267
+· "
+ac 3,1,3 0 0270
+¸ "
+S1 4,8 0 0271
+¹ "
+Om 5,9 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 10,9 0 0274
+¼ "
+12 10,9 0 0275
+½ "
+34 10,9 0 0276
+¾ "
+r? 7,6,3 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,11 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 11,9 0 0306
+Æ "
+,C 9,9,3 0 0307
+Ç "
+`E 8,12 0 0310
+È "
+'E 8,12 0 0311
+É "
+^E 8,12 0 0312
+Ê "
+:E 8,11 0 0313
+Ë "
+`I 3,12 0 0314
+Ì "
+'I 3,12 0 0315
+Í "
+^I 3,12 0 0316
+Î "
+:I 3,11 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 10,12 0 0322
+Ò "
+'O 10,12 0 0323
+Ó "
+^O 10,12 0 0324
+Ô "
+~O 10,12 0 0325
+Õ "
+:O 10,11 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 10,10,1 0 0330
+Ø "
+`U 8,12 0 0331
+Ù "
+'U 8,12 0 0332
+Ú "
+^U 8,12 0 0333
+Û "
+:U 8,11 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 8,9 0 0336
+Þ "
+ss 7,9 0 0337
+ß "
+`a 7,10 0 0340
+à "
+'a 7,10 0 0341
+á "
+^a 7,10 0 0342
+â "
+~a 7,10 0 0343
+ã "
+:a 7,9 0 0344
+ä "
+oa 7,10 0 0345
+å "
+ae 11,7 0 0346
+æ "
+,c 7,7,3 0 0347
+ç "
+`e 7,10 0 0350
+è "
+'e 7,10 0 0351
+é "
+^e 7,10 0 0352
+ê "
+:e 7,9 0 0353
+ë "
+`i 3,10 0 0354
+ì "
+'i 3,10 0 0355
+í "
+^i 3,10 0 0356
+î "
+:i 3,9 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 7,10 0 0361
+ñ "
+`o 7,10 0 0362
+ò "
+'o 7,10 0 0363
+ó "
+^o 7,10 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,9 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 7,7 0 0370
+ø "
+`u 7,10 0 0371
+ù "
+'u 7,10 0 0372
+ú "
+^u 7,10 0 0373
+û "
+:u 7,9 0 0374
+ü "
+'y 7,10,3 0 0375
+ý "
+Tp 7,9,3 0 0376
+þ "
+:y 7,9,3 0 0377
+ÿ "
diff --git a/font/devX75-12/Makefile.sub b/font/devX75-12/Makefile.sub
new file mode 100644
index 00000000..37f4b7cb
--- /dev/null
+++ b/font/devX75-12/Makefile.sub
@@ -0,0 +1,2 @@
+DEV=X75-12
+DEVFILES=DESC TR TI TB TBI CR CI CB CBI HR HI HB HBI NR NI NB NBI S
diff --git a/font/devX75-12/NB b/font/devX75-12/NB
new file mode 100644
index 00000000..5fea0171
--- /dev/null
+++ b/font/devX75-12/NB
@@ -0,0 +1,306 @@
+name NB
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,9 0 041
+" 6,9 0 042
+# 8,9 0 043
+sh "
+$ 7,10,1 0 044
+Do "
+% 13,9 0 045
+& 11,9 0 046
+' 3,9 0 047
+( 5,9,2 0 050
+) 5,9,2 0 051
+* 6,9 0 052
++ 8,7 0 053
+, 4,2,2 0 054
+\- 7,4 0 055
+. 4,2 0 056
+/ 4,9 0 057
+sl "
+0 7,9 0 060
+1 5,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 4,6 0 072
+; 4,6,2 0 073
+< 7,6 0 074
+= 7,5 0 075
+eq "
+> 7,6 0 076
+? 7,9 0 077
+@ 11,9 0 0100
+at "
+A 11,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 10,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 10,9 0 0107
+H 11,9 0 0110
+I 5,9 0 0111
+J 8,9 0 0112
+K 10,9 0 0113
+L 9,9 0 0114
+M 12,9 0 0115
+N 11,9 0 0116
+O 10,9 0 0117
+P 9,9 0 0120
+Q 10,9,2 0 0121
+R 10,9 0 0122
+S 8,9 0 0123
+T 9,9 0 0124
+U 10,9 0 0125
+V 11,9 0 0126
+W 14,9 0 0127
+X 10,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 5,9,2 0 0133
+lB "
+\ 6,9 0 0134
+rs "
+] 5,9,2 0 0135
+rB "
+^ 6,9 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 3,9 0 0140
+oq "
+a 8,6 0 0141
+b 8,9 0 0142
+c 7,6 0 0143
+d 9,9 0 0144
+e 7,6 0 0145
+f 5,9 0 0146
+g 7,7,3 0 0147
+h 9,9 0 0150
+i 5,9 0 0151
+j 3,9,3 0 0152
+k 8,9 0 0153
+l 5,9 0 0154
+m 13,6 0 0155
+n 9,6 0 0156
+o 8,6 0 0157
+p 8,6,3 0 0160
+q 8,6,3 0 0161
+r 6,6 0 0162
+s 6,6 0 0163
+t 5,9 0 0164
+u 9,6 0 0165
+v 7,6 0 0166
+w 11,6 0 0167
+x 8,6 0 0170
+y 7,6,3 0 0171
+z 7,6 0 0172
+{ 5,9,2 0 0173
+lC "
+| 8,9 0 0174
+or "
+ba "
+} 5,9,2 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,3 0 0241
+¡ "
+ct 7,7,1 0 0242
+¢ "
+Po 8,9 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 9,9 0 0245
+¥ "
+bb 8,9 0 0246
+¦ "
+sc 6,9,1 0 0247
+§ "
+ad 5,9 0 0250
+¨ "
+co 10,9 0 0251
+© "
+Of 6,9 0 0252
+ª "
+Fo 8,6 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 6,8 0 0257
+¯ "
+de 5,9 0 0260
+° "
++- 8,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 5,9 0 0264
+´ "
+µ 9,6,3 0 0265
+ps 10,9 0 0266
+¶ "
+md 3,5 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 4,9 0 0271
+¹ "
+Om 6,9 0 0272
+º "
+Fc 8,6 0 0273
+» "
+14 10,9 0 0274
+¼ "
+12 10,9 0 0275
+½ "
+34 10,9 0 0276
+¾ "
+r? 7,6,3 0 0277
+¿ "
+`A 11,12 0 0300
+À "
+'A 11,12 0 0301
+Á "
+^A 11,12 0 0302
+Â "
+~A 11,12 0 0303
+Ã "
+:A 11,12 0 0304
+Ä "
+oA 11,12 0 0305
+Å "
+AE 14,9 0 0306
+Æ "
+,C 9,9,3 0 0307
+Ç "
+`E 9,12 0 0310
+È "
+'E 9,12 0 0311
+É "
+^E 9,12 0 0312
+Ê "
+:E 9,12 0 0313
+Ë "
+`I 5,12 0 0314
+Ì "
+'I 5,12 0 0315
+Í "
+^I 5,12 0 0316
+Î "
+:I 5,12 0 0317
+Ï "
+-D 10,9 0 0320
+Ð "
+~N 11,12 0 0321
+Ñ "
+`O 10,12 0 0322
+Ò "
+'O 10,12 0 0323
+Ó "
+^O 10,12 0 0324
+Ô "
+~O 10,12 0 0325
+Õ "
+:O 10,12 0 0326
+Ö "
+mu 8,7 0 0327
+× "
+/O 10,9 0 0330
+Ø "
+`U 10,12 0 0331
+Ù "
+'U 10,12 0 0332
+Ú "
+^U 10,12 0 0333
+Û "
+:U 10,12 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 9,9 0 0336
+Þ "
+ss 8,9 0 0337
+ß "
+`a 8,9 0 0340
+à "
+'a 8,9 0 0341
+á "
+^a 8,9 0 0342
+â "
+~a 8,9 0 0343
+ã "
+:a 8,9 0 0344
+ä "
+oa 8,9 0 0345
+å "
+ae 11,6 0 0346
+æ "
+,c 7,6,3 0 0347
+ç "
+`e 7,9 0 0350
+è "
+'e 7,9 0 0351
+é "
+^e 7,9 0 0352
+ê "
+:e 7,9 0 0353
+ë "
+`i 5,9 0 0354
+ì "
+'i 5,9 0 0355
+í "
+^i 5,9 0 0356
+î "
+:i 5,9 0 0357
+ï "
+Sd 8,9 0 0360
+ð "
+~n 9,9 0 0361
+ñ "
+`o 8,9 0 0362
+ò "
+'o 8,9 0 0363
+ó "
+^o 8,9 0 0364
+ô "
+~o 8,9 0 0365
+õ "
+:o 8,9 0 0366
+ö "
+di 8,7 0 0367
+÷ "
+/o 8,7,1 0 0370
+ø "
+`u 9,9 0 0371
+ù "
+'u 9,9 0 0372
+ú "
+^u 9,9 0 0373
+û "
+:u 9,9 0 0374
+ü "
+'y 7,9,3 0 0375
+ý "
+Tp 8,9,3 0 0376
+þ "
+:y 7,9,3 0 0377
+ÿ "
diff --git a/font/devX75-12/NBI b/font/devX75-12/NBI
new file mode 100644
index 00000000..0da124ad
--- /dev/null
+++ b/font/devX75-12/NBI
@@ -0,0 +1,306 @@
+name NBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,9 0 041
+" 6,9 0 042
+# 8,8 0 043
+sh "
+$ 7,10,1 0 044
+Do "
+% 12,9 0 045
+& 12,9 0 046
+' 3,9 0 047
+( 5,9,2 0 050
+) 5,9,2 0 051
+* 6,9 0 052
++ 8,7 0 053
+, 3,2,2 0 054
+\- 8,4 0 055
+. 3,2 0 056
+/ 6,9 0 057
+sl "
+0 7,9 0 060
+1 7,9 0 061
+2 7,9 0 062
+3 7,9 0 063
+4 7,9 0 064
+5 7,9 0 065
+6 7,9 0 066
+7 7,9 0 067
+8 7,9 0 070
+9 7,9 0 071
+: 4,6 0 072
+; 4,6,2 0 073
+< 7,7 0 074
+= 7,5 0 075
+eq "
+> 7,7 0 076
+? 6,9 0 077
+@ 11,9 0 0100
+at "
+A 10,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 10,9 0 0104
+E 9,9 0 0105
+F 8,9 0 0106
+G 10,9 0 0107
+H 11,9 0 0110
+I 6,9 0 0111
+J 8,9 0 0112
+K 10,9 0 0113
+L 9,9 0 0114
+M 14,9 0 0115
+N 11,9 0 0116
+O 10,9 0 0117
+P 9,9 0 0120
+Q 10,9,2 0 0121
+R 10,9 0 0122
+S 8,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 10,9 0 0126
+W 13,9 0 0127
+X 11,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 6,9,2 0 0133
+lB "
+\ 6,9 0 0134
+rs "
+] 6,9,2 0 0135
+rB "
+^ 8,9 0 0136
+a^ "
+ha "
+_ 8,0,2 0 0137
+` 3,9 0 0140
+oq "
+a 8,6 0 0141
+b 7,9 0 0142
+c 6,6 0 0143
+d 8,9 0 0144
+e 7,6 0 0145
+f 5,9,3 0 0146
+g 7,8,3 0 0147
+h 8,9 0 0150
+i 4,9 0 0151
+j 4,9,3 0 0152
+k 8,9 0 0153
+l 4,9 0 0154
+m 12,6 0 0155
+n 8,6 0 0156
+o 7,6 0 0157
+p 8,6,3 0 0160
+q 8,6,3 0 0161
+r 6,6 0 0162
+s 7,6 0 0163
+t 5,8 0 0164
+u 8,6 0 0165
+v 7,6 0 0166
+w 11,6 0 0167
+x 7,6 0 0170
+y 6,6,3 0 0171
+z 7,6 0 0172
+{ 6,9,2 0 0173
+lC "
+| 8,9 0 0174
+or "
+ba "
+} 6,9,2 0 0175
+rC "
+~ 8,5 0 0176
+a~ "
+ap "
+ti "
+r! 5,6,3 0 0241
+¡ "
+ct 7,7,1 0 0242
+¢ "
+Po 9,9 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 10,9 0 0245
+¥ "
+bb 8,9 0 0246
+¦ "
+sc 6,9,2 0 0247
+§ "
+ad 4,9 0 0250
+¨ "
+co 10,9 0 0251
+© "
+Of 6,9 0 0252
+ª "
+Fo 9,6 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 10,9 0 0256
+® "
+a- 5,8 0 0257
+¯ "
+de 5,9 0 0260
+° "
++- 8,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 4,9 0 0264
+´ "
+µ 8,6,3 0 0265
+ps 8,9 0 0266
+¶ "
+md 5,5 0 0267
+· "
+ac 4,0,3 0 0270
+¸ "
+S1 4,9 0 0271
+¹ "
+Om 5,9 0 0272
+º "
+Fc 9,6 0 0273
+» "
+14 10,9 0 0274
+¼ "
+12 10,9 0 0275
+½ "
+34 10,9 0 0276
+¾ "
+r? 6,6,3 0 0277
+¿ "
+`A 10,12 0 0300
+À "
+'A 10,12 0 0301
+Á "
+^A 10,12 0 0302
+Â "
+~A 10,12 0 0303
+Ã "
+:A 10,12 0 0304
+Ä "
+oA 10,12 0 0305
+Å "
+AE 12,9 0 0306
+Æ "
+,C 9,9,3 0 0307
+Ç "
+`E 9,12 0 0310
+È "
+'E 9,12 0 0311
+É "
+^E 9,12 0 0312
+Ê "
+:E 9,12 0 0313
+Ë "
+`I 6,12 0 0314
+Ì "
+'I 6,12 0 0315
+Í "
+^I 6,12 0 0316
+Î "
+:I 6,12 0 0317
+Ï "
+-D 10,9 0 0320
+Ð "
+~N 11,12 0 0321
+Ñ "
+`O 10,12 0 0322
+Ò "
+'O 10,12 0 0323
+Ó "
+^O 10,12 0 0324
+Ô "
+~O 10,12 0 0325
+Õ "
+:O 10,12 0 0326
+Ö "
+mu 8,7 0 0327
+× "
+/O 10,9 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,12 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 9,9 0 0336
+Þ "
+ss 9,9,2 0 0337
+ß "
+`a 8,9 0 0340
+à "
+'a 8,9 0 0341
+á "
+^a 8,10 0 0342
+â "
+~a 8,9 0 0343
+ã "
+:a 8,9 0 0344
+ä "
+oa 8,10 0 0345
+å "
+ae 11,6 0 0346
+æ "
+,c 6,6,3 0 0347
+ç "
+`e 7,9 0 0350
+è "
+'e 7,9 0 0351
+é "
+^e 7,10 0 0352
+ê "
+:e 7,9 0 0353
+ë "
+`i 4,9 0 0354
+ì "
+'i 4,9 0 0355
+í "
+^i 4,10 0 0356
+î "
+:i 4,9 0 0357
+ï "
+Sd 7,9 0 0360
+ð "
+~n 8,9 0 0361
+ñ "
+`o 7,9 0 0362
+ò "
+'o 7,9 0 0363
+ó "
+^o 7,10 0 0364
+ô "
+~o 7,9 0 0365
+õ "
+:o 7,9 0 0366
+ö "
+di 8,7 0 0367
+÷ "
+/o 7,6 0 0370
+ø "
+`u 8,9 0 0371
+ù "
+'u 8,9 0 0372
+ú "
+^u 8,10 0 0373
+û "
+:u 8,9 0 0374
+ü "
+'y 6,9,3 0 0375
+ý "
+Tp 8,9,3 0 0376
+þ "
+:y 6,9,3 0 0377
+ÿ "
diff --git a/font/devX75-12/NI b/font/devX75-12/NI
new file mode 100644
index 00000000..05ee8cdb
--- /dev/null
+++ b/font/devX75-12/NI
@@ -0,0 +1,306 @@
+name NI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,9 0 041
+" 6,9 0 042
+# 8,8 0 043
+sh "
+$ 6,10,1 0 044
+Do "
+% 10,9 0 045
+& 10,9 0 046
+' 3,9 0 047
+( 5,9,2 0 050
+) 5,9,2 0 051
+* 7,9 0 052
++ 8,7 0 053
+, 2,2,1 0 054
+\- 7,4 0 055
+. 2,2 0 056
+/ 8,9,1 0 057
+sl "
+0 6,9 0 060
+1 6,9 0 061
+2 6,9 0 062
+3 6,9 0 063
+4 6,9 0 064
+5 6,9 0 065
+6 6,9 0 066
+7 6,9 0 067
+8 6,9 0 070
+9 6,9 0 071
+: 3,6 0 072
+; 3,6,1 0 073
+< 7,6 0 074
+= 7,5 0 075
+eq "
+> 7,6 0 076
+? 5,9 0 077
+@ 11,9 0 0100
+at "
+A 8,9 0 0101
+B 8,9 0 0102
+C 9,9 0 0103
+D 10,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 9,9 0 0107
+H 10,9 0 0110
+I 5,9 0 0111
+J 7,9 0 0112
+K 9,9 0 0113
+L 8,9 0 0114
+M 13,9 0 0115
+N 11,9 0 0116
+O 9,9 0 0117
+P 8,9 0 0120
+Q 9,9,2 0 0121
+R 10,9 0 0122
+S 9,9 0 0123
+T 8,9 0 0124
+U 8,9 0 0125
+V 9,9 0 0126
+W 13,9 0 0127
+X 10,9 0 0130
+Y 8,9 0 0131
+Z 9,9 0 0132
+[ 6,9,2 0 0133
+lB "
+\ 8,9 0 0134
+rs "
+] 6,9,2 0 0135
+rB "
+^ 6,9 0 0136
+a^ "
+ha "
+_ 8,0,2 0 0137
+` 3,9 0 0140
+oq "
+a 8,6 0 0141
+b 7,9 0 0142
+c 6,6 0 0143
+d 8,9 0 0144
+e 6,6 0 0145
+f 4,9,3 0 0146
+g 6,7,3 0 0147
+h 8,9 0 0150
+i 4,9 0 0151
+j 3,9,3 0 0152
+k 7,9 0 0153
+l 4,9 0 0154
+m 12,6 0 0155
+n 8,6 0 0156
+o 6,6 0 0157
+p 7,6,3 0 0160
+q 7,6,3 0 0161
+r 5,6 0 0162
+s 6,6 0 0163
+t 4,8 0 0164
+u 8,6 0 0165
+v 7,6 0 0166
+w 10,6 0 0167
+x 6,6 0 0170
+y 6,6,3 0 0171
+z 6,6 0 0172
+{ 5,9,2 0 0173
+lC "
+| 6,9 0 0174
+or "
+ba "
+} 5,9,2 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,7,2 0 0241
+¡ "
+ct 6,7,1 0 0242
+¢ "
+Po 8,9 0 0243
+£ "
+Cs 9,8 0 0244
+¤ "
+Ye 9,9 0 0245
+¥ "
+bb 6,9 0 0246
+¦ "
+sc 6,9,2 0 0247
+§ "
+ad 5,9 0 0250
+¨ "
+co 10,9 0 0251
+© "
+Of 5,9 0 0252
+ª "
+Fo 7,5 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 10,9 0 0256
+® "
+a- 5,8 0 0257
+¯ "
+de 5,9 0 0260
+° "
++- 8,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 4,9 0 0264
+´ "
+µ 8,6,3 0 0265
+ps 9,9 0 0266
+¶ "
+md 5,5 0 0267
+· "
+ac 4,0,3 0 0270
+¸ "
+S1 4,9 0 0271
+¹ "
+Om 4,9 0 0272
+º "
+Fc 7,5 0 0273
+» "
+14 9,9 0 0274
+¼ "
+12 9,9 0 0275
+½ "
+34 9,9 0 0276
+¾ "
+r? 5,7,2 0 0277
+¿ "
+`A 8,12 0 0300
+À "
+'A 8,12 0 0301
+Á "
+^A 8,12 0 0302
+Â "
+~A 8,12 0 0303
+Ã "
+:A 8,12 0 0304
+Ä "
+oA 8,12 0 0305
+Å "
+AE 13,9 0 0306
+Æ "
+,C 9,9,3 0 0307
+Ç "
+`E 9,12 0 0310
+È "
+'E 9,12 0 0311
+É "
+^E 9,12 0 0312
+Ê "
+:E 9,12 0 0313
+Ë "
+`I 5,12 0 0314
+Ì "
+'I 5,12 0 0315
+Í "
+^I 5,12 0 0316
+Î "
+:I 5,12 0 0317
+Ï "
+-D 10,9 0 0320
+Ð "
+~N 11,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,12 0 0326
+Ö "
+mu 8,7 0 0327
+× "
+/O 9,9 0 0330
+Ø "
+`U 8,12 0 0331
+Ù "
+'U 8,12 0 0332
+Ú "
+^U 8,12 0 0333
+Û "
+:U 8,12 0 0334
+Ü "
+'Y 8,12 0 0335
+Ý "
+TP 8,9 0 0336
+Þ "
+ss 8,9,3 0 0337
+ß "
+`a 8,9 0 0340
+à "
+'a 8,9 0 0341
+á "
+^a 8,9 0 0342
+â "
+~a 8,9 0 0343
+ã "
+:a 8,9 0 0344
+ä "
+oa 8,10 0 0345
+å "
+ae 9,6 0 0346
+æ "
+,c 6,6,3 0 0347
+ç "
+`e 6,9 0 0350
+è "
+'e 6,9 0 0351
+é "
+^e 6,9 0 0352
+ê "
+:e 6,9 0 0353
+ë "
+`i 4,9 0 0354
+ì "
+'i 4,9 0 0355
+í "
+^i 4,9 0 0356
+î "
+:i 4,9 0 0357
+ï "
+Sd 6,9 0 0360
+ð "
+~n 8,9 0 0361
+ñ "
+`o 6,9 0 0362
+ò "
+'o 6,9 0 0363
+ó "
+^o 6,9 0 0364
+ô "
+~o 6,9 0 0365
+õ "
+:o 6,9 0 0366
+ö "
+di 8,7 0 0367
+÷ "
+/o 6,6 0 0370
+ø "
+`u 8,9 0 0371
+ù "
+'u 8,9 0 0372
+ú "
+^u 8,9 0 0373
+û "
+:u 8,9 0 0374
+ü "
+'y 6,9,3 0 0375
+ý "
+Tp 7,9,3 0 0376
+þ "
+:y 8,9,3 0 0377
+ÿ "
diff --git a/font/devX75-12/NR b/font/devX75-12/NR
new file mode 100644
index 00000000..a1df4867
--- /dev/null
+++ b/font/devX75-12/NR
@@ -0,0 +1,306 @@
+name NR
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,9 0 041
+" 6,9 0 042
+# 8,8 0 043
+sh "
+$ 6,10,1 0 044
+Do "
+% 11,9 0 045
+& 9,9 0 046
+' 4,9 0 047
+( 4,9,2 0 050
+) 4,9,2 0 051
+* 6,9 0 052
++ 8,7 0 053
+, 4,2,1 0 054
+\- 7,4 0 055
+. 4,2 0 056
+/ 4,9 0 057
+sl "
+0 6,9 0 060
+1 6,9 0 061
+2 6,9 0 062
+3 6,9 0 063
+4 6,9 0 064
+5 6,9 0 065
+6 6,9 0 066
+7 6,9 0 067
+8 6,9 0 070
+9 6,9 0 071
+: 4,6 0 072
+; 4,6,1 0 073
+< 7,6 0 074
+= 7,5 0 075
+eq "
+> 7,6 0 076
+? 5,9 0 077
+@ 10,9 0 0100
+at "
+A 10,9 0 0101
+B 8,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 8,9 0 0105
+F 8,9 0 0106
+G 10,9 0 0107
+H 10,9 0 0110
+I 6,9 0 0111
+J 7,9 0 0112
+K 9,9 0 0113
+L 8,9 0 0114
+M 12,9 0 0115
+N 10,9 0 0116
+O 9,9 0 0117
+P 8,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 7,9 0 0123
+T 8,9 0 0124
+U 10,9 0 0125
+V 10,9 0 0126
+W 12,9 0 0127
+X 9,9 0 0130
+Y 10,9 0 0131
+Z 7,9 0 0132
+[ 4,9,2 0 0133
+lB "
+\ 6,9 0 0134
+rs "
+] 4,9,2 0 0135
+rB "
+^ 6,9 0 0136
+a^ "
+ha "
+_ 8,0,2 0 0137
+` 4,9 0 0140
+oq "
+a 7,6 0 0141
+b 6,9 0 0142
+c 6,6 0 0143
+d 7,9 0 0144
+e 6,6 0 0145
+f 4,9 0 0146
+g 7,7,3 0 0147
+h 8,9 0 0150
+i 4,9 0 0151
+j 4,9,3 0 0152
+k 7,9 0 0153
+l 4,9 0 0154
+m 12,6 0 0155
+n 8,6 0 0156
+o 6,6 0 0157
+p 7,6,3 0 0160
+q 6,6,3 0 0161
+r 6,6 0 0162
+s 6,6 0 0163
+t 4,8 0 0164
+u 8,6 0 0165
+v 6,6 0 0166
+w 10,6 0 0167
+x 7,6 0 0170
+y 6,6,3 0 0171
+z 6,6 0 0172
+{ 4,9,2 0 0173
+lC "
+| 8,9 0 0174
+or "
+ba "
+} 4,9,2 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,7,2 0 0241
+¡ "
+ct 7,7,1 0 0242
+¢ "
+Po 8,9 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 8,9 0 0245
+¥ "
+bb 8,9 0 0246
+¦ "
+sc 6,9,2 0 0247
+§ "
+ad 4,9 0 0250
+¨ "
+co 11,9 0 0251
+© "
+Of 5,9 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 5,8 0 0257
+¯ "
+de 5,9 0 0260
+° "
++- 8,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 3,9 0 0264
+´ "
+µ 8,6,3 0 0265
+ps 8,9,2 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 4,0,3 0 0270
+¸ "
+S1 4,9 0 0271
+¹ "
+Om 5,9 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 9,9 0 0274
+¼ "
+12 9,9 0 0275
+½ "
+34 9,9 0 0276
+¾ "
+r? 5,7,2 0 0277
+¿ "
+`A 10,12 0 0300
+À "
+'A 10,12 0 0301
+Á "
+^A 10,12 0 0302
+Â "
+~A 10,12 0 0303
+Ã "
+:A 10,12 0 0304
+Ä "
+oA 10,12 0 0305
+Å "
+AE 13,9 0 0306
+Æ "
+,C 9,9,3 0 0307
+Ç "
+`E 8,12 0 0310
+È "
+'E 8,12 0 0311
+É "
+^E 8,12 0 0312
+Ê "
+:E 8,12 0 0313
+Ë "
+`I 6,12 0 0314
+Ì "
+'I 6,12 0 0315
+Í "
+^I 6,12 0 0316
+Î "
+:I 6,12 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 10,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,12 0 0326
+Ö "
+mu 8,7 0 0327
+× "
+/O 9,9 0 0330
+Ø "
+`U 10,12 0 0331
+Ù "
+'U 10,12 0 0332
+Ú "
+^U 10,12 0 0333
+Û "
+:U 10,12 0 0334
+Ü "
+'Y 10,12 0 0335
+Ý "
+TP 8,9 0 0336
+Þ "
+ss 7,9 0 0337
+ß "
+`a 7,9 0 0340
+à "
+'a 7,9 0 0341
+á "
+^a 7,9 0 0342
+â "
+~a 7,9 0 0343
+ã "
+:a 7,9 0 0344
+ä "
+oa 7,9 0 0345
+å "
+ae 10,6 0 0346
+æ "
+,c 6,6,3 0 0347
+ç "
+`e 6,9 0 0350
+è "
+'e 6,9 0 0351
+é "
+^e 6,9 0 0352
+ê "
+:e 6,9 0 0353
+ë "
+`i 4,9 0 0354
+ì "
+'i 4,9 0 0355
+í "
+^i 4,9 0 0356
+î "
+:i 4,9 0 0357
+ï "
+Sd 6,9 0 0360
+ð "
+~n 8,9 0 0361
+ñ "
+`o 6,9 0 0362
+ò "
+'o 6,9 0 0363
+ó "
+^o 6,9 0 0364
+ô "
+~o 6,9 0 0365
+õ "
+:o 6,8 0 0366
+ö "
+di 8,7 0 0367
+÷ "
+/o 6,7,1 0 0370
+ø "
+`u 8,9 0 0371
+ù "
+'u 8,9 0 0372
+ú "
+^u 8,9 0 0373
+û "
+:u 8,9 0 0374
+ü "
+'y 6,9,3 0 0375
+ý "
+Tp 7,9,3 0 0376
+þ "
+:y 6,9,3 0 0377
+ÿ "
diff --git a/font/devX75-12/S b/font/devX75-12/S
new file mode 100644
index 00000000..2e66ad09
--- /dev/null
+++ b/font/devX75-12/S
@@ -0,0 +1,226 @@
+name S
+special
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,9 0 041
+fa 9,9 0 042
+# 7,9 0 043
+sh "
+te 7,9 0 044
+% 10,9 0 045
+& 10,9 0 046
+st 6,6 0 047
+( 5,9,3 0 050
+) 5,9,3 0 051
+** 6,7 0 052
++ 7,6 0 053
+pl "
+, 3,1,2 0 054
+\- 7,4 0 055
+mi "
+. 3,1 0 056
+/ 3,9 0 057
+sl "
+0 6,9 0 060
+1 6,9 0 061
+2 6,9 0 062
+3 6,9 0 063
+4 6,9 0 064
+5 6,9 0 065
+6 6,9 0 066
+7 6,9 0 067
+8 6,9 0 070
+9 6,9 0 071
+: 3,6 0 072
+; 3,6,2 0 073
+< 7,6 0 074
+= 7,5 0 075
+eq "
+> 7,6 0 076
+? 6,9 0 077
+=~ 7,6 0 0100
+*A 9,9 0 0101
+*B 8,9 0 0102
+*X 9,9 0 0103
+*D 8,9 0 0104
+*E 8,9 0 0105
+*F 10,9 0 0106
+*G 8,9 0 0107
+*Y 9,9 0 0110
+*I 4,9 0 0111
++h 8,9 0 0112
+*K 9,9 0 0113
+*L 9,9 0 0114
+*M 11,9 0 0115
+*N 9,9 0 0116
+*O 9,9 0 0117
+*P 9,9 0 0120
+*H 9,9 0 0121
+*R 7,9 0 0122
+*S 7,9 0 0123
+*T 8,9 0 0124
+--- 9,9 0 0125
+ts 7,6,3 0 0126
+*W 10,9 0 0127
+*C 8,9 0 0130
+*Q 10,9 0 0131
+*Z 8,9 0 0132
+[ 5,9,3 0 0133
+lB "
+tf 9,6 0 0134
+3d "
+] 5,9,3 0 0135
+rB "
+pp 8,9 0 0136
+_ 6,0,3 0 0137
+radicalex 6,12 0 0140
+*a 8,6 0 0141
+*b 7,10,3 0 0142
+*x 7,6,3 0 0143
+*d 7,10 0 0144
+*e 6,6 0 0145
+*f 8,8,3 0 0146
+*g 7,6,3 0 0147
+*y 8,6,3 0 0150
+*i 3,6 0 0151
++f 8,6,3 0 0152
+*k 7,6 0 0153
+*l 7,9 0 0154
+*m 8,6,3 0 0155
+µ "
+*n 7,6 0 0156
+*o 7,6 0 0157
+*p 7,6 0 0160
+*h 7,9 0 0161
+*r 7,6,3 0 0162
+*s 8,6 0 0163
+*t 6,6 0 0164
+*u 8,6 0 0165
++p 9,7 0 0166
+*w 9,6 0 0167
+*c 6,11,3 0 0170
+*q 9,6,3 0 0171
+*z 6,10,3 0 0172
+lC 6,9,3 0 0173
+{ "
+ba 3,9,3 0 0174
+or "
+| "
+rC 6,9,3 0 0175
+} "
+ap 7,5 0 0176
+*U 8,9 0 0241
+fm 3,9 0 0242
+<= 7,7 0 0243
+f/ 4,9 0 0244
+if 9,5 0 0245
+Fn 6,9,3 0 0246
+CL 9,6,1 0 0247
+DI 7,6 0 0250
+HE 9,6 0 0251
+SP 9,6,1 0 0252
+<> 13,6 0 0253
+<- 12,6 0 0254
+ua 7,12,4 0 0255
+arrowverttp "
+-> 12,6 0 0256
+da 7,12,3 0 0257
+arrowvertbt "
+de 5,9 0 0260
+° "
++- 7,7 0 0261
+± "
+sd 5,9 0 0262
+>= 7,7 0 0263
+mu 7,6 0 0264
+× "
+pt 9,5 0 0265
+pd 6,10 0 0266
+bu 6,5 0 0267
+di 7,6 0 0270
+÷ "
+!= 7,7 0 0271
+== 7,6 0 0272
+~= 7,6 0 0273
+~~ "
+--- 11,1 0 0274
+arrowvertex 7,12,4 0 0275
+an 13,4 0 0276
+CR 8,8 0 0277
+Ah 10,9 0 0300
+Im 9,10,1 0 0301
+Re 10,10 0 0302
+wp 10,8,3 0 0303
+c* 10,9 0 0304
+c+ 10,9 0 0305
+es 10,9 0 0306
+ca 10,6 0 0307
+cu 10,6 0 0310
+sp 9,6 0 0311
+ip 9,6,2 0 0312
+--- 9,7,1 0 0313
+sb 9,6 0 0314
+ib 9,6,2 0 0315
+mo 8,6 0 0316
+nm 8,7,1 0 0317
+/_ 10,9 0 0320
+gr 9,9 0 0321
+rg 10,9 0 0322
+co 10,9 0 0323
+tm 11,9 0 0324
+--- 10,10,1 0 0325
+sr 7,12 0 0326
+md 3,4 0 0327
+no 9,4 0 0330
+¬ "
+AN 8,6 0 0331
+OR 8,6 0 0332
+hA 13,6 0 0333
+lA 12,6 0 0334
+uA 8,11,1 0 0335
+rA 12,6 0 0336
+dA 8,12 0 0337
+lz 6,9 0 0340
+la 4,10,1 0 0341
+--- 10,9 0 0342
+--- 10,9 0 0343
+--- 10,9 0 0344
+--- 9,10,1 0 0345
+parenlefttp 5,12,4 0 0346
+parenleftex 5,12,4 0 0347
+parenleftbt 5,12,4 0 0350
+bracketlefttp 5,12,4 0 0351
+lc "
+bracketleftex 5,12,4 0 0352
+bracketleftbt 5,12,3 0 0353
+lf "
+bracelefttp 6,12,4 0 0354
+lt "
+braceleftmid 6,12,4 0 0355
+lk "
+braceleftbt 6,12,3 0 0356
+lb "
+bracerightex 6,12,4 0 0357
+braceleftex "
+bv "
+--- 10,11 0 0360
+ra 4,10,2 0 0361
+is 4,12,3 0 0362
+--- 9,12,4 0 0363
+--- 9,12,4 0 0364
+--- 9,12,3 0 0365
+parenrighttp 5,12,4 0 0366
+parenrightex 5,12,4 0 0367
+parenrightbt 5,12,4 0 0370
+bracketrighttp 5,12,4 0 0371
+rc "
+bracketrightex 5,12,4 0 0372
+bracketrightbt 5,12,3 0 0373
+rf "
+bracerighttp 6,12,4 0 0374
+rt "
+bracerightmid 6,12,4 0 0375
+rk "
+bracerightbt 6,12,3 0 0376
+rb "
diff --git a/font/devX75-12/TB b/font/devX75-12/TB
new file mode 100644
index 00000000..348d3881
--- /dev/null
+++ b/font/devX75-12/TB
@@ -0,0 +1,306 @@
+name TB
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,9 0 041
+" 5,9 0 042
+# 6,9 0 043
+sh "
+$ 6,10,1 0 044
+Do "
+% 12,9 0 045
+& 10,9 0 046
+' 4,9 0 047
+( 4,9,3 0 050
+) 4,9,3 0 051
+* 6,9 0 052
++ 7,6 0 053
+, 4,2,2 0 054
+\- 8,4 0 055
+. 4,2 0 056
+/ 4,9 0 057
+sl "
+0 6,9 0 060
+1 6,9 0 061
+2 6,9 0 062
+3 6,9 0 063
+4 6,9 0 064
+5 6,9 0 065
+6 6,9 0 066
+7 6,9 0 067
+8 6,9 0 070
+9 6,9 0 071
+: 4,6 0 072
+; 4,6,2 0 073
+< 7,6 0 074
+= 7,5 0 075
+eq "
+> 8,6 0 076
+? 7,9 0 077
+@ 12,9,2 0 0100
+at "
+A 9,9 0 0101
+B 9,9 0 0102
+C 8,9 0 0103
+D 9,9 0 0104
+E 8,9 0 0105
+F 8,9 0 0106
+G 9,9 0 0107
+H 10,9 0 0110
+I 5,9 0 0111
+J 7,9,1 0 0112
+K 10,9 0 0113
+L 8,9 0 0114
+M 11,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 8,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 7,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 9,9 0 0126
+W 12,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 8,9 0 0132
+[ 4,9,3 0 0133
+lB "
+\ 3,9 0 0134
+rs "
+] 4,9,3 0 0135
+rB "
+^ 7,9 0 0136
+a^ "
+ha "
+_ 6,0,3 0 0137
+` 4,9 0 0140
+oq "
+a 7,6 0 0141
+b 6,9 0 0142
+c 6,6 0 0143
+d 6,9 0 0144
+e 7,6 0 0145
+f 4,9 0 0146
+g 6,6,3 0 0147
+h 6,9 0 0150
+i 3,9 0 0151
+j 3,9,3 0 0152
+k 7,9 0 0153
+l 3,9 0 0154
+m 9,6 0 0155
+n 6,6 0 0156
+o 7,6 0 0157
+p 6,6,3 0 0160
+q 6,6,3 0 0161
+r 5,6 0 0162
+s 6,6 0 0163
+t 4,8 0 0164
+u 6,6 0 0165
+v 6,6 0 0166
+w 9,6 0 0167
+x 6,6 0 0170
+y 6,6,3 0 0171
+z 6,6 0 0172
+{ 5,9,3 0 0173
+lC "
+| 3,9,3 0 0174
+or "
+ba "
+} 5,9,3 0 0175
+rC "
+~ 7,6 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,3 0 0241
+¡ "
+ct 6,7,2 0 0242
+¢ "
+Po 6,9 0 0243
+£ "
+Cs 7,8 0 0244
+¤ "
+Ye 8,9 0 0245
+¥ "
+bb 3,9,3 0 0246
+¦ "
+sc 6,9,3 0 0247
+§ "
+ad 4,9 0 0250
+¨ "
+co 11,9 0 0251
+© "
+Of 4,9 0 0252
+ª "
+Fo 8,6 0 0253
+« "
+no 8,5 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 4,8 0 0257
+¯ "
+de 5,9 0 0260
+° "
++- 7,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 4,9 0 0264
+´ "
+µ 6,6,3 0 0265
+ps 8,9,3 0 0266
+¶ "
+md 3,5 0 0267
+· "
+ac 4,0,3 0 0270
+¸ "
+S1 4,9 0 0271
+¹ "
+Om 4,9 0 0272
+º "
+Fc 8,6 0 0273
+» "
+14 9,9 0 0274
+¼ "
+12 9,9 0 0275
+½ "
+34 9,9 0 0276
+¾ "
+r? 7,6,3 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,12 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 13,9 0 0306
+Æ "
+,C 8,9,3 0 0307
+Ç "
+`E 8,12 0 0310
+È "
+'E 8,12 0 0311
+É "
+^E 8,12 0 0312
+Ê "
+:E 8,12 0 0313
+Ë "
+`I 5,12 0 0314
+Ì "
+'I 5,12 0 0315
+Í "
+^I 5,12 0 0316
+Î "
+:I 5,12 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,12 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 9,10,1 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,12 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 8,9 0 0336
+Þ "
+ss 8,9 0 0337
+ß "
+`a 7,9 0 0340
+à "
+'a 7,9 0 0341
+á "
+^a 7,9 0 0342
+â "
+~a 7,9 0 0343
+ã "
+:a 7,9 0 0344
+ä "
+oa 7,10 0 0345
+å "
+ae 8,6 0 0346
+æ "
+,c 6,6,3 0 0347
+ç "
+`e 7,9 0 0350
+è "
+'e 7,9 0 0351
+é "
+^e 7,9 0 0352
+ê "
+:e 7,9 0 0353
+ë "
+`i 3,9 0 0354
+ì "
+'i 3,9 0 0355
+í "
+^i 3,9 0 0356
+î "
+:i 3,9 0 0357
+ï "
+Sd 7,9 0 0360
+ð "
+~n 6,9 0 0361
+ñ "
+`o 7,9 0 0362
+ò "
+'o 7,9 0 0363
+ó "
+^o 7,9 0 0364
+ô "
+~o 7,9 0 0365
+õ "
+:o 7,9 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 7,7,1 0 0370
+ø "
+`u 6,9 0 0371
+ù "
+'u 6,9 0 0372
+ú "
+^u 6,9 0 0373
+û "
+:u 6,9 0 0374
+ü "
+'y 6,9,3 0 0375
+ý "
+Tp 6,9,3 0 0376
+þ "
+:y 6,9,3 0 0377
+ÿ "
diff --git a/font/devX75-12/TBI b/font/devX75-12/TBI
new file mode 100644
index 00000000..02793a58
--- /dev/null
+++ b/font/devX75-12/TBI
@@ -0,0 +1,306 @@
+name TBI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 5,9 0 041
+" 7,9 0 042
+# 7,9 0 043
+sh "
+$ 7,10,1 0 044
+Do "
+% 12,9 0 045
+& 9,9 0 046
+' 4,9 0 047
+( 6,9,2 0 050
+) 6,9,2 0 051
+* 6,9 0 052
++ 7,6 0 053
+, 4,2,1 0 054
+\- 8,4 0 055
+. 4,2 0 056
+/ 5,9 0 057
+sl "
+0 6,9 0 060
+1 6,9 0 061
+2 6,9 0 062
+3 6,9 0 063
+4 6,9 0 064
+5 6,9 0 065
+6 6,9 0 066
+7 6,9 0 067
+8 6,9 0 070
+9 6,9 0 071
+: 5,6 0 072
+; 5,6,1 0 073
+< 9,7 0 074
+= 8,5 0 075
+eq "
+> 9,7 0 076
+? 6,9 0 077
+@ 12,9,1 0 0100
+at "
+A 8,9 0 0101
+B 8,9 0 0102
+C 8,9 0 0103
+D 9,9 0 0104
+E 8,9 0 0105
+F 8,9 0 0106
+G 9,9 0 0107
+H 10,9 0 0110
+I 5,9 0 0111
+J 6,9,1 0 0112
+K 8,9 0 0113
+L 8,9 0 0114
+M 11,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 8,9 0 0120
+Q 9,9,3 0 0121
+R 8,9 0 0122
+S 8,9 0 0123
+T 7,9 0 0124
+U 10,9 0 0125
+V 8,9 0 0126
+W 11,9 0 0127
+X 8,9 0 0130
+Y 7,9 0 0131
+Z 7,9 0 0132
+[ 6,9,2 0 0133
+lB "
+\ 5,9 0 0134
+rs "
+] 7,9,2 0 0135
+rB "
+^ 8,9 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 5,9 0 0140
+oq "
+a 7,6 0 0141
+b 6,9 0 0142
+c 5,6 0 0143
+d 6,9 0 0144
+e 6,6 0 0145
+f 3,9,3 0 0146
+g 5,6,3 0 0147
+h 6,9 0 0150
+i 4,9 0 0151
+j 4,9,3 0 0152
+k 6,9 0 0153
+l 4,9 0 0154
+m 9,6 0 0155
+n 6,6 0 0156
+o 6,6 0 0157
+p 6,6,3 0 0160
+q 6,6,3 0 0161
+r 5,6 0 0162
+s 5,6 0 0163
+t 3,7 0 0164
+u 7,6 0 0165
+v 6,6 0 0166
+w 8,6 0 0167
+x 6,6 0 0170
+y 6,6,3 0 0171
+z 6,6,1 0 0172
+{ 6,9,2 0 0173
+lC "
+| 4,9 0 0174
+or "
+ba "
+} 6,9,2 0 0175
+rC "
+~ 9,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,3 0 0241
+¡ "
+ct 6,8,2 0 0242
+¢ "
+Po 6,9 0 0243
+£ "
+Cs 8,7 0 0244
+¤ "
+Ye 6,9 0 0245
+¥ "
+bb 4,9 0 0246
+¦ "
+sc 7,9,3 0 0247
+§ "
+ad 5,9 0 0250
+¨ "
+co 11,9 0 0251
+© "
+Of 6,9 0 0252
+ª "
+Fo 9,6 0 0253
+« "
+no 8,6 0 0254
+¬ "
+- 6,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 4,8 0 0257
+¯ "
+de 5,9 0 0260
+° "
++- 7,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 4,9 0 0264
+´ "
+µ 7,6,3 0 0265
+ps 7,9,3 0 0266
+¶ "
+md 3,5 0 0267
+· "
+ac 4,0,3 0 0270
+¸ "
+S1 4,9 0 0271
+¹ "
+Om 6,9 0 0272
+º "
+Fc 9,6 0 0273
+» "
+14 9,9 0 0274
+¼ "
+12 9,9 0 0275
+½ "
+34 9,9 0 0276
+¾ "
+r? 6,6,3 0 0277
+¿ "
+`A 8,12 0 0300
+À "
+'A 8,12 0 0301
+Á "
+^A 8,12 0 0302
+Â "
+~A 8,12 0 0303
+Ã "
+:A 8,12 0 0304
+Ä "
+oA 8,12 0 0305
+Å "
+AE 12,9 0 0306
+Æ "
+,C 8,9,3 0 0307
+Ç "
+`E 8,12 0 0310
+È "
+'E 8,12 0 0311
+É "
+^E 8,12 0 0312
+Ê "
+:E 8,12 0 0313
+Ë "
+`I 5,12 0 0314
+Ì "
+'I 5,12 0 0315
+Í "
+^I 5,12 0 0316
+Î "
+:I 5,12 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,11 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,12 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 9,10,1 0 0330
+Ø "
+`U 10,12 0 0331
+Ù "
+'U 10,12 0 0332
+Ú "
+^U 10,12 0 0333
+Û "
+:U 10,12 0 0334
+Ü "
+'Y 7,12 0 0335
+Ý "
+TP 8,9 0 0336
+Þ "
+ss 7,9,3 0 0337
+ß "
+`a 7,9 0 0340
+à "
+'a 7,9 0 0341
+á "
+^a 7,9 0 0342
+â "
+~a 7,9 0 0343
+ã "
+:a 7,9 0 0344
+ä "
+oa 7,9 0 0345
+å "
+ae 10,6 0 0346
+æ "
+,c 5,6,3 0 0347
+ç "
+`e 6,9 0 0350
+è "
+'e 6,9 0 0351
+é "
+^e 6,9 0 0352
+ê "
+:e 6,9 0 0353
+ë "
+`i 3,9 0 0354
+ì "
+'i 3,9 0 0355
+í "
+^i 3,9 0 0356
+î "
+:i 3,9 0 0357
+ï "
+Sd 6,9 0 0360
+ð "
+~n 7,9 0 0361
+ñ "
+`o 6,9 0 0362
+ò "
+'o 6,9 0 0363
+ó "
+^o 6,9 0 0364
+ô "
+~o 6,9 0 0365
+õ "
+:o 6,9 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 6,7,1 0 0370
+ø "
+`u 7,9 0 0371
+ù "
+'u 7,9 0 0372
+ú "
+^u 7,9 0 0373
+û "
+:u 7,9 0 0374
+ü "
+'y 6,9,3 0 0375
+ý "
+Tp 6,9,3 0 0376
+þ "
+:y 6,9,3 0 0377
+ÿ "
diff --git a/font/devX75-12/TI b/font/devX75-12/TI
new file mode 100644
index 00000000..dd79bd1d
--- /dev/null
+++ b/font/devX75-12/TI
@@ -0,0 +1,306 @@
+name TI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,9 0 041
+" 5,9 0 042
+# 6,9 0 043
+sh "
+$ 6,10,1 0 044
+Do "
+% 10,9 0 045
+& 9,9 0 046
+' 4,9 0 047
+( 4,9,3 0 050
+) 4,9,3 0 051
+* 6,9 0 052
++ 8,6 0 053
+, 3,1,2 0 054
+\- 8,4 0 055
+. 3,1 0 056
+/ 4,9 0 057
+sl "
+0 6,9 0 060
+1 6,9 0 061
+2 6,9 0 062
+3 6,9 0 063
+4 6,9 0 064
+5 6,9 0 065
+6 6,9 0 066
+7 6,9 0 067
+8 6,9 0 070
+9 6,9 0 071
+: 4,6 0 072
+; 4,6,2 0 073
+< 8,7 0 074
+= 8,5 0 075
+eq "
+> 8,7 0 076
+? 6,9 0 077
+@ 12,9,1 0 0100
+at "
+A 8,9 0 0101
+B 8,9 0 0102
+C 7,9 0 0103
+D 9,9 0 0104
+E 8,9 0 0105
+F 8,9 0 0106
+G 8,9 0 0107
+H 9,9 0 0110
+I 5,9 0 0111
+J 5,9 0 0112
+K 8,9 0 0113
+L 7,9 0 0114
+M 11,9 0 0115
+N 9,9 0 0116
+O 7,9 0 0117
+P 8,9 0 0120
+Q 7,9,2 0 0121
+R 8,9 0 0122
+S 6,9 0 0123
+T 7,9 0 0124
+U 8,9 0 0125
+V 7,9 0 0126
+W 10,9 0 0127
+X 8,9 0 0130
+Y 7,9 0 0131
+Z 7,9 0 0132
+[ 5,9,2 0 0133
+lB "
+\ 3,9 0 0134
+rs "
+] 5,9,2 0 0135
+rB "
+^ 5,9 0 0136
+a^ "
+ha "
+_ 6,0,3 0 0137
+` 4,9 0 0140
+oq "
+a 6,6 0 0141
+b 6,9 0 0142
+c 5,6 0 0143
+d 6,9 0 0144
+e 6,6 0 0145
+f 4,9,3 0 0146
+g 5,6,3 0 0147
+h 6,9 0 0150
+i 4,9 0 0151
+j 4,9,3 0 0152
+k 6,9 0 0153
+l 3,9 0 0154
+m 9,6 0 0155
+n 6,6 0 0156
+o 6,6 0 0157
+p 6,6,3 0 0160
+q 6,6,3 0 0161
+r 4,6 0 0162
+s 5,6 0 0163
+t 4,7 0 0164
+u 6,6 0 0165
+v 6,6 0 0166
+w 9,6 0 0167
+x 6,6 0 0170
+y 6,6,3 0 0171
+z 5,6 0 0172
+{ 5,9,3 0 0173
+lC "
+| 4,9,3 0 0174
+or "
+ba "
+} 5,9,3 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 5,6,3 0 0241
+¡ "
+ct 6,8,2 0 0242
+¢ "
+Po 6,9 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 6,9 0 0245
+¥ "
+bb 4,9,3 0 0246
+¦ "
+sc 6,9,2 0 0247
+§ "
+ad 4,8 0 0250
+¨ "
+co 11,9 0 0251
+© "
+Of 4,9 0 0252
+ª "
+Fo 6,6 0 0253
+« "
+no 8,5 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 4,8 0 0257
+¯ "
+de 5,9 0 0260
+° "
++- 8,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 4,9 0 0264
+´ "
+µ 6,6,3 0 0265
+ps 7,9,2 0 0266
+¶ "
+md 3,4 0 0267
+· "
+ac 4,0,3 0 0270
+¸ "
+S1 3,9 0 0271
+¹ "
+Om 4,9 0 0272
+º "
+Fc 6,6 0 0273
+» "
+14 9,9 0 0274
+¼ "
+12 9,9 0 0275
+½ "
+34 9,9 0 0276
+¾ "
+r? 6,6,3 0 0277
+¿ "
+`A 8,12 0 0300
+À "
+'A 8,12 0 0301
+Á "
+^A 8,12 0 0302
+Â "
+~A 8,12 0 0303
+Ã "
+:A 8,11 0 0304
+Ä "
+oA 8,12 0 0305
+Å "
+AE 11,9 0 0306
+Æ "
+,C 7,9,3 0 0307
+Ç "
+`E 8,12 0 0310
+È "
+'E 8,12 0 0311
+É "
+^E 8,12 0 0312
+Ê "
+:E 8,11 0 0313
+Ë "
+`I 5,12 0 0314
+Ì "
+'I 5,12 0 0315
+Í "
+^I 5,12 0 0316
+Î "
+:I 5,11 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 7,12 0 0322
+Ò "
+'O 7,12 0 0323
+Ó "
+^O 7,12 0 0324
+Ô "
+~O 7,12 0 0325
+Õ "
+:O 7,11 0 0326
+Ö "
+mu 8,6 0 0327
+× "
+/O 7,10,1 0 0330
+Ø "
+`U 8,12 0 0331
+Ù "
+'U 8,12 0 0332
+Ú "
+^U 8,12 0 0333
+Û "
+:U 8,11 0 0334
+Ü "
+'Y 7,12 0 0335
+Ý "
+TP 8,9 0 0336
+Þ "
+ss 6,9,3 0 0337
+ß "
+`a 7,9 0 0340
+à "
+'a 7,9 0 0341
+á "
+^a 7,9 0 0342
+â "
+~a 7,9 0 0343
+ã "
+:a 7,8 0 0344
+ä "
+oa 7,9 0 0345
+å "
+ae 9,6 0 0346
+æ "
+,c 5,6,3 0 0347
+ç "
+`e 6,9 0 0350
+è "
+'e 6,9 0 0351
+é "
+^e 6,9 0 0352
+ê "
+:e 6,8 0 0353
+ë "
+`i 4,9 0 0354
+ì "
+'i 4,9 0 0355
+í "
+^i 4,9 0 0356
+î "
+:i 4,8 0 0357
+ï "
+Sd 6,9 0 0360
+ð "
+~n 6,9 0 0361
+ñ "
+`o 6,9 0 0362
+ò "
+'o 6,9 0 0363
+ó "
+^o 6,9 0 0364
+ô "
+~o 6,9 0 0365
+õ "
+:o 6,8 0 0366
+ö "
+di 8,6 0 0367
+÷ "
+/o 6,7,1 0 0370
+ø "
+`u 6,9 0 0371
+ù "
+'u 6,9 0 0372
+ú "
+^u 6,9 0 0373
+û "
+:u 6,8 0 0374
+ü "
+'y 6,9,3 0 0375
+ý "
+Tp 6,9,3 0 0376
+þ "
+:y 6,8,3 0 0377
+ÿ "
diff --git a/font/devX75-12/TR b/font/devX75-12/TR
new file mode 100644
index 00000000..da7c961a
--- /dev/null
+++ b/font/devX75-12/TR
@@ -0,0 +1,306 @@
+name TR
+spacewidth 3
+charset
+--- 3,1 0 040
+! 3,9 0 041
+" 5,9 0 042
+# 6,8 0 043
+sh "
+$ 6,10,1 0 044
+Do "
+% 9,9 0 045
+& 10,9 0 046
+' 4,9 0 047
+( 5,9,3 0 050
+) 5,9,3 0 051
+* 6,9 0 052
++ 7,6 0 053
+, 3,1,2 0 054
+\- 8,4 0 055
+. 3,1 0 056
+/ 3,9 0 057
+sl "
+0 6,9 0 060
+1 6,9 0 061
+2 6,9 0 062
+3 6,9 0 063
+4 6,9 0 064
+5 6,9 0 065
+6 6,9 0 066
+7 6,9 0 067
+8 6,9 0 070
+9 6,9 0 071
+: 3,6 0 072
+; 3,6,2 0 073
+< 8,6 0 074
+= 7,5 0 075
+eq "
+> 8,6 0 076
+? 5,9 0 077
+@ 11,9,2 0 0100
+at "
+A 9,9 0 0101
+B 8,9 0 0102
+C 8,9 0 0103
+D 9,9 0 0104
+E 8,9 0 0105
+F 8,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 4,9 0 0111
+J 4,9 0 0112
+K 8,9 0 0113
+L 7,9 0 0114
+M 11,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 7,9 0 0120
+Q 9,9,2 0 0121
+R 8,9 0 0122
+S 7,9 0 0123
+T 7,9 0 0124
+U 8,9 0 0125
+V 9,9 0 0126
+W 12,9 0 0127
+X 8,9 0 0130
+Y 9,9 0 0131
+Z 8,9 0 0132
+[ 5,9,3 0 0133
+lB "
+\ 3,9 0 0134
+rs "
+] 5,9,3 0 0135
+rB "
+^ 6,9 0 0136
+a^ "
+ha "
+_ 6,0,3 0 0137
+` 4,9 0 0140
+oq "
+a 6,6 0 0141
+b 6,9 0 0142
+c 5,6 0 0143
+d 6,9 0 0144
+e 6,6 0 0145
+f 3,9 0 0146
+g 6,6,3 0 0147
+h 6,9 0 0150
+i 3,9 0 0151
+j 3,9,3 0 0152
+k 6,9 0 0153
+l 3,9 0 0154
+m 9,6 0 0155
+n 6,6 0 0156
+o 6,6 0 0157
+p 6,6,3 0 0160
+q 6,6,3 0 0161
+r 4,6 0 0162
+s 6,6 0 0163
+t 4,7 0 0164
+u 6,6 0 0165
+v 6,6 0 0166
+w 9,6 0 0167
+x 6,6 0 0170
+y 6,6,3 0 0171
+z 6,6 0 0172
+{ 6,9,3 0 0173
+lC "
+| 3,9 0 0174
+or "
+ba "
+} 6,9,3 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,3 0 0241
+¡ "
+ct 6,7,1 0 0242
+¢ "
+Po 6,9 0 0243
+£ "
+Cs 7,8 0 0244
+¤ "
+Ye 6,9 0 0245
+¥ "
+bb 3,9 0 0246
+¦ "
+sc 6,9,3 0 0247
+§ "
+ad 3,8 0 0250
+¨ "
+co 11,9 0 0251
+© "
+Of 5,9 0 0252
+ª "
+Fo 7,5 0 0253
+« "
+no 8,5 0 0254
+¬ "
+- 6,4 0 0255
+hy "
+­ "
+rg 11,9 0 0256
+® "
+a- 4,8 0 0257
+¯ "
+de 5,9 0 0260
+° "
++- 7,7 0 0261
+± "
+S2 4,9 0 0262
+² "
+S3 4,9 0 0263
+³ "
+aa 4,9 0 0264
+´ "
+µ 6,6,3 0 0265
+ps 7,9,3 0 0266
+¶ "
+md 3,4 0 0267
+· "
+ac 3,0,3 0 0270
+¸ "
+S1 4,9 0 0271
+¹ "
+Om 5,9 0 0272
+º "
+Fc 7,5 0 0273
+» "
+14 9,9 0 0274
+¼ "
+12 9,9 0 0275
+½ "
+34 9,9 0 0276
+¾ "
+r? 5,6,3 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,11 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 11,9 0 0306
+Æ "
+,C 8,9,3 0 0307
+Ç "
+`E 8,12 0 0310
+È "
+'E 8,12 0 0311
+É "
+^E 8,12 0 0312
+Ê "
+:E 8,11 0 0313
+Ë "
+`I 4,12 0 0314
+Ì "
+'I 4,12 0 0315
+Í "
+^I 4,12 0 0316
+Î "
+:I 4,11 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,11 0 0326
+Ö "
+mu 7,6 0 0327
+× "
+/O 9,10 0 0330
+Ø "
+`U 8,12 0 0331
+Ù "
+'U 8,12 0 0332
+Ú "
+^U 8,12 0 0333
+Û "
+:U 8,11 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 7,9 0 0336
+Þ "
+ss 6,9 0 0337
+ß "
+`a 6,9 0 0340
+à "
+'a 6,9 0 0341
+á "
+^a 6,9 0 0342
+â "
+~a 6,9 0 0343
+ã "
+:a 6,8 0 0344
+ä "
+oa 6,9 0 0345
+å "
+ae 9,6 0 0346
+æ "
+,c 5,6,3 0 0347
+ç "
+`e 6,9 0 0350
+è "
+'e 6,9 0 0351
+é "
+^e 6,9 0 0352
+ê "
+:e 6,8 0 0353
+ë "
+`i 3,9 0 0354
+ì "
+'i 3,9 0 0355
+í "
+^i 3,9 0 0356
+î "
+:i 3,8 0 0357
+ï "
+Sd 6,9 0 0360
+ð "
+~n 6,9 0 0361
+ñ "
+`o 6,9 0 0362
+ò "
+'o 6,9 0 0363
+ó "
+^o 6,9 0 0364
+ô "
+~o 6,9 0 0365
+õ "
+:o 6,8 0 0366
+ö "
+di 7,6 0 0367
+÷ "
+/o 6,6,1 0 0370
+ø "
+`u 6,9 0 0371
+ù "
+'u 6,9 0 0372
+ú "
+^u 6,9 0 0373
+û "
+:u 6,8 0 0374
+ü "
+'y 6,9,3 0 0375
+ý "
+Tp 6,9,3 0 0376
+þ "
+:y 6,8,3 0 0377
+ÿ "
diff --git a/font/devX75/CB b/font/devX75/CB
new file mode 100644
index 00000000..55831359
--- /dev/null
+++ b/font/devX75/CB
@@ -0,0 +1,306 @@
+name CB
+spacewidth 6
+charset
+--- 6,1 0 040
+! 6,7 0 041
+" 6,6 0 042
+# 6,7 0 043
+sh "
+$ 6,7,1 0 044
+Do "
+% 6,6 0 045
+& 6,6 0 046
+' 6,7 0 047
+( 6,7,1 0 050
+) 6,7,1 0 051
+* 6,7 0 052
++ 6,6 0 053
+, 6,1,2 0 054
+\- 6,4 0 055
+. 6,1 0 056
+/ 6,7,1 0 057
+sl "
+0 6,7 0 060
+1 6,7 0 061
+2 6,7 0 062
+3 6,7 0 063
+4 6,7 0 064
+5 6,7 0 065
+6 6,7 0 066
+7 6,7 0 067
+8 6,7 0 070
+9 6,7 0 071
+: 6,4 0 072
+; 6,4,2 0 073
+< 6,6 0 074
+= 6,5 0 075
+eq "
+> 6,6 0 076
+? 6,6 0 077
+@ 6,7,1 0 0100
+at "
+A 6,6 0 0101
+B 6,6 0 0102
+C 6,6 0 0103
+D 6,6 0 0104
+E 6,6 0 0105
+F 6,6 0 0106
+G 6,6 0 0107
+H 6,6 0 0110
+I 6,6 0 0111
+J 6,6 0 0112
+K 6,6 0 0113
+L 6,6 0 0114
+M 6,6 0 0115
+N 6,6 0 0116
+O 6,6 0 0117
+P 6,6 0 0120
+Q 6,6,1 0 0121
+R 6,6 0 0122
+S 6,6 0 0123
+T 6,6 0 0124
+U 6,6 0 0125
+V 6,6 0 0126
+W 6,6 0 0127
+X 6,6 0 0130
+Y 6,6 0 0131
+Z 6,6 0 0132
+[ 6,7,1 0 0133
+lB "
+\ 6,7,1 0 0134
+rs "
+] 6,7,1 0 0135
+rB "
+^ 6,7 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 6,7 0 0140
+oq "
+a 6,5 0 0141
+b 6,7 0 0142
+c 6,5 0 0143
+d 6,7 0 0144
+e 6,5 0 0145
+f 6,7 0 0146
+g 6,5,2 0 0147
+h 6,7 0 0150
+i 6,7 0 0151
+j 6,7,2 0 0152
+k 6,7 0 0153
+l 6,7 0 0154
+m 6,5 0 0155
+n 6,5 0 0156
+o 6,5 0 0157
+p 6,5,2 0 0160
+q 6,5,2 0 0161
+r 6,5 0 0162
+s 6,5 0 0163
+t 6,7 0 0164
+u 6,5 0 0165
+v 6,5 0 0166
+w 6,5 0 0167
+x 6,5 0 0170
+y 6,5,2 0 0171
+z 6,5 0 0172
+{ 6,7,1 0 0173
+lC "
+| 6,7,2 0 0174
+or "
+ba "
+} 6,7,1 0 0175
+rC "
+~ 6,5 0 0176
+a~ "
+ap "
+ti "
+r! 6,5,2 0 0241
+¡ "
+ct 6,7,1 0 0242
+¢ "
+Po 6,7 0 0243
+£ "
+Cs 6,6 0 0244
+¤ "
+Ye 6,7 0 0245
+¥ "
+bb 6,7,2 0 0246
+¦ "
+sc 6,7,1 0 0247
+§ "
+ad 6,7 0 0250
+¨ "
+co 6,7 0 0251
+© "
+Of 6,7 0 0252
+ª "
+Fo 6,5 0 0253
+« "
+no 6,5 0 0254
+¬ "
+- 6,4 0 0255
+hy "
+­ "
+rg 6,7 0 0256
+® "
+a- 6,7 0 0257
+¯ "
+de 6,7 0 0260
+° "
++- 6,6 0 0261
+± "
+S2 6,7 0 0262
+² "
+S3 6,7 0 0263
+³ "
+aa 6,8 0 0264
+´ "
+µ 6,5,2 0 0265
+ps 6,7,1 0 0266
+¶ "
+md 6,5 0 0267
+· "
+ac 6,1,2 0 0270
+¸ "
+S1 6,7 0 0271
+¹ "
+Om 6,7 0 0272
+º "
+Fc 6,5 0 0273
+» "
+14 6,8,1 0 0274
+¼ "
+12 6,8,1 0 0275
+½ "
+34 6,8,1 0 0276
+¾ "
+r? 6,4,2 0 0277
+¿ "
+`A 6,9 0 0300
+À "
+'A 6,9 0 0301
+Á "
+^A 6,9 0 0302
+Â "
+~A 6,9 0 0303
+Ã "
+:A 6,9 0 0304
+Ä "
+oA 6,9 0 0305
+Å "
+AE 6,6 0 0306
+Æ "
+,C 6,6,2 0 0307
+Ç "
+`E 6,9 0 0310
+È "
+'E 6,9 0 0311
+É "
+^E 6,9 0 0312
+Ê "
+:E 6,9 0 0313
+Ë "
+`I 6,9 0 0314
+Ì "
+'I 6,9 0 0315
+Í "
+^I 6,9 0 0316
+Î "
+:I 6,9 0 0317
+Ï "
+-D 6,6 0 0320
+Ð "
+~N 6,9 0 0321
+Ñ "
+`O 6,9 0 0322
+Ò "
+'O 6,9 0 0323
+Ó "
+^O 6,9 0 0324
+Ô "
+~O 6,9 0 0325
+Õ "
+:O 6,9 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 6,6,1 0 0330
+Ø "
+`U 6,9 0 0331
+Ù "
+'U 6,9 0 0332
+Ú "
+^U 6,9 0 0333
+Û "
+:U 6,9 0 0334
+Ü "
+'Y 6,9 0 0335
+Ý "
+TP 6,6 0 0336
+Þ "
+ss 6,7 0 0337
+ß "
+`a 6,8 0 0340
+à "
+'a 6,8 0 0341
+á "
+^a 6,8 0 0342
+â "
+~a 6,8 0 0343
+ã "
+:a 6,8 0 0344
+ä "
+oa 6,9 0 0345
+å "
+ae 6,5 0 0346
+æ "
+,c 6,5,2 0 0347
+ç "
+`e 6,8 0 0350
+è "
+'e 6,8 0 0351
+é "
+^e 6,8 0 0352
+ê "
+:e 6,8 0 0353
+ë "
+`i 6,8 0 0354
+ì "
+'i 6,8 0 0355
+í "
+^i 6,8 0 0356
+î "
+:i 6,8 0 0357
+ï "
+Sd 6,8 0 0360
+ð "
+~n 6,8 0 0361
+ñ "
+`o 6,8 0 0362
+ò "
+'o 6,8 0 0363
+ó "
+^o 6,8 0 0364
+ô "
+~o 6,8 0 0365
+õ "
+:o 6,8 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 6,6,1 0 0370
+ø "
+`u 6,8 0 0371
+ù "
+'u 6,8 0 0372
+ú "
+^u 6,8 0 0373
+û "
+:u 6,8 0 0374
+ü "
+'y 6,8,2 0 0375
+ý "
+Tp 6,7,2 0 0376
+þ "
+:y 6,8,2 0 0377
+ÿ "
diff --git a/font/devX75/CBI b/font/devX75/CBI
new file mode 100644
index 00000000..e6281f44
--- /dev/null
+++ b/font/devX75/CBI
@@ -0,0 +1,306 @@
+name CBI
+spacewidth 6
+charset
+--- 6,1 0 040
+! 6,7 0 041
+" 6,7 0 042
+# 6,7 0 043
+sh "
+$ 6,7,1 0 044
+Do "
+% 6,7 0 045
+& 6,6 0 046
+' 6,7 0 047
+( 6,7,2 0 050
+) 6,7,2 0 051
+* 6,7 0 052
++ 6,6 0 053
+, 6,1,2 0 054
+\- 6,4 0 055
+. 6,1 0 056
+/ 6,7,1 0 057
+sl "
+0 6,7 0 060
+1 6,7 0 061
+2 6,7 0 062
+3 6,7 0 063
+4 6,7 0 064
+5 6,7 0 065
+6 6,7 0 066
+7 6,7 0 067
+8 6,7 0 070
+9 6,7 0 071
+: 6,4 0 072
+; 6,4,2 0 073
+< 6,6 0 074
+= 6,5 0 075
+eq "
+> 6,6 0 076
+? 6,7 0 077
+@ 6,7,1 0 0100
+at "
+A 6,6 0 0101
+B 6,6 0 0102
+C 6,6 0 0103
+D 6,6 0 0104
+E 6,6 0 0105
+F 6,6 0 0106
+G 6,6 0 0107
+H 6,6 0 0110
+I 6,6 0 0111
+J 6,6 0 0112
+K 6,6 0 0113
+L 6,6 0 0114
+M 6,6 0 0115
+N 6,6 0 0116
+O 6,6 0 0117
+P 6,6 0 0120
+Q 6,6,1 0 0121
+R 6,6 0 0122
+S 6,6 0 0123
+T 6,6 0 0124
+U 6,6 0 0125
+V 6,6 0 0126
+W 6,6 0 0127
+X 6,6 0 0130
+Y 6,6 0 0131
+Z 6,6 0 0132
+[ 6,7,2 0 0133
+lB "
+\ 6,7,1 0 0134
+rs "
+] 6,7,2 0 0135
+rB "
+^ 6,7 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 6,7 0 0140
+oq "
+a 6,5 0 0141
+b 6,7 0 0142
+c 6,5 0 0143
+d 6,7 0 0144
+e 6,5 0 0145
+f 6,7 0 0146
+g 6,5,2 0 0147
+h 6,7 0 0150
+i 6,7 0 0151
+j 6,7,2 0 0152
+k 6,7 0 0153
+l 6,7 0 0154
+m 6,5 0 0155
+n 6,5 0 0156
+o 6,5 0 0157
+p 6,5,2 0 0160
+q 6,5,2 0 0161
+r 6,5 0 0162
+s 6,5 0 0163
+t 6,7 0 0164
+u 6,5 0 0165
+v 6,5 0 0166
+w 6,5 0 0167
+x 6,5 0 0170
+y 6,5,2 0 0171
+z 6,5 0 0172
+{ 6,7,2 0 0173
+lC "
+| 6,7,1 0 0174
+or "
+ba "
+} 6,7,2 0 0175
+rC "
+~ 6,5 0 0176
+a~ "
+ap "
+ti "
+r! 6,5,2 0 0241
+¡ "
+ct 6,7,1 0 0242
+¢ "
+Po 6,6 0 0243
+£ "
+Cs 6,6 0 0244
+¤ "
+Ye 6,6 0 0245
+¥ "
+bb 6,7,1 0 0246
+¦ "
+sc 6,7,1 0 0247
+§ "
+ad 6,7 0 0250
+¨ "
+co 6,7 0 0251
+© "
+Of 6,6 0 0252
+ª "
+Fo 6,4 0 0253
+« "
+no 6,5 0 0254
+¬ "
+- 6,4 0 0255
+hy "
+­ "
+rg 6,7 0 0256
+® "
+a- 6,7 0 0257
+¯ "
+de 6,7 0 0260
+° "
++- 6,6 0 0261
+± "
+S2 6,7 0 0262
+² "
+S3 6,7 0 0263
+³ "
+aa 6,8 0 0264
+´ "
+µ 6,5,2 0 0265
+ps 6,7,1 0 0266
+¶ "
+md 6,4 0 0267
+· "
+ac 6,0,2 0 0270
+¸ "
+S1 6,7 0 0271
+¹ "
+Om 6,6 0 0272
+º "
+Fc 6,4 0 0273
+» "
+14 6,8,1 0 0274
+¼ "
+12 6,8,1 0 0275
+½ "
+34 6,8,1 0 0276
+¾ "
+r? 6,6,2 0 0277
+¿ "
+`A 6,9 0 0300
+À "
+'A 6,9 0 0301
+Á "
+^A 6,9 0 0302
+Â "
+~A 6,9 0 0303
+Ã "
+:A 6,8 0 0304
+Ä "
+oA 6,9 0 0305
+Å "
+AE 6,6 0 0306
+Æ "
+,C 6,6,2 0 0307
+Ç "
+`E 6,9 0 0310
+È "
+'E 6,9 0 0311
+É "
+^E 6,9 0 0312
+Ê "
+:E 6,8 0 0313
+Ë "
+`I 6,9 0 0314
+Ì "
+'I 6,9 0 0315
+Í "
+^I 6,9 0 0316
+Î "
+:I 6,8 0 0317
+Ï "
+-D 6,6 0 0320
+Ð "
+~N 6,9 0 0321
+Ñ "
+`O 6,9 0 0322
+Ò "
+'O 6,9 0 0323
+Ó "
+^O 6,9 0 0324
+Ô "
+~O 6,9 0 0325
+Õ "
+:O 6,8 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 6,7 0 0330
+Ø "
+`U 6,9 0 0331
+Ù "
+'U 6,9 0 0332
+Ú "
+^U 6,9 0 0333
+Û "
+:U 6,8 0 0334
+Ü "
+'Y 6,9 0 0335
+Ý "
+TP 6,6 0 0336
+Þ "
+ss 6,7 0 0337
+ß "
+`a 6,8 0 0340
+à "
+'a 6,8 0 0341
+á "
+^a 6,8 0 0342
+â "
+~a 6,8 0 0343
+ã "
+:a 6,7 0 0344
+ä "
+oa 6,9 0 0345
+å "
+ae 6,5 0 0346
+æ "
+,c 6,5,2 0 0347
+ç "
+`e 6,8 0 0350
+è "
+'e 6,8 0 0351
+é "
+^e 6,8 0 0352
+ê "
+:e 6,7 0 0353
+ë "
+`i 6,8 0 0354
+ì "
+'i 6,8 0 0355
+í "
+^i 6,8 0 0356
+î "
+:i 6,7 0 0357
+ï "
+Sd 6,8 0 0360
+ð "
+~n 6,8 0 0361
+ñ "
+`o 6,8 0 0362
+ò "
+'o 6,8 0 0363
+ó "
+^o 6,8 0 0364
+ô "
+~o 6,8 0 0365
+õ "
+:o 6,7 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 6,5 0 0370
+ø "
+`u 6,8 0 0371
+ù "
+'u 6,8 0 0372
+ú "
+^u 6,8 0 0373
+û "
+:u 6,7 0 0374
+ü "
+'y 6,8,2 0 0375
+ý "
+Tp 6,7,2 0 0376
+þ "
+:y 6,7,2 0 0377
+ÿ "
diff --git a/font/devX75/CI b/font/devX75/CI
new file mode 100644
index 00000000..f19be187
--- /dev/null
+++ b/font/devX75/CI
@@ -0,0 +1,306 @@
+name CI
+spacewidth 6
+charset
+--- 6,1 0 040
+! 6,7 0 041
+" 6,7 0 042
+# 6,7 0 043
+sh "
+$ 6,7,1 0 044
+Do "
+% 6,7 0 045
+& 6,6 0 046
+' 6,7 0 047
+( 6,7,1 0 050
+) 6,7,1 0 051
+* 6,7 0 052
++ 6,6 0 053
+, 6,1,2 0 054
+\- 6,4 0 055
+. 6,1 0 056
+/ 6,7,1 0 057
+sl "
+0 6,7 0 060
+1 6,7 0 061
+2 6,7 0 062
+3 6,7 0 063
+4 6,7 0 064
+5 6,7 0 065
+6 6,7 0 066
+7 6,7 0 067
+8 6,7 0 070
+9 6,7 0 071
+: 6,4 0 072
+; 6,4,2 0 073
+< 6,6 0 074
+= 6,5 0 075
+eq "
+> 6,6 0 076
+? 6,6 0 077
+@ 6,7 0 0100
+at "
+A 6,6 0 0101
+B 6,6 0 0102
+C 6,6 0 0103
+D 6,6 0 0104
+E 6,6 0 0105
+F 6,6 0 0106
+G 6,6 0 0107
+H 6,6 0 0110
+I 6,6 0 0111
+J 6,6 0 0112
+K 6,6 0 0113
+L 6,6 0 0114
+M 6,6 0 0115
+N 6,6 0 0116
+O 6,6 0 0117
+P 6,6 0 0120
+Q 6,6,2 0 0121
+R 6,6 0 0122
+S 6,6 0 0123
+T 6,6 0 0124
+U 6,6 0 0125
+V 6,6 0 0126
+W 6,6 0 0127
+X 6,6 0 0130
+Y 6,6 0 0131
+Z 6,6 0 0132
+[ 6,7,1 0 0133
+lB "
+\ 6,7,1 0 0134
+rs "
+] 6,7,1 0 0135
+rB "
+^ 6,7 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 6,7 0 0140
+oq "
+a 6,5 0 0141
+b 6,7 0 0142
+c 6,5 0 0143
+d 6,7 0 0144
+e 6,5 0 0145
+f 6,7 0 0146
+g 6,5,2 0 0147
+h 6,7 0 0150
+i 6,7 0 0151
+j 6,7,2 0 0152
+k 6,7 0 0153
+l 6,7 0 0154
+m 6,5 0 0155
+n 6,5 0 0156
+o 6,5 0 0157
+p 6,5,2 0 0160
+q 6,5,2 0 0161
+r 6,5 0 0162
+s 6,5 0 0163
+t 6,7 0 0164
+u 6,5 0 0165
+v 6,5 0 0166
+w 6,5 0 0167
+x 6,5 0 0170
+y 6,5,2 0 0171
+z 6,5 0 0172
+{ 6,7,1 0 0173
+lC "
+| 6,7,1 0 0174
+or "
+ba "
+} 6,7,1 0 0175
+rC "
+~ 6,5 0 0176
+a~ "
+ap "
+ti "
+r! 6,5,2 0 0241
+¡ "
+ct 6,6 0 0242
+¢ "
+Po 6,7 0 0243
+£ "
+Cs 6,6 0 0244
+¤ "
+Ye 6,6 0 0245
+¥ "
+bb 6,7,2 0 0246
+¦ "
+sc 6,7,1 0 0247
+§ "
+ad 6,7 0 0250
+¨ "
+co 6,7 0 0251
+© "
+Of 6,7 0 0252
+ª "
+Fo 6,4 0 0253
+« "
+no 6,5 0 0254
+¬ "
+- 6,4 0 0255
+hy "
+­ "
+rg 6,7 0 0256
+® "
+a- 6,7 0 0257
+¯ "
+de 6,7 0 0260
+° "
++- 6,6 0 0261
+± "
+S2 6,7 0 0262
+² "
+S3 6,7 0 0263
+³ "
+aa 6,8 0 0264
+´ "
+µ 6,5,2 0 0265
+ps 6,7,1 0 0266
+¶ "
+md 6,4 0 0267
+· "
+ac 6,0,2 0 0270
+¸ "
+S1 6,7 0 0271
+¹ "
+Om 6,7 0 0272
+º "
+Fc 6,4 0 0273
+» "
+14 6,8,1 0 0274
+¼ "
+12 6,8,1 0 0275
+½ "
+34 6,8,1 0 0276
+¾ "
+r? 6,4,2 0 0277
+¿ "
+`A 6,9 0 0300
+À "
+'A 6,9 0 0301
+Á "
+^A 6,9 0 0302
+Â "
+~A 6,9 0 0303
+Ã "
+:A 6,8 0 0304
+Ä "
+oA 6,9 0 0305
+Å "
+AE 6,6 0 0306
+Æ "
+,C 6,6,2 0 0307
+Ç "
+`E 6,9 0 0310
+È "
+'E 6,9 0 0311
+É "
+^E 6,9 0 0312
+Ê "
+:E 6,8 0 0313
+Ë "
+`I 6,9 0 0314
+Ì "
+'I 6,9 0 0315
+Í "
+^I 6,9 0 0316
+Î "
+:I 6,8 0 0317
+Ï "
+-D 6,6 0 0320
+Ð "
+~N 6,9 0 0321
+Ñ "
+`O 6,9 0 0322
+Ò "
+'O 6,9 0 0323
+Ó "
+^O 6,9 0 0324
+Ô "
+~O 6,9 0 0325
+Õ "
+:O 6,8 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 6,6 0 0330
+Ø "
+`U 6,9 0 0331
+Ù "
+'U 6,9 0 0332
+Ú "
+^U 6,9 0 0333
+Û "
+:U 6,8 0 0334
+Ü "
+'Y 6,9 0 0335
+Ý "
+TP 6,6 0 0336
+Þ "
+ss 6,7 0 0337
+ß "
+`a 6,8 0 0340
+à "
+'a 6,8 0 0341
+á "
+^a 6,8 0 0342
+â "
+~a 6,8 0 0343
+ã "
+:a 6,7 0 0344
+ä "
+oa 6,9 0 0345
+å "
+ae 6,5 0 0346
+æ "
+,c 6,5,2 0 0347
+ç "
+`e 6,8 0 0350
+è "
+'e 6,8 0 0351
+é "
+^e 6,8 0 0352
+ê "
+:e 6,7 0 0353
+ë "
+`i 6,8 0 0354
+ì "
+'i 6,8 0 0355
+í "
+^i 6,8 0 0356
+î "
+:i 6,7 0 0357
+ï "
+Sd 6,8 0 0360
+ð "
+~n 6,8 0 0361
+ñ "
+`o 6,8 0 0362
+ò "
+'o 6,8 0 0363
+ó "
+^o 6,8 0 0364
+ô "
+~o 6,8 0 0365
+õ "
+:o 6,7 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 6,6,1 0 0370
+ø "
+`u 6,8 0 0371
+ù "
+'u 6,8 0 0372
+ú "
+^u 6,8 0 0373
+û "
+:u 6,7 0 0374
+ü "
+'y 6,8,2 0 0375
+ý "
+Tp 6,7,2 0 0376
+þ "
+:y 6,7,2 0 0377
+ÿ "
diff --git a/font/devX75/CR b/font/devX75/CR
new file mode 100644
index 00000000..8bb40b27
--- /dev/null
+++ b/font/devX75/CR
@@ -0,0 +1,306 @@
+name CR
+spacewidth 6
+charset
+--- 6,1 0 040
+! 6,7 0 041
+" 6,7 0 042
+# 6,7 0 043
+sh "
+$ 6,7,1 0 044
+Do "
+% 6,6 0 045
+& 6,6 0 046
+' 6,7 0 047
+( 6,7,2 0 050
+) 6,7,2 0 051
+* 6,7 0 052
++ 6,6 0 053
+, 6,1,2 0 054
+\- 6,4 0 055
+. 6,1 0 056
+/ 6,7,1 0 057
+sl "
+0 6,7 0 060
+1 6,7 0 061
+2 6,7 0 062
+3 6,7 0 063
+4 6,7 0 064
+5 6,7 0 065
+6 6,7 0 066
+7 6,7 0 067
+8 6,7 0 070
+9 6,7 0 071
+: 6,4 0 072
+; 6,4,2 0 073
+< 6,6 0 074
+= 6,5 0 075
+eq "
+> 6,6 0 076
+? 6,6 0 077
+@ 6,7,1 0 0100
+at "
+A 6,6 0 0101
+B 6,6 0 0102
+C 6,6 0 0103
+D 6,6 0 0104
+E 6,6 0 0105
+F 6,6 0 0106
+G 6,6 0 0107
+H 6,6 0 0110
+I 6,6 0 0111
+J 6,6 0 0112
+K 6,6 0 0113
+L 6,6 0 0114
+M 6,6 0 0115
+N 6,6 0 0116
+O 6,6 0 0117
+P 6,6 0 0120
+Q 6,6,1 0 0121
+R 6,6 0 0122
+S 6,6 0 0123
+T 6,6 0 0124
+U 6,6 0 0125
+V 6,6 0 0126
+W 6,6 0 0127
+X 6,6 0 0130
+Y 6,6 0 0131
+Z 6,6 0 0132
+[ 6,7,2 0 0133
+lB "
+\ 6,7,1 0 0134
+rs "
+] 6,7,2 0 0135
+rB "
+^ 6,7 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 6,7 0 0140
+oq "
+a 6,5 0 0141
+b 6,7 0 0142
+c 6,5 0 0143
+d 6,7 0 0144
+e 6,5 0 0145
+f 6,7 0 0146
+g 6,5,2 0 0147
+h 6,7 0 0150
+i 6,7 0 0151
+j 6,7,2 0 0152
+k 6,7 0 0153
+l 6,7 0 0154
+m 6,5 0 0155
+n 6,5 0 0156
+o 6,5 0 0157
+p 6,5,2 0 0160
+q 6,5,2 0 0161
+r 6,5 0 0162
+s 6,5 0 0163
+t 6,7 0 0164
+u 6,5 0 0165
+v 6,5 0 0166
+w 6,5 0 0167
+x 6,5 0 0170
+y 6,5,2 0 0171
+z 6,5 0 0172
+{ 6,7,2 0 0173
+lC "
+| 6,7,2 0 0174
+or "
+ba "
+} 6,7,2 0 0175
+rC "
+~ 6,5 0 0176
+a~ "
+ap "
+ti "
+r! 6,5,2 0 0241
+¡ "
+ct 6,7,1 0 0242
+¢ "
+Po 6,7 0 0243
+£ "
+Cs 6,6 0 0244
+¤ "
+Ye 6,7 0 0245
+¥ "
+bb 6,7,2 0 0246
+¦ "
+sc 6,6,1 0 0247
+§ "
+ad 6,7 0 0250
+¨ "
+co 6,7 0 0251
+© "
+Of 6,6 0 0252
+ª "
+Fo 6,4 0 0253
+« "
+no 6,5 0 0254
+¬ "
+- 6,4 0 0255
+hy "
+­ "
+rg 6,7 0 0256
+® "
+a- 6,7 0 0257
+¯ "
+de 6,7 0 0260
+° "
++- 6,6 0 0261
+± "
+S2 6,7 0 0262
+² "
+S3 6,7 0 0263
+³ "
+aa 6,8 0 0264
+´ "
+µ 6,5,2 0 0265
+ps 6,6,1 0 0266
+¶ "
+md 6,4 0 0267
+· "
+ac 6,1,2 0 0270
+¸ "
+S1 6,7 0 0271
+¹ "
+Om 6,6 0 0272
+º "
+Fc 6,4 0 0273
+» "
+14 6,8,1 0 0274
+¼ "
+12 6,8,1 0 0275
+½ "
+34 6,8,1 0 0276
+¾ "
+r? 6,4,2 0 0277
+¿ "
+`A 6,9 0 0300
+À "
+'A 6,9 0 0301
+Á "
+^A 6,9 0 0302
+Â "
+~A 6,9 0 0303
+Ã "
+:A 6,8 0 0304
+Ä "
+oA 6,9 0 0305
+Å "
+AE 6,6 0 0306
+Æ "
+,C 6,6,2 0 0307
+Ç "
+`E 6,9 0 0310
+È "
+'E 6,9 0 0311
+É "
+^E 6,9 0 0312
+Ê "
+:E 6,8 0 0313
+Ë "
+`I 6,9 0 0314
+Ì "
+'I 6,9 0 0315
+Í "
+^I 6,9 0 0316
+Î "
+:I 6,8 0 0317
+Ï "
+-D 6,6 0 0320
+Ð "
+~N 6,9 0 0321
+Ñ "
+`O 6,9 0 0322
+Ò "
+'O 6,9 0 0323
+Ó "
+^O 6,9 0 0324
+Ô "
+~O 6,9 0 0325
+Õ "
+:O 6,8 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 6,6 0 0330
+Ø "
+`U 6,9 0 0331
+Ù "
+'U 6,9 0 0332
+Ú "
+^U 6,9 0 0333
+Û "
+:U 6,8 0 0334
+Ü "
+'Y 6,9 0 0335
+Ý "
+TP 6,6 0 0336
+Þ "
+ss 6,7 0 0337
+ß "
+`a 6,8 0 0340
+à "
+'a 6,8 0 0341
+á "
+^a 6,8 0 0342
+â "
+~a 6,8 0 0343
+ã "
+:a 6,7 0 0344
+ä "
+oa 6,9 0 0345
+å "
+ae 6,5 0 0346
+æ "
+,c 6,5,2 0 0347
+ç "
+`e 6,8 0 0350
+è "
+'e 6,8 0 0351
+é "
+^e 6,8 0 0352
+ê "
+:e 6,7 0 0353
+ë "
+`i 6,8 0 0354
+ì "
+'i 6,8 0 0355
+í "
+^i 6,8 0 0356
+î "
+:i 6,7 0 0357
+ï "
+Sd 6,8 0 0360
+ð "
+~n 6,8 0 0361
+ñ "
+`o 6,8 0 0362
+ò "
+'o 6,8 0 0363
+ó "
+^o 6,8 0 0364
+ô "
+~o 6,8 0 0365
+õ "
+:o 6,7 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 6,5 0 0370
+ø "
+`u 6,8 0 0371
+ù "
+'u 6,8 0 0372
+ú "
+^u 6,8 0 0373
+û "
+:u 6,7 0 0374
+ü "
+'y 6,8,2 0 0375
+ý "
+Tp 6,7,2 0 0376
+þ "
+:y 6,7,2 0 0377
+ÿ "
diff --git a/font/devX75/DESC b/font/devX75/DESC
new file mode 100644
index 00000000..172170c9
--- /dev/null
+++ b/font/devX75/DESC
@@ -0,0 +1,9 @@
+styles R I B BI
+fonts 6 0 0 0 0 0 S
+sizes 8 10 12 14 18 24 0
+res 75
+X11
+hor 1
+vert 1
+unitwidth 10
+postpro gxditview
diff --git a/font/devX75/HB b/font/devX75/HB
new file mode 100644
index 00000000..26894e07
--- /dev/null
+++ b/font/devX75/HB
@@ -0,0 +1,306 @@
+name HB
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,8 0 041
+" 5,8 0 042
+# 6,7 0 043
+sh "
+$ 6,8,1 0 044
+Do "
+% 8,8 0 045
+& 8,8 0 046
+' 3,8 0 047
+( 4,8,2 0 050
+) 4,8,2 0 051
+* 4,8 0 052
++ 6,6 0 053
+, 3,2,2 0 054
+\- 7,4 0 055
+. 3,2 0 056
+/ 4,8 0 057
+sl "
+0 6,8 0 060
+1 6,8 0 061
+2 6,8 0 062
+3 6,8 0 063
+4 6,8 0 064
+5 6,8 0 065
+6 6,8 0 066
+7 6,8 0 067
+8 6,8 0 070
+9 6,8 0 071
+: 3,6 0 072
+; 3,6,2 0 073
+< 5,6 0 074
+= 6,5 0 075
+eq "
+> 5,6 0 076
+? 6,8 0 077
+@ 11,7,2 0 0100
+at "
+A 8,8 0 0101
+B 7,8 0 0102
+C 8,8 0 0103
+D 7,8 0 0104
+E 6,8 0 0105
+F 6,8 0 0106
+G 8,8 0 0107
+H 7,8 0 0110
+I 3,8 0 0111
+J 6,8 0 0112
+K 7,8 0 0113
+L 6,8 0 0114
+M 10,8 0 0115
+N 8,8 0 0116
+O 8,8 0 0117
+P 7,8 0 0120
+Q 8,8,1 0 0121
+R 7,8 0 0122
+S 7,8 0 0123
+T 7,8 0 0124
+U 7,8 0 0125
+V 8,8 0 0126
+W 11,8 0 0127
+X 8,8 0 0130
+Y 9,8 0 0131
+Z 7,8 0 0132
+[ 4,8,2 0 0133
+lB "
+\ 4,8 0 0134
+rs "
+] 4,8,2 0 0135
+rB "
+^ 5,8 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 3,8 0 0140
+oq "
+a 6,6 0 0141
+b 6,8 0 0142
+c 5,6 0 0143
+d 6,8 0 0144
+e 6,6 0 0145
+f 4,8 0 0146
+g 6,6,2 0 0147
+h 6,8 0 0150
+i 3,8 0 0151
+j 3,8,2 0 0152
+k 6,8 0 0153
+l 3,8 0 0154
+m 9,6 0 0155
+n 6,6 0 0156
+o 6,6 0 0157
+p 6,6,2 0 0160
+q 6,6,2 0 0161
+r 4,6 0 0162
+s 6,6 0 0163
+t 4,8 0 0164
+u 6,6 0 0165
+v 6,6 0 0166
+w 8,6 0 0167
+x 7,6 0 0170
+y 6,6,2 0 0171
+z 6,6 0 0172
+{ 5,8,2 0 0173
+lC "
+| 3,8,2 0 0174
+or "
+ba "
+} 5,8,2 0 0175
+rC "
+~ 6,4 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,2 0 0241
+¡ "
+ct 6,7,1 0 0242
+¢ "
+Po 6,8 0 0243
+£ "
+Cs 6,7 0 0244
+¤ "
+Ye 7,8 0 0245
+¥ "
+bb 3,8,2 0 0246
+¦ "
+sc 6,8,2 0 0247
+§ "
+ad 3,8 0 0250
+¨ "
+co 10,8 0 0251
+© "
+Of 5,8 0 0252
+ª "
+Fo 7,4 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 10,8 0 0256
+® "
+a- 3,8 0 0257
+¯ "
+de 4,7 0 0260
+° "
++- 6,7 0 0261
+± "
+S2 3,7 0 0262
+² "
+S3 3,7 0 0263
+³ "
+aa 3,9 0 0264
+´ "
+µ 6,6,2 0 0265
+ps 6,8,2 0 0266
+¶ "
+md 3,4 0 0267
+· "
+ac 3,0,2 0 0270
+¸ "
+S1 3,7 0 0271
+¹ "
+Om 5,8 0 0272
+º "
+Fc 7,4 0 0273
+» "
+14 9,8 0 0274
+¼ "
+12 9,8 0 0275
+½ "
+34 9,8 0 0276
+¾ "
+r? 6,6,2 0 0277
+¿ "
+`A 8,11 0 0300
+À "
+'A 8,11 0 0301
+Á "
+^A 8,11 0 0302
+Â "
+~A 8,11 0 0303
+Ã "
+:A 8,10 0 0304
+Ä "
+oA 8,11 0 0305
+Å "
+AE 10,8 0 0306
+Æ "
+,C 8,8,2 0 0307
+Ç "
+`E 6,11 0 0310
+È "
+'E 6,11 0 0311
+É "
+^E 6,11 0 0312
+Ê "
+:E 6,10 0 0313
+Ë "
+`I 3,11 0 0314
+Ì "
+'I 3,11 0 0315
+Í "
+^I 3,11 0 0316
+Î "
+:I 3,10 0 0317
+Ï "
+-D 7,8 0 0320
+Ð "
+~N 8,11 0 0321
+Ñ "
+`O 8,11 0 0322
+Ò "
+'O 8,11 0 0323
+Ó "
+^O 8,11 0 0324
+Ô "
+~O 8,11 0 0325
+Õ "
+:O 8,10 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 8,8 0 0330
+Ø "
+`U 7,11 0 0331
+Ù "
+'U 7,11 0 0332
+Ú "
+^U 7,11 0 0333
+Û "
+:U 7,10 0 0334
+Ü "
+'Y 9,11 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 6,8 0 0337
+ß "
+`a 6,9 0 0340
+à "
+'a 6,9 0 0341
+á "
+^a 6,9 0 0342
+â "
+~a 6,9 0 0343
+ã "
+:a 6,9 0 0344
+ä "
+oa 6,9 0 0345
+å "
+ae 9,6 0 0346
+æ "
+,c 5,6,2 0 0347
+ç "
+`e 6,9 0 0350
+è "
+'e 6,9 0 0351
+é "
+^e 6,9 0 0352
+ê "
+:e 6,9 0 0353
+ë "
+`i 3,9 0 0354
+ì "
+'i 3,9 0 0355
+í "
+^i 3,9 0 0356
+î "
+:i 3,9 0 0357
+ï "
+Sd 6,9 0 0360
+ð "
+~n 6,9 0 0361
+ñ "
+`o 6,9 0 0362
+ò "
+'o 6,9 0 0363
+ó "
+^o 6,9 0 0364
+ô "
+~o 6,9 0 0365
+õ "
+:o 6,9 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 6,6 0 0370
+ø "
+`u 6,9 0 0371
+ù "
+'u 6,9 0 0372
+ú "
+^u 6,9 0 0373
+û "
+:u 6,9 0 0374
+ü "
+'y 6,9,2 0 0375
+ý "
+Tp 6,8,2 0 0376
+þ "
+:y 6,9,2 0 0377
+ÿ "
diff --git a/font/devX75/HBI b/font/devX75/HBI
new file mode 100644
index 00000000..64880034
--- /dev/null
+++ b/font/devX75/HBI
@@ -0,0 +1,306 @@
+name HBI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,8 0 041
+" 6,8 0 042
+# 7,7 0 043
+sh "
+$ 6,8,1 0 044
+Do "
+% 9,8 0 045
+& 8,8 0 046
+' 3,8 0 047
+( 5,8,2 0 050
+) 5,8,2 0 051
+* 6,8 0 052
++ 6,6 0 053
+, 3,2,2 0 054
+\- 7,4 0 055
+. 3,2 0 056
+/ 5,8 0 057
+sl "
+0 6,8 0 060
+1 6,8 0 061
+2 6,8 0 062
+3 6,8 0 063
+4 6,8 0 064
+5 6,8 0 065
+6 6,8 0 066
+7 6,8 0 067
+8 6,8 0 070
+9 6,8 0 071
+: 3,6 0 072
+; 3,6,2 0 073
+< 6,6 0 074
+= 6,5 0 075
+eq "
+> 7,6 0 076
+? 6,8 0 077
+@ 10,7,2 0 0100
+at "
+A 8,8 0 0101
+B 7,8 0 0102
+C 7,8 0 0103
+D 8,8 0 0104
+E 6,8 0 0105
+F 5,8 0 0106
+G 8,8 0 0107
+H 7,8 0 0110
+I 3,8 0 0111
+J 6,8 0 0112
+K 8,8 0 0113
+L 6,8 0 0114
+M 10,8 0 0115
+N 8,8 0 0116
+O 8,8 0 0117
+P 7,8 0 0120
+Q 8,8 0 0121
+R 8,8 0 0122
+S 7,8 0 0123
+T 6,8 0 0124
+U 7,8 0 0125
+V 8,8 0 0126
+W 10,8 0 0127
+X 7,8 0 0130
+Y 7,8 0 0131
+Z 7,8 0 0132
+[ 4,8,2 0 0133
+lB "
+\ 5,8 0 0134
+rs "
+] 4,8,2 0 0135
+rB "
+^ 6,8 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 4,8 0 0140
+oq "
+a 6,6 0 0141
+b 6,8 0 0142
+c 5,6 0 0143
+d 6,8 0 0144
+e 6,6 0 0145
+f 3,8 0 0146
+g 6,6,2 0 0147
+h 6,8 0 0150
+i 3,8 0 0151
+j 3,8,2 0 0152
+k 6,8 0 0153
+l 3,8 0 0154
+m 9,6 0 0155
+n 6,6 0 0156
+o 6,6 0 0157
+p 6,6,2 0 0160
+q 6,6,2 0 0161
+r 4,6 0 0162
+s 6,6 0 0163
+t 4,8 0 0164
+u 6,6 0 0165
+v 6,6 0 0166
+w 8,6 0 0167
+x 5,6 0 0170
+y 6,6,2 0 0171
+z 5,6 0 0172
+{ 5,8,2 0 0173
+lC "
+| 4,8,2 0 0174
+or "
+ba "
+} 5,8,2 0 0175
+rC "
+~ 6,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,2 0 0241
+¡ "
+ct 7,7,1 0 0242
+¢ "
+Po 7,7 0 0243
+£ "
+Cs 6,7 0 0244
+¤ "
+Ye 7,8 0 0245
+¥ "
+bb 4,8,1 0 0246
+¦ "
+sc 7,8,2 0 0247
+§ "
+ad 4,8 0 0250
+¨ "
+co 10,8 0 0251
+© "
+Of 5,8 0 0252
+ª "
+Fo 8,5 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 5,4 0 0255
+hy "
+­ "
+rg 10,8 0 0256
+® "
+a- 4,8 0 0257
+¯ "
+de 4,7 0 0260
+° "
++- 6,7 0 0261
+± "
+S2 3,7 0 0262
+² "
+S3 3,7 0 0263
+³ "
+aa 3,9 0 0264
+´ "
+µ 6,6,2 0 0265
+ps 7,8,2 0 0266
+¶ "
+md 3,4 0 0267
+· "
+ac 3,1,2 0 0270
+¸ "
+S1 3,7 0 0271
+¹ "
+Om 5,8 0 0272
+º "
+Fc 8,5 0 0273
+» "
+14 9,8 0 0274
+¼ "
+12 9,8 0 0275
+½ "
+34 9,8 0 0276
+¾ "
+r? 6,6,2 0 0277
+¿ "
+`A 8,11 0 0300
+À "
+'A 8,11 0 0301
+Á "
+^A 8,11 0 0302
+Â "
+~A 8,11 0 0303
+Ã "
+:A 8,10 0 0304
+Ä "
+oA 8,11 0 0305
+Å "
+AE 10,8 0 0306
+Æ "
+,C 7,8,2 0 0307
+Ç "
+`E 6,11 0 0310
+È "
+'E 6,11 0 0311
+É "
+^E 6,11 0 0312
+Ê "
+:E 6,10 0 0313
+Ë "
+`I 3,11 0 0314
+Ì "
+'I 3,11 0 0315
+Í "
+^I 3,11 0 0316
+Î "
+:I 3,10 0 0317
+Ï "
+-D 8,8 0 0320
+Ð "
+~N 8,11 0 0321
+Ñ "
+`O 8,11 0 0322
+Ò "
+'O 8,11 0 0323
+Ó "
+^O 8,11 0 0324
+Ô "
+~O 8,11 0 0325
+Õ "
+:O 8,10 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 8,8 0 0330
+Ø "
+`U 7,11 0 0331
+Ù "
+'U 7,11 0 0332
+Ú "
+^U 7,11 0 0333
+Û "
+:U 7,10 0 0334
+Ü "
+'Y 7,11 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 7,8 0 0337
+ß "
+`a 6,9 0 0340
+à "
+'a 6,9 0 0341
+á "
+^a 6,9 0 0342
+â "
+~a 6,9 0 0343
+ã "
+:a 6,8 0 0344
+ä "
+oa 6,9 0 0345
+å "
+ae 9,6 0 0346
+æ "
+,c 5,6,2 0 0347
+ç "
+`e 6,9 0 0350
+è "
+'e 6,9 0 0351
+é "
+^e 6,9 0 0352
+ê "
+:e 6,8 0 0353
+ë "
+`i 3,9 0 0354
+ì "
+'i 3,9 0 0355
+í "
+^i 3,9 0 0356
+î "
+:i 3,8 0 0357
+ï "
+Sd 6,9 0 0360
+ð "
+~n 6,9 0 0361
+ñ "
+`o 6,9 0 0362
+ò "
+'o 6,9 0 0363
+ó "
+^o 6,9 0 0364
+ô "
+~o 6,9 0 0365
+õ "
+:o 6,8 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 8,6 0 0370
+ø "
+`u 6,9 0 0371
+ù "
+'u 6,9 0 0372
+ú "
+^u 6,9 0 0373
+û "
+:u 6,8 0 0374
+ü "
+'y 6,9,2 0 0375
+ý "
+Tp 6,8,2 0 0376
+þ "
+:y 6,8,2 0 0377
+ÿ "
diff --git a/font/devX75/HI b/font/devX75/HI
new file mode 100644
index 00000000..07509511
--- /dev/null
+++ b/font/devX75/HI
@@ -0,0 +1,306 @@
+name HI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,8 0 041
+" 4,8 0 042
+# 7,7 0 043
+sh "
+$ 6,8,1 0 044
+Do "
+% 9,8 0 045
+& 8,8 0 046
+' 3,8 0 047
+( 4,8,2 0 050
+) 4,8,2 0 051
+* 4,8 0 052
++ 6,6 0 053
+, 3,1,2 0 054
+\- 7,4 0 055
+. 3,1 0 056
+/ 3,8 0 057
+sl "
+0 6,8 0 060
+1 6,8 0 061
+2 6,8 0 062
+3 6,8 0 063
+4 6,8 0 064
+5 6,8 0 065
+6 6,8 0 066
+7 6,8 0 067
+8 6,8 0 070
+9 6,8 0 071
+: 3,6 0 072
+; 3,6,2 0 073
+< 6,6 0 074
+= 7,5 0 075
+eq "
+> 6,6 0 076
+? 6,8 0 077
+@ 11,8,2 0 0100
+at "
+A 7,8 0 0101
+B 7,8 0 0102
+C 8,8 0 0103
+D 8,8 0 0104
+E 7,8 0 0105
+F 6,8 0 0106
+G 8,8 0 0107
+H 8,8 0 0110
+I 3,8 0 0111
+J 5,8 0 0112
+K 7,8 0 0113
+L 5,8 0 0114
+M 9,8 0 0115
+N 8,8 0 0116
+O 8,8 0 0117
+P 7,8 0 0120
+Q 8,8,1 0 0121
+R 7,8 0 0122
+S 7,8 0 0123
+T 5,8 0 0124
+U 8,8 0 0125
+V 7,8 0 0126
+W 10,8 0 0127
+X 7,8 0 0130
+Y 7,8 0 0131
+Z 7,8 0 0132
+[ 4,8,2 0 0133
+lB "
+\ 3,8 0 0134
+rs "
+] 4,8,2 0 0135
+rB "
+^ 6,7 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 3,8 0 0140
+oq "
+a 5,6 0 0141
+b 5,8 0 0142
+c 5,6 0 0143
+d 5,8 0 0144
+e 5,6 0 0145
+f 4,8 0 0146
+g 5,6,2 0 0147
+h 6,8 0 0150
+i 2,8 0 0151
+j 2,8,2 0 0152
+k 5,8 0 0153
+l 2,8 0 0154
+m 8,6 0 0155
+n 6,6 0 0156
+o 6,6 0 0157
+p 5,6,2 0 0160
+q 5,6,2 0 0161
+r 4,6 0 0162
+s 5,6 0 0163
+t 4,8 0 0164
+u 5,6 0 0165
+v 6,6 0 0166
+w 8,6 0 0167
+x 6,6 0 0170
+y 5,6,2 0 0171
+z 5,6 0 0172
+{ 4,8,2 0 0173
+lC "
+| 3,8,2 0 0174
+or "
+ba "
+} 4,8,2 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,2 0 0241
+¡ "
+ct 7,7,1 0 0242
+¢ "
+Po 6,8 0 0243
+£ "
+Cs 6,7 0 0244
+¤ "
+Ye 6,8 0 0245
+¥ "
+bb 3,8,2 0 0246
+¦ "
+sc 6,8,2 0 0247
+§ "
+ad 3,8 0 0250
+¨ "
+co 10,8 0 0251
+© "
+Of 5,8 0 0252
+ª "
+Fo 8,5 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 6,4 0 0255
+hy "
+­ "
+rg 10,8 0 0256
+® "
+a- 3,8 0 0257
+¯ "
+de 4,7 0 0260
+° "
++- 6,7 0 0261
+± "
+S2 3,8 0 0262
+² "
+S3 3,8 0 0263
+³ "
+aa 3,9 0 0264
+´ "
+µ 5,6,2 0 0265
+ps 6,8,2 0 0266
+¶ "
+md 3,5 0 0267
+· "
+ac 3,1,2 0 0270
+¸ "
+S1 3,8 0 0271
+¹ "
+Om 5,8 0 0272
+º "
+Fc 8,5 0 0273
+» "
+14 9,8,1 0 0274
+¼ "
+12 9,8,1 0 0275
+½ "
+34 9,8,1 0 0276
+¾ "
+r? 6,6,2 0 0277
+¿ "
+`A 7,11 0 0300
+À "
+'A 7,11 0 0301
+Á "
+^A 7,11 0 0302
+Â "
+~A 7,11 0 0303
+Ã "
+:A 7,10 0 0304
+Ä "
+oA 7,11 0 0305
+Å "
+AE 10,8 0 0306
+Æ "
+,C 8,8,2 0 0307
+Ç "
+`E 7,11 0 0310
+È "
+'E 7,11 0 0311
+É "
+^E 7,11 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 3,11 0 0314
+Ì "
+'I 3,11 0 0315
+Í "
+^I 3,11 0 0316
+Î "
+:I 3,10 0 0317
+Ï "
+-D 8,8 0 0320
+Ð "
+~N 8,11 0 0321
+Ñ "
+`O 8,11 0 0322
+Ò "
+'O 8,11 0 0323
+Ó "
+^O 8,11 0 0324
+Ô "
+~O 8,11 0 0325
+Õ "
+:O 8,10 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 8,8 0 0330
+Ø "
+`U 8,11 0 0331
+Ù "
+'U 8,11 0 0332
+Ú "
+^U 8,11 0 0333
+Û "
+:U 8,10 0 0334
+Ü "
+'Y 7,11 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 6,8 0 0337
+ß "
+`a 5,9 0 0340
+à "
+'a 5,9 0 0341
+á "
+^a 5,9 0 0342
+â "
+~a 5,9 0 0343
+ã "
+:a 5,8 0 0344
+ä "
+oa 5,9 0 0345
+å "
+ae 8,6 0 0346
+æ "
+,c 5,6,2 0 0347
+ç "
+`e 5,9 0 0350
+è "
+'e 5,9 0 0351
+é "
+^e 5,9 0 0352
+ê "
+:e 5,8 0 0353
+ë "
+`i 2,9 0 0354
+ì "
+'i 2,9 0 0355
+í "
+^i 2,9 0 0356
+î "
+:i 2,8 0 0357
+ï "
+Sd 6,9 0 0360
+ð "
+~n 6,9 0 0361
+ñ "
+`o 6,9 0 0362
+ò "
+'o 6,9 0 0363
+ó "
+^o 6,9 0 0364
+ô "
+~o 6,9 0 0365
+õ "
+:o 6,8 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 6,6 0 0370
+ø "
+`u 5,9 0 0371
+ù "
+'u 5,9 0 0372
+ú "
+^u 5,9 0 0373
+û "
+:u 5,8 0 0374
+ü "
+'y 5,9,2 0 0375
+ý "
+Tp 5,8,2 0 0376
+þ "
+:y 5,8,2 0 0377
+ÿ "
diff --git a/font/devX75/HR b/font/devX75/HR
new file mode 100644
index 00000000..aeac63ed
--- /dev/null
+++ b/font/devX75/HR
@@ -0,0 +1,306 @@
+name HR
+spacewidth 3
+charset
+--- 3,1 0 040
+! 3,8 0 041
+" 4,8 0 042
+# 6,7 0 043
+sh "
+$ 6,8,1 0 044
+Do "
+% 9,8 0 045
+& 8,8 0 046
+' 3,8 0 047
+( 4,8,2 0 050
+) 4,8,2 0 051
+* 4,8 0 052
++ 6,6 0 053
+, 3,1,2 0 054
+\- 7,4 0 055
+. 3,1 0 056
+/ 3,8 0 057
+sl "
+0 6,8 0 060
+1 6,8 0 061
+2 6,8 0 062
+3 6,8 0 063
+4 6,8 0 064
+5 6,8 0 065
+6 6,8 0 066
+7 6,8 0 067
+8 6,8 0 070
+9 6,8 0 071
+: 3,6 0 072
+; 3,6,2 0 073
+< 6,6 0 074
+= 5,5 0 075
+eq "
+> 6,6 0 076
+? 6,8 0 077
+@ 11,8,2 0 0100
+at "
+A 7,8 0 0101
+B 7,8 0 0102
+C 8,8 0 0103
+D 8,8 0 0104
+E 7,8 0 0105
+F 6,8 0 0106
+G 8,8 0 0107
+H 8,8 0 0110
+I 3,8 0 0111
+J 5,8 0 0112
+K 7,8 0 0113
+L 6,8 0 0114
+M 9,8 0 0115
+N 8,8 0 0116
+O 8,8 0 0117
+P 7,8 0 0120
+Q 8,8,1 0 0121
+R 7,8 0 0122
+S 7,8 0 0123
+T 5,8 0 0124
+U 8,8 0 0125
+V 7,8 0 0126
+W 9,8 0 0127
+X 7,8 0 0130
+Y 7,8 0 0131
+Z 7,8 0 0132
+[ 3,8,2 0 0133
+lB "
+\ 3,8 0 0134
+rs "
+] 3,8,2 0 0135
+rB "
+^ 6,8 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 3,8 0 0140
+oq "
+a 5,6 0 0141
+b 6,8 0 0142
+c 5,6 0 0143
+d 6,8 0 0144
+e 5,6 0 0145
+f 4,8 0 0146
+g 6,6,2 0 0147
+h 6,8 0 0150
+i 2,8 0 0151
+j 2,8,1 0 0152
+k 5,8 0 0153
+l 2,8 0 0154
+m 8,6 0 0155
+n 6,6 0 0156
+o 6,6 0 0157
+p 6,6,2 0 0160
+q 6,6,2 0 0161
+r 4,6 0 0162
+s 5,6 0 0163
+t 4,8 0 0164
+u 5,6 0 0165
+v 6,6 0 0166
+w 8,6 0 0167
+x 6,6 0 0170
+y 5,6,2 0 0171
+z 5,6 0 0172
+{ 3,8,2 0 0173
+lC "
+| 3,8,2 0 0174
+or "
+ba "
+} 3,8,2 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 3,6,2 0 0241
+¡ "
+ct 6,7,1 0 0242
+¢ "
+Po 6,8 0 0243
+£ "
+Cs 5,7 0 0244
+¤ "
+Ye 6,8 0 0245
+¥ "
+bb 3,8,2 0 0246
+¦ "
+sc 6,8,2 0 0247
+§ "
+ad 3,8 0 0250
+¨ "
+co 9,7 0 0251
+© "
+Of 4,8 0 0252
+ª "
+Fo 6,5 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 9,7 0 0256
+® "
+a- 3,8 0 0257
+¯ "
+de 4,7 0 0260
+° "
++- 6,7 0 0261
+± "
+S2 3,7 0 0262
+² "
+S3 3,7 0 0263
+³ "
+aa 3,8 0 0264
+´ "
+µ 5,6,2 0 0265
+ps 6,8,2 0 0266
+¶ "
+md 3,4 0 0267
+· "
+ac 3,0,2 0 0270
+¸ "
+S1 3,7 0 0271
+¹ "
+Om 4,8 0 0272
+º "
+Fc 6,5 0 0273
+» "
+14 9,8 0 0274
+¼ "
+12 9,8 0 0275
+½ "
+34 9,8 0 0276
+¾ "
+r? 6,6,2 0 0277
+¿ "
+`A 7,11 0 0300
+À "
+'A 7,11 0 0301
+Á "
+^A 7,11 0 0302
+Â "
+~A 7,11 0 0303
+Ã "
+:A 7,10 0 0304
+Ä "
+oA 7,11 0 0305
+Å "
+AE 10,8 0 0306
+Æ "
+,C 8,8,2 0 0307
+Ç "
+`E 7,11 0 0310
+È "
+'E 7,11 0 0311
+É "
+^E 7,11 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 3,11 0 0314
+Ì "
+'I 3,11 0 0315
+Í "
+^I 3,11 0 0316
+Î "
+:I 3,10 0 0317
+Ï "
+-D 8,8 0 0320
+Ð "
+~N 8,11 0 0321
+Ñ "
+`O 8,11 0 0322
+Ò "
+'O 8,11 0 0323
+Ó "
+^O 8,11 0 0324
+Ô "
+~O 8,11 0 0325
+Õ "
+:O 8,10 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 8,9,1 0 0330
+Ø "
+`U 8,11 0 0331
+Ù "
+'U 8,11 0 0332
+Ú "
+^U 8,11 0 0333
+Û "
+:U 8,10 0 0334
+Ü "
+'Y 7,11 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 5,8 0 0337
+ß "
+`a 5,9 0 0340
+à "
+'a 5,9 0 0341
+á "
+^a 5,9 0 0342
+â "
+~a 5,9 0 0343
+ã "
+:a 5,8 0 0344
+ä "
+oa 5,9 0 0345
+å "
+ae 8,6 0 0346
+æ "
+,c 5,6,2 0 0347
+ç "
+`e 5,9 0 0350
+è "
+'e 5,9 0 0351
+é "
+^e 5,9 0 0352
+ê "
+:e 5,8 0 0353
+ë "
+`i 2,9 0 0354
+ì "
+'i 2,9 0 0355
+í "
+^i 2,9 0 0356
+î "
+:i 2,8 0 0357
+ï "
+Sd 6,9 0 0360
+ð "
+~n 5,9 0 0361
+ñ "
+`o 6,9 0 0362
+ò "
+'o 6,9 0 0363
+ó "
+^o 6,9 0 0364
+ô "
+~o 6,9 0 0365
+õ "
+:o 6,8 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 6,6 0 0370
+ø "
+`u 5,9 0 0371
+ù "
+'u 5,9 0 0372
+ú "
+^u 5,9 0 0373
+û "
+:u 5,8 0 0374
+ü "
+'y 5,9,2 0 0375
+ý "
+Tp 6,8,2 0 0376
+þ "
+:y 5,8,2 0 0377
+ÿ "
diff --git a/font/devX75/Makefile.sub b/font/devX75/Makefile.sub
new file mode 100644
index 00000000..2a90fcab
--- /dev/null
+++ b/font/devX75/Makefile.sub
@@ -0,0 +1,2 @@
+DEV=X75
+DEVFILES=DESC TR TI TB TBI CR CI CB CBI HR HI HB HBI NR NI NB NBI S
diff --git a/font/devX75/NB b/font/devX75/NB
new file mode 100644
index 00000000..d783d02b
--- /dev/null
+++ b/font/devX75/NB
@@ -0,0 +1,306 @@
+name NB
+spacewidth 2
+charset
+--- 2,1 0 040
+! 3,8 0 041
+" 6,8 0 042
+# 8,8 0 043
+sh "
+$ 6,9,1 0 044
+Do "
+% 11,8 0 045
+& 9,8 0 046
+' 3,8 0 047
+( 5,8,2 0 050
+) 5,8,2 0 051
+* 6,8 0 052
++ 6,6 0 053
+, 3,2,2 0 054
+\- 6,4 0 055
+. 3,2 0 056
+/ 5,8 0 057
+sl "
+0 6,8 0 060
+1 5,8 0 061
+2 6,8 0 062
+3 6,8 0 063
+4 6,8 0 064
+5 6,8 0 065
+6 6,8 0 066
+7 5,8 0 067
+8 6,8 0 070
+9 6,8 0 071
+: 3,5 0 072
+; 3,5,2 0 073
+< 7,6 0 074
+= 6,5 0 075
+eq "
+> 7,6 0 076
+? 6,8 0 077
+@ 10,8 0 0100
+at "
+A 8,8 0 0101
+B 8,8 0 0102
+C 8,8 0 0103
+D 9,8 0 0104
+E 7,8 0 0105
+F 7,8 0 0106
+G 8,8 0 0107
+H 10,8 0 0110
+I 5,8 0 0111
+J 7,8 0 0112
+K 9,8 0 0113
+L 7,8 0 0114
+M 12,8 0 0115
+N 9,8 0 0116
+O 8,8 0 0117
+P 8,8 0 0120
+Q 8,8,1 0 0121
+R 9,8 0 0122
+S 7,8 0 0123
+T 7,8 0 0124
+U 9,8 0 0125
+V 9,8 0 0126
+W 12,8 0 0127
+X 9,8 0 0130
+Y 9,8 0 0131
+Z 7,8 0 0132
+[ 4,8,2 0 0133
+lB "
+\ 5,8 0 0134
+rs "
+] 4,8,2 0 0135
+rB "
+^ 6,8 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 3,8 0 0140
+oq "
+a 5,5 0 0141
+b 7,8 0 0142
+c 6,5 0 0143
+d 7,8 0 0144
+e 6,5 0 0145
+f 5,8 0 0146
+g 6,6,2 0 0147
+h 7,8 0 0150
+i 5,8 0 0151
+j 5,8,2 0 0152
+k 6,8 0 0153
+l 5,8 0 0154
+m 11,5 0 0155
+n 7,5 0 0156
+o 7,5 0 0157
+p 7,5,2 0 0160
+q 7,5,2 0 0161
+r 5,5 0 0162
+s 5,5 0 0163
+t 4,7 0 0164
+u 7,5 0 0165
+v 7,5 0 0166
+w 10,5 0 0167
+x 7,5 0 0170
+y 7,5,2 0 0171
+z 6,5 0 0172
+{ 5,8,2 0 0173
+lC "
+| 6,8 0 0174
+or "
+ba "
+} 5,8,2 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 3,6,2 0 0241
+¡ "
+ct 6,6,1 0 0242
+¢ "
+Po 8,8 0 0243
+£ "
+Cs 8,6 0 0244
+¤ "
+Ye 9,8 0 0245
+¥ "
+bb 6,8 0 0246
+¦ "
+sc 5,8,2 0 0247
+§ "
+ad 4,8 0 0250
+¨ "
+co 9,8 0 0251
+© "
+Of 4,8 0 0252
+ª "
+Fo 7,5 0 0253
+« "
+no 6,5 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 9,8 0 0256
+® "
+a- 5,7 0 0257
+¯ "
+de 4,8 0 0260
+° "
++- 6,6 0 0261
+± "
+S2 3,8 0 0262
+² "
+S3 3,8 0 0263
+³ "
+aa 4,8 0 0264
+´ "
+µ 7,5,2 0 0265
+ps 8,8 0 0266
+¶ "
+md 3,5 0 0267
+· "
+ac 4,1,2 0 0270
+¸ "
+S1 3,8 0 0271
+¹ "
+Om 5,8 0 0272
+º "
+Fc 7,5 0 0273
+» "
+14 9,8 0 0274
+¼ "
+12 9,8 0 0275
+½ "
+34 9,8 0 0276
+¾ "
+r? 6,6,2 0 0277
+¿ "
+`A 8,11 0 0300
+À "
+'A 8,11 0 0301
+Á "
+^A 8,11 0 0302
+Â "
+~A 8,11 0 0303
+Ã "
+:A 8,11 0 0304
+Ä "
+oA 8,11 0 0305
+Å "
+AE 11,8 0 0306
+Æ "
+,C 8,8,2 0 0307
+Ç "
+`E 7,11 0 0310
+È "
+'E 7,11 0 0311
+É "
+^E 7,11 0 0312
+Ê "
+:E 7,11 0 0313
+Ë "
+`I 5,11 0 0314
+Ì "
+'I 5,11 0 0315
+Í "
+^I 5,11 0 0316
+Î "
+:I 5,11 0 0317
+Ï "
+-D 9,8 0 0320
+Ð "
+~N 9,11 0 0321
+Ñ "
+`O 8,11 0 0322
+Ò "
+'O 8,11 0 0323
+Ó "
+^O 8,11 0 0324
+Ô "
+~O 8,11 0 0325
+Õ "
+:O 8,11 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 8,8 0 0330
+Ø "
+`U 9,11 0 0331
+Ù "
+'U 9,11 0 0332
+Ú "
+^U 9,11 0 0333
+Û "
+:U 9,11 0 0334
+Ü "
+'Y 9,11 0 0335
+Ý "
+TP 8,8 0 0336
+Þ "
+ss 8,8 0 0337
+ß "
+`a 5,8 0 0340
+à "
+'a 5,8 0 0341
+á "
+^a 5,9 0 0342
+â "
+~a 5,8 0 0343
+ã "
+:a 5,8 0 0344
+ä "
+oa 5,8 0 0345
+å "
+ae 9,5 0 0346
+æ "
+,c 6,5,2 0 0347
+ç "
+`e 6,8 0 0350
+è "
+'e 6,8 0 0351
+é "
+^e 6,9 0 0352
+ê "
+:e 6,8 0 0353
+ë "
+`i 5,8 0 0354
+ì "
+'i 5,8 0 0355
+í "
+^i 5,9 0 0356
+î "
+:i 5,8 0 0357
+ï "
+Sd 7,8 0 0360
+ð "
+~n 7,8 0 0361
+ñ "
+`o 7,8 0 0362
+ò "
+'o 7,8 0 0363
+ó "
+^o 7,9 0 0364
+ô "
+~o 7,8 0 0365
+õ "
+:o 7,8 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 7,6,1 0 0370
+ø "
+`u 7,8 0 0371
+ù "
+'u 7,8 0 0372
+ú "
+^u 7,9 0 0373
+û "
+:u 7,8 0 0374
+ü "
+'y 7,8,2 0 0375
+ý "
+Tp 7,8,2 0 0376
+þ "
+:y 7,8,2 0 0377
+ÿ "
diff --git a/font/devX75/NBI b/font/devX75/NBI
new file mode 100644
index 00000000..bdad1059
--- /dev/null
+++ b/font/devX75/NBI
@@ -0,0 +1,306 @@
+name NBI
+spacewidth 2
+charset
+--- 2,1 0 040
+! 5,8 0 041
+" 6,8 0 042
+# 8,7 0 043
+sh "
+$ 6,9,1 0 044
+Do "
+% 11,8 0 045
+& 10,8 0 046
+' 3,8 0 047
+( 4,8,1 0 050
+) 5,8,1 0 051
+* 6,8 0 052
++ 6,6 0 053
+, 3,2,2 0 054
+\- 7,4 0 055
+. 3,2 0 056
+/ 5,8 0 057
+sl "
+0 6,8 0 060
+1 6,8 0 061
+2 6,8 0 062
+3 6,8 0 063
+4 6,8 0 064
+5 6,8 0 065
+6 6,8 0 066
+7 6,8 0 067
+8 6,8 0 070
+9 6,8 0 071
+: 4,5 0 072
+; 4,5,2 0 073
+< 7,6 0 074
+= 6,5 0 075
+eq "
+> 7,6 0 076
+? 6,8 0 077
+@ 11,8 0 0100
+at "
+A 8,8 0 0101
+B 8,8 0 0102
+C 7,8 0 0103
+D 9,8 0 0104
+E 8,8 0 0105
+F 7,8 0 0106
+G 8,8 0 0107
+H 10,8 0 0110
+I 6,8 0 0111
+J 7,8 0 0112
+K 10,8 0 0113
+L 7,8 0 0114
+M 11,8 0 0115
+N 8,8 0 0116
+O 8,8 0 0117
+P 8,8 0 0120
+Q 8,8,2 0 0121
+R 9,8 0 0122
+S 7,8 0 0123
+T 7,8 0 0124
+U 8,8 0 0125
+V 8,8 0 0126
+W 11,8 0 0127
+X 8,8 0 0130
+Y 7,8 0 0131
+Z 8,8 0 0132
+[ 5,8,1 0 0133
+lB "
+\ 5,8 0 0134
+rs "
+] 5,8,1 0 0135
+rB "
+^ 6,8 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 3,8 0 0140
+oq "
+a 7,5 0 0141
+b 7,8 0 0142
+c 6,5 0 0143
+d 7,8 0 0144
+e 6,5 0 0145
+f 5,8,2 0 0146
+g 6,6,2 0 0147
+h 7,8 0 0150
+i 4,8 0 0151
+j 4,8,2 0 0152
+k 7,8 0 0153
+l 4,8 0 0154
+m 10,5 0 0155
+n 7,5 0 0156
+o 6,5 0 0157
+p 7,5,2 0 0160
+q 7,5,2 0 0161
+r 5,5 0 0162
+s 4,5 0 0163
+t 4,7 0 0164
+u 7,5 0 0165
+v 6,5 0 0166
+w 10,5 0 0167
+x 7,5 0 0170
+y 7,5,2 0 0171
+z 5,5 0 0172
+{ 5,8,1 0 0173
+lC "
+| 6,8 0 0174
+or "
+ba "
+} 5,8,1 0 0175
+rC "
+~ 7,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,2 0 0241
+¡ "
+ct 6,6,1 0 0242
+¢ "
+Po 7,8 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 7,8 0 0245
+¥ "
+bb 6,8 0 0246
+¦ "
+sc 6,8,2 0 0247
+§ "
+ad 4,8 0 0250
+¨ "
+co 9,8 0 0251
+© "
+Of 6,8 0 0252
+ª "
+Fo 8,5 0 0253
+« "
+no 6,5 0 0254
+¬ "
+- 4,4 0 0255
+hy "
+­ "
+rg 9,8 0 0256
+® "
+a- 5,7 0 0257
+¯ "
+de 4,8 0 0260
+° "
++- 6,6 0 0261
+± "
+S2 3,8 0 0262
+² "
+S3 3,8 0 0263
+³ "
+aa 4,8 0 0264
+´ "
+µ 7,5,2 0 0265
+ps 8,8 0 0266
+¶ "
+md 3,5 0 0267
+· "
+ac 4,1,2 0 0270
+¸ "
+S1 3,8 0 0271
+¹ "
+Om 5,8 0 0272
+º "
+Fc 8,5 0 0273
+» "
+14 9,8 0 0274
+¼ "
+12 9,8 0 0275
+½ "
+34 9,8 0 0276
+¾ "
+r? 6,6,2 0 0277
+¿ "
+`A 8,11 0 0300
+À "
+'A 8,11 0 0301
+Á "
+^A 8,11 0 0302
+Â "
+~A 8,11 0 0303
+Ã "
+:A 8,11 0 0304
+Ä "
+oA 8,11 0 0305
+Å "
+AE 10,8 0 0306
+Æ "
+,C 7,8,2 0 0307
+Ç "
+`E 8,11 0 0310
+È "
+'E 8,11 0 0311
+É "
+^E 8,11 0 0312
+Ê "
+:E 8,11 0 0313
+Ë "
+`I 6,11 0 0314
+Ì "
+'I 6,11 0 0315
+Í "
+^I 6,11 0 0316
+Î "
+:I 6,11 0 0317
+Ï "
+-D 9,8 0 0320
+Ð "
+~N 8,11 0 0321
+Ñ "
+`O 8,11 0 0322
+Ò "
+'O 8,11 0 0323
+Ó "
+^O 8,11 0 0324
+Ô "
+~O 8,11 0 0325
+Õ "
+:O 8,11 0 0326
+Ö "
+mu 6,6 0 0327
+× "
+/O 8,8 0 0330
+Ø "
+`U 8,11 0 0331
+Ù "
+'U 8,11 0 0332
+Ú "
+^U 8,11 0 0333
+Û "
+:U 8,11 0 0334
+Ü "
+'Y 7,11 0 0335
+Ý "
+TP 8,8 0 0336
+Þ "
+ss 8,8,2 0 0337
+ß "
+`a 7,8 0 0340
+à "
+'a 7,8 0 0341
+á "
+^a 7,8 0 0342
+â "
+~a 7,8 0 0343
+ã "
+:a 7,8 0 0344
+ä "
+oa 7,9 0 0345
+å "
+ae 9,5 0 0346
+æ "
+,c 6,5,2 0 0347
+ç "
+`e 6,8 0 0350
+è "
+'e 6,8 0 0351
+é "
+^e 6,8 0 0352
+ê "
+:e 6,8 0 0353
+ë "
+`i 4,8 0 0354
+ì "
+'i 4,8 0 0355
+í "
+^i 4,8 0 0356
+î "
+:i 4,8 0 0357
+ï "
+Sd 6,8 0 0360
+ð "
+~n 7,8 0 0361
+ñ "
+`o 6,8 0 0362
+ò "
+'o 6,8 0 0363
+ó "
+^o 6,8 0 0364
+ô "
+~o 6,8 0 0365
+õ "
+:o 6,8 0 0366
+ö "
+di 6,6 0 0367
+÷ "
+/o 6,5 0 0370
+ø "
+`u 7,8 0 0371
+ù "
+'u 7,8 0 0372
+ú "
+^u 7,8 0 0373
+û "
+:u 7,8 0 0374
+ü "
+'y 7,8,2 0 0375
+ý "
+Tp 7,8,2 0 0376
+þ "
+:y 7,8,2 0 0377
+ÿ "
diff --git a/font/devX75/NI b/font/devX75/NI
new file mode 100644
index 00000000..20c2c424
--- /dev/null
+++ b/font/devX75/NI
@@ -0,0 +1,306 @@
+name NI
+spacewidth 2
+charset
+--- 2,1 0 040
+! 4,8 0 041
+" 6,8 0 042
+# 8,7 0 043
+sh "
+$ 5,9,1 0 044
+Do "
+% 9,8 0 045
+& 9,8 0 046
+' 3,8 0 047
+( 5,8,1 0 050
+) 5,8,1 0 051
+* 6,8 0 052
++ 6,5 0 053
+, 2,2,1 0 054
+\- 6,3 0 055
+. 2,2 0 056
+/ 5,8,1 0 057
+sl "
+0 5,8 0 060
+1 5,8 0 061
+2 5,8 0 062
+3 5,8 0 063
+4 5,8 0 064
+5 5,8 0 065
+6 5,8 0 066
+7 5,8 0 067
+8 5,8 0 070
+9 5,8 0 071
+: 3,5 0 072
+; 3,5,1 0 073
+< 7,5 0 074
+= 6,4 0 075
+eq "
+> 7,5 0 076
+? 6,8 0 077
+@ 9,8 0 0100
+at "
+A 8,8 0 0101
+B 7,8 0 0102
+C 6,8 0 0103
+D 8,8 0 0104
+E 7,8 0 0105
+F 7,8 0 0106
+G 8,8 0 0107
+H 9,8 0 0110
+I 5,8 0 0111
+J 5,8 0 0112
+K 8,8 0 0113
+L 7,8 0 0114
+M 12,8 0 0115
+N 9,8 0 0116
+O 7,8 0 0117
+P 7,8 0 0120
+Q 7,8,2 0 0121
+R 8,8 0 0122
+S 7,8 0 0123
+T 7,8 0 0124
+U 7,8 0 0125
+V 8,8 0 0126
+W 11,8 0 0127
+X 8,8 0 0130
+Y 8,8 0 0131
+Z 8,8 0 0132
+[ 5,8,1 0 0133
+lB "
+\ 5,8 0 0134
+rs "
+] 5,8,1 0 0135
+rB "
+^ 6,8 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 3,8 0 0140
+oq "
+a 6,5 0 0141
+b 6,8 0 0142
+c 5,5 0 0143
+d 6,8 0 0144
+e 5,5 0 0145
+f 4,8,2 0 0146
+g 5,6,2 0 0147
+h 6,8 0 0150
+i 3,8 0 0151
+j 3,8,2 0 0152
+k 6,8 0 0153
+l 3,8 0 0154
+m 9,5 0 0155
+n 6,5 0 0156
+o 6,5 0 0157
+p 6,5,2 0 0160
+q 6,5,2 0 0161
+r 5,5 0 0162
+s 4,5 0 0163
+t 3,7 0 0164
+u 6,5 0 0165
+v 6,5 0 0166
+w 9,5 0 0167
+x 6,5 0 0170
+y 6,5,2 0 0171
+z 6,5 0 0172
+{ 5,8,1 0 0173
+lC "
+| 6,8 0 0174
+or "
+ba "
+} 5,8,1 0 0175
+rC "
+~ 7,4 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,2 0 0241
+¡ "
+ct 5,6,1 0 0242
+¢ "
+Po 6,8 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 8,8 0 0245
+¥ "
+bb 6,8 0 0246
+¦ "
+sc 6,8,1 0 0247
+§ "
+ad 4,7 0 0250
+¨ "
+co 9,8 0 0251
+© "
+Of 5,8 0 0252
+ª "
+Fo 6,5 0 0253
+« "
+no 6,4 0 0254
+¬ "
+- 4,3 0 0255
+hy "
+­ "
+rg 9,8 0 0256
+® "
+a- 4,7 0 0257
+¯ "
+de 4,8 0 0260
+° "
++- 6,5 0 0261
+± "
+S2 3,8 0 0262
+² "
+S3 3,8 0 0263
+³ "
+aa 3,8 0 0264
+´ "
+µ 6,5,2 0 0265
+ps 8,8 0 0266
+¶ "
+md 3,4 0 0267
+· "
+ac 4,1,2 0 0270
+¸ "
+S1 3,8 0 0271
+¹ "
+Om 4,8 0 0272
+º "
+Fc 6,5 0 0273
+» "
+14 7,8 0 0274
+¼ "
+12 7,8 0 0275
+½ "
+34 7,8 0 0276
+¾ "
+r? 6,6,2 0 0277
+¿ "
+`A 8,11 0 0300
+À "
+'A 8,11 0 0301
+Á "
+^A 8,11 0 0302
+Â "
+~A 8,11 0 0303
+Ã "
+:A 8,10 0 0304
+Ä "
+oA 8,11 0 0305
+Å "
+AE 10,8 0 0306
+Æ "
+,C 6,8,2 0 0307
+Ç "
+`E 7,11 0 0310
+È "
+'E 7,11 0 0311
+É "
+^E 7,11 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 5,11 0 0314
+Ì "
+'I 5,11 0 0315
+Í "
+^I 5,11 0 0316
+Î "
+:I 5,10 0 0317
+Ï "
+-D 8,8 0 0320
+Ð "
+~N 9,11 0 0321
+Ñ "
+`O 7,11 0 0322
+Ò "
+'O 7,11 0 0323
+Ó "
+^O 7,11 0 0324
+Ô "
+~O 7,11 0 0325
+Õ "
+:O 7,10 0 0326
+Ö "
+mu 6,5 0 0327
+× "
+/O 7,8 0 0330
+Ø "
+`U 7,11 0 0331
+Ù "
+'U 7,11 0 0332
+Ú "
+^U 7,11 0 0333
+Û "
+:U 7,10 0 0334
+Ü "
+'Y 8,10 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 7,8,2 0 0337
+ß "
+`a 6,8 0 0340
+à "
+'a 6,8 0 0341
+á "
+^a 6,8 0 0342
+â "
+~a 6,8 0 0343
+ã "
+:a 6,7 0 0344
+ä "
+oa 6,9 0 0345
+å "
+ae 8,5 0 0346
+æ "
+,c 5,5,2 0 0347
+ç "
+`e 5,8 0 0350
+è "
+'e 5,8 0 0351
+é "
+^e 5,8 0 0352
+ê "
+:e 5,7 0 0353
+ë "
+`i 3,8 0 0354
+ì "
+'i 3,8 0 0355
+í "
+^i 3,8 0 0356
+î "
+:i 3,7 0 0357
+ï "
+Sd 6,8 0 0360
+ð "
+~n 6,8 0 0361
+ñ "
+`o 6,8 0 0362
+ò "
+'o 6,8 0 0363
+ó "
+^o 6,8 0 0364
+ô "
+~o 6,8 0 0365
+õ "
+:o 6,7 0 0366
+ö "
+di 6,5 0 0367
+÷ "
+/o 6,5 0 0370
+ø "
+`u 6,8 0 0371
+ù "
+'u 6,8 0 0372
+ú "
+^u 6,8 0 0373
+û "
+:u 6,7 0 0374
+ü "
+'y 6,8,2 0 0375
+ý "
+Tp 6,8,2 0 0376
+þ "
+:y 6,7,2 0 0377
+ÿ "
diff --git a/font/devX75/NR b/font/devX75/NR
new file mode 100644
index 00000000..aa05125e
--- /dev/null
+++ b/font/devX75/NR
@@ -0,0 +1,306 @@
+name NR
+spacewidth 2
+charset
+--- 2,1 0 040
+! 4,8 0 041
+" 6,8 0 042
+# 8,8 0 043
+sh "
+$ 5,9,1 0 044
+Do "
+% 9,8 0 045
+& 10,8 0 046
+' 3,8 0 047
+( 4,8,1 0 050
+) 4,8,1 0 051
+* 6,8 0 052
++ 6,5 0 053
+, 3,2,1 0 054
+\- 6,3 0 055
+. 4,2 0 056
+/ 4,8 0 057
+sl "
+0 5,8 0 060
+1 5,8 0 061
+2 5,8 0 062
+3 5,8 0 063
+4 5,8 0 064
+5 5,8 0 065
+6 5,8 0 066
+7 5,8 0 067
+8 5,8 0 070
+9 5,8 0 071
+: 4,5 0 072
+; 4,5,1 0 073
+< 7,5 0 074
+= 6,4 0 075
+eq "
+> 7,5 0 076
+? 5,8 0 077
+@ 9,8 0 0100
+at "
+A 8,8 0 0101
+B 7,8 0 0102
+C 7,8 0 0103
+D 8,8 0 0104
+E 7,8 0 0105
+F 7,8 0 0106
+G 8,8 0 0107
+H 9,8 0 0110
+I 4,8 0 0111
+J 5,8 0 0112
+K 8,8 0 0113
+L 7,8 0 0114
+M 10,8 0 0115
+N 9,8 0 0116
+O 8,8 0 0117
+P 7,8 0 0120
+Q 8,8,1 0 0121
+R 8,8 0 0122
+S 6,8 0 0123
+T 8,8 0 0124
+U 8,8 0 0125
+V 8,8 0 0126
+W 12,8 0 0127
+X 7,8 0 0130
+Y 8,8 0 0131
+Z 6,8 0 0132
+[ 3,8,1 0 0133
+lB "
+\ 5,8 0 0134
+rs "
+] 3,8,1 0 0135
+rB "
+^ 6,8 0 0136
+a^ "
+ha "
+_ 6,0,2 0 0137
+` 3,8 0 0140
+oq "
+a 6,5 0 0141
+b 5,8 0 0142
+c 5,5 0 0143
+d 6,8 0 0144
+e 5,5 0 0145
+f 4,8 0 0146
+g 6,5,2 0 0147
+h 6,8 0 0150
+i 4,7 0 0151
+j 4,7,2 0 0152
+k 7,8 0 0153
+l 4,8 0 0154
+m 10,5 0 0155
+n 7,5 0 0156
+o 5,5 0 0157
+p 5,5,2 0 0160
+q 6,5,2 0 0161
+r 5,5 0 0162
+s 5,5 0 0163
+t 3,7 0 0164
+u 6,5 0 0165
+v 6,5 0 0166
+w 8,5 0 0167
+x 6,5 0 0170
+y 6,5,2 0 0171
+z 5,5 0 0172
+{ 4,8,1 0 0173
+lC "
+| 6,8 0 0174
+or "
+ba "
+} 4,8,1 0 0175
+rC "
+~ 7,4 0 0176
+a~ "
+ap "
+ti "
+r! 4,6,2 0 0241
+¡ "
+ct 6,6,1 0 0242
+¢ "
+Po 7,8 0 0243
+£ "
+Cs 7,7 0 0244
+¤ "
+Ye 8,8 0 0245
+¥ "
+bb 6,8 0 0246
+¦ "
+sc 5,8,2 0 0247
+§ "
+ad 4,7 0 0250
+¨ "
+co 10,8 0 0251
+© "
+Of 5,8 0 0252
+ª "
+Fo 6,4 0 0253
+« "
+no 6,4 0 0254
+¬ "
+- 4,3 0 0255
+hy "
+­ "
+rg 10,8 0 0256
+® "
+a- 5,7 0 0257
+¯ "
+de 4,8 0 0260
+° "
++- 6,5 0 0261
+± "
+S2 3,8 0 0262
+² "
+S3 3,8 0 0263
+³ "
+aa 3,8 0 0264
+´ "
+µ 6,5,2 0 0265
+ps 7,8,2 0 0266
+¶ "
+md 4,4 0 0267
+· "
+ac 3,1,2 0 0270
+¸ "
+S1 3,8 0 0271
+¹ "
+Om 5,8 0 0272
+º "
+Fc 6,4 0 0273
+» "
+14 7,8 0 0274
+¼ "
+12 7,8 0 0275
+½ "
+34 7,8 0 0276
+¾ "
+r? 5,6,2 0 0277
+¿ "
+`A 8,11 0 0300
+À "
+'A 8,11 0 0301
+Á "
+^A 8,11 0 0302
+Â "
+~A 8,11 0 0303
+Ã "
+:A 8,10 0 0304
+Ä "
+oA 8,11 0 0305
+Å "
+AE 11,8 0 0306
+Æ "
+,C 7,8,2 0 0307
+Ç "
+`E 7,11 0 0310
+È "
+'E 7,11 0 0311
+É "
+^E 7,11 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 4,11 0 0314
+Ì "
+'I 4,11 0 0315
+Í "
+^I 4,11 0 0316
+Î "
+:I 4,10 0 0317
+Ï "
+-D 8,8 0 0320
+Ð "
+~N 9,11 0 0321
+Ñ "
+`O 8,11 0 0322
+Ò "
+'O 8,11 0 0323
+Ó "
+^O 8,11 0 0324
+Ô "
+~O 8,11 0 0325
+Õ "
+:O 8,10 0 0326
+Ö "
+mu 6,5 0 0327
+× "
+/O 8,8 0 0330
+Ø "
+`U 8,11 0 0331
+Ù "
+'U 8,11 0 0332
+Ú "
+^U 8,11 0 0333
+Û "
+:U 8,10 0 0334
+Ü "
+'Y 8,10 0 0335
+Ý "
+TP 7,8 0 0336
+Þ "
+ss 7,8 0 0337
+ß "
+`a 6,8 0 0340
+à "
+'a 6,8 0 0341
+á "
+^a 6,8 0 0342
+â "
+~a 6,8 0 0343
+ã "
+:a 6,7 0 0344
+ä "
+oa 6,8 0 0345
+å "
+ae 8,5 0 0346
+æ "
+,c 5,5,2 0 0347
+ç "
+`e 5,8 0 0350
+è "
+'e 5,8 0 0351
+é "
+^e 5,8 0 0352
+ê "
+:e 5,7 0 0353
+ë "
+`i 4,8 0 0354
+ì "
+'i 4,8 0 0355
+í "
+^i 4,8 0 0356
+î "
+:i 4,7 0 0357
+ï "
+Sd 5,8 0 0360
+ð "
+~n 7,8 0 0361
+ñ "
+`o 5,8 0 0362
+ò "
+'o 5,8 0 0363
+ó "
+^o 5,8 0 0364
+ô "
+~o 5,8 0 0365
+õ "
+:o 5,7 0 0366
+ö "
+di 6,5 0 0367
+÷ "
+/o 5,5,1 0 0370
+ø "
+`u 6,8 0 0371
+ù "
+'u 6,8 0 0372
+ú "
+^u 6,8 0 0373
+û "
+:u 6,7 0 0374
+ü "
+'y 6,8,2 0 0375
+ý "
+Tp 5,8,2 0 0376
+þ "
+:y 6,7,2 0 0377
+ÿ "
diff --git a/font/devX75/S b/font/devX75/S
new file mode 100644
index 00000000..b1cfbbf1
--- /dev/null
+++ b/font/devX75/S
@@ -0,0 +1,226 @@
+name S
+special
+spacewidth 3
+charset
+--- 3,1 0 040
+! 3,7 0 041
+fa 7,7 0 042
+# 5,7 0 043
+sh "
+te 6,7 0 044
+% 8,7 0 045
+& 7,7 0 046
+st 5,5 0 047
+( 4,7,2 0 050
+) 4,7,2 0 051
+** 5,6 0 052
++ 6,5 0 053
+pl "
+, 2,1,2 0 054
+\- 6,3 0 055
+mi "
+. 2,2 0 056
+/ 3,7 0 057
+sl "
+0 5,7 0 060
+1 5,7 0 061
+2 5,7 0 062
+3 5,7 0 063
+4 5,7 0 064
+5 5,7 0 065
+6 5,7 0 066
+7 5,7 0 067
+8 5,7 0 070
+9 5,7 0 071
+: 2,5 0 072
+; 2,5,2 0 073
+< 7,5 0 074
+= 6,4 0 075
+eq "
+> 6,5 0 076
+? 5,7 0 077
+=~ 6,6 0 0100
+*A 8,7 0 0101
+*B 6,7 0 0102
+*X 8,7 0 0103
+*D 7,7 0 0104
+*E 6,7 0 0105
+*F 8,7 0 0106
+*G 6,7 0 0107
+*Y 8,7 0 0110
+*I 3,7 0 0111
++h 7,7 0 0112
+*K 7,7 0 0113
+*L 7,7 0 0114
+*M 10,7 0 0115
+*N 8,7 0 0116
+*O 7,7 0 0117
+*P 8,7 0 0120
+*H 7,7 0 0121
+*R 6,7 0 0122
+*S 6,7 0 0123
+*T 6,7 0 0124
+--- 8,7 0 0125
+ts 5,5,2 0 0126
+*W 9,7 0 0127
+*C 7,7 0 0130
+*Q 9,7 0 0131
+*Z 6,7 0 0132
+[ 3,7,2 0 0133
+lB "
+tf 7,5 0 0134
+3d "
+] 3,7,2 0 0135
+rB "
+pp 7,7 0 0136
+_ 5,0,3 0 0137
+radicalex 5,10 0 0140
+*a 7,5 0 0141
+*b 5,8,2 0 0142
+*x 6,5,2 0 0143
+*d 5,8 0 0144
+*e 5,5 0 0145
+*f 6,7,2 0 0146
+*g 6,5,2 0 0147
+*y 6,5,2 0 0150
+*i 4,5 0 0151
++f 6,5,2 0 0152
+*k 6,5 0 0153
+*l 6,8 0 0154
+*m 6,5,2 0 0155
+µ "
+*n 6,5 0 0156
+*o 5,5 0 0157
+*p 6,5 0 0160
+*h 5,7 0 0161
+*r 5,5,3 0 0162
+*s 6,5 0 0163
+*t 5,5 0 0164
+*u 6,5 0 0165
++p 8,6 0 0166
+*w 8,5 0 0167
+*c 5,8,2 0 0170
+*q 7,5,2 0 0171
+*z 5,8,2 0 0172
+lC 5,7,2 0 0173
+{ "
+ba 2,7,2 0 0174
+or "
+| "
+rC 5,7,2 0 0175
+} "
+ap 6,4 0 0176
+*U 7,7 0 0241
+fm 3,8 0 0242
+<= 6,7 0 0243
+f/ 3,7 0 0244
+if 7,4 0 0245
+Fn 5,7,2 0 0246
+CL 7,5 0 0247
+DI 7,5 0 0250
+HE 7,5 0 0251
+SP 7,5 0 0252
+<> 10,5 0 0253
+<- 10,5 0 0254
+ua 6,10,4 0 0255
+arrowverttp "
+-> 10,5 0 0256
+da 6,10,2 0 0257
+arrowvertbt "
+de 4,7 0 0260
+° "
++- 6,7 0 0261
+± "
+sd 4,8 0 0262
+>= 6,7 0 0263
+mu 6,5 0 0264
+× "
+pt 7,4 0 0265
+pd 5,8 0 0266
+bu 5,4 0 0267
+di 6,5 0 0270
+÷ "
+!= 6,5 0 0271
+== 6,5 0 0272
+~= 6,5 0 0273
+~~ "
+--- 9,1 0 0274
+arrowvertex 6,10,4 0 0275
+an 10,3 0 0276
+CR 7,6 0 0277
+Ah 8,7 0 0300
+Im 7,8,1 0 0301
+Re 8,8 0 0302
+wp 9,6,2 0 0303
+c* 8,7 0 0304
+c+ 8,7 0 0305
+es 8,8,1 0 0306
+ca 8,5 0 0307
+cu 8,5 0 0310
+sp 7,5 0 0311
+ip 7,5,2 0 0312
+--- 7,6,1 0 0313
+sb 7,5 0 0314
+ib 7,5,2 0 0315
+mo 7,5 0 0316
+nm 7,6,1 0 0317
+/_ 8,7 0 0320
+gr 7,7 0 0321
+rg 8,7,1 0 0322
+co 8,7,1 0 0323
+tm 10,7 0 0324
+--- 9,8,1 0 0325
+sr 6,10 0 0326
+md 3,3 0 0327
+no 7,3 0 0330
+¬ "
+AN 6,5 0 0331
+OR 6,5 0 0332
+hA 11,5 0 0333
+lA 10,5 0 0334
+uA 6,10 0 0335
+rA 10,5 0 0336
+dA 6,10 0 0337
+lz 7,7 0 0340
+la 3,7,2 0 0341
+--- 8,7,1 0 0342
+--- 8,7,1 0 0343
+--- 9,7 0 0344
+--- 7,8,1 0 0345
+parenlefttp 4,10,4 0 0346
+parenleftex 4,10,4 0 0347
+parenleftbt 4,10,4 0 0350
+bracketlefttp 4,10,4 0 0351
+lc "
+bracketleftex 4,10,4 0 0352
+bracketleftbt 4,10,2 0 0353
+lf "
+bracelefttp 5,10,4 0 0354
+lt "
+braceleftmid 5,10,4 0 0355
+lk "
+braceleftbt 5,10,2 0 0356
+lb "
+bracerightex 5,10,4 0 0357
+braceleftex "
+bv "
+--- 8,9 0 0360
+ra 3,7,2 0 0361
+is 3,10,2 0 0362
+--- 7,10,4 0 0363
+--- 7,10,4 0 0364
+--- 7,10,2 0 0365
+parenrighttp 4,10,4 0 0366
+parenrightex 4,10,4 0 0367
+parenrightbt 4,10,4 0 0370
+bracketrighttp 4,10,4 0 0371
+rc "
+bracketrightex 4,10,4 0 0372
+bracketrightbt 4,10,2 0 0373
+rf "
+bracerighttp 5,10,4 0 0374
+rt "
+bracerightmid 5,10,4 0 0375
+rk "
+bracerightbt 5,10,2 0 0376
+rb "
diff --git a/font/devX75/TB b/font/devX75/TB
new file mode 100644
index 00000000..09077142
--- /dev/null
+++ b/font/devX75/TB
@@ -0,0 +1,306 @@
+name TB
+spacewidth 2
+charset
+--- 2,1 0 040
+! 4,7 0 041
+" 5,7 0 042
+# 6,7 0 043
+sh "
+$ 5,8,1 0 044
+Do "
+% 9,7 0 045
+& 9,7 0 046
+' 4,7 0 047
+( 4,7,3 0 050
+) 4,7,3 0 051
+* 6,7 0 052
++ 6,5 0 053
+, 4,2,1 0 054
+\- 7,3 0 055
+. 3,2 0 056
+/ 3,7 0 057
+sl "
+0 5,7 0 060
+1 5,7 0 061
+2 5,7 0 062
+3 5,7 0 063
+4 5,7 0 064
+5 5,7 0 065
+6 5,7 0 066
+7 5,7 0 067
+8 5,7 0 070
+9 5,7 0 071
+: 4,5 0 072
+; 4,5,1 0 073
+< 6,5 0 074
+= 6,4 0 075
+eq "
+> 6,5 0 076
+? 6,7 0 077
+@ 11,7,2 0 0100
+at "
+A 7,7 0 0101
+B 7,7 0 0102
+C 7,7 0 0103
+D 8,7 0 0104
+E 7,7 0 0105
+F 7,7 0 0106
+G 7,7 0 0107
+H 9,7 0 0110
+I 5,7 0 0111
+J 5,7,1 0 0112
+K 8,7 0 0113
+L 7,7 0 0114
+M 10,7 0 0115
+N 8,7 0 0116
+O 7,7 0 0117
+P 6,7 0 0120
+Q 7,7,2 0 0121
+R 7,7 0 0122
+S 6,7 0 0123
+T 7,7 0 0124
+U 7,7 0 0125
+V 8,7 0 0126
+W 10,7 0 0127
+X 7,7 0 0130
+Y 8,7 0 0131
+Z 7,7 0 0132
+[ 4,7,3 0 0133
+lB "
+\ 3,7 0 0134
+rs "
+] 4,7,3 0 0135
+rB "
+^ 6,7 0 0136
+a^ "
+ha "
+_ 5,0,3 0 0137
+` 4,7 0 0140
+oq "
+a 5,5 0 0141
+b 5,7 0 0142
+c 5,5 0 0143
+d 6,7 0 0144
+e 5,5 0 0145
+f 3,7 0 0146
+g 5,5,3 0 0147
+h 5,7 0 0150
+i 3,8 0 0151
+j 4,8,2 0 0152
+k 5,7 0 0153
+l 3,7 0 0154
+m 8,5 0 0155
+n 6,5 0 0156
+o 6,5 0 0157
+p 5,5,2 0 0160
+q 5,5,2 0 0161
+r 4,5 0 0162
+s 4,5 0 0163
+t 4,7 0 0164
+u 5,5 0 0165
+v 5,5 0 0166
+w 6,5 0 0167
+x 5,5 0 0170
+y 5,5,2 0 0171
+z 5,5 0 0172
+{ 4,7,3 0 0173
+lC "
+| 3,7,2 0 0174
+or "
+ba "
+} 4,7,3 0 0175
+rC "
+~ 6,4 0 0176
+a~ "
+ap "
+ti "
+r! 4,4,3 0 0241
+¡ "
+ct 6,6,1 0 0242
+¢ "
+Po 6,7 0 0243
+£ "
+Cs 6,6 0 0244
+¤ "
+Ye 6,7 0 0245
+¥ "
+bb 3,7,2 0 0246
+¦ "
+sc 5,7,2 0 0247
+§ "
+ad 4,8 0 0250
+¨ "
+co 9,7 0 0251
+© "
+Of 4,7 0 0252
+ª "
+Fo 6,5 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 3,3 0 0255
+hy "
+­ "
+rg 9,7 0 0256
+® "
+a- 4,7 0 0257
+¯ "
+de 4,7 0 0260
+° "
++- 6,7 0 0261
+± "
+S2 3,7 0 0262
+² "
+S3 3,7 0 0263
+³ "
+aa 4,7 0 0264
+´ "
+µ 5,5,3 0 0265
+ps 6,7,3 0 0266
+¶ "
+md 3,4 0 0267
+· "
+ac 3,0,3 0 0270
+¸ "
+S1 3,7 0 0271
+¹ "
+Om 4,7 0 0272
+º "
+Fc 6,5 0 0273
+» "
+14 7,7 0 0274
+¼ "
+12 7,7 0 0275
+½ "
+34 7,7 0 0276
+¾ "
+r? 6,4,3 0 0277
+¿ "
+`A 7,10 0 0300
+À "
+'A 7,10 0 0301
+Á "
+^A 7,10 0 0302
+Â "
+~A 7,10 0 0303
+Ã "
+:A 7,10 0 0304
+Ä "
+oA 7,10 0 0305
+Å "
+AE 9,7 0 0306
+Æ "
+,C 7,7,3 0 0307
+Ç "
+`E 7,10 0 0310
+È "
+'E 7,10 0 0311
+É "
+^E 7,10 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 5,10 0 0314
+Ì "
+'I 5,10 0 0315
+Í "
+^I 5,10 0 0316
+Î "
+:I 5,10 0 0317
+Ï "
+-D 8,7 0 0320
+Ð "
+~N 8,10 0 0321
+Ñ "
+`O 7,10 0 0322
+Ò "
+'O 7,10 0 0323
+Ó "
+^O 7,10 0 0324
+Ô "
+~O 7,10 0 0325
+Õ "
+:O 7,10 0 0326
+Ö "
+mu 6,5 0 0327
+× "
+/O 7,8,1 0 0330
+Ø "
+`U 7,10 0 0331
+Ù "
+'U 7,10 0 0332
+Ú "
+^U 7,10 0 0333
+Û "
+:U 7,10 0 0334
+Ü "
+'Y 8,10 0 0335
+Ý "
+TP 6,7 0 0336
+Þ "
+ss 6,7 0 0337
+ß "
+`a 5,8 0 0340
+à "
+'a 5,8 0 0341
+á "
+^a 5,8 0 0342
+â "
+~a 5,8 0 0343
+ã "
+:a 5,8 0 0344
+ä "
+oa 5,8 0 0345
+å "
+ae 8,5 0 0346
+æ "
+,c 5,5,3 0 0347
+ç "
+`e 5,8 0 0350
+è "
+'e 5,8 0 0351
+é "
+^e 5,8 0 0352
+ê "
+:e 5,8 0 0353
+ë "
+`i 3,8 0 0354
+ì "
+'i 3,8 0 0355
+í "
+^i 3,8 0 0356
+î "
+:i 3,8 0 0357
+ï "
+Sd 6,8 0 0360
+ð "
+~n 6,8 0 0361
+ñ "
+`o 6,8 0 0362
+ò "
+'o 6,8 0 0363
+ó "
+^o 6,8 0 0364
+ô "
+~o 6,8 0 0365
+õ "
+:o 6,8 0 0366
+ö "
+di 6,5 0 0367
+÷ "
+/o 6,6,1 0 0370
+ø "
+`u 5,8 0 0371
+ù "
+'u 5,8 0 0372
+ú "
+^u 5,8 0 0373
+û "
+:u 5,8 0 0374
+ü "
+'y 5,8,3 0 0375
+ý "
+Tp 5,7,3 0 0376
+þ "
+:y 5,8,3 0 0377
+ÿ "
diff --git a/font/devX75/TBI b/font/devX75/TBI
new file mode 100644
index 00000000..37d92b0a
--- /dev/null
+++ b/font/devX75/TBI
@@ -0,0 +1,306 @@
+name TBI
+spacewidth 2
+charset
+--- 2,1 0 040
+! 6,7 0 041
+" 6,7 0 042
+# 8,7 0 043
+sh "
+$ 5,7 0 044
+Do "
+% 11,7 0 045
+& 8,7 0 046
+' 4,7 0 047
+( 6,7,2 0 050
+) 6,7,2 0 051
+* 7,8 0 052
++ 7,5 0 053
+, 4,2,1 0 054
+\- 7,3 0 055
+. 4,2 0 056
+/ 5,7 0 057
+sl "
+0 5,7 0 060
+1 5,7 0 061
+2 5,7 0 062
+3 5,7 0 063
+4 5,7 0 064
+5 5,7 0 065
+6 5,7 0 066
+7 5,7 0 067
+8 5,7 0 070
+9 5,7 0 071
+: 3,5 0 072
+; 5,5,1 0 073
+< 6,5 0 074
+= 7,4 0 075
+eq "
+> 6,5 0 076
+? 5,7 0 077
+@ 11,7,2 0 0100
+at "
+A 6,7 0 0101
+B 7,7 0 0102
+C 7,7 0 0103
+D 7,7 0 0104
+E 7,7 0 0105
+F 7,7 0 0106
+G 7,7 0 0107
+H 8,7 0 0110
+I 4,7 0 0111
+J 5,7,1 0 0112
+K 7,7 0 0113
+L 6,7 0 0114
+M 10,7 0 0115
+N 8,7 0 0116
+O 7,7 0 0117
+P 6,7 0 0120
+Q 7,7,2 0 0121
+R 7,7 0 0122
+S 6,7 0 0123
+T 6,7 0 0124
+U 8,7 0 0125
+V 7,7 0 0126
+W 9,7 0 0127
+X 7,7 0 0130
+Y 6,7 0 0131
+Z 6,7 0 0132
+[ 5,7,2 0 0133
+lB "
+\ 5,7 0 0134
+rs "
+] 5,7,2 0 0135
+rB "
+^ 7,7 0 0136
+a^ "
+ha "
+_ 5,0,2 0 0137
+` 4,7 0 0140
+oq "
+a 5,5 0 0141
+b 5,7 0 0142
+c 5,5 0 0143
+d 5,7 0 0144
+e 5,5 0 0145
+f 4,7,3 0 0146
+g 4,5,3 0 0147
+h 5,7 0 0150
+i 3,7 0 0151
+j 3,7,3 0 0152
+k 5,7 0 0153
+l 3,7 0 0154
+m 7,5 0 0155
+n 5,5 0 0156
+o 5,5 0 0157
+p 5,5,3 0 0160
+q 5,5,3 0 0161
+r 4,5 0 0162
+s 4,5 0 0163
+t 4,6 0 0164
+u 5,5 0 0165
+v 4,5 0 0166
+w 7,5 0 0167
+x 4,5 0 0170
+y 5,5,2 0 0171
+z 4,5 0 0172
+{ 5,7,2 0 0173
+lC "
+| 3,7 0 0174
+or "
+ba "
+} 5,7,2 0 0175
+rC "
+~ 6,4 0 0176
+a~ "
+ap "
+ti "
+r! 5,5,3 0 0241
+¡ "
+ct 5,6,1 0 0242
+¢ "
+Po 5,7 0 0243
+£ "
+Cs 7,6 0 0244
+¤ "
+Ye 5,7 0 0245
+¥ "
+bb 3,7 0 0246
+¦ "
+sc 5,7,2 0 0247
+§ "
+ad 5,7 0 0250
+¨ "
+co 9,7 0 0251
+© "
+Of 5,7 0 0252
+ª "
+Fo 8,5 0 0253
+« "
+no 7,5 0 0254
+¬ "
+- 3,3 0 0255
+hy "
+­ "
+rg 9,7 0 0256
+® "
+a- 4,7 0 0257
+¯ "
+de 4,7 0 0260
+° "
++- 7,7 0 0261
+± "
+S2 3,7 0 0262
+² "
+S3 3,7 0 0263
+³ "
+aa 4,7 0 0264
+´ "
+µ 5,5,3 0 0265
+ps 8,7,3 0 0266
+¶ "
+md 4,4 0 0267
+· "
+ac 3,0,3 0 0270
+¸ "
+S1 3,7 0 0271
+¹ "
+Om 5,7 0 0272
+º "
+Fc 8,5 0 0273
+» "
+14 7,7 0 0274
+¼ "
+12 7,7 0 0275
+½ "
+34 7,7 0 0276
+¾ "
+r? 5,5,3 0 0277
+¿ "
+`A 6,10 0 0300
+À "
+'A 6,10 0 0301
+Á "
+^A 6,10 0 0302
+Â "
+~A 6,10 0 0303
+Ã "
+:A 6,10 0 0304
+Ä "
+oA 6,10 0 0305
+Å "
+AE 9,7 0 0306
+Æ "
+,C 7,7,3 0 0307
+Ç "
+`E 7,10 0 0310
+È "
+'E 7,10 0 0311
+É "
+^E 7,10 0 0312
+Ê "
+:E 7,10 0 0313
+Ë "
+`I 4,10 0 0314
+Ì "
+'I 4,10 0 0315
+Í "
+^I 4,10 0 0316
+Î "
+:I 4,10 0 0317
+Ï "
+-D 7,7 0 0320
+Ð "
+~N 8,10 0 0321
+Ñ "
+`O 7,10 0 0322
+Ò "
+'O 7,10 0 0323
+Ó "
+^O 7,10 0 0324
+Ô "
+~O 7,10 0 0325
+Õ "
+:O 7,10 0 0326
+Ö "
+mu 7,5 0 0327
+× "
+/O 7,8,1 0 0330
+Ø "
+`U 8,10 0 0331
+Ù "
+'U 8,10 0 0332
+Ú "
+^U 8,10 0 0333
+Û "
+:U 8,10 0 0334
+Ü "
+'Y 6,10 0 0335
+Ý "
+TP 6,7 0 0336
+Þ "
+ss 6,7,3 0 0337
+ß "
+`a 5,8 0 0340
+à "
+'a 5,8 0 0341
+á "
+^a 5,8 0 0342
+â "
+~a 5,8 0 0343
+ã "
+:a 5,8 0 0344
+ä "
+oa 5,8 0 0345
+å "
+ae 8,5 0 0346
+æ "
+,c 5,5,3 0 0347
+ç "
+`e 5,8 0 0350
+è "
+'e 5,8 0 0351
+é "
+^e 5,8 0 0352
+ê "
+:e 5,8 0 0353
+ë "
+`i 3,8 0 0354
+ì "
+'i 3,8 0 0355
+í "
+^i 3,8 0 0356
+î "
+:i 3,8 0 0357
+ï "
+Sd 5,8 0 0360
+ð "
+~n 5,8 0 0361
+ñ "
+`o 5,8 0 0362
+ò "
+'o 5,8 0 0363
+ó "
+^o 5,8 0 0364
+ô "
+~o 5,8 0 0365
+õ "
+:o 5,8 0 0366
+ö "
+di 7,5 0 0367
+÷ "
+/o 5,6,1 0 0370
+ø "
+`u 5,8 0 0371
+ù "
+'u 5,8 0 0372
+ú "
+^u 5,8 0 0373
+û "
+:u 5,8 0 0374
+ü "
+'y 5,8,2 0 0375
+ý "
+Tp 5,7,3 0 0376
+þ "
+:y 5,8,2 0 0377
+ÿ "
diff --git a/font/devX75/TI b/font/devX75/TI
new file mode 100644
index 00000000..daa858e2
--- /dev/null
+++ b/font/devX75/TI
@@ -0,0 +1,306 @@
+name TI
+spacewidth 2
+charset
+--- 2,1 0 040
+! 3,7 0 041
+" 4,8 0 042
+# 5,7 0 043
+sh "
+$ 5,8,1 0 044
+Do "
+% 9,7 0 045
+& 8,7 0 046
+' 3,8 0 047
+( 3,7,2 0 050
+) 4,7,2 0 051
+* 5,7 0 052
++ 7,5 0 053
+, 3,1,2 0 054
+\- 7,3 0 055
+. 3,1 0 056
+/ 4,7 0 057
+sl "
+0 5,7 0 060
+1 5,7 0 061
+2 5,7 0 062
+3 5,7 0 063
+4 5,7 0 064
+5 5,7 0 065
+6 5,7 0 066
+7 5,7 0 067
+8 5,7 0 070
+9 5,7 0 071
+: 3,5 0 072
+; 3,5,2 0 073
+< 5,5 0 074
+= 7,4 0 075
+eq "
+> 5,5 0 076
+? 5,7 0 077
+@ 10,7,2 0 0100
+at "
+A 7,7 0 0101
+B 6,7 0 0102
+C 7,7 0 0103
+D 7,7 0 0104
+E 6,7 0 0105
+F 6,7 0 0106
+G 8,7 0 0107
+H 7,7 0 0110
+I 3,7 0 0111
+J 4,7 0 0112
+K 7,7 0 0113
+L 6,7 0 0114
+M 10,7 0 0115
+N 7,7 0 0116
+O 7,7 0 0117
+P 6,7 0 0120
+Q 7,7,2 0 0121
+R 6,7 0 0122
+S 5,7 0 0123
+T 6,7 0 0124
+U 7,7 0 0125
+V 6,7 0 0126
+W 9,7 0 0127
+X 6,7 0 0130
+Y 6,7 0 0131
+Z 6,7 0 0132
+[ 4,7,2 0 0133
+lB "
+\ 5,7 0 0134
+rs "
+] 4,7,2 0 0135
+rB "
+^ 5,7 0 0136
+a^ "
+ha "
+_ 5,0,3 0 0137
+` 3,8 0 0140
+oq "
+a 5,5 0 0141
+b 5,7 0 0142
+c 5,5 0 0143
+d 5,7 0 0144
+e 5,5 0 0145
+f 3,7,3 0 0146
+g 4,5,3 0 0147
+h 5,7 0 0150
+i 3,7 0 0151
+j 3,7,3 0 0152
+k 5,7 0 0153
+l 3,7 0 0154
+m 7,5 0 0155
+n 5,5 0 0156
+o 5,5 0 0157
+p 5,5,3 0 0160
+q 5,5,3 0 0161
+r 4,5 0 0162
+s 4,5 0 0163
+t 3,6 0 0164
+u 5,5 0 0165
+v 5,5 0 0166
+w 7,5 0 0167
+x 4,5 0 0170
+y 5,5,3 0 0171
+z 4,5 0 0172
+{ 4,7,2 0 0173
+lC "
+| 3,7,2 0 0174
+or "
+ba "
+} 4,7,2 0 0175
+rC "
+~ 6,4 0 0176
+a~ "
+ap "
+ti "
+r! 4,5,2 0 0241
+¡ "
+ct 5,6,1 0 0242
+¢ "
+Po 5,7 0 0243
+£ "
+Cs 5,7 0 0244
+¤ "
+Ye 7,7 0 0245
+¥ "
+bb 3,7,2 0 0246
+¦ "
+sc 5,7,2 0 0247
+§ "
+ad 3,7 0 0250
+¨ "
+co 9,7 0 0251
+© "
+Of 4,7 0 0252
+ª "
+Fo 5,5 0 0253
+« "
+no 7,4 0 0254
+¬ "
+- 4,3 0 0255
+hy "
+­ "
+rg 9,7 0 0256
+® "
+a- 3,7 0 0257
+¯ "
+de 4,7 0 0260
+° "
++- 7,7 0 0261
+± "
+S2 3,7 0 0262
+² "
+S3 3,7 0 0263
+³ "
+aa 3,8 0 0264
+´ "
+µ 5,5,3 0 0265
+ps 6,7,3 0 0266
+¶ "
+md 3,3 0 0267
+· "
+ac 3,0,2 0 0270
+¸ "
+S1 3,7 0 0271
+¹ "
+Om 3,7 0 0272
+º "
+Fc 5,5 0 0273
+» "
+14 7,7 0 0274
+¼ "
+12 7,7 0 0275
+½ "
+34 7,7 0 0276
+¾ "
+r? 5,5,2 0 0277
+¿ "
+`A 7,10 0 0300
+À "
+'A 7,10 0 0301
+Á "
+^A 7,10 0 0302
+Â "
+~A 7,10 0 0303
+Ã "
+:A 7,9 0 0304
+Ä "
+oA 7,10 0 0305
+Å "
+AE 8,7 0 0306
+Æ "
+,C 7,7,2 0 0307
+Ç "
+`E 6,10 0 0310
+È "
+'E 6,10 0 0311
+É "
+^E 6,10 0 0312
+Ê "
+:E 6,9 0 0313
+Ë "
+`I 3,10 0 0314
+Ì "
+'I 3,10 0 0315
+Í "
+^I 3,10 0 0316
+Î "
+:I 3,9 0 0317
+Ï "
+-D 7,7 0 0320
+Ð "
+~N 7,10 0 0321
+Ñ "
+`O 7,10 0 0322
+Ò "
+'O 7,10 0 0323
+Ó "
+^O 7,10 0 0324
+Ô "
+~O 7,10 0 0325
+Õ "
+:O 7,9 0 0326
+Ö "
+mu 7,5 0 0327
+× "
+/O 7,8,1 0 0330
+Ø "
+`U 7,10 0 0331
+Ù "
+'U 7,10 0 0332
+Ú "
+^U 7,10 0 0333
+Û "
+:U 7,9 0 0334
+Ü "
+'Y 6,9 0 0335
+Ý "
+TP 6,7 0 0336
+Þ "
+ss 6,7,2 0 0337
+ß "
+`a 5,8 0 0340
+à "
+'a 5,8 0 0341
+á "
+^a 5,8 0 0342
+â "
+~a 5,8 0 0343
+ã "
+:a 5,7 0 0344
+ä "
+oa 5,8 0 0345
+å "
+ae 7,5 0 0346
+æ "
+,c 5,5,2 0 0347
+ç "
+`e 5,8 0 0350
+è "
+'e 5,8 0 0351
+é "
+^e 5,8 0 0352
+ê "
+:e 5,7 0 0353
+ë "
+`i 3,8 0 0354
+ì "
+'i 3,8 0 0355
+í "
+^i 3,8 0 0356
+î "
+:i 3,7 0 0357
+ï "
+Sd 5,8 0 0360
+ð "
+~n 5,8 0 0361
+ñ "
+`o 5,8 0 0362
+ò "
+'o 5,8 0 0363
+ó "
+^o 5,8 0 0364
+ô "
+~o 5,8 0 0365
+õ "
+:o 5,7 0 0366
+ö "
+di 7,5 0 0367
+÷ "
+/o 5,6,1 0 0370
+ø "
+`u 5,8 0 0371
+ù "
+'u 5,8 0 0372
+ú "
+^u 5,8 0 0373
+û "
+:u 5,7 0 0374
+ü "
+'y 5,8,3 0 0375
+ý "
+Tp 5,7,3 0 0376
+þ "
+:y 5,7,3 0 0377
+ÿ "
diff --git a/font/devX75/TR b/font/devX75/TR
new file mode 100644
index 00000000..c1ac847b
--- /dev/null
+++ b/font/devX75/TR
@@ -0,0 +1,306 @@
+name TR
+spacewidth 2
+charset
+--- 2,1 0 040
+! 3,7 0 041
+" 4,7 0 042
+# 5,7 0 043
+sh "
+$ 5,8,1 0 044
+Do "
+% 8,7 0 045
+& 8,7 0 046
+' 3,7 0 047
+( 4,7,2 0 050
+) 4,7,2 0 051
+* 5,7 0 052
++ 6,5 0 053
+, 3,1,2 0 054
+\- 7,3 0 055
+. 3,1 0 056
+/ 3,7 0 057
+sl "
+0 5,7 0 060
+1 5,7 0 061
+2 5,7 0 062
+3 5,7 0 063
+4 5,7 0 064
+5 5,7 0 065
+6 5,7 0 066
+7 5,7 0 067
+8 5,7 0 070
+9 5,7 0 071
+: 3,5 0 072
+; 3,5,2 0 073
+< 5,5 0 074
+= 6,4 0 075
+eq "
+> 5,5 0 076
+? 4,7 0 077
+@ 9,7,2 0 0100
+at "
+A 8,7 0 0101
+B 6,7 0 0102
+C 7,7 0 0103
+D 7,7 0 0104
+E 6,7 0 0105
+F 6,7 0 0106
+G 7,7 0 0107
+H 8,7 0 0110
+I 4,7 0 0111
+J 4,7 0 0112
+K 7,7 0 0113
+L 6,7 0 0114
+M 10,7 0 0115
+N 8,7 0 0116
+O 7,7 0 0117
+P 6,7 0 0120
+Q 7,7,2 0 0121
+R 7,7 0 0122
+S 5,7 0 0123
+T 6,7 0 0124
+U 8,7 0 0125
+V 8,7 0 0126
+W 10,7 0 0127
+X 8,7 0 0130
+Y 8,7 0 0131
+Z 6,7 0 0132
+[ 3,7,2 0 0133
+lB "
+\ 3,7 0 0134
+rs "
+] 3,7,2 0 0135
+rB "
+^ 5,7 0 0136
+a^ "
+ha "
+_ 5,0,3 0 0137
+` 3,7 0 0140
+oq "
+a 4,5 0 0141
+b 5,7 0 0142
+c 4,5 0 0143
+d 5,7 0 0144
+e 4,5 0 0145
+f 4,7 0 0146
+g 5,5,2 0 0147
+h 5,7 0 0150
+i 3,7 0 0151
+j 3,7,2 0 0152
+k 5,7 0 0153
+l 4,7 0 0154
+m 8,5 0 0155
+n 5,5 0 0156
+o 5,5 0 0157
+p 5,5,2 0 0160
+q 5,5,2 0 0161
+r 4,5 0 0162
+s 4,5 0 0163
+t 4,6 0 0164
+u 5,5 0 0165
+v 5,5 0 0166
+w 8,5 0 0167
+x 6,5 0 0170
+y 5,5,2 0 0171
+z 5,5 0 0172
+{ 4,7,2 0 0173
+lC "
+| 2,7,2 0 0174
+or "
+ba "
+} 4,7,2 0 0175
+rC "
+~ 7,4 0 0176
+a~ "
+ap "
+ti "
+r! 3,5,2 0 0241
+¡ "
+ct 5,6,1 0 0242
+¢ "
+Po 5,7 0 0243
+£ "
+Cs 5,7 0 0244
+¤ "
+Ye 5,7 0 0245
+¥ "
+bb 2,7 0 0246
+¦ "
+sc 5,8,1 0 0247
+§ "
+ad 5,7 0 0250
+¨ "
+co 9,7 0 0251
+© "
+Of 4,7 0 0252
+ª "
+Fo 5,5 0 0253
+« "
+no 7,4 0 0254
+¬ "
+- 4,3 0 0255
+hy "
+­ "
+rg 9,7 0 0256
+® "
+a- 4,7 0 0257
+¯ "
+de 4,7 0 0260
+° "
++- 6,7 0 0261
+± "
+S2 3,7 0 0262
+² "
+S3 3,7 0 0263
+³ "
+aa 3,7 0 0264
+´ "
+µ 5,5,2 0 0265
+ps 6,7,2 0 0266
+¶ "
+md 2,3 0 0267
+· "
+ac 4,0,3 0 0270
+¸ "
+S1 3,7 0 0271
+¹ "
+Om 4,7 0 0272
+º "
+Fc 5,5 0 0273
+» "
+14 8,7 0 0274
+¼ "
+12 8,7 0 0275
+½ "
+34 8,7 0 0276
+¾ "
+r? 4,5,2 0 0277
+¿ "
+`A 8,10 0 0300
+À "
+'A 8,10 0 0301
+Á "
+^A 8,10 0 0302
+Â "
+~A 8,10 0 0303
+Ã "
+:A 8,9 0 0304
+Ä "
+oA 8,10 0 0305
+Å "
+AE 9,7 0 0306
+Æ "
+,C 7,7,3 0 0307
+Ç "
+`E 6,10 0 0310
+È "
+'E 6,10 0 0311
+É "
+^E 6,10 0 0312
+Ê "
+:E 6,9 0 0313
+Ë "
+`I 4,10 0 0314
+Ì "
+'I 4,10 0 0315
+Í "
+^I 4,10 0 0316
+Î "
+:I 4,9 0 0317
+Ï "
+-D 7,7 0 0320
+Ð "
+~N 8,10 0 0321
+Ñ "
+`O 7,10 0 0322
+Ò "
+'O 7,10 0 0323
+Ó "
+^O 7,10 0 0324
+Ô "
+~O 7,10 0 0325
+Õ "
+:O 7,9 0 0326
+Ö "
+mu 6,5 0 0327
+× "
+/O 8,8,1 0 0330
+Ø "
+`U 8,10 0 0331
+Ù "
+'U 8,10 0 0332
+Ú "
+^U 8,10 0 0333
+Û "
+:U 8,9 0 0334
+Ü "
+'Y 8,10 0 0335
+Ý "
+TP 6,7 0 0336
+Þ "
+ss 5,7 0 0337
+ß "
+`a 4,8 0 0340
+à "
+'a 4,8 0 0341
+á "
+^a 4,8 0 0342
+â "
+~a 4,8 0 0343
+ã "
+:a 4,7 0 0344
+ä "
+oa 4,8 0 0345
+å "
+ae 6,5 0 0346
+æ "
+,c 4,5,3 0 0347
+ç "
+`e 4,8 0 0350
+è "
+'e 4,8 0 0351
+é "
+^e 4,8 0 0352
+ê "
+:e 4,7 0 0353
+ë "
+`i 4,8 0 0354
+ì "
+'i 4,8 0 0355
+í "
+^i 4,8 0 0356
+î "
+:i 4,7 0 0357
+ï "
+Sd 5,8 0 0360
+ð "
+~n 5,8 0 0361
+ñ "
+`o 5,8 0 0362
+ò "
+'o 5,8 0 0363
+ó "
+^o 5,8 0 0364
+ô "
+~o 5,8 0 0365
+õ "
+:o 5,7 0 0366
+ö "
+di 6,5 0 0367
+÷ "
+/o 5,6,1 0 0370
+ø "
+`u 5,8 0 0371
+ù "
+'u 5,8 0 0372
+ú "
+^u 5,8 0 0373
+û "
+:u 5,7 0 0374
+ü "
+'y 5,8,2 0 0375
+ý "
+Tp 5,7,2 0 0376
+þ "
+:y 5,7,2 0 0377
+ÿ "
diff --git a/font/devascii/DESC.proto b/font/devascii/DESC.proto
new file mode 100644
index 00000000..88399ab1
--- /dev/null
+++ b/font/devascii/DESC.proto
@@ -0,0 +1,8 @@
+res 240
+hor 24
+vert 40
+unitwidth 10
+sizes 10 0
+fonts 4 R I B BI
+tcommand
+postpro grotty
diff --git a/font/devascii/Makefile.sub b/font/devascii/Makefile.sub
new file mode 100644
index 00000000..238f7b74
--- /dev/null
+++ b/font/devascii/Makefile.sub
@@ -0,0 +1,31 @@
+DEV=ascii
+FONTS=R I B BI
+DEVFILES=$(FONTS) DESC
+CLEANADD=$(FONTS) DESC
+
+RES=240
+CPI=10
+LPI=6
+
+$(FONTS): R.proto
+ @echo Making $@
+ @-rm -f $@
+ @(charwidth=`expr $(RES) / $(CPI)` ; \
+ sed -e "s/^name [A-Z]*$$/name $@/" \
+ -e "s/^\\([^ ]*\\) [0-9]+ /\\1 $$charwidth /" \
+ -e "s/^spacewidth [0-9]+$$/spacewidth $$charwidth/" \
+ -e "s/^internalname .*$$/internalname $@/" \
+ -e "/^internalname/s/BI/3/" \
+ -e "/^internalname/s/B/2/" \
+ -e "/^internalname/s/I/1/" \
+ -e "/^internalname .*[^ 0-9]/d" \
+ $(srcdir)/R.proto >$@)
+
+DESC: DESC.proto
+ @echo Making $@
+ @-rm -f $@
+ @sed -e "s/^res .*$$/res $(RES)/" \
+ -e "s/^hor .*$$/hor `expr $(RES) / $(CPI)`/" \
+ -e "s/^vert .*$$/vert `expr $(RES) / $(LPI)`/" \
+ -e "s/^fonts .*$$/fonts `set $(FONTS); echo $$#` $(FONTS)/" \
+ $(srcdir)/DESC.proto >$@
diff --git a/font/devascii/R.proto b/font/devascii/R.proto
new file mode 100644
index 00000000..876c74c4
--- /dev/null
+++ b/font/devascii/R.proto
@@ -0,0 +1,165 @@
+name R
+internalname 0
+spacewidth 24
+charset
+! 24 0 0041
+" 24 0 0042
+lq "
+rq "
+# 24 0 0043
+sh "
+$ 24 0 0044
+Do "
+% 24 0 0045
+& 24 0 0046
+' 24 0 0047
+aa "
+fm "
+aq "
+( 24 0 0050
+) 24 0 0051
+* 24 0 0052
+** "
++ 24 0 0053
+pl "
+, 24 0 0054
+\- 24 0 0055
+hy "
+- "
+mi "
+en "
+. 24 0 0056
+/ 24 0 0057
+sl "
+f/ "
+0 24 0 0060
+1 24 0 0061
+2 24 0 0062
+3 24 0 0063
+4 24 0 0064
+5 24 0 0065
+6 24 0 0066
+7 24 0 0067
+8 24 0 0070
+9 24 0 0071
+: 24 0 0072
+; 24 0 0073
+< 24 0 0074
+la "
+fo "
+= 24 0 0075
+eq "
+> 24 0 0076
+ra "
+fc "
+? 24 0 0077
+@ 24 0 0100
+at "
+A 24 0 0101
+*A "
+B 24 0 0102
+*B "
+C 24 0 0103
+D 24 0 0104
+E 24 0 0105
+*E "
+F 24 0 0106
+G 24 0 0107
+H 24 0 0110
+*Y "
+I 24 0 0111
+*I "
+J 24 0 0112
+K 24 0 0113
+*K "
+L 24 0 0114
+M 24 0 0115
+*M "
+N 24 0 0116
+*N "
+O 24 0 0117
+ci "
+*O "
+P 24 0 0120
+*R "
+Q 24 0 0121
+R 24 0 0122
+S 24 0 0123
+T 24 0 0124
+*T "
+U 24 0 0125
+V 24 0 0126
+W 24 0 0127
+X 24 0 0130
+*X "
+Y 24 0 0131
+*U "
+Z 24 0 0132
+*Z "
+[ 24 0 0133
+lB "
+\ 24 0 0134
+rs "
+] 24 0 0135
+rB "
+a^ 24 0 0136
+^ "
+ha "
+_ 24 0 0137
+ru "
+ul "
+` 24 0 0140
+oq "
+ga "
+a 24 0 0141
+b 24 0 0142
+c 24 0 0143
+d 24 0 0144
+e 24 0 0145
+f 24 0 0146
+g 24 0 0147
+h 24 0 0150
+i 24 0 0151
+.i "
+j 24 0 0152
+k 24 0 0153
+l 24 0 0154
+m 24 0 0155
+n 24 0 0156
+o 24 0 0157
+*o "
+p 24 0 0160
+q 24 0 0161
+r 24 0 0162
+s 24 0 0163
+t 24 0 0164
+u 24 0 0165
+v 24 0 0166
+w 24 0 0167
+x 24 0 0170
+mu "
+y 24 0 0171
+z 24 0 0172
+lC 24 0 0173
+{ "
+ba 24 0 0174
+or "
+bv "
+br "
+| "
+lb "
+lc "
+lf "
+lk "
+lt "
+rb "
+rc "
+rf "
+rk "
+rt "
+rC 24 0 0175
+} "
+a~ 24 0 0176
+~ "
+ap "
+ti "
diff --git a/font/devdvi/B b/font/devdvi/B
new file mode 100755
index 00000000..240731a7
--- /dev/null
+++ b/font/devdvi/B
@@ -0,0 +1,347 @@
+name B
+internalname cmbx10
+spacewidth 401952
+ligatures ff fi fl ffi ffl 0
+checksum 452076118
+designsize 10485760
+kernpairs
+ff ' 114323
+ff ? 114323
+ff ! 114323
+ff ) 114323
+ff rB 114323
+ff ] 114323
+' ' -100488
+' ? 133984
+' ! 133984
+A t -33496
+A C -33496
+A O -33496
+A G -33496
+A U -33496
+A Q -33496
+A T -100488
+A Y -100488
+A V -133984
+A W -133984
+D X -33496
+D W -33496
+D A -33496
+D V -33496
+D Y -33496
+F o -100488
+F e -100488
+F u -100488
+F r -100488
+F a -100488
+F A -133984
+F O -33496
+F C -33496
+F G -33496
+F Q -33496
+I I 33496
+K O -33496
+K C -33496
+K G -33496
+K Q -33496
+L T -100488
+L Y -100488
+L V -133984
+L W -133984
+O X -33496
+O W -33496
+O A -33496
+O V -33496
+O Y -33496
+P A -100488
+P o -33496
+P e -33496
+P a -33496
+P . -100488
+P , -100488
+R t -33496
+R C -33496
+R O -33496
+R G -33496
+R U -33496
+R Q -33496
+R T -100488
+R Y -100488
+R V -133984
+R W -133984
+T y -33496
+T e -100488
+T o -100488
+T r -100488
+T a -100488
+T A -100488
+T u -100488
+V o -100488
+V e -100488
+V u -100488
+V r -100488
+V a -100488
+V A -133984
+V O -33496
+V C -33496
+V G -33496
+V Q -33496
+W o -100488
+W e -100488
+W u -100488
+W r -100488
+W a -100488
+W A -133984
+W O -33496
+W C -33496
+W G -33496
+W Q -33496
+X O -33496
+X C -33496
+X G -33496
+X Q -33496
+Y e -100488
+Y o -100488
+Y r -100488
+Y a -100488
+Y A -100488
+Y u -100488
+oq oq -100488
+oq ` -100488
+` oq -100488
+` ` -100488
+a v -33496
+a j 66992
+a y -33496
+a w -33496
+b e 33496
+b o 33496
+b x -33496
+b d 33496
+b c 33496
+b q 33496
+b v -33496
+b j 66992
+b y -33496
+b w -33496
+c h -33496
+c k -33496
+f ' 114323
+f ? 114323
+f ! 114323
+f ) 114323
+f rB 114323
+f ] 114323
+g j 33496
+h t -33496
+h u -33496
+h b -33496
+h y -33496
+h v -33496
+h w -33496
+k a -66992
+k e -33496
+k a -33496
+k o -33496
+k c -33496
+m t -33496
+m u -33496
+m b -33496
+m y -33496
+m v -33496
+m w -33496
+n t -33496
+n u -33496
+n b -33496
+n y -33496
+n v -33496
+n w -33496
+o e 33496
+o o 33496
+o x -33496
+o d 33496
+o c 33496
+o q 33496
+o v -33496
+o j 66992
+o y -33496
+o w -33496
+p e 33496
+p o 33496
+p x -33496
+p d 33496
+p c 33496
+p q 33496
+p v -33496
+p j 66992
+p y -33496
+p w -33496
+t y -33496
+t w -33496
+u w -33496
+v a -66992
+v e -33496
+v a -33496
+v o -33496
+v c -33496
+w e -33496
+w a -33496
+w o -33496
+w c -33496
+y o -33496
+y e -33496
+y a -33496
+y . -100488
+y , -100488
+charset
+*G 725261,719440,0,0,0,-167480 2 0000
+*D 1004880,719440 2 0001
+*H 937888,719440,0,0,-33496,-33496 2 0002
+*L 844682,719440 2 0003
+*C 803904,719440 2 0004
+*P 943714,719440 2 0005
+*S 870896,719440 2 0006
+*U 937888,719440,0,0,-33496,-167480 2 0007
+*F 870896,719440,0,0,-33496 2 0010
+*Q 937888,719440,0,0,-33496,-83741 2 0011
+*W 870896,719440 2 0012
+ff 703416,728178,0,114323 2 0013
+fi 669920,728178 2 0014
+fl 669920,728178 2 0015
+Fi 1004880,728178 2 0016
+Fl 1004880,728178 2 0017
+.i 334960,466034 0 0020
+.j 368456,466034,203890 1 0021
+ga 602928,728178 2 0022
+char180 602928,728178 2 0023
+aa "
+ah 602928,662642 2 0024
+ab 602928,728178 2 0025
+char175 602928,625066 2 0026
+a- "
+ao 911674,728178 2 0027
+char184 535936,0,178403 1 0030
+ac "
+char223 626230,728178 2 0031
+ss "
+char230 870896,466034 0 0032
+ae "
+oe 937888,466034 0 0033
+char248 602928,567979,101946 3 0034
+/o "
+char198 1092261,719440 2 0035
+AE "
+OE 1226245,719440 2 0036
+char216 937888,770413,50973 3 0037
+/O "
+--- 334960,466034 0 0040
+! 367000,728178 2 0041
+rq 632056,728178 2 0042
+sh 1004880,728178,203888 3 0043
+# "
+Do 602928,786432,58254 3 0044
+$ "
+% 1004880,786432,58254 3 0045
+& 937888,728178 2 0046
+' 334960,728178 2 0047
+( 468944,786432,262144 3 0050
+) 468944,786432,262144 3 0051
+* 602928,786432 2 0052
++ 937888,664096,139808 3 0053
+, 334960,163112,203890 1 0054
+char173 401952,466034 0 0055
+hy "
+- "
+. 334960,163112 0 0056
+sl 602928,786432,262144 3 0057
+/ "
+0 602928,675749 2 0060
+1 602928,675749 2 0061
+2 602928,675749 2 0062
+3 602928,675749 2 0063
+4 602928,675749 2 0064
+5 602928,675749 2 0065
+6 602928,675749 2 0066
+7 602928,675749 2 0067
+8 602928,675749 2 0070
+9 602928,675749 2 0071
+: 334960,466034 0 0072
+; 334960,466034,203890 1 0073
+char161 367000,524288,203890 3 0074
+r! "
+= 937888,410110,-114178 0 0075
+char191 569432,524288,203890 3 0076
+r? "
+? 569432,728178 2 0077
+at 937888,728178 2 0100
+@ "
+A 911674,719440 2 0101
+B 857789,719440 2 0102
+C 870896,719440,0,0,-33496 2 0103
+D 924781,719440,0,0,0,-33496 2 0104
+E 792253,719440 2 0105
+F 758757,719440,0,0,0,-167480 2 0106
+G 948083,719440,0,0,-33496 2 0107
+H 943714,719440 2 0110
+I 457294,719440 2 0111
+J 623317,719440,0,0,0,-33496 2 0112
+K 945170,719440 2 0113
+L 725261,719440,0,0,0,66992 2 0114
+M 1144690,719440 2 0115
+N 943714,719440 2 0116
+O 905848,719440,0,0,-33496,-33496 2 0117
+P 824293,719440,0,0,0,-167480 2 0120
+Q 905848,719440,203890,0,-33496 3 0121
+R 904392,719440 2 0122
+S 669920,719440 2 0123
+T 838856,719440,0,0,0,-167480 2 0124
+U 927694,719440,0,0,-20389 2 0125
+V 911674,719440,0,16749,50245,-251219 2 0126
+W 1246634,719440,0,16749,50245,-150731 2 0127
+X 911674,719440 2 0130
+Y 911674,719440,0,30146,33496,-237822 2 0131
+Z 736912,719440 2 0132
+lB 334960,786432,262144 3 0133
+[ "
+lq 632056,728178 2 0134
+rB 334960,786432,262144 3 0135
+] "
+ha 602928,728178 2 0136
+^ "
+a^ "
+a. 334960,728178 2 0137
+oq 334960,728178 2 0140
+` "
+a 586179,466034 0 0141
+b 669920,728178 2 0142
+c 535936,466034 0 0143
+d 669920,728178 2 0144
+e 552685,466034 0 0145
+f 368456,728178,0,114323 2 0146
+g 602928,466034,203890,16749 1 0147
+h 669920,728178 2 0150
+i 334960,728178 2 0151
+j 368456,728178,203890 3 0152
+k 636424,728178 2 0153
+l 334960,728178 2 0154
+m 1004880,466034 0 0155
+n 669920,466034 0 0156
+o 602928,466034 0 0157
+p 669920,466034,203890 1 0160
+q 636424,466034,203890 1 0161
+r 496616,466034 0 0162
+s 475643,466034 0 0163
+t 468944,665763 2 0164
+u 669920,466034 0 0165
+v 636424,466034,0,16749 0 0166
+w 870896,466034,0,16749 0 0167
+x 636424,466034 0 0170
+y 636424,466034,203890,16749 1 0171
+z 535936,466034 0 0172
+en 602928,466034,0,33496 0 0173
+em 1205856,466034,0,33496 0 0174
+a" 602928,728178 2 0175
+~ 602928,728178 2 0176
+a~ "
+char168 602928,728178 2 0177
+ad "
diff --git a/font/devdvi/BI b/font/devdvi/BI
new file mode 100755
index 00000000..16d0193c
--- /dev/null
+++ b/font/devdvi/BI
@@ -0,0 +1,352 @@
+name BI
+internalname cmbxti10
+spacewidth 434573
+slant 14.036243
+ligatures ff fi fl ffi ffl 0
+checksum 1175274390
+designsize 10485760
+kernpairs
+ff ' 111848
+ff ? 111848
+ff ! 111848
+ff ) 111848
+ff rB 111848
+ff ] 111848
+' ' -92624
+' ? 123498
+' ! 123498
+A n -30875
+A l -30875
+A r -30875
+A u -30875
+A m -30875
+A t -30875
+A i -30875
+A C -30875
+A O -30875
+A G -30875
+A h -30875
+A b -30875
+A U -30875
+A k -30875
+A v -30875
+A w -30875
+A Q -30875
+A T -92624
+A Y -92624
+A V -123498
+A W -123498
+A e -61749
+A a -61749
+A o -61749
+A d -61749
+A c -61749
+A g -61749
+A q -61749
+D X -30875
+D W -30875
+D A -30875
+D V -30875
+D Y -30875
+F o -92624
+F e -92624
+F u -92624
+F r -92624
+F a -92624
+F A -123498
+F O -30875
+F C -30875
+F G -30875
+F Q -30875
+K O -30875
+K C -30875
+K G -30875
+K Q -30875
+L T -92624
+L Y -92624
+L V -123498
+L W -123498
+L e -61749
+L a -61749
+L o -61749
+L d -61749
+L c -61749
+L g -61749
+L q -61749
+O X -30875
+O W -30875
+O A -30875
+O V -30875
+O Y -30875
+P A -92624
+R n -30875
+R l -30875
+R r -30875
+R u -30875
+R m -30875
+R t -30875
+R i -30875
+R C -30875
+R O -30875
+R G -30875
+R h -30875
+R b -30875
+R U -30875
+R k -30875
+R v -30875
+R w -30875
+R Q -30875
+R T -92624
+R Y -92624
+R V -123498
+R W -123498
+R e -61749
+R a -61749
+R o -61749
+R d -61749
+R c -61749
+R g -61749
+R q -61749
+T y -92624
+T e -92624
+T o -92624
+T r -92624
+T a -92624
+T u -92624
+T A -92624
+V o -92624
+V e -92624
+V u -92624
+V r -92624
+V a -92624
+V A -123498
+V O -30875
+V C -30875
+V G -30875
+V Q -30875
+W A -92624
+X O -30875
+X C -30875
+X G -30875
+X Q -30875
+Y e -92624
+Y o -92624
+Y r -92624
+Y a -92624
+Y u -92624
+Y A -92624
+oq oq -92624
+oq ` -92624
+` oq -92624
+` ` -92624
+b e -61749
+b a -61749
+b o -61749
+b d -61749
+b c -61749
+b g -61749
+b q -61749
+c e -61749
+c a -61749
+c o -61749
+c d -61749
+c c -61749
+c g -61749
+c q -61749
+d l 61749
+e e -61749
+e a -61749
+e o -61749
+e d -61749
+e c -61749
+e g -61749
+e q -61749
+Fn ' 111848
+f ' 111848
+Fn ? 111848
+f ? 111848
+Fn ! 111848
+f ! 111848
+Fn ) 111848
+f ) 111848
+Fn rB 111848
+Fn ] 111848
+f rB 111848
+f ] 111848
+l l 61749
+n ' -123498
+o e -61749
+o a -61749
+o o -61749
+o d -61749
+o c -61749
+o g -61749
+o q -61749
+p e -61749
+p a -61749
+p o -61749
+p d -61749
+p c -61749
+p g -61749
+p q -61749
+r e -61749
+r a -61749
+r o -61749
+r d -61749
+r c -61749
+r g -61749
+r q -61749
+w l 61749
+charset
+*G 731666,719440,0,135298,0,-19075 2 0000
+*D 990312,719440 2 0001
+*H 928563,719440,0,95027,-84834,64152 2 0002
+*L 845843,719440 2 0003
+*C 805066,719440,0,158248,0,79125 2 0004
+*P 939632,719440,0,180443,0,90222 2 0005
+*S 866814,719440,0,119859,0,59930 2 0006
+*U 928563,719440,0,113013,-174763,-41360 2 0007
+*F 866814,719440,0,59054,-120805,59054 2 0010
+*Q 928563,719440,0,113013,-174763,-5243 2 0011
+*W 866814,719440,0,104021,0,52011 2 0012
+ff 792256,728178,203890,228357 3 0013
+fi 707205,728178,203890,113890 3 0014
+fl 738078,728178,203890,113890 3 0015
+Fi 1095466,728178,203890,113890 3 0016
+Fl 1110902,728178,203890,113890 3 0017
+.i 372824,466034,0,98840 0 0020
+.j 403699,466034,203890,48354 1 0021
+ga 619819,728178 2 0022
+char180 619819,728178,0,89421 2 0023
+aa "
+ah 619819,662642,0,86728 2 0024
+ab 619819,728178,0,108354 2 0025
+char175 619819,623318,0,109518 2 0026
+a- "
+ao 994973,728178 2 0027
+char184 558070,0,178403 1 0030
+ac "
+char223 697302,728178,203890,102090 3 0031
+ss "
+char230 866814,466034,0,89131 0 0032
+ae "
+oe 866814,466034,0,89131 0 0033
+char248 619819,567979,101946,99179 3 0034
+/o "
+char198 1072450,719440,0,119859 2 0035
+AE "
+OE 1195947,719440,0,119859 2 0036
+char216 928563,770413,50973,95027 3 0037
+/O "
+--- 311075,466034 0 0040
+! 404864,728178,0,119714 2 0041
+rq 650696,728178,0,83248 2 0042
+sh 990312,728178,203888,71653 3 0043
+# "
+char163 910723,728178 2 0044
+Po "
+% 990312,786432,58254,134859 3 0045
+& 928563,728178,0,89421 2 0046
+' 372824,728178,0,135734 2 0047
+( 496322,786432,262144,165733 3 0050
+) 496322,786432,262144,34661 3 0051
+* 619819,786432,0,150296 2 0052
++ 928563,632637,108349,34661 3 0053
+, 372824,154374,203890 1 0054
+char173 434573,466034,0,27379 0 0055
+hy "
+- "
+. 372824,154374 0 0056
+sl 619819,786432,262144,165733 3 0057
+/ "
+0 619819,675749,0,138062 2 0060
+1 619819,675749,0,138062 2 0061
+2 619819,675749,0,138062 2 0062
+3 619819,675749,0,138062 2 0063
+4 619819,675749,203890,138062 3 0064
+5 619819,675749,0,138062 2 0065
+6 619819,675749,0,138062 2 0066
+7 619819,675749,203890,138062 3 0067
+8 619819,675749,0,138062 2 0070
+9 619819,675749,0,138062 2 0071
+: 372824,466034,0,70198 0 0072
+; 372824,466034,203890,70198 1 0073
+char161 404864,524288,203890,68741 3 0074
+r! "
+= 928563,410110,-114178,71653 0 0075
+char191 619819,524288,203890 3 0076
+r? "
+? 619819,728178,0,120296 2 0077
+at 928563,728178,0,96555 2 0100
+@ "
+A 907592,719440 2 0101
+B 856330,719440,0,104021,0,52011 2 0102
+C 866814,719440,0,148986,-84834,74493 2 0103
+D 918078,719440,0,95027,0,64152 2 0104
+E 793414,719440,0,119859,0,59930 2 0105
+F 762541,719440,0,135298,0,-19075 2 0106
+G 938758,719440,0,77042,-84834,77042 2 0107
+H 939632,719440,0,180443,0,90222 2 0110
+I 494576,719440,0,164424,0,82213 2 0111
+J 640208,719440,0,152045,0,45147 2 0112
+K 938467,719440,0,148986,0,74493 2 0113
+L 731666,719440,0,0,0,61749 2 0114
+M 1124878,719440,0,180443,0,59347 2 0115
+N 939632,719440,0,180443,0,59347 2 0116
+O 896523,719440,0,95027,-84834,64152 2 0117
+P 825454,719440,0,104021,0,-50352 2 0120
+Q 896523,719440,203890,95027,-84834,95027 3 0121
+R 901186,719440,0,26835,0,20126 2 0122
+S 681568,719440,0,118112,0,59056 2 0123
+T 834774,719440,0,135298,-134896,-19075 2 0124
+U 923613,719440,0,180443,-136096,59347 2 0125
+V 907592,719440,0,195298,-133549,-51698 2 0126
+W 1216336,719440,0,195298,-133549,40925 2 0127
+X 907592,719440,0,164424,0,82213 2 0130
+Y 907592,719440,0,207648,-148986,-39347 2 0131
+Z 743317,719440,0,148986,0,74493 2 0132
+lB 373408,786432,262144,196608 3 0133
+[ "
+lq 650696,728178,0,175869 2 0134
+rB 373408,786432,262144,104568 3 0135
+] "
+ha 619819,728178,0,70344 2 0136
+^ "
+a^ "
+a. 372824,728178,0,135734 2 0137
+oq 372824,728178,0,135734 2 0140
+` "
+a 619819,466034,0,98840,-34078,98840 0 0141
+b 558070,728178,0,82430,-34078,82430 2 0142
+c 558070,466034,0,54760,-34078,54760 0 0143
+d 619819,728178,0,113890,-34078,113890 2 0144
+e 558070,466034,0,89131,-34078,89131 0 0145
+Fn 419432,728178,203890,228357,112722,116509 3 0146
+f "
+g 558070,466034,203890,110102,-35829,71266 1 0147
+h 619819,728178,0,98840,0,98840 2 0150
+i 372824,726931,0,119403,-17669,119403 2 0151
+j 372824,726931,203890,175326,50973,110102 3 0152
+k 558070,728178,0,116509,0,98840 2 0153
+l 311075,728178,0,113890,-30875,129714 2 0154
+m 990312,466034,0,98840,-17669,98840 0 0155
+n 681568,466034,0,98840,-17669,98840 0 0156
+o 619819,466034,0,82430,-34078,82430 0 0157
+p 619819,466034,203890,82430,-17182,82430 1 0160
+q 558070,466034,203890,110102,-34078,71266 1 0161
+r 526034,466034,0,116509,-17669,85634 0 0162
+s 510595,466034,0,85634,0,85634 0 0163
+t 403699,665763,0,101072,-39323,101072 2 0164
+u 650694,466034,0,98840,-17669,98840 0 0165
+v 558070,466034,0,116509,-17669,77672 0 0166
+w 805066,466034,0,116509,-17669,87382 0 0167
+x 587782,466034,0,131946,0,131946 0 0170
+y 588946,466034,203890,110102,-17669,71266 1 0171
+z 514382,466034,0,145637,0,98840 0 0172
+en 619819,466034,0,102880 0 0173
+em 1239638,466034,0,102880 0 0174
+a" 619819,728178,0,120296 2 0175
+~ 619819,728178,0,120296 2 0176
+a~ "
+char168 619819,728178,0,120298 2 0177
+ad "
diff --git a/font/devdvi/CW b/font/devdvi/CW
new file mode 100644
index 00000000..fd94235c
--- /dev/null
+++ b/font/devdvi/CW
@@ -0,0 +1,158 @@
+name CW
+special
+internalname cmtt10
+spacewidth 550498
+checksum -538297224
+designsize 10485760
+charset
+*G 550498,640797 2 0000
+*D 550498,640797 2 0001
+*H 550498,640797 2 0002
+*L 550498,640797 2 0003
+*C 550498,640797 2 0004
+*P 550498,640797 2 0005
+*S 550498,640797 2 0006
+*U 550498,640797 2 0007
+*F 550498,640797 2 0010
+*Q 550498,640797 2 0011
+*W 550498,640797 2 0012
+ff 550498,640797 2 0013
+fi 550498,640797 2 0014
+fl 550498,640797 2 0015
+Fi 550498,407779,233018 1 0016
+Fl 550498,407779,233018 1 0017
+.i 550498,451470 0 0020
+.j 550498,451470,233018 1 0021
+ga 550498,640797 2 0022
+char180 550498,640797 2 0023
+aa "
+ah 550498,593466 2 0024
+ab 550498,640797 2 0025
+char175 550498,593027 2 0026
+a- "
+ao 550498,640797 2 0027
+char184 550498,0,203891 1 0030
+ac "
+char223 550498,640797 2 0031
+ss "
+char230 550498,451470 0 0032
+ae "
+oe 550498,451470 0 0033
+char248 550498,567979,116509 3 0034
+/o "
+char198 550498,640797 2 0035
+AE "
+OE 550498,640797 2 0036
+char216 550498,699051,58254 3 0037
+/O "
+--- 550498,230104,116509 1 0040
+! 550498,640797 2 0041
+" 550498,640797 2 0042
+sh 550498,640797 2 0043
+# "
+Do 550498,728178,87381 3 0044
+$ "
+% 550498,728178,87381 3 0045
+& 550498,640797 2 0046
+' 550498,640797 2 0047
+( 550498,728178,87379 3 0050
+) 550498,728178,87379 3 0051
+* 550498,546134 2 0052
++ 550498,556326,-84470 2 0053
+, 550498,131072,145635 1 0054
+\- 550498,556326,-84470 2 0055
+- "
+. 550498,131072 0 0056
+sl 550498,728178,87379 3 0057
+/ "
+0 550498,640797 2 0060
+1 550498,640797 2 0061
+2 550498,640797 2 0062
+3 550498,640797 2 0063
+4 550498,640797 2 0064
+5 550498,640797 2 0065
+6 550498,640797 2 0066
+7 550498,640797 2 0067
+8 550498,640797 2 0070
+9 550498,640797 2 0071
+: 550498,451470 0 0072
+; 550498,451470,145635 1 0073
+< 550498,582542,-58254 2 0074
+= 550498,435813,-204984 0 0075
+> 550498,582542,-58254 2 0076
+? 550498,640797 2 0077
+at 550498,640797 2 0100
+@ "
+A 550498,640797 2 0101
+B 550498,640797 2 0102
+C 550498,640797 2 0103
+D 550498,640797 2 0104
+E 550498,640797 2 0105
+F 550498,640797 2 0106
+G 550498,640797 2 0107
+H 550498,640797 2 0110
+I 550498,640797 2 0111
+J 550498,640797 2 0112
+K 550498,640797 2 0113
+L 550498,640797 2 0114
+M 550498,640797 2 0115
+N 550498,640797 2 0116
+O 550498,640797 2 0117
+P 550498,640797 2 0120
+Q 550498,640797,145635 3 0121
+R 550498,640797 2 0122
+S 550498,640797 2 0123
+T 550498,640797 2 0124
+U 550498,640797 2 0125
+V 550498,640797 2 0126
+W 550498,640797 2 0127
+X 550498,640797 2 0130
+Y 550498,640797 2 0131
+Z 550498,640797 2 0132
+lB 550498,728178,87379 3 0133
+[ "
+rs 550498,728178,87379 3 0134
+\ "
+rB 550498,728178,87379 3 0135
+] "
+ha 550498,640797 2 0136
+^ "
+a^ "
+_ 550498,0,99757 1 0137
+oq 550498,640797 2 0140
+` "
+a 550498,451470 0 0141
+b 550498,640797 2 0142
+c 550498,451470 0 0143
+d 550498,640797 2 0144
+e 550498,451470 0 0145
+f 550498,640797 2 0146
+g 550498,451470,233018 1 0147
+h 550498,640797 2 0150
+i 550498,640797 2 0151
+j 550498,640797,233018 3 0152
+k 550498,640797 2 0153
+l 550498,640797 2 0154
+m 550498,451470 0 0155
+n 550498,451470 0 0156
+o 550498,451470 0 0157
+p 550498,451470,233018 1 0160
+q 550498,451470,233018 1 0161
+r 550498,451470 0 0162
+s 550498,451470 0 0163
+t 550498,580466 2 0164
+u 550498,451470 0 0165
+v 550498,451470 0 0166
+w 550498,451470 0 0167
+x 550498,451470 0 0170
+y 550498,451470,233018 1 0171
+z 550498,451470 0 0172
+{ 550498,728178,87379 3 0173
+lC "
+| 550498,728178,87379 3 0174
+ba "
+} 550498,728178,87379 3 0175
+rC "
+~ 550498,640797 2 0176
+a~ "
+--- 550498,640797 2 0177
diff --git a/font/devdvi/DESC.in b/font/devdvi/DESC.in
new file mode 100644
index 00000000..b605255d
--- /dev/null
+++ b/font/devdvi/DESC.in
@@ -0,0 +1,10 @@
+sizescale 100
+unitwidth 131072
+res 57816
+hor 1
+vert 1
+sizes 500 600 700 800 900 1000 1100 1200 1400 1440 1600 1728 1800
+2000 2074 2200 2400 2488 2800 3600 0
+fonts 13 R I B BI 0 0 0 0 0 MI S EX CW
+tcommand
+postpro grodvi
diff --git a/font/devdvi/EX b/font/devdvi/EX
new file mode 100644
index 00000000..6e83d02b
--- /dev/null
+++ b/font/devdvi/EX
@@ -0,0 +1,144 @@
+name EX
+special
+internalname cmex10
+checksum -89033454
+designsize 10485760
+charset
+parenleft0 480600,41942,1216362 1 0000
+parenright0 480600,41942,1216362 1 0001
+bracketleft0 436909,41942,1216362 1 0002
+bracketright0 436909,41942,1216362 1 0003
+floorleft0 495163,41942,1216362 1 0004
+floorright0 495163,41942,1216362 1 0005
+ceilingleft0 495163,41942,1216362 1 0006
+ceilingright0 495163,41942,1216362 1 0007
+braceleft0 611672,41942,1216362 1 0010
+braceright0 611672,41942,1216362 1 0011
+angleleft0 495163,41942,1216362 1 0012
+angleright0 495163,41942,1216362 1 0013
+barex 349526,0,629152 1 0014
+bardblex 582544,0,629152 1 0015
+slash0 605845,41942,1216362 1 0016
+backslash0 605845,41942,1216362 1 0017
+parenleft1 626235,41942,1845514 1 0020
+parenright1 626235,41942,1845514 1 0021
+parenleft2 771872,41942,2474666 1 0022
+parenright2 771872,41942,2474666 1 0023
+bracketleft2 553418,41942,2474666 1 0024
+bracketright2 553418,41942,2474666 1 0025
+floorleft2 611672,41942,2474666 1 0026
+floorright2 611672,41942,2474666 1 0027
+ceilingleft2 611672,41942,2474666 1 0030
+ceilingright2 611672,41942,2474666 1 0031
+braceleft2 786434,41942,2474666 1 0032
+braceright2 786434,41942,2474666 1 0033
+angleleft2 786434,41942,2474666 1 0034
+angleright2 786434,41942,2474666 1 0035
+slash2 1095182,41942,2474666 1 0036
+backslash2 1095182,41942,2474666 1 0037
+parenleft3 830126,41942,3103818 1 0040
+parenright3 830126,41942,3103818 1 0041
+bracketleft3 611672,41942,3103818 1 0042
+bracketright3 611672,41942,3103818 1 0043
+floorleft3 669926,41942,3103818 1 0044
+floorright3 669926,41942,3103818 1 0045
+ceilingleft3 669926,41942,3103818 1 0046
+ceilingright3 669926,41942,3103818 1 0047
+braceleft3 844691,41942,3103818 1 0050
+braceright3 844691,41942,3103818 1 0051
+angleleft3 844691,41942,3103818 1 0052
+angleright3 844691,41942,3103818 1 0053
+slash3 1339851,41942,3103818 1 0054
+backslash3 1339851,41942,3103818 1 0055
+slash1 850515,41942,1845514 1 0056
+backslash1 850515,41942,1845514 1 0057
+parenlefttp 917507,41942,1845514 1 0060
+parenrighttp 917507,41942,1845514 1 0061
+bracketlefttp 699053,41942,1845514 1 0062
+bracketrighttp 699053,41942,1845514 1 0063
+bracketleftbt 699053,41942,1845514 1 0064
+bracketrightbt 699053,41942,1845514 1 0065
+bracketleftex 699053,0,629152 1 0066
+bracketrightex 699053,0,629152 1 0067
+lt 932070,0,943728 1 0070
+bracelefttp "
+rt 932070,0,943728 1 0071
+bracerighttp "
+lb 932070,0,943728 1 0072
+braceleftbt "
+rb 932070,0,943728 1 0073
+bracerightbt "
+lk 932070,0,1887456 1 0074
+braceleftmid "
+rk 932070,0,1887456 1 0075
+bracerightmid "
+braceleftex 932070,0,314576 1 0076
+bracerightex "
+braceex "
+arrowvertex 699053,0,629152 1 0077
+parenleftbt 917507,41942,1845514 1 0100
+parenrightbt 917507,41942,1845514 1 0101
+parenleftex 917507,0,629152 1 0102
+parenrightex 917507,0,629152 1 0103
+angleleft1 640798,41942,1845514 1 0104
+angleright1 640798,41942,1845514 1 0105
+--- 873816,0,1048590 1 0106
+--- 1165088,104859,1572877 1 0107
+--- 495162,0,1165096,203891 1 0110
+ointegral 582544,0,2330194,466035 1 0111
+ois "
+--- 1165088,0,1048590 1 0112
+bigcircledot 1584520,104859,1572877 1 0113
+--- 1165088,0,1048590 1 0114
+bigcircleplus 1584520,104859,1572877 1 0115
+--- 1165088,0,1048590 1 0116
+bigcirclemultiply 1584520,104859,1572877 1 0117
+--- 1106834,0,1048590 1 0120
+--- 990325,0,1048590 1 0121
+--- 495162,0,1165096,203891 1 0122
+--- 873816,0,1048590 1 0123
+--- 873816,0,1048590 1 0124
+--- 873816,0,1048590 1 0125
+--- 873816,0,1048590 1 0126
+--- 873816,0,1048590 1 0127
+sum 1514614,104859,1572877 1 0130
+product 1339851,104859,1572877 1 0131
+integral 582544,0,2330194,466035 1 0132
+is "
+bigunion 1165088,104859,1572877 1 0133
+bigintersection 1165088,104859,1572877 1 0134
+bigunionplus 1165088,104859,1572877 1 0135
+biglogicaland 1165088,104859,1572877 1 0136
+biglogicalor 1165088,104859,1572877 1 0137
+--- 990325,0,1048590 1 0140
+coproduct 1339851,104859,1572877 1 0141
+--- 582544,757306 2 0142
+--- 1048579,786432 2 0143
+--- 1514614,786432 2 0144
+--- 582544,757306 2 0145
+--- 1048579,786432 2 0146
+--- 1514614,786432 2 0147
+bracketleft1 495163,41942,1845514 1 0150
+bracketright1 495163,41942,1845514 1 0151
+floorleft1 553418,41942,1845514 1 0152
+floorright1 553418,41942,1845514 1 0153
+ceilingleft1 553418,41942,1845514 1 0154
+ceilingright1 553418,41942,1845514 1 0155
+braceleft1 699053,41942,1845514 1 0156
+braceright1 699053,41942,1845514 1 0157
+sr0 1048579,41942,1216362 1 0160
+sr1 1048579,41942,1845514 1 0161
+sr2 1048579,41942,2474666 1 0162
+sr3 1048579,41942,3103818 1 0163
+--- 1106834,0,1887456 1 0164
+--- 1106834,0,629152 1 0165
+--- 1106834,41942,587210 1 0166
+arrowvertdblex 815562,0,629152 1 0167
+arrowverttp 699053,0,629152 1 0170
+arrowvertbt 699053,0,629152 1 0171
+--- 471864,125827 0 0172
+--- 471864,125827 0 0173
+--- 471864,125827 0 0174
+--- 471864,125827 0 0175
+arrowvertdbltp 815562,0,629152 1 0176
+arrowvertdblbt 815562,0,629152 1 0177
diff --git a/font/devdvi/H b/font/devdvi/H
new file mode 100755
index 00000000..96ae0f5f
--- /dev/null
+++ b/font/devdvi/H
@@ -0,0 +1,302 @@
+name H
+internalname cmss10
+spacewidth 349526
+ligatures ff fi fl ffi ffl 0
+checksum 1831058770
+designsize 10485760
+kernpairs
+ff ' 72818
+ff ? 72818
+ff ! 72818
+ff ) 72818
+ff rB 72818
+ff ] 72818
+' ? 116509
+' ! 116509
+A t -29128
+A C -29128
+A O -29128
+A G -29128
+A U -29128
+A Q -29128
+A T -87382
+A Y -87382
+A V -116509
+A W -116509
+D X -29128
+D W -29128
+D A -29128
+D V -29128
+D Y -29128
+F o -29128
+F e -29128
+F u -29128
+F r -29128
+F a -29128
+F A -87382
+F O -29128
+F C -29128
+F G -29128
+F Q -29128
+I I 29128
+K O -29128
+K C -29128
+K G -29128
+K Q -29128
+L T -87382
+L Y -87382
+L V -116509
+L W -116509
+O X -29128
+O W -29128
+O A -29128
+O V -29128
+O Y -29128
+P A -87382
+P o -29128
+P e -29128
+P a -29128
+P . -87382
+P , -87382
+T y -87382
+T e -87382
+T o -87382
+T r -87382
+T a -87382
+T A -87382
+T u -87382
+V o -29128
+V e -29128
+V u -29128
+V r -29128
+V a -29128
+V A -87382
+V O -29128
+V C -29128
+V G -29128
+V Q -29128
+W o -29128
+W e -29128
+W u -29128
+W r -29128
+W a -29128
+W A -87382
+W O -29128
+W C -29128
+W G -29128
+W Q -29128
+X O -29128
+X C -29128
+X G -29128
+X Q -29128
+Y e -87382
+Y o -87382
+Y r -87382
+Y a -87382
+Y A -87382
+Y u -87382
+a r -29128
+a y -29128
+a w -29128
+b e 29128
+b o 29128
+b x -29128
+b d 29128
+b c 29128
+b q 29128
+b r -29128
+b y -29128
+b w -29128
+f ' 72818
+f ? 72818
+f ! 72818
+f ) 72818
+f rB 72818
+f ] 72818
+g j 29128
+k e -29128
+k a -29128
+k o -29128
+k c -29128
+o e 29128
+o o 29128
+o x -29128
+o d 29128
+o c 29128
+o q 29128
+o r -29128
+o y -29128
+o w -29128
+p e 29128
+p o 29128
+p x -29128
+p d 29128
+p c 29128
+p q 29128
+p r -29128
+p y -29128
+p w -29128
+t y -29128
+t w -29128
+u w -29128
+w e -29128
+w a -29128
+w o -29128
+w c -29128
+y o -29128
+y e -29128
+y a -29128
+y . -87382
+y , -87382
+charset
+*G 567981,728178,0,0,0,-145637 2 0000
+*D 873816,728178 2 0001
+*H 815562,728178,0,0,-29128,-29128 2 0002
+*L 640800,728178 2 0003
+*C 699053,728178 2 0004
+*P 742746,728178 2 0005
+*S 757307,728178 2 0006
+*U 815562,728178,0,0,-29128,-145637 2 0007
+*F 757307,728178,0,0,-29128 2 0010
+*Q 815562,728178,0,0,-29128,-72818 2 0011
+*W 757307,728178 2 0012
+ff 611672,728178,0,72818 2 0013
+fi 562155,728178 2 0014
+fl 562155,728178 2 0015
+Fi 853427,728178 2 0016
+Fl 853427,728178 2 0017
+.i 250494,466034 0 0020
+.j 279622,466034,203890 1 0021
+ga 524290,728178 2 0022
+char180 524290,728178 2 0023
+aa "
+ah 524290,662642 2 0024
+ab 524290,728178 2 0025
+char175 524290,638464 2 0026
+a- "
+ao 699054,728178 2 0027
+char184 466035,0,178403 1 0030
+ac "
+char223 503902,728178 2 0031
+ss "
+char230 757307,466034 0 0032
+ae "
+oe 815562,466034 0 0033
+char248 524290,567979,101946 3 0034
+/o "
+char198 902944,728178 2 0035
+AE "
+OE 1019453,728178 2 0036
+char216 815562,779150,50973 3 0037
+/O "
+--- 250494,466034 0 0040
+! 334963,728178 2 0041
+rq 524290,728178 2 0042
+sh 873816,728178,203888 3 0043
+# "
+Do 524290,786432,58254 3 0044
+$ "
+% 873816,786432,58254 3 0045
+& 795173,728178 2 0046
+' 291272,728178 2 0047
+( 407781,786432,262144 3 0050
+) 407781,786432,262144 3 0051
+* 524290,786432 2 0052
++ 815562,611670,87382 3 0053
+, 291272,87381,131072 1 0054
+char173 349526,466034 0 0055
+hy "
+- "
+. 291272,87381 0 0056
+sl 524290,786432,262144 3 0057
+/ "
+0 524290,687400 2 0060
+1 524290,687400 2 0061
+2 524290,687400 2 0062
+3 524290,687400 2 0063
+4 524290,687400 2 0064
+5 524290,687400 2 0065
+6 524290,687400 2 0066
+7 524290,687400 2 0067
+8 524290,687400 2 0070
+9 524290,687400 2 0071
+: 291272,466034 0 0072
+; 291272,466034,131072 1 0073
+char161 334963,524288,203890 3 0074
+r! "
+= 815562,387973,-136315 0 0075
+char191 495163,524288,203890 3 0076
+r? "
+? 495163,728178 2 0077
+at 699053,728178 2 0100
+@ "
+A 699054,728178 2 0101
+B 699054,728178 2 0102
+C 669926,728178,0,0,-29128 2 0103
+D 757309,728178,0,0,0,-29128 2 0104
+E 626235,728178 2 0105
+F 597109,728178,0,0,0,-145637 2 0106
+G 699053,728178,0,0,-29128 2 0107
+H 742746,728178 2 0110
+I 291274,728178 2 0111
+J 495163,728178,0,0,0,-29128 2 0112
+K 728182,728178 2 0113
+L 567981,728178,0,0,0,58254 2 0114
+M 917509,728178 2 0115
+N 742746,728178 2 0116
+O 771870,728178,0,0,-29128,-29128 2 0117
+P 669926,728178,0,0,0,-145637 2 0120
+Q 771870,728178,131072,0,-29128 3 0121
+R 677208,728178 2 0122
+S 582544,728178 2 0123
+T 713616,728178,0,0,0,-145637 2 0124
+U 720901,728178,0,0,29126 2 0125
+V 699054,728178,0,14563,43691,-218454 2 0126
+W 990326,728178,0,14563,43691,-131074 2 0127
+X 699054,728178 2 0130
+Y 699054,728178,0,26214,29128,-206803 2 0131
+Z 640798,728178 2 0132
+lB 302923,786432,262144 3 0133
+[ "
+lq 524290,728178 2 0134
+rB 302923,786432,262144 3 0135
+] "
+ha 524290,728178 2 0136
+^ "
+a^ "
+a. 291272,712366 2 0137
+oq 291272,728178 2 0140
+` "
+a 503901,466034 0 0141
+b 541766,728178 2 0142
+c 466035,466034 0 0143
+d 541766,728178 2 0144
+e 466035,466034 0 0145
+f 320400,728178,0,72818 2 0146
+g 524290,466034,203890,14563 1 0147
+h 541766,728178 2 0150
+i 250494,712366 2 0151
+j 279622,712366,203890 3 0152
+k 512640,728178 2 0153
+l 250494,728178 2 0154
+m 833038,466034 0 0155
+n 541766,466034 0 0156
+o 524290,466034 0 0157
+p 541766,466034,203890 1 0160
+q 541766,466034,203890 1 0161
+r 358266,466034,0,14563 0 0162
+s 401955,466034 0 0163
+t 378653,599189 2 0164
+u 541766,466034 0 0165
+v 483512,466034,0,14563 0 0166
+w 716530,466034,0,14563 0 0167
+x 483512,466034 0 0170
+y 483512,466034,203890,14563 1 0171
+z 455840,466034 0 0172
+en 524290,466034,0,29128 0 0173
+em 1048579,466034,0,29128 0 0174
+a" 524290,728178 2 0175
+~ 524290,709454 2 0176
+a~ "
+char168 524290,712366 2 0177
+ad "
diff --git a/font/devdvi/HB b/font/devdvi/HB
new file mode 100644
index 00000000..aaff8968
--- /dev/null
+++ b/font/devdvi/HB
@@ -0,0 +1,302 @@
+name HB
+internalname cmssbx10
+spacewidth 384480
+ligatures ff fi fl ffi ffl 0
+checksum -244629176
+designsize 10485760
+kernpairs
+ff ' 80101
+ff ? 80101
+ff ! 80101
+ff ) 80101
+ff rB 80101
+ff ] 80101
+' ? 128160
+' ! 128160
+A t -32040
+A C -32040
+A O -32040
+A G -32040
+A U -32040
+A Q -32040
+A T -96120
+A Y -96120
+A V -128160
+A W -128160
+D X -32040
+D W -32040
+D A -32040
+D V -32040
+D Y -32040
+F o -32040
+F e -32040
+F u -32040
+F r -32040
+F a -32040
+F A -96120
+F O -32040
+F C -32040
+F G -32040
+F Q -32040
+I I 32040
+K O -32040
+K C -32040
+K G -32040
+K Q -32040
+L T -96120
+L Y -96120
+L V -128160
+L W -128160
+O X -32040
+O W -32040
+O A -32040
+O V -32040
+O Y -32040
+P A -96120
+P o -32040
+P e -32040
+P a -32040
+P . -96120
+P , -96120
+T y -96120
+T e -96120
+T o -96120
+T r -96120
+T a -96120
+T A -96120
+T u -96120
+V o -32040
+V e -32040
+V u -32040
+V r -32040
+V a -32040
+V A -96120
+V O -32040
+V C -32040
+V G -32040
+V Q -32040
+W o -32040
+W e -32040
+W u -32040
+W r -32040
+W a -32040
+W A -96120
+W O -32040
+W C -32040
+W G -32040
+W Q -32040
+X O -32040
+X C -32040
+X G -32040
+X Q -32040
+Y e -96120
+Y o -96120
+Y r -96120
+Y a -96120
+Y A -96120
+Y u -96120
+a r -32040
+a y -32040
+a w -32040
+b e 32040
+b o 32040
+b x -32040
+b d 32040
+b c 32040
+b q 32040
+b r -32040
+b y -32040
+b w -32040
+f ' 80101
+f ? 80101
+f ! 80101
+f ) 80101
+f rB 80101
+f ] 80101
+g j 32040
+k e -32040
+k a -32040
+k o -32040
+k c -32040
+o e 32040
+o o 32040
+o x -32040
+o d 32040
+o c 32040
+o q 32040
+o r -32040
+o y -32040
+o w -32040
+p e 32040
+p o 32040
+p x -32040
+p d 32040
+p c 32040
+p q 32040
+p r -32040
+p y -32040
+p w -32040
+t y -32040
+t w -32040
+u w -32040
+w e -32040
+w a -32040
+w o -32040
+w c -32040
+y o -32040
+y e -32040
+y a -32040
+y . -96120
+y , -96120
+charset
+*G 608760,728178,0,0,0,-160200 2 0000
+*D 961200,728178 2 0001
+*H 897120,728178,0,0,-32040,-32040 2 0002
+*L 704880,728178 2 0003
+*C 768960,728178 2 0004
+*P 833040,728178 2 0005
+*S 833040,728178 2 0006
+*U 897120,728178,0,0,-32040,-160200 2 0007
+*F 833040,728178,0,0,-32040 2 0010
+*Q 897120,728178,0,0,-32040,-80101 2 0011
+*W 833040,728178 2 0012
+ff 672840,728178,0,80101 2 0013
+fi 614586,728178 2 0014
+fl 614586,728178 2 0015
+Fi 934986,728178 2 0016
+Fl 934986,728178 2 0017
+.i 267971,480597 0 0020
+.j 300011,480597,203890 1 0021
+ga 576720,728178 2 0022
+char180 576720,728178 2 0023
+aa "
+ah 576720,666283 2 0024
+ab 576720,728178 2 0025
+char175 576720,668757 2 0026
+a- "
+ao 768960,728178 2 0027
+char184 512640,0,178403 1 0030
+ac "
+char223 592739,728178 2 0031
+ss "
+char230 833040,480597 0 0032
+ae "
+oe 897120,480597 0 0033
+char248 576720,582542,101946 3 0034
+/o "
+char198 993240,728178 2 0035
+AE "
+OE 1121400,728178 2 0036
+char216 897120,779150,50973 3 0037
+/O "
+--- 267971,480597 0 0040
+! 384480,728178 2 0041
+rq 585458,728178 2 0042
+sh 961200,728178,203888 3 0043
+# "
+Do 576720,786432,58254 3 0044
+$ "
+% 1079109,786432,58254 3 0045
+& 870906,728178 2 0046
+' 320400,728178 2 0047
+( 448560,786432,262144 3 0050
+) 448560,786432,262144 3 0051
+* 576720,786432 2 0052
++ 897120,646624,122336 3 0053
+, 320400,136898,110683 1 0054
+char173 384480,480597 0 0055
+hy "
+- "
+. 320400,136898 0 0056
+sl 576720,786432,262144 3 0057
+/ "
+0 576720,728178 2 0060
+1 576720,728178 2 0061
+2 576720,728178 2 0062
+3 576720,728178 2 0063
+4 576720,728178 2 0064
+5 576720,728178 2 0065
+6 576720,728178 2 0066
+7 576720,728178 2 0067
+8 576720,728178 2 0070
+9 576720,728178 2 0071
+: 320400,480597 0 0072
+; 320400,480597,110683 1 0073
+char161 384480,524288,203890 3 0074
+r! "
+= 897120,425984,-98304 0 0075
+char191 544680,524288,203890 3 0076
+r? "
+? 544680,728178 2 0077
+at 768960,728178 2 0100
+@ "
+A 768960,728178 2 0101
+B 768960,728178 2 0102
+C 736920,728178,0,0,-32040 2 0103
+D 833040,728178,0,0,0,-32040 2 0104
+E 672840,728178 2 0105
+F 640800,728178,0,0,0,-160200 2 0106
+G 768960,728178,0,0,-32040 2 0107
+H 833040,728178 2 0110
+I 346614,728178 2 0111
+J 544680,728178,0,0,0,-32040 2 0112
+K 801000,728178 2 0113
+L 608760,728178,0,0,0,64080 2 0114
+M 1025280,728178 2 0115
+N 833040,728178 2 0116
+O 833040,728178,0,0,-32040,-32040 2 0117
+P 736920,728178,0,0,0,-160200 2 0120
+Q 833040,728178,110683,0,-32040 3 0121
+R 736920,728178 2 0122
+S 640800,728178 2 0123
+T 768960,728178,0,0,0,-160200 2 0124
+U 801000,728178,0,0,32040 2 0125
+V 768960,728178,0,16021,48061,-240299 2 0126
+W 1089360,728178,0,16021,48061,-144179 2 0127
+X 768960,728178 2 0130
+Y 768960,728178,0,28835,32040,-227485 2 0131
+Z 704880,728178 2 0132
+lB 359722,786432,262144 3 0133
+[ "
+lq 585458,728178 2 0134
+rB 359722,786432,262144 3 0135
+] "
+ha 576720,728178 2 0136
+^ "
+a^ "
+a. 320400,728178 2 0137
+oq 320400,728178 2 0140
+` "
+a 550506,480597 0 0141
+b 588371,728178 2 0142
+c 512640,480597 0 0143
+d 588371,728178 2 0144
+e 535942,480597 0 0145
+f 352440,728178,0,80101 2 0146
+g 576720,480597,203890,16021 1 0147
+h 588371,728178 2 0150
+i 267971,728178 2 0151
+j 300011,728178,203890 3 0152
+k 556331,728178 2 0153
+l 267971,728178 2 0154
+m 908771,480597 0 0155
+n 588371,480597 0 0156
+o 576720,480597 0 0157
+p 588371,480597,203890 1 0160
+q 588371,480597,203890 1 0161
+r 390306,480597,0,16021 0 0162
+s 442152,480597 0 0163
+t 423802,617914 2 0164
+u 588371,480597 0 0165
+v 524291,480597,0,16021 0 0166
+w 780611,480597,0,16021 0 0167
+x 524291,480597 0 0170
+y 524291,480597,203890,16021 1 0171
+z 499533,480597 0 0172
+en 576720,480597,0,32040 0 0173
+em 1153440,480597,0,32040 0 0174
+a" 576720,728178 2 0175
+~ 576720,728178 2 0176
+a~ "
+char168 576720,728178 2 0177
+ad "
diff --git a/font/devdvi/HI b/font/devdvi/HI
new file mode 100644
index 00000000..dcfcced1
--- /dev/null
+++ b/font/devdvi/HI
@@ -0,0 +1,303 @@
+name HI
+internalname cmssi10
+spacewidth 349526
+slant 11.999911
+ligatures ff fi fl ffi ffl 0
+checksum -984248855
+designsize 10485760
+kernpairs
+ff ' 72818
+ff ? 72818
+ff ! 72818
+ff ) 72818
+ff rB 72818
+ff ] 72818
+' ? 116509
+' ! 116509
+A t -29128
+A C -29128
+A O -29128
+A G -29128
+A U -29128
+A Q -29128
+A T -87382
+A Y -87382
+A V -116509
+A W -116509
+D X -29128
+D W -29128
+D A -29128
+D V -29128
+D Y -29128
+F o -29128
+F e -29128
+F u -29128
+F r -29128
+F a -29128
+F A -87382
+F O -29128
+F C -29128
+F G -29128
+F Q -29128
+I I 29128
+K O -29128
+K C -29128
+K G -29128
+K Q -29128
+L T -87382
+L Y -87382
+L V -116509
+L W -116509
+O X -29128
+O W -29128
+O A -29128
+O V -29128
+O Y -29128
+P A -87382
+P o -29128
+P e -29128
+P a -29128
+P . -87382
+P , -87382
+T y -87382
+T e -87382
+T o -87382
+T r -87382
+T a -87382
+T A -87382
+T u -87382
+V o -29128
+V e -29128
+V u -29128
+V r -29128
+V a -29128
+V A -87382
+V O -29128
+V C -29128
+V G -29128
+V Q -29128
+W o -29128
+W e -29128
+W u -29128
+W r -29128
+W a -29128
+W A -87382
+W O -29128
+W C -29128
+W G -29128
+W Q -29128
+X O -29128
+X C -29128
+X G -29128
+X Q -29128
+Y e -87382
+Y o -87382
+Y r -87382
+Y a -87382
+Y A -87382
+Y u -87382
+a r -29128
+a y -29128
+a w -29128
+b e 29128
+b o 29128
+b x -29128
+b d 29128
+b c 29128
+b q 29128
+b r -29128
+b y -29128
+b w -29128
+f ' 72818
+f ? 72818
+f ! 72818
+f ) 72818
+f rB 72818
+f ] 72818
+g j 29128
+k e -29128
+k a -29128
+k o -29128
+k c -29128
+o e 29128
+o o 29128
+o x -29128
+o d 29128
+o c 29128
+o q 29128
+o r -29128
+o y -29128
+o w -29128
+p e 29128
+p o 29128
+p x -29128
+p d 29128
+p c 29128
+p q 29128
+p r -29128
+p y -29128
+p w -29128
+t y -29128
+t w -29128
+u w -29128
+w e -29128
+w a -29128
+w o -29128
+w c -29128
+y o -29128
+y e -29128
+y a -29128
+y . -87382
+y , -87382
+charset
+*G 567981,728178,0,140214,0,-5422 2 0000
+*D 873816,728178 2 0001
+*H 815562,728178,0,79216,-75562,50088 2 0002
+*L 640800,728178 2 0003
+*C 699053,728178,0,134389,0,67195 2 0004
+*P 742746,728178,0,84870,0,42435 2 0005
+*S 757307,728178,0,125650,0,62826 2 0006
+*U 815562,728178,0,94694,-152950,-50942 2 0007
+*F 757307,728178,0,48261,-106517,48261 2 0010
+*Q 815562,728178,0,94694,-152950,-10907 2 0011
+*W 757307,728178,0,86955,0,43478 2 0012
+ff 611672,728178,0,227595 2 0013
+fi 562155,728178,0,102349 2 0014
+fl 562155,728178,0,99435 2 0015
+Fi 853427,728178,0,102349 2 0016
+Fl 853427,728178,0,99435 2 0017
+.i 250494,466034,0,43715 0 0020
+.j 279622,466034,203890,43715 1 0021
+ga 524290,728178 2 0022
+char180 524290,728178,0,96523 2 0023
+aa "
+ah 524290,662642,0,88419 2 0024
+ab 524290,728178,0,99435 2 0025
+char175 524290,638464,0,92018 2 0026
+a- "
+ao 773347,728178 2 0027
+char184 466035,0,178403 1 0030
+ac "
+char223 503902,728178,0,96523 2 0031
+ss "
+char230 757307,466034,0,71070 0 0032
+ae "
+oe 815562,466034,0,71070 0 0033
+char248 524290,567979,101946,50821 3 0034
+/o "
+char198 902944,728178,0,125650 2 0035
+AE "
+OE 1019453,728178,0,125650 2 0036
+char216 815562,779150,50973,79216 3 0037
+/O "
+--- 250494,466034 0 0040
+! 334963,728178,0,60114 2 0041
+rq 524290,728178,0,3315 2 0042
+sh 873816,728178,203888,53338 3 0043
+# "
+Do 524290,786432,58254,116982 3 0044
+$ "
+% 873816,786432,58254,32782 3 0045
+& 795173,728178,0,32064 2 0046
+' 291272,728178,0,81960 2 0047
+( 407781,786432,262144,138032 3 0050
+) 407781,786432,262144,26592 3 0051
+* 524290,786432,0,123469 2 0052
++ 815562,611670,87382,26592 3 0053
+, 291272,87381,131072 1 0054
+char173 349526,466034,0,20402 0 0055
+hy "
+- "
+. 291272,87381 0 0056
+sl 524290,786432,262144,138032 3 0057
+/ "
+0 524290,687400,0,116982 2 0060
+1 524290,687400,0,116982 2 0061
+2 524290,687400,0,116982 2 0062
+3 524290,687400,0,116982 2 0063
+4 524290,687400,0,116982 2 0064
+5 524290,687400,0,116982 2 0065
+6 524290,687400,0,116982 2 0066
+7 524290,687400,0,116982 2 0067
+8 524290,687400,0,116982 2 0070
+9 524290,687400,0,116982 2 0071
+: 291272,466034,0,26240 0 0072
+; 291272,466034,131072,26240 1 0073
+char161 334963,524288,203890,16776 3 0074
+r! "
+= 815562,387973,-136315,53338 0 0075
+char191 495163,524288,203890 3 0076
+r? "
+? 495163,728178,0,123822 2 0077
+at 699053,728178,0,79216 2 0100
+@ "
+A 699054,728178 2 0101
+B 699054,728178,0,86955,0,43478 2 0102
+C 669926,728178,0,125650,-75562,62826 2 0103
+D 757309,728178,0,79216,0,50088 2 0104
+E 626235,728178,0,125650,0,62826 2 0105
+F 597109,728178,0,140214,0,-5422 2 0106
+G 699053,728178,0,125650,-75562,62826 2 0107
+H 742746,728178,0,84870,0,42435 2 0110
+I 291274,728178,0,140214,0,70107 2 0111
+J 495163,728178,0,84870,0,13307 2 0112
+K 728182,728178,0,125650,0,62826 2 0113
+L 567981,728178,0,0,0,58254 2 0114
+M 917509,728178,0,84870,0,13307 2 0115
+N 742746,728178,0,84870,0,13307 2 0116
+O 771870,728178,0,79216,-75562,50088 2 0117
+P 669926,728178,0,86955,0,-58682 2 0120
+Q 771870,728178,131072,79216,-75562,79216 3 0121
+R 677208,728178,0,86955,0,65216 2 0122
+S 582544,728178,0,96523,0,48262 2 0123
+T 713616,728178,0,140214,-116083,-5422 2 0124
+U 720901,728178,0,84870,-75562,13307 2 0125
+V 699054,728178,0,169341,-111086,-63677 2 0126
+W 990326,728178,0,169341,-111086,23704 2 0127
+X 699054,728178,0,140214,0,70107 2 0130
+Y 699054,728178,0,180992,-125650,-52026 2 0131
+Z 640798,728178,0,125650,0,62826 2 0132
+lB 302923,786432,262144,167160 3 0133
+[ "
+lq 524290,728178,0,148952 2 0134
+rB 302923,786432,262144,91429 3 0135
+] "
+ha 524290,728178,0,83776 2 0136
+^ "
+a^ "
+a. 291272,712366,0,81512 2 0137
+oq 291272,728178,0,81960 2 0140
+` "
+a 503901,466034,0,10283 0 0141
+b 541766,728178,0,32053 2 0142
+c 466035,466034,0,87406 0 0143
+d 541766,728178,0,99435 2 0144
+e 466035,466034,0,71070 0 0145
+f 320400,728178,0,227595 2 0146
+g 524290,466034,203890,113621 1 0147
+h 541766,728178,0,18642 2 0150
+i 250494,712366,0,101901 2 0151
+j 279622,712366,203890,96075 3 0152
+k 512640,728178,0,87406 2 0153
+l 250494,728178,0,99435 2 0154
+m 833038,466034,0,18642 0 0155
+n 541766,466034,0,18642 0 0156
+o 524290,466034,0,69341 0 0157
+p 541766,466034,203890,40790 1 0160
+q 541766,466034,203890,43715 1 0161
+r 358266,466034,0,113621 0 0162
+s 401955,466034,0,81581 0 0163
+t 378653,599189,0,75757 2 0164
+u 541766,466034,0,43715 0 0165
+v 483512,466034,0,113621 0 0166
+w 716530,466034,0,113621 0 0167
+x 483512,466034,0,96144 0 0170
+y 483512,466034,203890,113621 1 0171
+z 455840,466034,0,91776 0 0172
+en 524290,466034,0,90349 0 0173
+em 1048579,466034,0,90349 0 0174
+a" 524290,728178,0,96523 2 0175
+~ 524290,709454,0,92544 2 0176
+a~ "
+char168 524290,712366,0,66949 2 0177
+ad "
diff --git a/font/devdvi/I b/font/devdvi/I
new file mode 100755
index 00000000..a4650166
--- /dev/null
+++ b/font/devdvi/I
@@ -0,0 +1,353 @@
+name I
+special
+internalname cmti10
+spacewidth 375155
+slant 14.036243
+ligatures ff fi fl ffi ffl 0
+checksum -50321606
+designsize 10485760
+kernpairs
+ff ' 109373
+ff ? 109373
+ff ! 109373
+ff ) 109373
+ff rB 109373
+ff ] 109373
+' ' -80390
+' ? 107187
+' ! 107187
+A n -26797
+A l -26797
+A r -26797
+A u -26797
+A m -26797
+A t -26797
+A i -26797
+A C -26797
+A O -26797
+A G -26797
+A h -26797
+A b -26797
+A U -26797
+A k -26797
+A v -26797
+A w -26797
+A Q -26797
+A T -80390
+A Y -80390
+A V -107187
+A W -107187
+A e -53594
+A a -53594
+A o -53594
+A d -53594
+A c -53594
+A g -53594
+A q -53594
+D X -26797
+D W -26797
+D A -26797
+D V -26797
+D Y -26797
+F o -80390
+F e -80390
+F u -80390
+F r -80390
+F a -80390
+F A -107187
+F O -26797
+F C -26797
+F G -26797
+F Q -26797
+K O -26797
+K C -26797
+K G -26797
+K Q -26797
+L T -80390
+L Y -80390
+L V -107187
+L W -107187
+L e -53594
+L a -53594
+L o -53594
+L d -53594
+L c -53594
+L g -53594
+L q -53594
+O X -26797
+O W -26797
+O A -26797
+O V -26797
+O Y -26797
+P A -80390
+R n -26797
+R l -26797
+R r -26797
+R u -26797
+R m -26797
+R t -26797
+R i -26797
+R C -26797
+R O -26797
+R G -26797
+R h -26797
+R b -26797
+R U -26797
+R k -26797
+R v -26797
+R w -26797
+R Q -26797
+R T -80390
+R Y -80390
+R V -107187
+R W -107187
+R e -53594
+R a -53594
+R o -53594
+R d -53594
+R c -53594
+R g -53594
+R q -53594
+T y -80390
+T e -80390
+T o -80390
+T r -80390
+T a -80390
+T u -80390
+T A -80390
+V o -80390
+V e -80390
+V u -80390
+V r -80390
+V a -80390
+V A -107187
+V O -26797
+V C -26797
+V G -26797
+V Q -26797
+W A -80390
+X O -26797
+X C -26797
+X G -26797
+X Q -26797
+Y e -80390
+Y o -80390
+Y r -80390
+Y a -80390
+Y u -80390
+Y A -80390
+oq oq -80390
+oq ` -80390
+` oq -80390
+` ` -80390
+b e -53594
+b a -53594
+b o -53594
+b d -53594
+b c -53594
+b g -53594
+b q -53594
+c e -53594
+c a -53594
+c o -53594
+c d -53594
+c c -53594
+c g -53594
+c q -53594
+d l 53594
+e e -53594
+e a -53594
+e o -53594
+e d -53594
+e c -53594
+e g -53594
+e q -53594
+Fn ' 109373
+f ' 109373
+Fn ? 109373
+f ? 109373
+Fn ! 109373
+f ! 109373
+Fn ) 109373
+f ) 109373
+Fn rB 109373
+Fn ] 109373
+f rB 109373
+f ] 109373
+l l 53594
+n ' -107187
+o e -53594
+o a -53594
+o o -53594
+o d -53594
+o c -53594
+o g -53594
+o q -53594
+p e -53594
+p a -53594
+p o -53594
+p d -53594
+p c -53594
+p g -53594
+p q -53594
+r e -53594
+r a -53594
+r o -53594
+r d -53594
+r c -53594
+r g -53594
+r q -53594
+w l 53594
+charset
+*G 657686,716526,0,139518,0,5534 2 0000
+*D 857498,716526 2 0001
+*H 803904,716526,0,98595,-80538,71798 2 0002
+*L 725843,716526 2 0003
+*C 696717,716526,0,160373,0,80187 2 0004
+*P 779437,716526,0,171851,0,85926 2 0005
+*S 750310,716526,0,126120,0,63061 2 0006
+*U 803904,716526,0,116509,-170102,-17475 2 0007
+*F 750310,716526,0,62770,-116363,62770 2 0010
+*Q 803904,716526,0,116509,-170102,4659 2 0011
+*W 750310,716526,0,107552,0,53776 2 0012
+ff 643123,728178,203890,222240 3 0013
+fi 589530,728178,203890,108354 3 0014
+fl 616326,728178,203890,108354 3 0015
+Fi 924490,728178,203890,108354 3 0016
+Fl 937888,728178,203890,108354 3 0017
+.i 321562,451470,0,80440 0 0020
+.j 348358,451470,203890,39176 1 0021
+ga 535936,728178 2 0022
+char180 535936,728178,0,101654 2 0023
+aa "
+ah 535936,659002,0,86982 2 0024
+ab 535936,728178,0,113306 2 0025
+char175 535936,588949,0,108354 2 0026
+a- "
+ao 871672,728178 2 0027
+char184 482342,0,178403 1 0030
+ac "
+char223 562733,728178,203890,110245 3 0031
+ss "
+char230 750310,451470,0,78789 0 0032
+ae "
+oe 750310,451470,0,78789 0 0033
+char248 535936,553416,101946,96411 3 0034
+/o "
+char198 925654,716526,0,126120 2 0035
+AE "
+OE 1032842,716526,0,126120 2 0036
+char216 803904,767499,50973,98595 3 0037
+/O "
+--- 267968,451470 0 0040
+! 321562,728178,0,130200 2 0041
+rq 539432,728178,0,72994 2 0042
+sh 857498,728178,203888,69378 3 0043
+# "
+char163 806453,728178 2 0044
+Po "
+% 857498,786432,58254,143014 3 0045
+& 803904,728178,0,101654 2 0046
+' 321562,728178,0,130200 2 0047
+( 428749,786432,262144,169811 3 0050
+) 428749,786432,262144,38739 3 0051
+* 535936,786432,0,156413 2 0052
++ 803904,588949,59418,38739 3 0053
+, 321562,110683,203890 1 0054
+char173 375155,451470,0,29637 0 0055
+hy "
+- "
+. 321562,110683 0 0056
+sl 535936,786432,262144,169811 3 0057
+/ "
+0 535936,675749,0,142141 2 0060
+1 535936,675749,0,142141 2 0061
+2 535936,675749,0,142141 2 0062
+3 535936,675749,0,142141 2 0063
+4 535936,675749,203890,142141 3 0064
+5 535936,675749,0,142141 2 0065
+6 535936,675749,0,142141 2 0066
+7 535936,675749,203890,142141 3 0067
+8 535936,675749,0,142141 2 0070
+9 535936,675749,0,142141 2 0071
+: 321562,451470,0,61022 0 0072
+; 321562,451470,203890,61022 1 0073
+char161 321562,524288,203890,79227 3 0074
+r! "
+= 803904,384696,-139592,69378 0 0075
+char191 535936,524288,203890 3 0076
+r? "
+? 535936,728178,0,128451 2 0077
+at 803904,728178,0,100634 2 0100
+@ "
+A 779437,716526 2 0101
+B 738077,716526,0,107552,0,53776 2 0102
+C 750310,716526,0,152334,-80538,76168 2 0103
+D 791670,716526,0,98595,0,71798 2 0104
+E 711280,716526,0,126120,0,63061 2 0105
+F 684483,716526,0,139518,0,5534 2 0106
+G 811186,716526,0,91459,-80538,91459 2 0107
+H 779437,716526,0,171851,0,85926 2 0110
+I 404282,716526,0,165733,0,82867 2 0111
+J 550499,716526,0,147093,0,46750 2 0112
+K 806234,716526,0,152334,0,76168 2 0113
+L 657686,716526,0,0,0,53594 2 0114
+M 940218,716526,0,171851,0,59130 2 0115
+N 779437,716526,0,171851,0,59130 2 0116
+O 803904,716526,0,98595,-80538,71798 2 0117
+P 711280,716526,0,107552,0,-26432 2 0120
+Q 803904,716526,203890,98595,-80538,98595 3 0121
+R 764874,716526,0,40560,0,30421 2 0122
+S 589530,716526,0,125538,0,62770 2 0123
+T 750310,716526,0,139518,-134349,5534 2 0124
+U 779437,716526,0,171851,-121898,59130 2 0125
+V 779437,716526,0,192530,-138936,-21845 2 0126
+W 1047405,716526,0,192530,-138936,58546 2 0127
+X 779437,716526,0,165733,0,82867 2 0130
+Y 779437,716526,0,203248,-152334,-11126 2 0131
+Z 643123,716526,0,152334,0,76168 2 0132
+lB 321562,786432,262144,196608 3 0133
+[ "
+lq 539432,728178,0,176685 2 0134
+rB 321562,786432,262144,110392 3 0135
+] "
+ha 535936,728178,0,69688 2 0136
+^ "
+a^ "
+a. 321562,700301,0,123230 2 0137
+oq 321562,728178,0,130200 2 0140
+` "
+a 535936,451470,0,80440,-46677,80440 0 0141
+b 482342,728178,0,66190,-46677,66190 2 0142
+c 482342,451470,0,59274,-46677,59274 0 0143
+d 535936,728178,0,108354,-46677,108354 2 0144
+e 482342,451470,0,78789,-46677,78789 0 0145
+Fn 321562,728178,203890,222240,104566,112867 3 0146
+f "
+g 482342,451470,203890,92770,-21045,55147 1 0147
+h 535936,728178,0,80440,0,80440 2 0150
+i 321562,687194,0,106846,-32427,106846 2 0151
+j 321562,687194,203890,151701,50973,92770 3 0152
+k 482342,728178,0,112867,0,80440 2 0153
+l 267968,728178,0,108354,-26797,107237 2 0154
+m 857498,451470,0,80440,-32427,80440 0 0155
+n 589530,451470,0,80440,-32427,80440 0 0156
+o 535936,451470,0,66190,-46677,66190 0 0157
+p 535936,451470,203890,66190,-22718,66190 1 0160
+q 482342,451470,203890,92770,-46677,55147 1 0161
+r 442147,451470,0,112867,-32427,86070 0 0162
+s 428749,451470,0,86070,0,86070 0 0163
+t 348358,644958,0,99469,-45875,99469 2 0164
+u 562733,451470,0,80440,-32427,80440 0 0165
+v 482342,451470,0,112867,-32427,75245 0 0166
+w 696717,451470,0,112867,-32427,84651 0 0167
+x 486421,451470,0,126266,0,126266 0 0170
+y 509139,451470,203890,92770,-32427,55147 1 0171
+z 428749,451470,0,128888,0,80440 0 0172
+en 535936,451470,0,96552 0 0173
+em 1071872,451470,0,96552 0 0174
+a" 535936,728178,0,128451 2 0175
+~ 535936,700301,0,121482 2 0176
+a~ "
+char168 535936,700301,0,109832 2 0177
+ad "
diff --git a/font/devdvi/MI b/font/devdvi/MI
new file mode 100644
index 00000000..2b2e3491
--- /dev/null
+++ b/font/devdvi/MI
@@ -0,0 +1,136 @@
+name MI
+special
+internalname cmmi10
+slant 14.036243
+checksum 195060286
+designsize 10485760
+charset
+--- 645166,716526,0,145637 2 0000
+--- 873816,716526 2 0001
+--- 799829,716526,0,29128 2 0002
+--- 728179,716526 2 0003
+--- 778424,716526,0,79371 2 0004
+--- 871630,716526,0,85195 2 0005
+--- 817746,716526,0,60438 2 0006
+--- 611669,716526,0,145637 2 0007
+--- 699051,716526 2 0010
+--- 641962,716526,0,115344 2 0011
+--- 809918,716526,0,52610 2 0012
+*a 670776,451470,0,3882 0 0013
+*b 593102,728178,203890,55342 3 0014
+*g 542880,451470,203890,58254 1 0015
+*d 466034,728178,0,39685 2 0016
+*e 425621,451470 0 0017
+*z 458754,728178,203890,77368 3 0020
+*y 520651,451470,203890,37622 1 0021
+*h 492248,728178,0,29128 2 0022
+*i 371130,451470 0 0023
+*k 604147,451470 0 0024
+*l 611672,728178 2 0025
+char181 631819,451470,203890 1 0026
+*m "
+*n 517979,451470,0,66750 0 0027
+*c 458754,728178,203890,48242 3 0030
+*p 597717,451470,0,37622 0 0031
+*r 542130,451470,203890 1 0032
+*s 599171,451470,0,37622 0 0033
+*t 458390,451470,0,118694 0 0034
+*u 566525,451470,0,37622 0 0035
+*f 624778,728178,203890 3 0036
+*x 656086,451470,203890 1 0037
+*q 683034,728178,203890,37622 3 0040
+*w 652691,451470,0,37622 0 0041
+--- 488970,451470 0 0042
++h 620170,728178 2 0043
++p 868357,451470,0,29128 0 0044
+--- 542130,451470,203890 1 0045
+ts 380474,451470,101946,83739 1 0046
++f 685944,451470,203890 1 0047
+--- 1048579,384696,-139592 0 0050
+--- 1048579,384696,-139592 0 0051
+--- 1048579,384696,-139592 0 0052
+--- 1048579,384696,-139592 0 0053
+--- 291272,486275,-38013 2 0054
+--- 291272,486275,-38013 2 0055
+--- 524290,487880,-36408 2 0056
+--- 524290,487880,-36408 2 0057
+--- 524290,451470 0 0060
+--- 524290,451470 0 0061
+--- 524290,451470 0 0062
+--- 524290,451470,203890 1 0063
+--- 524290,451470,203890 1 0064
+--- 524290,451470,203890 1 0065
+--- 524290,675749 2 0066
+--- 524290,451470,203890 1 0067
+--- 524290,675749 2 0070
+--- 524290,451470,203890 1 0071
+--- 291272,110683 0 0072
+--- 291272,110683,203890 1 0073
+< 815562,565285,40997 3 0074
+--- 524290,786432,262144 3 0075
+> 815562,565285,40997 3 0076
+--- 524290,487880,-36408 2 0077
+pd 556693,728178,0,58254 2 0100
+--- 786434,716526 2 0101
+--- 795355,716526,0,52610 2 0102
+--- 749440,716526,0,75002 2 0103
+--- 868134,716526,0,29128 2 0104
+--- 774054,716526,0,60438 2 0105
+--- 674294,716526,0,145637 2 0106
+--- 824442,716526 2 0107
+--- 871630,716526,0,85195 2 0110
+--- 460938,716526,0,82283 2 0111
+--- 581450,716526,0,100853 2 0112
+--- 890563,716526,0,75002 2 0113
+--- 713616,716526 2 0114
+--- 1017266,716526,0,114323 2 0115
+--- 842502,716526,0,114323 2 0116
+--- 799829,716526,0,29128 2 0117
+--- 673200,716526,0,145637 2 0120
+--- 828957,716526,203890 3 0121
+--- 796173,716526,0,8101 2 0122
+--- 642982,716526,0,60438 2 0123
+--- 612763,716526,0,145637 2 0124
+--- 715944,716526,0,114323 2 0125
+--- 611670,716526,0,233018 2 0126
+--- 990323,716526,0,145637 2 0127
+--- 868718,716526,0,82283 2 0130
+--- 608758,716526,0,233018 2 0131
+--- 715800,716526,0,75002 2 0132
+--- 407781,786432 2 0133
+--- 407781,728178,203890 3 0134
+--- 407781,728178,203890 3 0135
+--- 1048579,375013,-149275 0 0136
+--- 1048579,375013,-149275 0 0137
+--- 436910,728178 2 0140
+--- 554267,451470 0 0141
+--- 450014,728178 2 0142
+--- 453778,451470 0 0143
+--- 545771,728178 2 0144
+--- 488245,451470 0 0145
+--- 513368,728178,203890,112869 3 0146
+--- 500138,451470,203890,37622 1 0147
+--- 604147,728178 2 0150
+--- 361248,691562 2 0151
+--- 431811,691562,203890,60024 3 0152
+--- 545893,728178,0,33010 2 0153
+--- 312874,728178,0,20634 2 0154
+--- 920664,451470 0 0155
+--- 629392,451470 0 0156
+*o 508269,451470 0 0157
+--- 527566,451470,203890 1 0160
+--- 468099,451470,203890,37622 1 0161
+--- 473075,451470,0,29128 0 0162
+--- 491520,451470 0 0163
+--- 378654,644958 2 0164
+--- 600266,451470 0 0165
+--- 508270,451470,0,37622 0 0166
+--- 750694,451470,0,28216 0 0167
+--- 599291,451470 0 0170
+--- 514098,451470,203890,37622 1 0171
+--- 487640,451470,0,46117 0 0172
+--- 338120,451470 0 0173
+--- 402685,451470,203890 1 0174
+wp 667376,451470,203890 1 0175
+--- 524290,749149,0,161291 2 0176
+--- 291272,728178,0,418866 2 0177
diff --git a/font/devdvi/Makefile.sub b/font/devdvi/Makefile.sub
new file mode 100644
index 00000000..8c3248fd
--- /dev/null
+++ b/font/devdvi/Makefile.sub
@@ -0,0 +1,11 @@
+DEV=dvi
+DEVFILES=DESC R I B BI CW MI S EX H HI HB SA SB \
+ generate/CompileFonts generate/Makefile generate/msam.map generate/msbm.map \
+ generate/texb.map generate/texex.map generate/texi.map generate/texmi.map \
+ generate/texr.map generate/texsy.map generate/textt.map
+
+CLEANADD=DESC
+
+DESC: DESC.in
+ cat $(srcdir)/DESC.in >DESC
+ test -z '$(DVIPRINT)' || echo print '$(DVIPRINT)' >>DESC
diff --git a/font/devdvi/R b/font/devdvi/R
new file mode 100755
index 00000000..3e49b938
--- /dev/null
+++ b/font/devdvi/R
@@ -0,0 +1,430 @@
+name R
+special
+internalname cmr10
+spacewidth 349526
+ligatures ff fi fl ffi ffl 0
+checksum 1274110073
+designsize 10485760
+kernpairs
+ff ' 81557
+ff ? 81557
+ff ! 81557
+ff ) 81557
+ff rB 81557
+ff ] 81557
+' ' -87382
+' ? 116509
+' ! 116509
+*A t -29128
+A t -29128
+*A C -29128
+A C -29128
+*A *O -29128
+*A O -29128
+A *O -29128
+A O -29128
+*A G -29128
+A G -29128
+*A U -29128
+A U -29128
+*A Q -29128
+A Q -29128
+*A *T -87382
+*A T -87382
+A *T -87382
+A T -87382
+*A Y -87382
+A Y -87382
+*A V -116509
+A V -116509
+*A W -116509
+A W -116509
+D *X -29128
+D X -29128
+D W -29128
+D *A -29128
+D A -29128
+D V -29128
+D Y -29128
+F o -87382
+F e -87382
+F u -87382
+F r -87382
+F a -87382
+F *A -116509
+F A -116509
+F *O -29128
+F O -29128
+F C -29128
+F G -29128
+F Q -29128
+*I *I 29128
+*I I 29128
+I *I 29128
+I I 29128
+*K *O -29128
+*K O -29128
+K *O -29128
+K O -29128
+*K C -29128
+K C -29128
+*K G -29128
+K G -29128
+*K Q -29128
+K Q -29128
+L *T -87382
+L T -87382
+L Y -87382
+L V -116509
+L W -116509
+*O *X -29128
+*O X -29128
+O *X -29128
+O X -29128
+*O W -29128
+O W -29128
+*O *A -29128
+*O A -29128
+O *A -29128
+O A -29128
+*O V -29128
+O V -29128
+*O Y -29128
+O Y -29128
+*R *A -87382
+*R A -87382
+P *A -87382
+P A -87382
+*R o -29128
+P o -29128
+*R e -29128
+P e -29128
+*R a -29128
+P a -29128
+*R . -87382
+P . -87382
+*R , -87382
+P , -87382
+R t -29128
+R C -29128
+R *O -29128
+R O -29128
+R G -29128
+R U -29128
+R Q -29128
+R *T -87382
+R T -87382
+R Y -87382
+R V -116509
+R W -116509
+*T y -29128
+T y -29128
+*T e -87382
+T e -87382
+*T o -87382
+T o -87382
+*T r -87382
+T r -87382
+*T a -87382
+T a -87382
+*T *A -87382
+*T A -87382
+T *A -87382
+T A -87382
+*T u -87382
+T u -87382
+V o -87382
+V e -87382
+V u -87382
+V r -87382
+V a -87382
+V *A -116509
+V A -116509
+V *O -29128
+V O -29128
+V C -29128
+V G -29128
+V Q -29128
+W o -87382
+W e -87382
+W u -87382
+W r -87382
+W a -87382
+W *A -116509
+W A -116509
+W *O -29128
+W O -29128
+W C -29128
+W G -29128
+W Q -29128
+*X *O -29128
+*X O -29128
+X *O -29128
+X O -29128
+*X C -29128
+X C -29128
+*X G -29128
+X G -29128
+*X Q -29128
+X Q -29128
+Y e -87382
+Y o -87382
+Y r -87382
+Y a -87382
+Y *A -87382
+Y A -87382
+Y u -87382
+oq oq -87382
+oq ` -87382
+` oq -87382
+` ` -87382
+a v -29128
+a j 58254
+a y -29128
+a w -29128
+b e 29128
+b o 29128
+b x -29128
+b d 29128
+b c 29128
+b q 29128
+b v -29128
+b j 58254
+b y -29128
+b w -29128
+c h -29128
+c k -29128
+f ' 81557
+f ? 81557
+f ! 81557
+f ) 81557
+f rB 81557
+f ] 81557
+g j 29128
+h t -29128
+h u -29128
+h b -29128
+h y -29128
+h v -29128
+h w -29128
+k a -58254
+k e -29128
+k a -29128
+k o -29128
+k c -29128
+m t -29128
+m u -29128
+m b -29128
+m y -29128
+m v -29128
+m w -29128
+n t -29128
+n u -29128
+n b -29128
+n y -29128
+n v -29128
+n w -29128
+o e 29128
+o o 29128
+o x -29128
+o d 29128
+o c 29128
+o q 29128
+o v -29128
+o j 58254
+o y -29128
+o w -29128
+p e 29128
+p o 29128
+p x -29128
+p d 29128
+p c 29128
+p q 29128
+p v -29128
+p j 58254
+p y -29128
+p w -29128
+t y -29128
+t w -29128
+u w -29128
+v a -58254
+v e -29128
+v a -29128
+v o -29128
+v c -29128
+w e -29128
+w a -29128
+w o -29128
+w c -29128
+y o -29128
+y e -29128
+y a -29128
+y . -87382
+y , -87382
+charset
+*G 655362,716526,0,0,0,-145637 2 0000
+*D 873816,716526 2 0001
+*H 815562,716526,0,0,-29128,-29128 2 0002
+*L 728179,716526 2 0003
+*C 699053,716526 2 0004
+*P 786434,716526 2 0005
+*S 757307,716526 2 0006
+*U 815562,716526,0,0,-29128,-145637 2 0007
+*F 757307,716526,0,0,-29128 2 0010
+*Q 815562,716526,0,0,-29128,-72818 2 0011
+*W 757307,716526 2 0012
+ff 611672,728178,0,81557 2 0013
+fi 582544,728178 2 0014
+fl 582544,728178 2 0015
+Fi 873816,728178 2 0016
+Fl 873816,728178 2 0017
+.i 291272,451470 0 0020
+.j 320400,451470,203890 1 0021
+ga 524290,728178 2 0022
+char180 524290,728178 2 0023
+aa "
+ah 524290,659002 2 0024
+ab 524290,728178 2 0025
+char175 524290,595357 2 0026
+a- "
+ao 786434,728178 2 0027
+char184 466035,0,178403 1 0030
+ac "
+char223 524291,728178 2 0031
+ss "
+char230 757307,451470 0 0032
+ae "
+oe 815562,451470 0 0033
+char248 524290,553416,101946 3 0034
+/o "
+char198 946634,716526 2 0035
+AE "
+OE 1063142,716526 2 0036
+char216 815562,767499,50973 3 0037
+/O "
+--- 291272,451470 0 0040
+! 291272,728178 2 0041
+rq 524290,728178 2 0042
+sh 873816,728178,203888 3 0043
+# "
+Do 524290,786432,58254 3 0044
+$ "
+% 873816,786432,58254 3 0045
+& 815562,728178 2 0046
+' 291272,728178 2 0047
+( 407781,786432,262144 3 0050
+) 407781,786432,262144 3 0051
+* 524290,786432 2 0052
+pl 815562,611670,87382 3 0053
++ "
+, 291272,110683,203890 1 0054
+char173 349526,451470 0 0055
+hy "
+- "
+. 291272,110683 0 0056
+sl 524290,786432,262144 3 0057
+/ "
+0 524290,675749 2 0060
+1 524290,675749 2 0061
+2 524290,675749 2 0062
+3 524290,675749 2 0063
+4 524290,675749 2 0064
+5 524290,675749 2 0065
+6 524290,675749 2 0066
+7 524290,675749 2 0067
+8 524290,675749 2 0070
+9 524290,675749 2 0071
+: 291272,451470 0 0072
+; 291272,451470,203890 1 0073
+char161 291272,524288,203890 3 0074
+r! "
+eq 815562,384696,-139592 0 0075
+= "
+char191 495163,524288,203890 3 0076
+r? "
+? 495163,728178 2 0077
+at 815562,728178 2 0100
+@ "
+*A 786434,716526 2 0101
+A "
+*B 742744,716526 2 0102
+B "
+C 757307,716526,0,0,-29128 2 0103
+D 800998,716526,0,0,0,-29128 2 0104
+*E 713616,716526 2 0105
+E "
+F 684490,716526,0,0,0,-145637 2 0106
+G 822843,716526,0,0,-29128 2 0107
+*Y 786434,716526 2 0110
+H "
+*I 378653,716526 2 0111
+I "
+J 538853,716526,0,0,0,-29128 2 0112
+*K 815562,716526 2 0113
+K "
+L 655362,716526,0,0,0,58254 2 0114
+*M 961197,716526 2 0115
+M "
+*N 786434,716526 2 0116
+N "
+*O 815562,716526,0,0,-29128,-29128 2 0117
+O "
+*R 713616,716526,0,0,0,-145637 2 0120
+P "
+Q 815562,716526,203890,0,-29128 3 0121
+R 771870,716526 2 0122
+S 582544,716526 2 0123
+*T 757307,716526,0,0,0,-145637 2 0124
+T "
+U 786434,716526,0,0,-14563 2 0125
+V 786434,716526,0,14563,43691,-218454 2 0126
+W 1077706,716526,0,14563,43691,-131074 2 0127
+*X 786434,716526 2 0130
+X "
+Y 786434,716526,0,26214,29128,-206803 2 0131
+*Z 640798,716526 2 0132
+Z "
+lB 291272,786432,262144 3 0133
+[ "
+lq 524290,728178 2 0134
+rB 291272,786432,262144 3 0135
+] "
+ha 524290,728178 2 0136
+^ "
+a^ "
+a. 291272,700301 2 0137
+oq 291272,728178 2 0140
+` "
+a 524290,451470 0 0141
+b 582544,728178 2 0142
+c 466035,451470 0 0143
+d 582544,728178 2 0144
+e 466035,451470 0 0145
+f 320400,728178,0,81557 2 0146
+g 524290,451470,203890,14563 1 0147
+h 582544,728178 2 0150
+i 291272,700301 2 0151
+j 320400,700301,203890 3 0152
+k 553418,728178 2 0153
+l 291272,728178 2 0154
+m 873816,451470 0 0155
+n 582544,451470 0 0156
+o 524290,451470 0 0157
+p 582544,451470,203890 1 0160
+q 553416,451470,203890 1 0161
+r 410694,451470 0 0162
+s 413606,451470 0 0163
+t 407781,644958 2 0164
+u 582544,451470 0 0165
+v 553418,451470,0,14563 0 0166
+w 757307,451470,0,14563 0 0167
+x 553418,451470 0 0170
+y 553418,451470,203890,14563 1 0171
+z 466035,451470 0 0172
+en 524290,451470,0,29128 0 0173
+em 1048579,451470,0,29128 0 0174
+a" 524290,728178 2 0175
+~ 524290,700301 2 0176
+a~ "
+char168 524290,700301 2 0177
+ad "
diff --git a/font/devdvi/S b/font/devdvi/S
new file mode 100644
index 00000000..11b79ff9
--- /dev/null
+++ b/font/devdvi/S
@@ -0,0 +1,152 @@
+name S
+special
+internalname cmsy10
+slant 14.036243
+checksum 555887770
+designsize 10485760
+charset
+mi 815562,611670,87382 3 0000
+\- "
+md 291272,466035,-58253 2 0001
+char215 815562,611670,87382 3 0002
+mu "
+** 524290,487880,-36408 2 0003
+char247 815562,611670,87382 3 0004
+di "
+--- 524290,466035,-58253 2 0005
+char177 815562,611670,87382 3 0006
++- "
+-+ 815562,611670,87382 3 0007
+c+ 815562,611670,87382 3 0010
+--- 815562,611670,87382 3 0011
+c* 815562,611670,87382 3 0012
+--- 815562,611670,87382 3 0013
+--- 815562,611670,87382 3 0014
+ci 1048579,728178,203890 3 0015
+--- 524290,466035,-58253 2 0016
+bu 524290,466035,-58253 2 0017
+--- 815562,486275,-38013 2 0020
+== 815562,486275,-38013 2 0021
+ib 815562,666864,142576 3 0022
+ip 815562,666864,142576 3 0023
+<= 815562,666864,142576 3 0024
+>= 815562,666864,142576 3 0025
+--- 815562,666864,142576 3 0026
+--- 815562,666864,142576 3 0027
+ti 815562,384696,-139592 0 0030
+ap "
+~~ 815562,506590,-17698 2 0031
+sb 815562,565285,40997 3 0032
+sp 815562,565285,40997 3 0033
+<< 1048579,565285,40997 3 0034
+>> 1048579,565285,40997 3 0035
+--- 815562,565285,40997 3 0036
+--- 815562,565285,40997 3 0037
+<- 1048579,384696,-139592 0 0040
+-> 1048579,384696,-139592 0 0041
+ua 524290,728178,203888 3 0042
+da 524290,728178,203888 3 0043
+<> 1048579,384696,-139592 0 0044
+--- 1048579,728178,203888 3 0045
+--- 1048579,728178,203888 3 0046
+~= 815562,486275,-38013 2 0047
+lh 1048579,384696,-139592 0 0050
+lA "
+rh 1048579,384696,-139592 0 0051
+rA "
+uA 640798,728178,203888 3 0052
+dA 640798,728178,203888 3 0053
+hA 1048579,384696,-139592 0 0054
+--- 1048579,728178,203888 3 0055
+--- 1048579,728178,203888 3 0056
+pt 815562,451470 0 0057
+prime 288358,582544 2 0060
+if 1048579,451470 0 0061
+mo 699053,565285,40997 3 0062
+st 699053,565285,40997 3 0063
+--- 932070,728178,203890 3 0064
+--- 932070,728178,203890 3 0065
+slashnot 0,728178,203888 3 0066
+--- 0,384696,-139592 0 0067
+fa 582544,728178 2 0070
+te 582544,728178 2 0071
+char172 699053,451470 0 0072
+no "
+es 524290,786432,58254 3 0073
+Re 757307,728178 2 0074
+Im 757307,728178 2 0075
+--- 815562,728178 2 0076
+pp 815562,728178 2 0077
+Ah 640798,728178 2 0100
+A 837258,716526 2 0101
+B 688715,716526,0,31890 2 0102
+C 552106,716526,0,61170 2 0103
+D 808864,716526,0,29128 2 0104
+E 553419,716526,0,93786 2 0105
+F 753662,716526,0,104130 2 0106
+G 623762,716526,101946,62184 3 0107
+H 885541,716526,0,10123 2 0110
+I 570966,716526,0,77408 2 0111
+J 710704,716526,101946,193694 3 0112
+K 798963,716526,0,15147 2 0113
+L 723229,716526 2 0114
+M 1259235,716526 2 0115
+N 860347,716526,0,154518 2 0116
+O 834786,716526,0,29128 2 0117
+P 729347,716526,0,86216 2 0120
+Q 856341,716526,101946 3 0121
+R 888672,716526 2 0122
+S 634974,716526,0,78638 2 0123
+T 571101,716526,0,266514 2 0124
+U 656232,716526,0,104130 2 0125
+V 642549,716526,0,86216 2 0126
+W 1035766,716526,0,86216 2 0127
+X 747946,716526,0,153541 2 0130
+Y 700802,716526,101946,86216 3 0131
+Z 759930,716526,0,83302 2 0132
+cu 699053,582544 2 0133
+ca 699053,582544 2 0134
+--- 699053,582544 2 0135
+AN 699053,582544 2 0136
+OR 699053,582544 2 0137
+--- 640798,728178 2 0140
+--- 640798,728178 2 0141
+lf 466035,786432,262144 3 0142
+rf 466035,786432,262144 3 0143
+lc 466035,786432,262144 3 0144
+rc 466035,786432,262144 3 0145
+{ 524290,786432,262144 3 0146
+lC "
+} 524290,786432,262144 3 0147
+rC "
+la 407781,786432,262144 3 0150
+ra 407781,786432,262144 3 0151
+bar 291272,786432,262144 3 0152
+or "
+bv "
+| "
+ba "
+bardbl 524290,786432,262144 3 0153
+va 524290,786432,262144 3 0154
+vA 640798,786432,262144 3 0155
+rs 524290,786432,262144 3 0156
+\ "
+--- 291272,728178,203888 3 0157
+sr 873816,41942,1006634 1 0160
+--- 786434,716526 2 0161
+gr 873816,716526 2 0162
+--- 436909,728178,203890,116509 3 0163
+--- 699053,582544 2 0164
+--- 699053,582544 2 0165
+--- 815562,666864,142576 3 0166
+--- 815562,666864,142576 3 0167
+char167 466037,728178,203890 3 0170
+sc "
+dg 466035,728178,203890 3 0171
+dd 466035,728178,203890 3 0172
+char182 640798,728178,203890 3 0173
+ps "
+CL 815562,728178,135926 3 0174
+DI 815562,728178,135926 3 0175
+HE 815562,728178,135926 3 0176
+SP 815562,728178,135926 3 0177
diff --git a/font/devdvi/SA b/font/devdvi/SA
new file mode 100644
index 00000000..f2b258f1
--- /dev/null
+++ b/font/devdvi/SA
@@ -0,0 +1,143 @@
+name SA
+special
+internalname msam10
+checksum -1749815603
+designsize 10485760
+charset
+boxdot 815562,709446 2 0000
+boxplus 815562,709446 2 0001
+boxtimes 815562,709446 2 0002
+square 815562,709446 2 0003
+blacksquare 815562,709446 2 0004
+centerdot 291272,576570 2 0005
+lz 699053,728178,116509 3 0006
+lozenge "
+blacklozenge 699053,728178,116509 3 0007
+circlearrowright 815562,610248,85960 3 0010
+circlearrowleft 815562,610248,85960 3 0011
+rightleftharpoons 1048579,547770,14197 3 0012
+leftrightharpoons 1048579,547770,14197 3 0013
+boxminus 815562,709446 2 0014
+Vdash 757307,728178 2 0015
+Vvdash 932070,728178 2 0016
+vDash 640798,728178 2 0017
+twoheadrightarrow 1048579,547770,14197 3 0020
+twoheadleftarrow 1048579,547770,14197 3 0021
+leftleftarrows 1048579,709446,189584 3 0022
+rightrightarrows 1048579,709446,189584 3 0023
+upuparrows 873816,728178,203888 3 0024
+downdownarrows 873816,728178,203888 3 0025
+upharpoonright 436909,728178,203888 3 0026
+downharpoonright 436909,728178,203888 3 0027
+upharpoonleft 436909,728178,203888 3 0030
+downharpoonleft 436909,728178,203888 3 0031
+rightarrowtail 1165088,547770,14197 3 0032
+leftarrowtail 1165088,547770,14197 3 0033
+leftrightarrows 1048579,709446,189584 3 0034
+rightleftarrows 1048579,709446,189584 3 0035
+Lsh 524290,728178 2 0036
+Rsh 524290,728178 2 0037
+rightsquigarrow 1048579,396238,-139592 0 0040
+leftrightsquigarrow 1456360,396238,-139592 0 0041
+looparrowleft 1048579,576570 2 0042
+looparrowright 1048579,576570 2 0043
+circeq 815562,765021,240733 3 0044
+succsim 815562,765021,240733 3 0045
+gtrsim 815562,765021,240733 3 0046
+gtrapprox 815562,792549,268261 3 0047
+multimap 1165088,576570 2 0050
+3d 699053,728178 2 0051
+tf "
+therefore "
+because 699053,728178 2 0052
+doteqdot 815562,610248,85960 3 0053
+triangleq 815562,961197,85960 3 0054
+precsim 815562,765021,240733 3 0055
+lesssim 815562,765021,240733 3 0056
+lessapprox 815562,792549,268261 3 0057
+eqslantless 815562,667592,143304 3 0060
+eqslantgtr 815562,667592,143304 3 0061
+curlyeqprec 815562,667592,143304 3 0062
+curlyeqsucc 815562,667592,143304 3 0063
+preccurlyeq 815562,667592,143304 3 0064
+leqq 815562,792549,268261 3 0065
+leqslant 815562,667592,143304 3 0066
+lessgtr 815562,709446,189584 3 0067
+backprime 288358,576570 2 0070
+--- 524290,486557,-37731 2 0071
+risingdotseq 815562,610248,85960 3 0072
+fallingdotseq 815562,610248,85960 3 0073
+succcurlyeq 815562,667592,143304 3 0074
+geqq 815562,792549,268261 3 0075
+geqslant 815562,667592,143304 3 0076
+gtrless 815562,709446,189584 3 0077
+sqsubset 815562,576570,36882 3 0100
+sqsupset 815562,576570,36882 3 0101
+vartriangleright 815562,576570,36882 3 0102
+vartriangleleft 815562,576570,36882 3 0103
+trianglerighteq 815562,667592,143304 3 0104
+trianglelefteq 815562,667592,143304 3 0105
+bigstar 990323,728178,203888 3 0106
+between 524290,792549,268261 3 0107
+blacktriangledown 757307,576570 2 0110
+blacktriangleright 815562,576570,36882 3 0111
+blacktriangleleft 815562,576570,36882 3 0112
+--- 524290,486557,-37731 2 0113
+--- 524290,486557,-37731 2 0114
+vartriangle 757307,576570 2 0115
+blacktriangle 757307,576570 2 0116
+triangledown 757307,576570 2 0117
+eqcirc 815562,728178 2 0120
+lesseqgtr 815562,928714,404426 3 0121
+gtreqless 815562,928714,404426 3 0122
+lesseqqgtr 815562,1030294,506006 3 0123
+gtreqqless 815562,1030294,506006 3 0124
+char165 786434,709446,0,26214 2 0125
+Ye "
+yen "
+Rrightarrow 1048579,667592,143304 3 0126
+Lleftarrow 1048579,667592,143304 3 0127
+OK 873816,728178 2 0130
+checkmark "
+veebar 640798,728178,203888 3 0131
+barwedge 640798,728178,203888 3 0132
+doublebarwedge 640798,792549,203888 3 0133
+/_ 757307,728178 2 0134
+angle "
+measuredangle 757307,728178 2 0135
+sphericalangle 757307,547770,36882 3 0136
+varpropto 815562,728178 2 0137
+smallsmile 815562,728178,203888 3 0140
+smallfrown 815562,728178,203888 3 0141
+Subset 815562,576570,36882 3 0142
+Supset 815562,576570,36882 3 0143
+Cup 699053,576570 2 0144
+Cap 699053,576570 2 0145
+curlywedge 797355,576570 2 0146
+curlyvee 797355,576570 2 0147
+leftthreetimes 815562,728178 2 0150
+rightthreetimes 815562,728178 2 0151
+subseteqq 815562,792549,268261 3 0152
+supseteqq 815562,792549,268261 3 0153
+bumpeq 815562,576570,63568 3 0154
+Bumpeq 815562,576570,63568 3 0155
+lll 1398106,576570,36882 3 0156
+ggg 1398106,576570,36882 3 0157
+ulcorner 524290,728178 2 0160
+urcorner 524290,728178 2 0161
+rg 992648,709446,159430 3 0162
+char174 "
+circledR "
+circledS 946045,709446,159430 3 0163
+pitchfork 699053,728178 2 0164
+dotplus 815562,728178,85960 3 0165
+backsim 815562,396238,-139592 0 0166
+backsimeq 815562,486557,-37731 2 0167
+llcorner 524290,396238 0 0170
+lrcorner 524290,396238 0 0171
+maltese 873816,728178 2 0172
+complement 524290,865080 2 0173
+intercal 582544,451470,203888 1 0174
+circledcirc 815562,610248,85960 3 0175
+circledast 815562,610248,85960 3 0176
+circleddash 815562,610248,85960 3 0177
diff --git a/font/devdvi/SB b/font/devdvi/SB
new file mode 100644
index 00000000..a4be59db
--- /dev/null
+++ b/font/devdvi/SB
@@ -0,0 +1,132 @@
+name SB
+special
+internalname msbm10
+spacewidth 314576
+slant 87.709390
+checksum -2001332536
+designsize 10485760
+charset
+lvertneqq 815562,794042,263635 3 0000
+gvertneqq 815562,794042,263635 3 0001
+nleq 815562,832390,317448 3 0002
+ngeq 815562,832390,317448 3 0003
+nless 815562,740048,215760 3 0004
+ngtr 815562,740048,215760 3 0005
+nprec 815562,740048,215760 3 0006
+nsucc 815562,740048,215760 3 0007
+lneqq 815562,794042,263635 3 0010
+gneqq 815562,794042,263635 3 0011
+nleqslant 815562,832390,317448 3 0012
+ngeqslant 815562,832390,317448 3 0013
+lneq 815562,666864,142576 3 0014
+gneq 815562,666864,142576 3 0015
+npreceq 815562,832390,317448 3 0016
+nsucceq 815562,832390,317448 3 0017
+precnsim 815562,777110,243501 3 0020
+succnsim 815562,777110,243501 3 0021
+lnsim 815562,777110,243501 3 0022
+gnsim 815562,777110,243501 3 0023
+nleqq 815562,964179,439891 3 0024
+ngeqq 815562,964179,439891 3 0025
+precneqq 815562,794042,263635 3 0026
+succneqq 815562,794042,263635 3 0027
+precnapprox 815562,794042,274379 3 0030
+succnapprox 815562,794042,274379 3 0031
+lnapprox 815562,794042,274379 3 0032
+gnapprox 815562,794042,274379 3 0033
+nsim 815562,384696,-139592 0 0034
+ncong 815562,832390,317448 3 0035
+diagup 932070,722352,203888 3 0036
+diagdown 932070,777110,203888 3 0037
+varsubsetneq 815562,666864,142576 3 0040
+varsupsetneq 815562,666864,142576 3 0041
+nsubseteqq 815562,794042,263635 3 0042
+nsupseteqq 815562,794042,263635 3 0043
+subsetneqq 815562,832390,298650 3 0044
+supsetneqq 815562,832390,298650 3 0045
+varsubsetneqq 815562,794042,263635 3 0046
+varsupsetneqq 815562,794042,263635 3 0047
+subsetneq 815562,666864,142576 3 0050
+supsetneq 815562,666864,142576 3 0051
+nsubseteq 815562,832390,317448 3 0052
+nsupseteq 815562,832390,317448 3 0053
+nparallel 524290,777110,263635 3 0054
+nmid 291272,777110,263635 3 0055
+nshortmid 233018,609920,85632 3 0056
+nshortparallel 407781,609920,85632 3 0057
+nvdash 640798,722352 2 0060
+nVdash 757307,722352 2 0061
+nvDash 640798,722352 2 0062
+nVDash 757307,722352 2 0063
+ntrianglerighteq 815562,832390,317448 3 0064
+ntrianglelefteq 815562,832390,317448 3 0065
+ntriangleleft 815562,740048,215760 3 0066
+ntriangleright 815562,740048,215760 3 0067
+nleftarrow 1048579,384696,-139592 0 0070
+nrightarrow 1048579,384696,-139592 0 0071
+nLeftarrow 1048579,384696,-139592 0 0072
+nRightarrow 1048579,384696,-139592 0 0073
+nLeftrightarrow 1048579,384696,-139592 0 0074
+nleftrightarrow 1048579,384696,-139592 0 0075
+divideontimes 815562,609920,85632 3 0076
+varnothing 815562,609920,85632 3 0077
+nexists 582544,722352 2 0100
+BbbA 757307,722352 2 0101
+BbbB 699053,722352 2 0102
+BbbC 757307,722352 2 0103
+BbbD 757307,722352 2 0104
+BbbE 699053,722352 2 0105
+BbbF 640798,722352 2 0106
+BbbG 815562,722352 2 0107
+BbbH 815562,722352 2 0110
+BbbI 407781,722352 2 0111
+BbbJ 524290,722352,174763 3 0112
+BbbK 815562,722352 2 0113
+BbbL 699053,722352 2 0114
+BbbM 990325,722352 2 0115
+BbbN 757307,722352 2 0116
+BbbO 815562,722352,174763 3 0117
+BbbP 640798,722352 2 0120
+BbbQ 815562,722352,174763 3 0121
+BbbR 757307,722352 2 0122
+BbbS 582544,722352 2 0123
+BbbT 699053,722352 2 0124
+BbbU 757307,722352 2 0125
+BbbV 757307,722352 2 0126
+BbbW 1048579,722352 2 0127
+BbbX 757307,722352 2 0130
+BbbY 757307,722352 2 0131
+BbbZ 699053,722352 2 0132
+--- 1980650,865080 2 0133
+--- 2446685,865080 2 0134
+--- 1980650,865080 2 0135
+--- 2446685,943717 2 0136
+Finv 582544,722352 2 0140
+Game 669925,722352 2 0141
+mho 757307,722352 2 0146
+eth 582544,722352 2 0147
+eqsim 815562,486275,-38013 2 0150
+beth 699053,722352 2 0151
+gimel 466035,722352 2 0152
+daleth 699053,722352 2 0153
+lessdot 815562,565285,40997 3 0154
+gtrdot 815562,565285,40997 3 0155
+ltimes 815562,609920,85632 3 0156
+rtimes 815562,609920,85632 3 0157
+shortmid 233018,609920,85632 3 0160
+shortparallel 407781,609920,85632 3 0161
+smallsetminus 815562,609920,85632 3 0162
+thicksim 815562,384696,-139592 0 0163
+thickapprox 815562,506590,-17698 2 0164
+approxeq 815562,609920,85632 3 0165
+succapprox 815562,794042,274379 3 0166
+precapprox 815562,794042,274379 3 0167
+curvearrowleft 1048579,451470 0 0170
+curvearrowright 1048579,451470 0 0171
+digamma 815562,609920,85632 3 0172
+varkappa 699053,451470,0,42235 0 0173
+Bbbk 582544,722352 2 0174
+hslash 566525,722352 2 0175
+-h 566525,722352 2 0176
+hbar "
+backepsilon 450016,451470 0 0177
diff --git a/font/devdvi/generate/CompileFonts b/font/devdvi/generate/CompileFonts
new file mode 100755
index 00000000..8859f8ea
--- /dev/null
+++ b/font/devdvi/generate/CompileFonts
@@ -0,0 +1,15 @@
+#! /bin/sh
+# Compile fonts in the sizes needed by groff.
+sizes="5 6 7 8 9 10 11 12 14 16 18 20 22 24 28 36"
+fonts="cmr10 cmti10 cmbx10 cmbxti10 cmtt10 cmex10 cmmi10 cmsy10 cmss10 cmssbx10 cmssi10"
+mode=cx
+dpi=300
+
+for f in $fonts; do
+ for s in $sizes; do
+ virmf "&cm \\mode=$mode; mag=$s/10; batchmode; input $f" >/dev/null
+ mag=`expr $s \* $dpi / 10`
+ gftopk $f.${mag}gf >/dev/null
+ rm $f.${mag}gf
+ done
+done
diff --git a/font/devdvi/generate/Makefile b/font/devdvi/generate/Makefile
new file mode 100644
index 00000000..aeca9774
--- /dev/null
+++ b/font/devdvi/generate/Makefile
@@ -0,0 +1,93 @@
+#Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+# Written by James Clark (jjc@jclark.com)
+#
+#This file is part of groff.
+#
+#groff 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.
+#
+#groff 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 groff; see the file COPYING. If not, write to the Free Software
+#Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# This is set up so you can do:
+# make -f generate/Makefile
+# in the parent directory of the directory containing this file.
+
+srcdir=.
+tfmdir=/usr/local/lib/groff-tfm
+gfdir=/usr/local/lib/groff-gf
+
+TFMTODIT=tfmtodit
+FONTS=R I B BI CW MI S EX H HI HB SA SB
+SPECIALFLAG=-s
+
+all: $(FONTS)
+
+# R is special because it contains \(pl \(eq
+
+R: $(srcdir)/texr.map
+ $(TFMTODIT) $(SPECIALFLAG) -g $(gfdir)/cmr10.300gf \
+ $(tfmdir)/cmr10.tfm $(srcdir)/texr.map $@
+
+# I is special because it contains \(Po
+
+I: $(srcdir)/texi.map
+ $(TFMTODIT) $(SPECIALFLAG) -g $(gfdir)/cmti10.300gf \
+ $(tfmdir)/cmti10.tfm $(srcdir)/texi.map $@
+
+B: $(srcdir)/texb.map
+ $(TFMTODIT) -g $(gfdir)/cmbx10.300gf \
+ $(tfmdir)/cmbx10.tfm $(srcdir)/texb.map $@
+
+BI: $(srcdir)/texi.map
+ $(TFMTODIT) -g $(gfdir)/cmbxti10.300gf \
+ $(tfmdir)/cmbxti10.tfm $(srcdir)/texi.map $@
+
+# CW is special because it contains "
+
+CW: $(srcdir)/textt.map
+ $(TFMTODIT) $(SPECIALFLAG) $(tfmdir)/cmtt10.tfm $(srcdir)/textt.map $@
+
+MI: $(srcdir)/texmi.map
+ $(TFMTODIT) $(SPECIALFLAG) -k 0177 $(tfmdir)/cmmi10.tfm $(srcdir)/texmi.map $@
+
+S: $(srcdir)/texsy.map
+ $(TFMTODIT) $(SPECIALFLAG) -k 060 $(tfmdir)/cmsy10.tfm $(srcdir)/texsy.map $@
+
+EX: $(srcdir)/texex.map
+ $(TFMTODIT) $(SPECIALFLAG) $(tfmdir)/cmex10.tfm $(srcdir)/texex.map $@
+
+H: $(srcdir)/texr.map
+ $(TFMTODIT) -g $(gfdir)/cmss10.300gf $(tfmdir)/cmss10.tfm $(srcdir)/texb.map $@
+
+HB: $(srcdir)/texr.map
+ $(TFMTODIT) -g $(gfdir)/cmssbx10.300gf \
+ $(tfmdir)/cmssbx10.tfm $(srcdir)/texb.map $@
+
+HI: $(srcdir)/texr.map
+ $(TFMTODIT) -g $(gfdir)/cmssi10.300gf \
+ $(tfmdir)/cmssi10.tfm $(srcdir)/texb.map $@
+
+SA: $(srcdir)/msam.map
+ $(TFMTODIT) $(SPECIALFLAG) $(tfmdir)/msam10.tfm $(srcdir)/msam.map $@
+
+SB: $(srcdir)/msbm.map
+ $(TFMTODIT) $(SPECIALFLAG) $(tfmdir)/msbm10.tfm $(srcdir)/msbm.map $@
+
+clean:
+
+realclean:
+ -rm -f $(FONTS)
+
+extraclean: realclean
+ -rm -f core *~ \#*
+
+.PHONY: clean realclean extraclean all
diff --git a/font/devdvi/generate/cork.map b/font/devdvi/generate/cork.map
new file mode 100755
index 00000000..52cac9c8
--- /dev/null
+++ b/font/devdvi/generate/cork.map
@@ -0,0 +1,206 @@
+# Map for DC/EC fonts with Cork encoding.
+# Contributed by Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+0 ga
+1 aa char180
+2 a^
+3 a~
+4 ad char168
+5 a"
+6 ao
+7 ah
+8 ab
+9 a- char175
+10 a.
+11 ac char184
+12 ho
+13 bq
+14 fo
+15 fc
+16 lq
+17 rq
+18 Bq
+19 Fo char171
+20 Fc char187
+21 en
+22 em
+25 .i
+26 .j
+27 ff
+28 fi
+29 fl
+30 Fi
+31 Fl
+33 !
+34 "
+35 # sh
+36 $ Do
+37 %
+38 &
+39 ' aq
+40 (
+41 )
+42 *
+43 + pl
+44 ,
+45 -
+46 .
+47 / sl
+48 0
+49 1
+50 2
+51 3
+52 4
+53 5
+54 6
+55 7
+56 8
+57 9
+58 :
+59 ;
+60 <
+61 = eq
+62 >
+63 ?
+64 @ at
+65 A
+66 B
+67 C
+68 D
+69 E
+70 F
+71 G
+72 H
+73 I
+74 J
+75 K
+76 L
+77 M
+78 N
+79 O
+80 P
+81 Q
+82 R
+83 S
+84 T
+85 U
+86 V
+87 W
+88 X
+89 Y
+90 Z
+91 [ lB
+92 \ rs
+93 ] rB
+94 ^ ha
+95 _
+96 ` oq
+97 a
+98 b
+99 c
+100 d
+101 e
+102 f
+103 g
+104 h
+105 i
+106 j
+107 k
+108 l
+109 m
+110 n
+111 o
+112 p
+113 q
+114 r
+115 s
+116 t
+117 u
+118 v
+119 w
+120 x
+121 y
+122 z
+123 { lC
+124 | or bv ba
+125 } rC
+126 ~
+127 hy char173
+130 'C
+138 /L
+146 vS
+152 :Y
+154 vZ
+156 IJ
+159 sc char167
+162 'c
+170 (l
+178 vs
+184 :y char255
+186 vz
+188 ij
+189 r! char161
+190 r? char191
+191 Po char163
+192 `A char192
+193 'A char193
+194 ^A char194
+195 ~A char195
+196 :A char196
+197 oA char197
+198 AE char198
+199 ,C char199
+200 `E char200
+201 'E char201
+202 ^E char202
+203 :E char203
+204 `I char204
+205 'I char205
+206 ^I char206
+207 :I char207
+208 -D char208
+209 ~N char209
+210 `O char210
+211 'O char211
+212 ^O char212
+213 ~O char213
+214 :O char214
+215 OE
+216 /O char216
+217 `U char217
+218 'U char218
+219 ^U char219
+220 :U char220
+221 char221
+222 TP char222
+224 `a char224
+225 'a char225
+226 ^a char226
+227 ~a char227
+228 :a char228
+229 oa char229
+230 ae char230
+231 ,c char231
+232 `e char232
+233 'e char233
+234 ^e char234
+235 :e char235
+236 `i char236
+237 'i char237
+238 ^i char238
+239 :i char239
+240 Sd char240
+241 ~n char241
+242 `o char242
+243 'o char243
+244 ^o char244
+245 ~o char245
+246 :o char246
+247 oe
+248 /o char248
+249 `u char249
+250 'u char250
+251 ^u char251
+252 :u char252
+253 char253
+254 Tp char254
+255 ss char223
diff --git a/font/devdvi/generate/msam.map b/font/devdvi/generate/msam.map
new file mode 100644
index 00000000..90006c95
--- /dev/null
+++ b/font/devdvi/generate/msam.map
@@ -0,0 +1,127 @@
+# Map for the AMSFonts 2.0 msam font using TeX names.
+# Contributed by Zdzislaw Meglicki (Zdzislaw.Meglicki@arp.anu.edu.au).
+0 boxdot
+1 boxplus
+2 boxtimes
+3 square
+4 blacksquare
+5 centerdot
+6 lozenge lz
+7 blacklozenge
+8 circlearrowright
+9 circlearrowleft
+10 rightleftharpoons
+11 leftrightharpoons
+12 boxminus
+13 Vdash
+14 Vvdash
+15 vDash
+16 twoheadrightarrow
+17 twoheadleftarrow
+18 leftleftarrows
+19 rightrightarrows
+20 upuparrows
+21 downdownarrows
+22 upharpoonright
+23 downharpoonright
+24 upharpoonleft
+25 downharpoonleft
+26 rightarrowtail
+27 leftarrowtail
+28 leftrightarrows
+29 rightleftarrows
+30 Lsh
+31 Rsh
+32 rightsquigarrow
+33 leftrightsquigarrow
+34 looparrowleft
+35 looparrowright
+36 circeq
+37 succsim
+38 gtrsim
+39 gtrapprox
+40 multimap
+41 therefore tf 3d
+42 because
+43 doteqdot
+44 triangleq
+45 precsim
+46 lesssim
+47 lessapprox
+48 eqslantless
+49 eqslantgtr
+50 curlyeqprec
+51 curlyeqsucc
+52 preccurlyeq
+53 leqq
+54 leqslant
+55 lessgtr
+56 backprime
+58 risingdotseq
+59 fallingdotseq
+60 succcurlyeq
+61 geqq
+62 geqslant
+63 gtrless
+64 sqsubset
+65 sqsupset
+66 vartriangleright
+67 vartriangleleft
+68 trianglerighteq
+69 trianglelefteq
+70 bigstar
+71 between
+72 blacktriangledown
+73 blacktriangleright
+74 blacktriangleleft
+77 vartriangle
+78 blacktriangle
+79 triangledown
+80 eqcirc
+81 lesseqgtr
+82 gtreqless
+83 lesseqqgtr
+84 gtreqqless
+85 yen Ye char165
+86 Rrightarrow
+87 Lleftarrow
+88 checkmark OK
+89 veebar
+90 barwedge
+91 doublebarwedge
+92 angle /_
+93 measuredangle
+94 sphericalangle
+95 varpropto
+96 smallsmile
+97 smallfrown
+98 Subset
+99 Supset
+100 Cup
+101 Cap
+102 curlywedge
+103 curlyvee
+104 leftthreetimes
+105 rightthreetimes
+106 subseteqq
+107 supseteqq
+108 bumpeq
+109 Bumpeq
+110 lll
+111 ggg
+112 ulcorner
+113 urcorner
+114 circledR char174 rg
+115 circledS
+116 pitchfork
+117 dotplus
+118 backsim
+119 backsimeq
+120 llcorner
+121 lrcorner
+122 maltese
+123 complement
+124 intercal
+125 circledcirc
+126 circledast
+127 circleddash
diff --git a/font/devdvi/generate/msbm.map b/font/devdvi/generate/msbm.map
new file mode 100644
index 00000000..07ee095d
--- /dev/null
+++ b/font/devdvi/generate/msbm.map
@@ -0,0 +1,121 @@
+# Map for the AMSFonts 2.0 msbm font using TeX names.
+# Contributed by Zdzislaw Meglicki (Zdzislaw.Meglicki@arp.anu.edu.au).
+0 lvertneqq
+1 gvertneqq
+2 nleq
+3 ngeq
+4 nless
+5 ngtr
+6 nprec
+7 nsucc
+8 lneqq
+9 gneqq
+10 nleqslant
+11 ngeqslant
+12 lneq
+13 gneq
+14 npreceq
+15 nsucceq
+16 precnsim
+17 succnsim
+18 lnsim
+19 gnsim
+20 nleqq
+21 ngeqq
+22 precneqq
+23 succneqq
+24 precnapprox
+25 succnapprox
+26 lnapprox
+27 gnapprox
+28 nsim
+29 ncong
+30 diagup
+31 diagdown
+32 varsubsetneq
+33 varsupsetneq
+34 nsubseteqq
+35 nsupseteqq
+36 subsetneqq
+37 supsetneqq
+38 varsubsetneqq
+39 varsupsetneqq
+40 subsetneq
+41 supsetneq
+42 nsubseteq
+43 nsupseteq
+44 nparallel
+45 nmid
+46 nshortmid
+47 nshortparallel
+48 nvdash
+49 nVdash
+50 nvDash
+51 nVDash
+52 ntrianglerighteq
+53 ntrianglelefteq
+54 ntriangleleft
+55 ntriangleright
+56 nleftarrow
+57 nrightarrow
+58 nLeftarrow
+59 nRightarrow
+60 nLeftrightarrow
+61 nleftrightarrow
+62 divideontimes
+63 varnothing
+64 nexists
+65 BbbA
+66 BbbB
+67 BbbC
+68 BbbD
+69 BbbE
+70 BbbF
+71 BbbG
+72 BbbH
+73 BbbI
+74 BbbJ
+75 BbbK
+76 BbbL
+77 BbbM
+78 BbbN
+79 BbbO
+80 BbbP
+81 BbbQ
+82 BbbR
+83 BbbS
+84 BbbT
+85 BbbU
+86 BbbV
+87 BbbW
+88 BbbX
+89 BbbY
+90 BbbZ
+96 Finv
+97 Game
+102 mho
+103 eth
+104 eqsim
+105 beth
+106 gimel
+107 daleth
+108 lessdot
+109 gtrdot
+110 ltimes
+111 rtimes
+112 shortmid
+113 shortparallel
+114 smallsetminus
+115 thicksim
+116 thickapprox
+117 approxeq
+118 succapprox
+119 precapprox
+120 curvearrowleft
+121 curvearrowright
+122 digamma
+123 varkappa
+124 Bbbk
+125 hslash
+126 hbar -h
+127 backepsilon
diff --git a/font/devdvi/generate/texb.map b/font/devdvi/generate/texb.map
new file mode 100644
index 00000000..67008339
--- /dev/null
+++ b/font/devdvi/generate/texb.map
@@ -0,0 +1,127 @@
+0 *G
+1 *D
+2 *H
+3 *L
+4 *C
+5 *P
+6 *S
+7 *U
+8 *F
+9 *Q
+10 *W
+11 ff
+12 fi
+13 fl
+14 Fi
+15 Fl
+16 .i
+17 .j
+18 ga
+19 aa char180
+20 ah
+21 ab
+22 a- char175
+23 ao
+24 ac char184
+25 ss char223
+26 ae char230
+27 oe
+28 /o char248
+29 AE char198
+30 OE
+31 /O char216
+33 !
+34 rq
+35 # sh
+36 $ Do
+37 %
+38 &
+39 '
+40 (
+41 )
+42 *
+43 +
+44 ,
+45 - hy char173
+46 .
+47 / sl
+48 0
+49 1
+50 2
+51 3
+52 4
+53 5
+54 6
+55 7
+56 8
+57 9
+58 :
+59 ;
+60 r! char161
+61 =
+62 r? char191
+63 ?
+64 @ at
+65 A
+66 B
+67 C
+68 D
+69 E
+70 F
+71 G
+72 H
+73 I
+74 J
+75 K
+76 L
+77 M
+78 N
+79 O
+80 P
+81 Q
+82 R
+83 S
+84 T
+85 U
+86 V
+87 W
+88 X
+89 Y
+90 Z
+91 [ lB
+92 lq
+93 ] rB
+94 a^ ^ ha
+95 a.
+96 ` oq
+97 a
+98 b
+99 c
+100 d
+101 e
+102 f
+103 g
+104 h
+105 i
+106 j
+107 k
+108 l
+109 m
+110 n
+111 o
+112 p
+113 q
+114 r
+115 s
+116 t
+117 u
+118 v
+119 w
+120 x
+121 y
+122 z
+123 en
+124 em
+125 a"
+126 a~ ~
+127 ad char168
diff --git a/font/devdvi/generate/texex.map b/font/devdvi/generate/texex.map
new file mode 100644
index 00000000..a5b26901
--- /dev/null
+++ b/font/devdvi/generate/texex.map
@@ -0,0 +1,100 @@
+0 parenleft0
+1 parenright0
+2 bracketleft0
+3 bracketright0
+4 floorleft0
+5 floorright0
+6 ceilingleft0
+7 ceilingright0
+8 braceleft0
+9 braceright0
+10 angleleft0
+11 angleright0
+12 barex
+13 bardblex
+14 slash0
+15 backslash0
+16 parenleft1
+17 parenright1
+18 parenleft2
+19 parenright2
+20 bracketleft2
+21 bracketright2
+22 floorleft2
+23 floorright2
+24 ceilingleft2
+25 ceilingright2
+26 braceleft2
+27 braceright2
+28 angleleft2
+29 angleright2
+30 slash2
+31 backslash2
+32 parenleft3
+33 parenright3
+34 bracketleft3
+35 bracketright3
+36 floorleft3
+37 floorright3
+38 ceilingleft3
+39 ceilingright3
+40 braceleft3
+41 braceright3
+42 angleleft3
+43 angleright3
+44 slash3
+45 backslash3
+46 slash1
+47 backslash1
+48 parenlefttp
+49 parenrighttp
+50 bracketlefttp
+51 bracketrighttp
+52 bracketleftbt
+53 bracketrightbt
+54 bracketleftex
+55 bracketrightex
+56 bracelefttp lt
+57 bracerighttp rt
+58 braceleftbt lb
+59 bracerightbt rb
+60 braceleftmid lk
+61 bracerightmid rk
+62 braceex bracerightex braceleftex
+63 arrowvertex
+64 parenleftbt
+65 parenrightbt
+66 parenleftex
+67 parenrightex
+68 angleleft1
+69 angleright1
+73 ois ointegral
+75 bigcircledot
+77 bigcircleplus
+79 bigcirclemultiply
+88 sum
+89 product
+90 is integral
+91 bigunion
+92 bigintersection
+93 bigunionplus
+94 biglogicaland
+95 biglogicalor
+97 coproduct
+104 bracketleft1
+105 bracketright1
+106 floorleft1
+107 floorright1
+108 ceilingleft1
+109 ceilingright1
+110 braceleft1
+111 braceright1
+112 sr0
+113 sr1
+114 sr2
+115 sr3
+119 arrowvertdblex
+120 arrowverttp
+121 arrowvertbt
+126 arrowvertdbltp
+127 arrowvertdblbt
diff --git a/font/devdvi/generate/texi.map b/font/devdvi/generate/texi.map
new file mode 100644
index 00000000..835c6421
--- /dev/null
+++ b/font/devdvi/generate/texi.map
@@ -0,0 +1,127 @@
+0 *G
+1 *D
+2 *H
+3 *L
+4 *C
+5 *P
+6 *S
+7 *U
+8 *F
+9 *Q
+10 *W
+11 ff
+12 fi
+13 fl
+14 Fi
+15 Fl
+16 .i
+17 .j
+18 ga
+19 aa char180
+20 ah
+21 ab
+22 a- char175
+23 ao
+24 ac char184
+25 ss char223
+26 ae char230
+27 oe
+28 /o char248
+29 AE char198
+30 OE
+31 /O char216
+33 !
+34 rq
+35 # sh
+36 Po char163
+37 %
+38 &
+39 '
+40 (
+41 )
+42 *
+43 +
+44 ,
+45 - hy char173
+46 .
+47 / sl
+48 0
+49 1
+50 2
+51 3
+52 4
+53 5
+54 6
+55 7
+56 8
+57 9
+58 :
+59 ;
+60 r! char161
+61 =
+62 r? char191
+63 ?
+64 @ at
+65 A
+66 B
+67 C
+68 D
+69 E
+70 F
+71 G
+72 H
+73 I
+74 J
+75 K
+76 L
+77 M
+78 N
+79 O
+80 P
+81 Q
+82 R
+83 S
+84 T
+85 U
+86 V
+87 W
+88 X
+89 Y
+90 Z
+91 [ lB
+92 lq
+93 ] rB
+94 a^ ^ ha
+95 a.
+96 ` oq
+97 a
+98 b
+99 c
+100 d
+101 e
+102 f Fn
+103 g
+104 h
+105 i
+106 j
+107 k
+108 l
+109 m
+110 n
+111 o
+112 p
+113 q
+114 r
+115 s
+116 t
+117 u
+118 v
+119 w
+120 x
+121 y
+122 z
+123 en
+124 em
+125 a"
+126 a~ ~
+127 ad char168
diff --git a/font/devdvi/generate/texmi.map b/font/devdvi/generate/texmi.map
new file mode 100644
index 00000000..6d01dc4c
--- /dev/null
+++ b/font/devdvi/generate/texmi.map
@@ -0,0 +1,32 @@
+11 *a
+12 *b
+13 *g
+14 *d
+15 *e
+16 *z
+17 *y
+18 *h
+19 *i
+20 *k
+21 *l
+22 *m char181
+23 *n
+24 *c
+25 *p
+26 *r
+27 *s
+28 *t
+29 *u
+30 *f
+31 *x
+32 *q
+33 *w
+35 +h
+36 +p
+38 ts
+39 +f
+60 <
+62 >
+64 pd
+111 *o
+125 wp
diff --git a/font/devdvi/generate/texr.map b/font/devdvi/generate/texr.map
new file mode 100644
index 00000000..bebf67b8
--- /dev/null
+++ b/font/devdvi/generate/texr.map
@@ -0,0 +1,127 @@
+0 *G
+1 *D
+2 *H
+3 *L
+4 *C
+5 *P
+6 *S
+7 *U
+8 *F
+9 *Q
+10 *W
+11 ff
+12 fi
+13 fl
+14 Fi
+15 Fl
+16 .i
+17 .j
+18 ga
+19 aa char180
+20 ah
+21 ab
+22 a- char175
+23 ao
+24 ac char184
+25 ss char223
+26 ae char230
+27 oe
+28 /o char248
+29 AE char198
+30 OE
+31 /O char216
+33 !
+34 rq
+35 # sh
+36 $ Do
+37 %
+38 &
+39 '
+40 (
+41 )
+42 *
+43 + pl
+44 ,
+45 - hy char173
+46 .
+47 / sl
+48 0
+49 1
+50 2
+51 3
+52 4
+53 5
+54 6
+55 7
+56 8
+57 9
+58 :
+59 ;
+60 r! char161
+61 = eq
+62 r? char191
+63 ?
+64 @ at
+65 A *A
+66 B *B
+67 C
+68 D
+69 E *E
+70 F
+71 G
+72 H *Y
+73 I *I
+74 J
+75 K *K
+76 L
+77 M *M
+78 N *N
+79 O *O
+80 P *R
+81 Q
+82 R
+83 S
+84 T *T
+85 U
+86 V
+87 W
+88 X *X
+89 Y
+90 Z *Z
+91 [ lB
+92 lq
+93 ] rB
+94 a^ ^ ha
+95 a.
+96 ` oq
+97 a
+98 b
+99 c
+100 d
+101 e
+102 f
+103 g
+104 h
+105 i
+106 j
+107 k
+108 l
+109 m
+110 n
+111 o
+112 p
+113 q
+114 r
+115 s
+116 t
+117 u
+118 v
+119 w
+120 x
+121 y
+122 z
+123 en
+124 em
+125 a"
+126 a~ ~
+127 ad char168
diff --git a/font/devdvi/generate/texsy.map b/font/devdvi/generate/texsy.map
new file mode 100644
index 00000000..2c970bc2
--- /dev/null
+++ b/font/devdvi/generate/texsy.map
@@ -0,0 +1,100 @@
+0 \- mi
+1 md
+2 mu char215
+3 **
+4 di char247
+6 +- char177
+7 -+
+8 c+
+10 c*
+13 ci
+15 bu
+17 ==
+18 ib
+19 ip
+20 <=
+21 >=
+24 ap ti
+25 ~~
+26 sb
+27 sp
+28 <<
+29 >>
+32 <-
+33 ->
+34 ua
+35 da
+36 <>
+39 ~=
+40 lA lh
+41 rA rh
+42 uA
+43 dA
+44 hA
+47 pt
+48 prime
+49 if
+50 mo
+51 st
+54 slashnot
+56 fa
+57 te
+58 no char172
+59 es
+60 Re
+61 Im
+63 pp
+64 Ah
+65 A
+66 B
+67 C
+68 D
+69 E
+70 F
+71 G
+72 H
+73 I
+74 J
+75 K
+76 L
+77 M
+78 N
+79 O
+80 P
+81 Q
+82 R
+83 S
+84 T
+85 U
+86 V
+87 W
+88 X
+89 Y
+90 Z
+91 cu
+92 ca
+94 AN
+95 OR
+98 lf
+99 rf
+100 lc
+101 rc
+102 lC {
+103 rC }
+104 la
+105 ra
+106 ba | bv or bar
+107 bardbl
+108 va
+109 vA
+110 \ rs
+112 sr
+114 gr
+120 sc char167
+121 dg
+122 dd
+123 ps char182
+124 CL
+125 DI
+126 HE
+127 SP
diff --git a/font/devdvi/generate/textt.map b/font/devdvi/generate/textt.map
new file mode 100644
index 00000000..1461d0ab
--- /dev/null
+++ b/font/devdvi/generate/textt.map
@@ -0,0 +1,126 @@
+0 *G
+1 *D
+2 *H
+3 *L
+4 *C
+5 *P
+6 *S
+7 *U
+8 *F
+9 *Q
+10 *W
+11 ff
+12 fi
+13 fl
+14 Fi
+15 Fl
+16 .i
+17 .j
+18 ga
+19 aa char180
+20 ah
+21 ab
+22 a- char175
+23 ao
+24 ac char184
+25 ss char223
+26 ae char230
+27 oe
+28 /o char248
+29 AE char198
+30 OE
+31 /O char216
+33 !
+34 "
+35 # sh
+36 $ Do
+37 %
+38 &
+39 '
+40 (
+41 )
+42 *
+43 +
+44 ,
+45 - \-
+46 .
+47 / sl
+48 0
+49 1
+50 2
+51 3
+52 4
+53 5
+54 6
+55 7
+56 8
+57 9
+58 :
+59 ;
+60 <
+61 =
+62 >
+63 ?
+64 @ at
+65 A
+66 B
+67 C
+68 D
+69 E
+70 F
+71 G
+72 H
+73 I
+74 J
+75 K
+76 L
+77 M
+78 N
+79 O
+80 P
+81 Q
+82 R
+83 S
+84 T
+85 U
+86 V
+87 W
+88 X
+89 Y
+90 Z
+91 [ lB
+92 \ rs
+93 ] rB
+94 a^ ^ ha
+95 _
+96 ` oq
+97 a
+98 b
+99 c
+100 d
+101 e
+102 f
+103 g
+104 h
+105 i
+106 j
+107 k
+108 l
+109 m
+110 n
+111 o
+112 p
+113 q
+114 r
+115 s
+116 t
+117 u
+118 v
+119 w
+120 x
+121 y
+122 z
+123 lC {
+124 ba |
+125 rC }
+126 a~ ~
diff --git a/font/devhtml/CB b/font/devhtml/CB
new file mode 100755
index 00000000..a1285e01
--- /dev/null
+++ b/font/devhtml/CB
@@ -0,0 +1,306 @@
+name CB
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,9 0 041
+" 9,10 0 042 &quot;
+# 9,10,1 0 043
+sh "
+$ 9,11,1 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046 &amp;
+' 9,10 0 047
+( 9,9,2 0 050
+) 9,9,2 0 051
+* 9,9 0 052
++ 9,8 0 053
+, 9,2,2 0 054
+\- 9,5 0 055
+. 9,2 0 056
+/ 9,10,2 0 057
+sl "
+0 9,10 0 060
+1 9,10 0 061
+2 9,10 0 062
+3 9,10 0 063
+4 9,10 0 064
+5 9,10 0 065
+6 9,10 0 066
+7 9,10 0 067
+8 9,10 0 070
+9 9,10 0 071
+: 9,7 0 072
+; 9,7,2 0 073
+< 9,8 0 074 &lt;
+= 9,6 0 075
+eq "
+> 9,8 0 076 &gt;
+? 9,9 0 077
+@ 9,9 0 0100
+at "
+A 9,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 9,9 0 0111
+J 9,9 0 0112
+K 9,9 0 0113
+L 9,9 0 0114
+M 9,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 9,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 9,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 9,9 0 0126
+W 9,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 9,9,2 0 0133
+lB "
+\ 9,10,2 0 0134
+rs "
+] 9,9,2 0 0135
+rB "
+^ 9,9 0 0136
+a^ "
+ha "
+_ 9,0,2 0 0137
+` 9,10 0 0140
+oq "
+a 9,7 0 0141
+b 9,10 0 0142
+c 9,7 0 0143
+d 9,10 0 0144
+e 9,7 0 0145
+f 9,10 0 0146
+g 9,7,3 0 0147
+h 9,10 0 0150
+i 9,10 0 0151
+j 9,10,3 0 0152
+k 9,10 0 0153
+l 9,10 0 0154
+m 9,7 0 0155
+n 9,7 0 0156
+o 9,7 0 0157
+p 9,7,3 0 0160
+q 9,7,3 0 0161
+r 9,7 0 0162
+s 9,7 0 0163
+t 9,9 0 0164
+u 9,7 0 0165
+v 9,7 0 0166
+w 9,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 9,9,2 0 0173
+lC "
+| 9,9,2 0 0174
+or "
+ba "
+} 9,9,2 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 9,7,2 0 0241 &iexcl;
+¡ "
+ct 9,9,1 0 0242 &cent;
+¢ "
+Po 9,9 0 0243 &pound;
+£ "
+Cs 9,7 0 0244 &curren;
+¤ "
+Ye 9,9 0 0245 &yen;
+¥ "
+bb 9,9,2 0 0246 &brvbar;
+¦ "
+sc 9,10,1 0 0247 &sect;
+§ "
+ad 9,10 0 0250 &uml;
+¨ "
+co 9,9 0 0251 &copy;
+© "
+Of 9,9 0 0252 &ordf;
+ª "
+Fo 9,6 0 0253 &laquo;
+« "
+no 9,5 0 0254 &not;
+¬ "
+- 9,5 0 055 &shy;
+hy " &shy;
+­ "
+rg 9,9 0 0256 &reg;
+® "
+a- 9,9 0 0257 &macr;
+¯ "
+de 9,9 0 0260 &deg;
+° "
++- 9,8 0 0261 &plusmn;
+± "
+S2 9,10 0 0262 &sup2;
+² "
+S3 9,10 0 0263 &sup3;
+³ "
+aa 9,9 0 0264 &acute;
+´ "
+µ 9,7,3 0 0265 &micro;
+ps 9,10,1 0 0266 &para;
+¶ "
+md 9,5 0 0267 &middot;
+· "
+ac 9,1,3 0 0270 &cedil;
+¸ "
+S1 9,10 0 0271 &sup1;
+¹ "
+Om 9,9 0 0272 &ordm;
+º "
+Fc 9,6 0 0273 &raquo;
+» "
+14 9,10 0 0274 &frac14;
+¼ "
+12 9,10 0 0275 &frac12;
+½ "
+34 9,10 0 0276 &frac34;
+¾ "
+r? 9,7,2 0 0277 &iquest;
+¿ "
+`A 9,12 0 0300 &Agrave;
+À "
+'A 9,12 0 0301 &Aacute;
+Á "
+^A 9,12 0 0302 &Acirc;
+Â "
+~A 9,12 0 0303 &Atilde;
+Ã "
+:A 9,12 0 0304 &Auml;
+Ä "
+oA 9,12 0 0305 &Aring;
+Å "
+AE 9,9 0 0306 &AElig;
+Æ "
+,C 9,9,4 0 0307 &Ccedil;
+Ç "
+`E 9,12 0 0310 &Egrave;
+È "
+'E 9,12 0 0311 &Eacute;
+É "
+^E 9,12 0 0312 &Ecirc;
+Ê "
+:E 9,12 0 0313 &Euml;
+Ë "
+`I 9,12 0 0314 &Igrave;
+Ì "
+'I 9,12 0 0315 &Iacute;
+Í "
+^I 9,12 0 0316 &Icirc;
+Î "
+:I 9,12 0 0317 &Iuml;
+Ï "
+-D 9,9 0 0320 &ETH;
+Ð "
+~N 9,12 0 0321 &Ntilde;
+Ñ "
+`O 9,12 0 0322 &Ograve;
+Ò "
+'O 9,12 0 0323 &Oacute;
+Ó "
+^O 9,12 0 0324 &Ocirc;
+Ô "
+~O 9,12 0 0325 &Otilde;
+Õ "
+:O 9,12 0 0326 &Ouml;
+Ö "
+mu 9,8 0 0327 &times;
+× "
+/O 9,10 0 0330 &Oslash;
+Ø "
+`U 9,12 0 0331 &Ugrave;
+Ù "
+'U 9,12 0 0332 &Uacute;
+Ú "
+^U 9,12 0 0333 &Ucirc;
+Û "
+:U 9,12 0 0334 &Uuml;
+Ü "
+'Y 9,12 0 0335 &Yacute;
+Ý "
+TP 9,9 0 0336 &THORN;
+Þ "
+ss 9,9 0 0337 &szlig;
+ß "
+`a 9,10 0 0340 &agrave;
+à "
+'a 9,10 0 0341 &aacute;
+á "
+^a 9,10 0 0342 &acirc;
+â "
+~a 9,10 0 0343 &atilde;
+ã "
+:a 9,10 0 0344 &auml;
+ä "
+oa 9,10 0 0345 &aring;
+å "
+ae 9,7 0 0346 &aelig;
+æ "
+,c 9,7,4 0 0347 &ccedil;
+ç "
+`e 9,10 0 0350 &egrave;
+è "
+'e 9,10 0 0351 &eacute;
+é "
+^e 9,10 0 0352 &ecirc;
+ê "
+:e 9,10 0 0353 &euml;
+ë "
+`i 9,10 0 0354 &igrave;
+ì "
+'i 9,10 0 0355 &iacute;
+í "
+^i 9,10 0 0356 &icirc;
+î "
+:i 9,10 0 0357 &iuml;
+ï "
+Sd 9,10 0 0360 &eth;
+ð "
+~n 9,10 0 0361 &ntilde;
+ñ "
+`o 9,10 0 0362 &ograve;
+ò "
+'o 9,10 0 0363 &oacute;
+ó "
+^o 9,10 0 0364 &ocirc;
+ô "
+~o 9,10 0 0365 &otilde;
+õ "
+:o 9,10 0 0366 &ouml;
+ö "
+di 9,8 0 0367 &divide;
+÷ "
+/o 9,7 0 0370 &oslash;
+ø "
+`u 9,10 0 0371 &ugrave;
+ù "
+'u 9,10 0 0372 &uacute;
+ú "
+^u 9,10 0 0373 &ucirc;
+û "
+:u 9,10 0 0374 &uuml;
+ü "
+'y 9,10,3 0 0375 &yacute;
+ý "
+Tp 9,9,3 0 0376 &thorn;
+þ "
+:y 9,10,3 0 0377 &yuml;
+ÿ "
diff --git a/font/devhtml/CBI b/font/devhtml/CBI
new file mode 100755
index 00000000..97103933
--- /dev/null
+++ b/font/devhtml/CBI
@@ -0,0 +1,306 @@
+name CBI
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,10 0 041
+" 9,9 0 042 &quot;
+# 9,11,1 0 043
+sh "
+$ 9,11,1 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046 &amp;
+' 9,9 0 047
+( 9,9,2 0 050
+) 9,9,2 0 051
+* 9,10 0 052
++ 9,8 0 053
+, 9,2,2 0 054
+\- 9,5 0 055
+. 9,2 0 056
+/ 9,10,2 0 057
+sl "
+0 9,10 0 060
+1 9,10 0 061
+2 9,10 0 062
+3 9,10 0 063
+4 9,10 0 064
+5 9,10 0 065
+6 9,10 0 066
+7 9,10 0 067
+8 9,10 0 070
+9 9,10 0 071
+: 9,7 0 072
+; 9,7,2 0 073
+< 9,8 0 074 &lt;
+= 9,6 0 075
+eq "
+> 9,8 0 076 &gt;
+? 9,9 0 077
+@ 9,9 0 0100
+at "
+A 9,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 9,9 0 0111
+J 9,9 0 0112
+K 9,9 0 0113
+L 9,9 0 0114
+M 9,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 9,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 9,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 9,9 0 0126
+W 9,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 9,9,2 0 0133
+lB "
+\ 9,10,2 0 0134
+rs "
+] 9,9,2 0 0135
+rB "
+^ 9,9 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 9,9 0 0140
+oq "
+a 9,7 0 0141
+b 9,10 0 0142
+c 9,7 0 0143
+d 9,10 0 0144
+e 9,7 0 0145
+f 9,10 0 0146
+g 9,7,3 0 0147
+h 9,10 0 0150
+i 9,10 0 0151
+j 9,10,3 0 0152
+k 9,10 0 0153
+l 9,10 0 0154
+m 9,7 0 0155
+n 9,7 0 0156
+o 9,7 0 0157
+p 9,7,3 0 0160
+q 9,7,3 0 0161
+r 9,7 0 0162
+s 9,7 0 0163
+t 9,9 0 0164
+u 9,7 0 0165
+v 9,7 0 0166
+w 9,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 9,9,2 0 0173
+lC "
+| 9,9,2 0 0174
+or "
+ba "
+} 9,9,2 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 9,7,3 0 0241 &iexcl;
+¡ "
+ct 9,9,1 0 0242 &cent;
+¢ "
+Po 9,9 0 0243 &pound;
+£ "
+Cs 9,7 0 0244 &curren;
+¤ "
+Ye 9,9 0 0245 &yen;
+¥ "
+bb 9,10,2 0 0246 &brvbar;
+¦ "
+sc 9,10,1 0 0247 &sect;
+§ "
+ad 9,10 0 0250 &uml;
+¨ "
+co 9,9 0 0251 &copy;
+© "
+Of 9,9 0 0252 &ordf;
+ª "
+Fo 9,6 0 0253 &laquo;
+« "
+no 9,6 0 0254 &not;
+¬ "
+- 9,5 0 055 &shy;
+hy " &shy;
+­ "
+rg 9,9 0 0256 &reg;
+® "
+a- 9,9 0 0257 &macr;
+¯ "
+de 9,10 0 0260 &deg;
+° "
++- 9,8 0 0261 &plusmn;
+± "
+S2 9,10 0 0262 &sup2;
+² "
+S3 9,10 0 0263 &sup3;
+³ "
+aa 9,10 0 0264 &acute;
+´ "
+µ 9,7,3 0 0265 &micro;
+ps 9,10,1 0 0266 &para;
+¶ "
+md 9,5 0 0267 &middot;
+· "
+ac 9,1,3 0 0270 &cedil;
+¸ "
+S1 9,10 0 0271 &sup1;
+¹ "
+Om 9,9 0 0272 &ordm;
+º "
+Fc 9,6 0 0273 &raquo;
+» "
+14 9,10 0 0274 &frac14;
+¼ "
+12 9,10 0 0275 &frac12;
+½ "
+34 9,10 0 0276 &frac34;
+¾ "
+r? 9,7,2 0 0277 &iquest;
+¿ "
+`A 9,12 0 0300 &Agrave;
+À "
+'A 9,12 0 0301 &Aacute;
+Á "
+^A 9,12 0 0302 &Acirc;
+Â "
+~A 9,12 0 0303 &Atilde;
+Ã "
+:A 9,12 0 0304 &Auml;
+Ä "
+oA 9,12 0 0305 &Aring;
+Å "
+AE 9,9 0 0306 &AElig;
+Æ "
+,C 9,9,4 0 0307 &Ccedil;
+Ç "
+`E 9,12 0 0310 &Egrave;
+È "
+'E 9,12 0 0311 &Eacute;
+É "
+^E 9,12 0 0312 &Ecirc;
+Ê "
+:E 9,12 0 0313 &Euml;
+Ë "
+`I 9,12 0 0314 &Igrave;
+Ì "
+'I 9,12 0 0315 &Iacute;
+Í "
+^I 9,12 0 0316 &Icirc;
+Î "
+:I 9,12 0 0317 &Iuml;
+Ï "
+-D 9,9 0 0320 &ETH;
+Ð "
+~N 9,12 0 0321 &Ntilde;
+Ñ "
+`O 9,12 0 0322 &Ograve;
+Ò "
+'O 9,12 0 0323 &Oacute;
+Ó "
+^O 9,12 0 0324 &Ocirc;
+Ô "
+~O 9,12 0 0325 &Otilde;
+Õ "
+:O 9,12 0 0326 &Ouml;
+Ö "
+mu 9,8 0 0327 &times;
+× "
+/O 9,9 0 0330 &Oslash;
+Ø "
+`U 9,12 0 0331 &Ugrave;
+Ù "
+'U 9,12 0 0332 &Uacute;
+Ú "
+^U 9,12 0 0333 &Ucirc;
+Û "
+:U 9,12 0 0334 &Uuml;
+Ü "
+'Y 9,12 0 0335 &Yacute;
+Ý "
+TP 9,9 0 0336 &THORN;
+Þ "
+ss 9,9 0 0337 &szlig;
+ß "
+`a 9,10 0 0340 &agrave;
+à "
+'a 9,10 0 0341 &aacute;
+á "
+^a 9,10 0 0342 &acirc;
+â "
+~a 9,10 0 0343 &atilde;
+ã "
+:a 9,10 0 0344 &auml;
+ä "
+oa 9,10 0 0345 &aring;
+å "
+ae 9,7 0 0346 &aelig;
+æ "
+,c 9,7,4 0 0347 &ccedil;
+ç "
+`e 9,10 0 0350 &egrave;
+è "
+'e 9,10 0 0351 &eacute;
+é "
+^e 9,10 0 0352 &ecirc;
+ê "
+:e 9,10 0 0353 &euml;
+ë "
+`i 9,10 0 0354 &igrave;
+ì "
+'i 9,10 0 0355 &iacute;
+í "
+^i 9,10 0 0356 &icirc;
+î "
+:i 9,10 0 0357 &iuml;
+ï "
+Sd 9,10 0 0360 &eth;
+ð "
+~n 9,10 0 0361 &ntilde;
+ñ "
+`o 9,10 0 0362 &ograve;
+ò "
+'o 9,10 0 0363 &oacute;
+ó "
+^o 9,10 0 0364 &ocirc;
+ô "
+~o 9,10 0 0365 &otilde;
+õ "
+:o 9,10 0 0366 &ouml;
+ö "
+di 9,8 0 0367 &divide;
+÷ "
+/o 9,8 0 0370 &oslash;
+ø "
+`u 9,10 0 0371 &ugrave;
+ù "
+'u 9,10 0 0372 &uacute;
+ú "
+^u 9,10 0 0373 &ucirc;
+û "
+:u 9,10 0 0374 &uuml;
+ü "
+'y 9,10,3 0 0375 &yacute;
+ý "
+Tp 9,9,3 0 0376 &thorn;
+þ "
+:y 9,10,3 0 0377 &yuml;
+ÿ "
diff --git a/font/devhtml/CI b/font/devhtml/CI
new file mode 100755
index 00000000..e1ca215e
--- /dev/null
+++ b/font/devhtml/CI
@@ -0,0 +1,306 @@
+name CI
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,9 0 041
+" 9,10 0 042 &quot;
+# 9,10,1 0 043
+sh "
+$ 9,10,1 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046 &amp;
+' 9,10 0 047
+( 9,10,3 0 050
+) 9,10,3 0 051
+* 9,9 0 052
++ 9,8 0 053
+, 9,2,2 0 054
+\- 9,5 0 055
+. 9,2 0 056
+/ 9,10,2 0 057
+sl "
+0 9,10 0 060
+1 9,10 0 061
+2 9,10 0 062
+3 9,10 0 063
+4 9,10 0 064
+5 9,10 0 065
+6 9,10 0 066
+7 9,10 0 067
+8 9,10 0 070
+9 9,10 0 071
+: 9,7 0 072
+; 9,7,2 0 073
+< 9,8 0 074 &lt;
+= 9,6 0 075
+eq "
+> 9,8 0 076 &gt;
+? 9,9 0 077
+@ 9,9 0 0100
+at "
+A 9,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 9,9 0 0111
+J 9,9 0 0112
+K 9,9 0 0113
+L 9,9 0 0114
+M 9,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 9,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 9,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 9,9 0 0126
+W 9,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 9,10,3 0 0133
+lB "
+\ 9,10,2 0 0134
+rs "
+] 9,10,3 0 0135
+rB "
+^ 9,9 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 9,10 0 0140
+oq "
+a 9,7 0 0141
+b 9,10 0 0142
+c 9,7 0 0143
+d 9,10 0 0144
+e 9,7 0 0145
+f 9,10 0 0146
+g 9,7,3 0 0147
+h 9,10 0 0150
+i 9,10 0 0151
+j 9,10,3 0 0152
+k 9,10 0 0153
+l 9,10 0 0154
+m 9,7 0 0155
+n 9,7 0 0156
+o 9,7 0 0157
+p 9,7,3 0 0160
+q 9,7,3 0 0161
+r 9,7 0 0162
+s 9,7 0 0163
+t 9,9 0 0164
+u 9,7 0 0165
+v 9,7 0 0166
+w 9,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 9,10,3 0 0173
+lC "
+| 9,9,2 0 0174
+or "
+ba "
+} 9,10,3 0 0175
+rC "
+~ 9,5 0 0176
+a~ "
+ap "
+ti "
+r! 9,7,2 0 0241 &iexcl;
+¡ "
+ct 9,10 0 0242 &cent;
+¢ "
+Po 9,9 0 0243 &pound;
+£ "
+Cs 9,7 0 0244 &curren;
+¤ "
+Ye 9,9 0 0245 &yen;
+¥ "
+bb 9,9,2 0 0246 &brvbar;
+¦ "
+sc 9,9,1 0 0247 &sect;
+§ "
+ad 9,9 0 0250 &uml;
+¨ "
+co 9,9 0 0251 &copy;
+© "
+Of 9,9 0 0252 &ordf;
+ª "
+Fo 9,7 0 0253 &laquo;
+« "
+no 9,6 0 0254 &not;
+¬ "
+- 9,5 0 055 &shy;
+hy " &shy;
+­ "
+rg 9,9 0 0256 &reg;
+® "
+a- 9,9 0 0257 &macr;
+¯ "
+de 9,10 0 0260 &deg;
+° "
++- 9,8 0 0261 &plusmn;
+± "
+S2 9,10 0 0262 &sup2;
+² "
+S3 9,10 0 0263 &sup3;
+³ "
+aa 9,9 0 0264 &acute;
+´ "
+µ 9,7,3 0 0265 &micro;
+ps 9,9,1 0 0266 &para;
+¶ "
+md 9,5 0 0267 &middot;
+· "
+ac 9,1,3 0 0270 &cedil;
+¸ "
+S1 9,10 0 0271 &sup1;
+¹ "
+Om 9,9 0 0272 &ordm;
+º "
+Fc 9,7 0 0273 &raquo;
+» "
+14 9,10 0 0274 &frac14;
+¼ "
+12 9,10 0 0275 &frac12;
+½ "
+34 9,10 0 0276 &frac34;
+¾ "
+r? 9,7,2 0 0277 &iquest;
+¿ "
+`A 9,12 0 0300 &Agrave;
+À "
+'A 9,12 0 0301 &Aacute;
+Á "
+^A 9,12 0 0302 &Acirc;
+Â "
+~A 9,12 0 0303 &Atilde;
+Ã "
+:A 9,11 0 0304 &Auml;
+Ä "
+oA 9,12 0 0305 &Aring;
+Å "
+AE 9,9 0 0306 &AElig;
+Æ "
+,C 9,9,3 0 0307 &Ccedil;
+Ç "
+`E 9,12 0 0310 &Egrave;
+È "
+'E 9,12 0 0311 &Eacute;
+É "
+^E 9,12 0 0312 &Ecirc;
+Ê "
+:E 9,11 0 0313 &Euml;
+Ë "
+`I 9,12 0 0314 &Igrave;
+Ì "
+'I 9,12 0 0315 &Iacute;
+Í "
+^I 9,12 0 0316 &Icirc;
+Î "
+:I 9,11 0 0317 &Iuml;
+Ï "
+-D 9,9 0 0320 &ETH;
+Ð "
+~N 9,12 0 0321 &Ntilde;
+Ñ "
+`O 9,12 0 0322 &Ograve;
+Ò "
+'O 9,12 0 0323 &Oacute;
+Ó "
+^O 9,12 0 0324 &Ocirc;
+Ô "
+~O 9,12 0 0325 &Otilde;
+Õ "
+:O 9,11 0 0326 &Ouml;
+Ö "
+mu 9,8 0 0327 &times;
+× "
+/O 9,9 0 0330 &Oslash;
+Ø "
+`U 9,12 0 0331 &Ugrave;
+Ù "
+'U 9,12 0 0332 &Uacute;
+Ú "
+^U 9,12 0 0333 &Ucirc;
+Û "
+:U 9,11 0 0334 &Uuml;
+Ü "
+'Y 9,12 0 0335 &Yacute;
+Ý "
+TP 9,9 0 0336 &THORN;
+Þ "
+ss 9,9 0 0337 &szlig;
+ß "
+`a 9,10 0 0340 &agrave;
+à "
+'a 9,10 0 0341 &aacute;
+á "
+^a 9,10 0 0342 &acirc;
+â "
+~a 9,10 0 0343 &atilde;
+ã "
+:a 9,9 0 0344 &auml;
+ä "
+oa 9,11 0 0345 &aring;
+å "
+ae 9,7 0 0346 &aelig;
+æ "
+,c 9,7,3 0 0347 &ccedil;
+ç "
+`e 9,10 0 0350 &egrave;
+è "
+'e 9,10 0 0351 &eacute;
+é "
+^e 9,10 0 0352 &ecirc;
+ê "
+:e 9,9 0 0353 &euml;
+ë "
+`i 9,10 0 0354 &igrave;
+ì "
+'i 9,10 0 0355 &iacute;
+í "
+^i 9,10 0 0356 &icirc;
+î "
+:i 9,9 0 0357 &iuml;
+ï "
+Sd 9,10 0 0360 &eth;
+ð "
+~n 9,10 0 0361 &ntilde;
+ñ "
+`o 9,10 0 0362 &ograve;
+ò "
+'o 9,10 0 0363 &oacute;
+ó "
+^o 9,10 0 0364 &ocirc;
+ô "
+~o 9,10 0 0365 &otilde;
+õ "
+:o 9,9 0 0366 &ouml;
+ö "
+di 9,8 0 0367 &divide;
+÷ "
+/o 9,7 0 0370 &oslash;
+ø "
+`u 9,10 0 0371 &ugrave;
+ù "
+'u 9,10 0 0372 &uacute;
+ú "
+^u 9,10 0 0373 &ucirc;
+û "
+:u 9,9 0 0374 &uuml;
+ü "
+'y 9,10,3 0 0375 &yacute;
+ý "
+Tp 9,9,3 0 0376 &thorn;
+þ "
+:y 9,9,3 0 0377 &yuml;
+ÿ "
diff --git a/font/devhtml/CR b/font/devhtml/CR
new file mode 100755
index 00000000..44f52c12
--- /dev/null
+++ b/font/devhtml/CR
@@ -0,0 +1,306 @@
+name CR
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,9 0 041
+" 9,10 0 042 &quot;
+# 9,9,1 0 043
+sh "
+$ 9,11,2 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046 &amp;
+' 9,10 0 047
+( 9,10,2 0 050
+) 9,10,2 0 051
+* 9,9 0 052
++ 9,8 0 053
+, 9,2,2 0 054
+\- 9,5 0 055
+. 9,2 0 056
+/ 9,10,1 0 057
+sl "
+0 9,10 0 060
+1 9,10 0 061
+2 9,10 0 062
+3 9,10 0 063
+4 9,10 0 064
+5 9,10 0 065
+6 9,10 0 066
+7 9,10 0 067
+8 9,10 0 070
+9 9,10 0 071
+: 9,7 0 072
+; 9,7,2 0 073
+< 9,8 0 074 &lt;
+= 9,6 0 075
+eq "
+> 9,8 0 076 &gt;
+? 9,9 0 077
+@ 9,9,1 0 0100
+at "
+A 9,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 9,9 0 0111
+J 9,9 0 0112
+K 9,9 0 0113
+L 9,9 0 0114
+M 9,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 9,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 9,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 9,9 0 0126
+W 9,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 9,10,2 0 0133
+lB "
+\ 9,10,1 0 0134
+rs "
+] 9,10,2 0 0135
+rB "
+^ 9,9 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 9,10 0 0140
+oq "
+a 9,7 0 0141
+b 9,10 0 0142
+c 9,7 0 0143
+d 9,10 0 0144
+e 9,7 0 0145
+f 9,10 0 0146
+g 9,7,3 0 0147
+h 9,10 0 0150
+i 9,10 0 0151
+j 9,10,3 0 0152
+k 9,10 0 0153
+l 9,10 0 0154
+m 9,7 0 0155
+n 9,7 0 0156
+o 9,7 0 0157
+p 9,7,3 0 0160
+q 9,7,3 0 0161
+r 9,7 0 0162
+s 9,7 0 0163
+t 9,9 0 0164
+u 9,7 0 0165
+v 9,7 0 0166
+w 9,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 9,10,2 0 0173
+lC "
+| 9,9,2 0 0174
+or "
+ba "
+} 9,10,2 0 0175
+rC "
+~ 9,5 0 0176
+a~ "
+ap "
+ti "
+r! 9,7,2 0 0241 &iexcl;
+¡ "
+ct 9,9 0 0242 &cent;
+¢ "
+Po 9,9 0 0243 &pound;
+£ "
+Cs 9,7 0 0244 &curren;
+¤ "
+Ye 9,9 0 0245 &yen;
+¥ "
+bb 9,9,2 0 0246 &brvbar;
+¦ "
+sc 9,9,1 0 0247 &sect;
+§ "
+ad 9,9 0 0250 &uml;
+¨ "
+co 9,9 0 0251 &copy;
+© "
+Of 9,9 0 0252 &ordf;
+ª "
+Fo 9,7 0 0253 &laquo;
+« "
+no 9,6 0 0254 &not;
+¬ "
+- 9,5 0 055 &shy;
+hy " &shy;
+­ "
+rg 9,9 0 0256 &reg;
+® "
+a- 9,9 0 0257 &macr;
+¯ "
+de 9,10 0 0260 &deg;
+° "
++- 9,8 0 0261 &plusmn;
+± "
+S2 9,10 0 0262 &sup2;
+² "
+S3 9,10 0 0263 &sup3;
+³ "
+aa 9,10 0 0264 &acute;
+´ "
+µ 9,7,3 0 0265 &micro;
+ps 9,9,1 0 0266 &para;
+¶ "
+md 9,5 0 0267 &middot;
+· "
+ac 9,0,3 0 0270 &cedil;
+¸ "
+S1 9,10 0 0271 &sup1;
+¹ "
+Om 9,9 0 0272 &ordm;
+º "
+Fc 9,7 0 0273 &raquo;
+» "
+14 9,10 0 0274 &frac14;
+¼ "
+12 9,10 0 0275 &frac12;
+½ "
+34 9,10 0 0276 &frac34;
+¾ "
+r? 9,7,2 0 0277 &iquest;
+¿ "
+`A 9,12 0 0300 &Agrave;
+À "
+'A 9,12 0 0301 &Aacute;
+Á "
+^A 9,12 0 0302 &Acirc;
+Â "
+~A 9,12 0 0303 &Atilde;
+Ã "
+:A 9,11 0 0304 &Auml;
+Ä "
+oA 9,12 0 0305 &Aring;
+Å "
+AE 9,9 0 0306 &AElig;
+Æ "
+,C 9,9,3 0 0307 &Ccedil;
+Ç "
+`E 9,12 0 0310 &Egrave;
+È "
+'E 9,12 0 0311 &Eacute;
+É "
+^E 9,12 0 0312 &Ecirc;
+Ê "
+:E 9,11 0 0313 &Euml;
+Ë "
+`I 9,12 0 0314 &Igrave;
+Ì "
+'I 9,12 0 0315 &Iacute;
+Í "
+^I 9,12 0 0316 &Icirc;
+Î "
+:I 9,11 0 0317 &Iuml;
+Ï "
+-D 9,9 0 0320 &ETH;
+Ð "
+~N 9,12 0 0321 &Ntilde;
+Ñ "
+`O 9,12 0 0322 &Ograve;
+Ò "
+'O 9,12 0 0323 &Oacute;
+Ó "
+^O 9,12 0 0324 &Ocirc;
+Ô "
+~O 9,12 0 0325 &Otilde;
+Õ "
+:O 9,11 0 0326 &Ouml;
+Ö "
+mu 9,8 0 0327 &times;
+× "
+/O 9,9 0 0330 &Oslash;
+Ø "
+`U 9,12 0 0331 &Ugrave;
+Ù "
+'U 9,12 0 0332 &Uacute;
+Ú "
+^U 9,12 0 0333 &Ucirc;
+Û "
+:U 9,11 0 0334 &Uuml;
+Ü "
+'Y 9,12 0 0335 &Yacute;
+Ý "
+TP 9,9 0 0336 &THORN;
+Þ "
+ss 9,9 0 0337 &szlig;
+ß "
+`a 9,10 0 0340 &agrave;
+à "
+'a 9,10 0 0341 &aacute;
+á "
+^a 9,10 0 0342 &acirc;
+â "
+~a 9,10 0 0343 &atilde;
+ã "
+:a 9,9 0 0344 &auml;
+ä "
+oa 9,10 0 0345 &aring;
+å "
+ae 9,7 0 0346 &aelig;
+æ "
+,c 9,7,3 0 0347 &ccedil;
+ç "
+`e 9,10 0 0350 &egrave;
+è "
+'e 9,10 0 0351 &eacute;
+é "
+^e 9,10 0 0352 &ecirc;
+ê "
+:e 9,9 0 0353 &euml;
+ë "
+`i 9,10 0 0354 &igrave;
+ì "
+'i 9,10 0 0355 &iacute;
+í "
+^i 9,10 0 0356 &icirc;
+î "
+:i 9,9 0 0357 &iuml;
+ï "
+Sd 9,12 0 0360 &eth;
+ð "
+~n 9,10 0 0361 &ntilde;
+ñ "
+`o 9,10 0 0362 &ograve;
+ò "
+'o 9,10 0 0363 &oacute;
+ó "
+^o 9,10 0 0364 &ocirc;
+ô "
+~o 9,10 0 0365 &otilde;
+õ "
+:o 9,9 0 0366 &ouml;
+ö "
+di 9,8 0 0367 &divide;
+÷ "
+/o 9,7 0 0370 &oslash;
+ø "
+`u 9,10 0 0371 &ugrave;
+ù "
+'u 9,10 0 0372 &uacute;
+ú "
+^u 9,10 0 0373 &ucirc;
+û "
+:u 9,9 0 0374 &uuml;
+ü "
+'y 9,10,3 0 0375 &yacute;
+ý "
+Tp 9,9,3 0 0376 &thorn;
+þ "
+:y 9,9,3 0 0377 &yuml;
+ÿ "
diff --git a/font/devhtml/DESC b/font/devhtml/DESC
new file mode 100755
index 00000000..a8977526
--- /dev/null
+++ b/font/devhtml/DESC
@@ -0,0 +1,12 @@
+styles R I B BI
+fonts 6 0 0 0 0 0 S
+sizes 8 10 12 14 18 24 0
+res 100
+tcommand
+html
+hor 1
+vert 1
+unitwidth 10
+postpro grohtml
+use_charnames_in_special
+pass_filenames
diff --git a/font/devhtml/HB b/font/devhtml/HB
new file mode 100755
index 00000000..fc8b0204
--- /dev/null
+++ b/font/devhtml/HB
@@ -0,0 +1,306 @@
+name HB
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,11 0 041
+" 7,11 0 042 &quot;
+# 9,10 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 13,11 0 045
+& 11,10 0 046 &amp;
+' 5,11 0 047
+( 5,11,3 0 050
+) 5,11,3 0 051
+* 6,11 0 052
++ 9,8 0 053
+, 4,2,1 0 054
+\- 9,5 0 055
+. 4,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 5,8 0 072
+; 5,8,1 0 073
+< 8,7 0 074 &lt;
+= 9,6 0 075
+eq "
+> 8,7 0 076 &gt;
+? 9,11 0 077
+@ 14,11,1 0 0100
+at "
+A 10,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 11,11 0 0104
+E 9,11 0 0105
+F 9,11 0 0106
+G 11,11 0 0107
+H 10,11 0 0110
+I 4,11 0 0111
+J 8,11 0 0112
+K 10,11 0 0113
+L 8,11 0 0114
+M 13,11 0 0115
+N 11,11 0 0116
+O 12,11 0 0117
+P 10,11 0 0120
+Q 12,11 0 0121
+R 11,11 0 0122
+S 10,11 0 0123
+T 8,11 0 0124
+U 11,11 0 0125
+V 10,11 0 0126
+W 14,11 0 0127
+X 9,11 0 0130
+Y 10,11 0 0131
+Z 9,11 0 0132
+[ 5,11,3 0 0133
+lB "
+\ 4,11 0 0134
+rs "
+] 5,11,3 0 0135
+rB "
+^ 8,11 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 5,11 0 0140
+oq "
+a 8,8 0 0141
+b 9,11 0 0142
+c 8,8 0 0143
+d 9,11 0 0144
+e 8,8 0 0145
+f 4,11 0 0146
+g 9,8,3 0 0147
+h 9,11 0 0150
+i 4,11 0 0151
+j 4,11,3 0 0152
+k 8,11 0 0153
+l 4,11 0 0154
+m 12,8 0 0155
+n 9,8 0 0156
+o 9,8 0 0157
+p 9,8,3 0 0160
+q 9,8,3 0 0161
+r 6,8 0 0162
+s 8,8 0 0163
+t 5,10 0 0164
+u 9,8 0 0165
+v 8,8 0 0166
+w 10,8 0 0167
+x 7,8 0 0170
+y 8,8,3 0 0171
+z 6,8 0 0172
+{ 6,11,3 0 0173
+lC "
+| 4,11,3 0 0174
+or "
+ba "
+} 6,11,3 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241 &iexcl;
+¡ "
+ct 8,9,1 0 0242 &cent;
+¢ "
+Po 8,11 0 0243 &pound;
+£ "
+Cs 8,9 0 0244 &curren;
+¤ "
+Ye 9,11 0 0245 &yen;
+¥ "
+bb 4,11,3 0 0246 &brvbar;
+¦ "
+sc 8,11,3 0 0247 &sect;
+§ "
+ad 5,11 0 0250 &uml;
+¨ "
+co 12,11 0 0251 &copy;
+© "
+Of 6,11 0 0252 &ordf;
+ª "
+Fo 9,7 0 0253 &laquo;
+« "
+no 9,6 0 0254 &not;
+¬ "
+- 4,5 0 055 &shy;
+hy " &shy;
+­ "
+rg 12,11 0 0256 &reg;
+® "
+a- 5,10 0 0257 &macr;
+¯ "
+de 6,11 0 0260 &deg;
+° "
++- 9,9 0 0261 &plusmn;
+± "
+S2 5,11 0 0262 &sup2;
+² "
+S3 5,11 0 0263 &sup3;
+³ "
+aa 5,11 0 0264 &acute;
+´ "
+µ 9,8,3 0 0265 &micro;
+ps 8,11,3 0 0266 &para;
+¶ "
+md 4,5 0 0267 &middot;
+· "
+ac 5,0,3 0 0270 &cedil;
+¸ "
+S1 4,11 0 0271 &sup1;
+¹ "
+Om 6,11 0 0272 &ordm;
+º "
+Fc 9,7 0 0273 &raquo;
+» "
+14 12,11 0 0274 &frac14;
+¼ "
+12 12,11 0 0275 &frac12;
+½ "
+34 12,11 0 0276 &frac34;
+¾ "
+r? 9,8,3 0 0277 &iquest;
+¿ "
+`A 10,14 0 0300 &Agrave;
+À "
+'A 10,14 0 0301 &Aacute;
+Á "
+^A 10,14 0 0302 &Acirc;
+Â "
+~A 10,14 0 0303 &Atilde;
+Ã "
+:A 10,14 0 0304 &Auml;
+Ä "
+oA 10,14 0 0305 &Aring;
+Å "
+AE 15,11 0 0306 &AElig;
+Æ "
+,C 11,11,3 0 0307 &Ccedil;
+Ç "
+`E 9,14 0 0310 &Egrave;
+È "
+'E 9,14 0 0311 &Eacute;
+É "
+^E 9,14 0 0312 &Ecirc;
+Ê "
+:E 9,14 0 0313 &Euml;
+Ë "
+`I 4,14 0 0314 &Igrave;
+Ì "
+'I 4,14 0 0315 &Iacute;
+Í "
+^I 4,14 0 0316 &Icirc;
+Î "
+:I 4,14 0 0317 &Iuml;
+Ï "
+-D 11,11 0 0320 &ETH;
+Ð "
+~N 11,14 0 0321 &Ntilde;
+Ñ "
+`O 12,14 0 0322 &Ograve;
+Ò "
+'O 12,14 0 0323 &Oacute;
+Ó "
+^O 12,14 0 0324 &Ocirc;
+Ô "
+~O 12,14 0 0325 &Otilde;
+Õ "
+:O 12,14 0 0326 &Ouml;
+Ö "
+mu 9,8 0 0327 &times;
+× "
+/O 12,11 0 0330 &Oslash;
+Ø "
+`U 11,14 0 0331 &Ugrave;
+Ù "
+'U 11,14 0 0332 &Uacute;
+Ú "
+^U 11,14 0 0333 &Ucirc;
+Û "
+:U 11,14 0 0334 &Uuml;
+Ü "
+'Y 10,14 0 0335 &Yacute;
+Ý "
+TP 10,11 0 0336 &THORN;
+Þ "
+ss 8,11 0 0337 &szlig;
+ß "
+`a 8,11 0 0340 &agrave;
+à "
+'a 8,11 0 0341 &aacute;
+á "
+^a 8,11 0 0342 &acirc;
+â "
+~a 8,11 0 0343 &atilde;
+ã "
+:a 8,11 0 0344 &auml;
+ä "
+oa 8,11 0 0345 &aring;
+å "
+ae 13,8 0 0346 &aelig;
+æ "
+,c 9,8,3 0 0347 &ccedil;
+ç "
+`e 8,11 0 0350 &egrave;
+è "
+'e 8,11 0 0351 &eacute;
+é "
+^e 8,11 0 0352 &ecirc;
+ê "
+:e 8,11 0 0353 &euml;
+ë "
+`i 4,11 0 0354 &igrave;
+ì "
+'i 4,11 0 0355 &iacute;
+í "
+^i 4,11 0 0356 &icirc;
+î "
+:i 4,11 0 0357 &iuml;
+ï "
+Sd 9,11 0 0360 &eth;
+ð "
+~n 9,11 0 0361 &ntilde;
+ñ "
+`o 9,11 0 0362 &ograve;
+ò "
+'o 9,11 0 0363 &oacute;
+ó "
+^o 9,11 0 0364 &ocirc;
+ô "
+~o 9,11 0 0365 &otilde;
+õ "
+:o 9,11 0 0366 &ouml;
+ö "
+di 9,8 0 0367 &divide;
+÷ "
+/o 9,8 0 0370 &oslash;
+ø "
+`u 9,11 0 0371 &ugrave;
+ù "
+'u 9,11 0 0372 &uacute;
+ú "
+^u 9,11 0 0373 &ucirc;
+û "
+:u 9,11 0 0374 &uuml;
+ü "
+'y 8,11,3 0 0375 &yacute;
+ý "
+Tp 9,11,3 0 0376 &thorn;
+þ "
+:y 8,11,3 0 0377 &yuml;
+ÿ "
diff --git a/font/devhtml/HBI b/font/devhtml/HBI
new file mode 100755
index 00000000..ede7b5d5
--- /dev/null
+++ b/font/devhtml/HBI
@@ -0,0 +1,306 @@
+name HBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+" 7,11 0 042 &quot;
+# 10,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11 0 045
+& 11,10 0 046 &amp;
+' 5,11 0 047
+( 5,11,3 0 050
+) 6,11,3 0 051
+* 6,11 0 052
++ 9,8 0 053
+, 4,2,2 0 054
+\- 9,5 0 055
+. 4,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 5,8 0 072
+; 5,8,2 0 073
+< 8,7 0 074 &lt;
+= 9,6 0 075
+eq "
+> 9,7 0 076 &gt;
+? 9,11 0 077
+@ 14,11,2 0 0100
+at "
+A 9,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 11,11 0 0104
+E 9,11 0 0105
+F 8,11 0 0106
+G 11,11 0 0107
+H 10,11 0 0110
+I 4,11 0 0111
+J 8,11 0 0112
+K 10,11 0 0113
+L 8,11 0 0114
+M 13,11 0 0115
+N 11,11 0 0116
+O 12,11 0 0117
+P 10,11 0 0120
+Q 12,11 0 0121
+R 10,11 0 0122
+S 10,11 0 0123
+T 8,11 0 0124
+U 11,11 0 0125
+V 10,11 0 0126
+W 14,11 0 0127
+X 9,11 0 0130
+Y 10,11 0 0131
+Z 9,11 0 0132
+[ 5,11,3 0 0133
+lB "
+\ 6,11 0 0134
+rs "
+] 5,11,3 0 0135
+rB "
+^ 8,11 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 5,11 0 0140
+oq "
+a 8,8 0 0141
+b 9,11 0 0142
+c 8,8 0 0143
+d 9,11 0 0144
+e 8,8 0 0145
+f 5,11 0 0146
+g 9,8,3 0 0147
+h 9,11 0 0150
+i 4,11 0 0151
+j 4,11,3 0 0152
+k 8,11 0 0153
+l 4,11 0 0154
+m 12,8 0 0155
+n 9,8 0 0156
+o 8,8 0 0157
+p 9,8,3 0 0160
+q 9,8,3 0 0161
+r 6,8 0 0162
+s 8,8 0 0163
+t 5,10 0 0164
+u 9,8 0 0165
+v 8,8 0 0166
+w 11,8 0 0167
+x 7,8 0 0170
+y 7,8,3 0 0171
+z 6,8 0 0172
+{ 6,11,3 0 0173
+lC "
+| 4,11,3 0 0174
+or "
+ba "
+} 6,11,3 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 5,8,3 0 0241 &iexcl;
+¡ "
+ct 8,9,1 0 0242 &cent;
+¢ "
+Po 9,11 0 0243 &pound;
+£ "
+Cs 9,8 0 0244 &curren;
+¤ "
+Ye 9,11 0 0245 &yen;
+¥ "
+bb 4,11,3 0 0246 &brvbar;
+¦ "
+sc 9,11,3 0 0247 &sect;
+§ "
+ad 5,11 0 0250 &uml;
+¨ "
+co 12,11 0 0251 &copy;
+© "
+Of 6,11 0 0252 &ordf;
+ª "
+Fo 11,7 0 0253 &laquo;
+« "
+no 9,6 0 0254 &not;
+¬ "
+- 5,5 0 055 &shy;
+hy " &shy;
+­ "
+rg 12,11 0 0256 &reg;
+® "
+a- 5,11 0 0257 &macr;
+¯ "
+de 6,11 0 0260 &deg;
+° "
++- 9,9 0 0261 &plusmn;
+± "
+S2 5,11 0 0262 &sup2;
+² "
+S3 5,11 0 0263 &sup3;
+³ "
+aa 5,11 0 0264 &acute;
+´ "
+µ 9,8,3 0 0265 &micro;
+ps 8,11,3 0 0266 &para;
+¶ "
+md 4,5 0 0267 &middot;
+· "
+ac 5,1,3 0 0270 &cedil;
+¸ "
+S1 5,11 0 0271 &sup1;
+¹ "
+Om 6,11 0 0272 &ordm;
+º "
+Fc 11,7 0 0273 &raquo;
+» "
+14 12,11 0 0274 &frac14;
+¼ "
+12 12,11 0 0275 &frac12;
+½ "
+34 13,11 0 0276 &frac34;
+¾ "
+r? 8,8,3 0 0277 &iquest;
+¿ "
+`A 9,14 0 0300 &Agrave;
+À "
+'A 9,14 0 0301 &Aacute;
+Á "
+^A 9,14 0 0302 &Acirc;
+Â "
+~A 9,14 0 0303 &Atilde;
+Ã "
+:A 9,14 0 0304 &Auml;
+Ä "
+oA 9,14 0 0305 &Aring;
+Å "
+AE 14,11 0 0306 &AElig;
+Æ "
+,C 11,11,3 0 0307 &Ccedil;
+Ç "
+`E 9,14 0 0310 &Egrave;
+È "
+'E 9,14 0 0311 &Eacute;
+É "
+^E 9,14 0 0312 &Ecirc;
+Ê "
+:E 9,14 0 0313 &Euml;
+Ë "
+`I 4,14 0 0314 &Igrave;
+Ì "
+'I 4,14 0 0315 &Iacute;
+Í "
+^I 4,14 0 0316 &Icirc;
+Î "
+:I 4,14 0 0317 &Iuml;
+Ï "
+-D 11,11 0 0320 &ETH;
+Ð "
+~N 11,14 0 0321 &Ntilde;
+Ñ "
+`O 12,14 0 0322 &Ograve;
+Ò "
+'O 12,14 0 0323 &Oacute;
+Ó "
+^O 12,14 0 0324 &Ocirc;
+Ô "
+~O 12,14 0 0325 &Otilde;
+Õ "
+:O 12,14 0 0326 &Ouml;
+Ö "
+mu 9,8 0 0327 &times;
+× "
+/O 12,11 0 0330 &Oslash;
+Ø "
+`U 11,14 0 0331 &Ugrave;
+Ù "
+'U 11,14 0 0332 &Uacute;
+Ú "
+^U 11,14 0 0333 &Ucirc;
+Û "
+:U 11,14 0 0334 &Uuml;
+Ü "
+'Y 10,14 0 0335 &Yacute;
+Ý "
+TP 10,11 0 0336 &THORN;
+Þ "
+ss 9,11 0 0337 &szlig;
+ß "
+`a 8,11 0 0340 &agrave;
+à "
+'a 8,11 0 0341 &aacute;
+á "
+^a 8,11 0 0342 &acirc;
+â "
+~a 8,11 0 0343 &atilde;
+ã "
+:a 8,11 0 0344 &auml;
+ä "
+oa 8,11 0 0345 &aring;
+å "
+ae 13,8 0 0346 &aelig;
+æ "
+,c 8,8,3 0 0347 &ccedil;
+ç "
+`e 8,11 0 0350 &egrave;
+è "
+'e 8,11 0 0351 &eacute;
+é "
+^e 8,11 0 0352 &ecirc;
+ê "
+:e 8,11 0 0353 &euml;
+ë "
+`i 4,11 0 0354 &igrave;
+ì "
+'i 4,11 0 0355 &iacute;
+í "
+^i 4,11 0 0356 &icirc;
+î "
+:i 4,11 0 0357 &iuml;
+ï "
+Sd 8,11 0 0360 &eth;
+ð "
+~n 9,11 0 0361 &ntilde;
+ñ "
+`o 8,11 0 0362 &ograve;
+ò "
+'o 8,11 0 0363 &oacute;
+ó "
+^o 8,11 0 0364 &ocirc;
+ô "
+~o 8,11 0 0365 &otilde;
+õ "
+:o 8,11 0 0366 &ouml;
+ö "
+di 9,8 0 0367 &divide;
+÷ "
+/o 8,8 0 0370 &oslash;
+ø "
+`u 9,11 0 0371 &ugrave;
+ù "
+'u 9,11 0 0372 &uacute;
+ú "
+^u 9,11 0 0373 &ucirc;
+û "
+:u 9,11 0 0374 &uuml;
+ü "
+'y 7,11,3 0 0375 &yacute;
+ý "
+Tp 9,11,3 0 0376 &thorn;
+þ "
+:y 7,11,3 0 0377 &yuml;
+ÿ "
diff --git a/font/devhtml/HI b/font/devhtml/HI
new file mode 100755
index 00000000..6497a160
--- /dev/null
+++ b/font/devhtml/HI
@@ -0,0 +1,306 @@
+name HI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,11 0 041
+" 5,11 0 042 &quot;
+# 9,10 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 12,11 0 045
+& 10,10 0 046 &amp;
+' 3,11 0 047
+( 5,11,3 0 050
+) 5,11,3 0 051
+* 8,11 0 052
++ 9,8 0 053
+, 3,2,2 0 054
+\- 9,5 0 055
+. 3,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,8 0 072
+; 4,8,2 0 073
+< 9,7 0 074 &lt;
+= 9,6 0 075
+eq "
+> 9,7 0 076 &gt;
+? 8,11 0 077
+@ 13,11,1 0 0100
+at "
+A 11,11 0 0101
+B 10,11 0 0102
+C 10,11 0 0103
+D 10,11 0 0104
+E 9,11 0 0105
+F 9,11 0 0106
+G 11,11 0 0107
+H 11,11 0 0110
+I 5,11 0 0111
+J 9,11 0 0112
+K 10,11 0 0113
+L 8,11 0 0114
+M 14,11 0 0115
+N 11,11 0 0116
+O 11,11 0 0117
+P 9,11 0 0120
+Q 11,11 0 0121
+R 10,11 0 0122
+S 9,11 0 0123
+T 8,11 0 0124
+U 11,11 0 0125
+V 11,11 0 0126
+W 14,11 0 0127
+X 10,11 0 0130
+Y 9,11 0 0131
+Z 9,11 0 0132
+[ 5,11,3 0 0133
+lB "
+\ 6,11 0 0134
+rs "
+] 5,11,3 0 0135
+rB "
+^ 7,11 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 3,11 0 0140
+oq "
+a 8,8 0 0141
+b 8,11 0 0142
+c 7,8 0 0143
+d 8,11 0 0144
+e 8,8 0 0145
+f 4,11 0 0146
+g 8,8,3 0 0147
+h 8,11 0 0150
+i 4,11 0 0151
+j 3,11,3 0 0152
+k 7,11 0 0153
+l 3,11 0 0154
+m 11,8 0 0155
+n 8,8 0 0156
+o 8,8 0 0157
+p 8,8,3 0 0160
+q 8,8,3 0 0161
+r 5,8 0 0162
+s 7,8 0 0163
+t 4,10 0 0164
+u 8,8 0 0165
+v 7,8 0 0166
+w 10,8 0 0167
+x 7,8 0 0170
+y 7,8,3 0 0171
+z 7,8 0 0172
+{ 5,11,3 0 0173
+lC "
+| 4,11,3 0 0174
+or "
+ba "
+} 5,11,3 0 0175
+rC "
+~ 8,6 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241 &iexcl;
+¡ "
+ct 8,9,1 0 0242 &cent;
+¢ "
+Po 9,11 0 0243 &pound;
+£ "
+Cs 8,8 0 0244 &curren;
+¤ "
+Ye 9,11 0 0245 &yen;
+¥ "
+bb 4,11,3 0 0246 &brvbar;
+¦ "
+sc 8,11,3 0 0247 &sect;
+§ "
+ad 5,10 0 0250 &uml;
+¨ "
+co 12,11 0 0251 &copy;
+© "
+Of 5,11 0 0252 &ordf;
+ª "
+Fo 8,6 0 0253 &laquo;
+« "
+no 9,6 0 0254 &not;
+¬ "
+- 5,5 0 055 &shy;
+hy " &shy;
+­ "
+rg 12,11 0 0256 &reg;
+® "
+a- 4,10 0 0257 &macr;
+¯ "
+de 6,11 0 0260 &deg;
+° "
++- 9,9 0 0261 &plusmn;
+± "
+S2 5,11 0 0262 &sup2;
+² "
+S3 5,11 0 0263 &sup3;
+³ "
+aa 4,11 0 0264 &acute;
+´ "
+µ 8,8,3 0 0265 &micro;
+ps 8,11,3 0 0266 &para;
+¶ "
+md 4,5 0 0267 &middot;
+· "
+ac 3,0,3 0 0270 &cedil;
+¸ "
+S1 5,11 0 0271 &sup1;
+¹ "
+Om 5,11 0 0272 &ordm;
+º "
+Fc 8,6 0 0273 &raquo;
+» "
+14 12,11 0 0274 &frac14;
+¼ "
+12 12,11 0 0275 &frac12;
+½ "
+34 12,11 0 0276 &frac34;
+¾ "
+r? 8,8,3 0 0277 &iquest;
+¿ "
+`A 11,14 0 0300 &Agrave;
+À "
+'A 11,14 0 0301 &Aacute;
+Á "
+^A 11,14 0 0302 &Acirc;
+Â "
+~A 11,14 0 0303 &Atilde;
+Ã "
+:A 11,13 0 0304 &Auml;
+Ä "
+oA 11,14 0 0305 &Aring;
+Å "
+AE 15,11 0 0306 &AElig;
+Æ "
+,C 10,11,3 0 0307 &Ccedil;
+Ç "
+`E 9,14 0 0310 &Egrave;
+È "
+'E 9,14 0 0311 &Eacute;
+É "
+^E 9,14 0 0312 &Ecirc;
+Ê "
+:E 9,13 0 0313 &Euml;
+Ë "
+`I 5,14 0 0314 &Igrave;
+Ì "
+'I 5,14 0 0315 &Iacute;
+Í "
+^I 5,14 0 0316 &Icirc;
+Î "
+:I 5,13 0 0317 &Iuml;
+Ï "
+-D 10,11 0 0320 &ETH;
+Ð "
+~N 11,14 0 0321 &Ntilde;
+Ñ "
+`O 11,14 0 0322 &Ograve;
+Ò "
+'O 11,14 0 0323 &Oacute;
+Ó "
+^O 11,14 0 0324 &Ocirc;
+Ô "
+~O 11,14 0 0325 &Otilde;
+Õ "
+:O 11,13 0 0326 &Ouml;
+Ö "
+mu 9,8 0 0327 &times;
+× "
+/O 11,11 0 0330 &Oslash;
+Ø "
+`U 11,14 0 0331 &Ugrave;
+Ù "
+'U 11,14 0 0332 &Uacute;
+Ú "
+^U 11,14 0 0333 &Ucirc;
+Û "
+:U 11,13 0 0334 &Uuml;
+Ü "
+'Y 9,14 0 0335 &Yacute;
+Ý "
+TP 9,11 0 0336 &THORN;
+Þ "
+ss 8,11 0 0337 &szlig;
+ß "
+`a 8,11 0 0340 &agrave;
+à "
+'a 8,11 0 0341 &aacute;
+á "
+^a 8,11 0 0342 &acirc;
+â "
+~a 8,11 0 0343 &atilde;
+ã "
+:a 8,11 0 0344 &auml;
+ä "
+oa 8,11 0 0345 &aring;
+å "
+ae 12,8 0 0346 &aelig;
+æ "
+,c 7,8,3 0 0347 &ccedil;
+ç "
+`e 8,11 0 0350 &egrave;
+è "
+'e 8,11 0 0351 &eacute;
+é "
+^e 8,11 0 0352 &ecirc;
+ê "
+:e 8,11 0 0353 &euml;
+ë "
+`i 3,11 0 0354 &igrave;
+ì "
+'i 3,11 0 0355 &iacute;
+í "
+^i 3,11 0 0356 &icirc;
+î "
+:i 3,11 0 0357 &iuml;
+ï "
+Sd 8,11 0 0360 &eth;
+ð "
+~n 8,11 0 0361 &ntilde;
+ñ "
+`o 8,11 0 0362 &ograve;
+ò "
+'o 8,11 0 0363 &oacute;
+ó "
+^o 8,11 0 0364 &ocirc;
+ô "
+~o 8,11 0 0365 &otilde;
+õ "
+:o 8,11 0 0366 &ouml;
+ö "
+di 9,8 0 0367 &divide;
+÷ "
+/o 8,9,1 0 0370 &oslash;
+ø "
+`u 8,11 0 0371 &ugrave;
+ù "
+'u 8,11 0 0372 &uacute;
+ú "
+^u 8,11 0 0373 &ucirc;
+û "
+:u 8,11 0 0374 &uuml;
+ü "
+'y 7,11,3 0 0375 &yacute;
+ý "
+Tp 8,11,3 0 0376 &thorn;
+þ "
+:y 7,11,3 0 0377 &yuml;
+ÿ "
diff --git a/font/devhtml/HR b/font/devhtml/HR
new file mode 100755
index 00000000..7ca41310
--- /dev/null
+++ b/font/devhtml/HR
@@ -0,0 +1,306 @@
+name HR
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,11 0 041
+" 5,11 0 042 &quot;
+# 8,10 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 12,11 0 045
+& 10,10 0 046 &amp;
+' 3,11 0 047
+( 5,11,3 0 050
+) 5,11,3 0 051
+* 7,11 0 052
++ 9,8 0 053
+, 3,2,2 0 054
+\- 9,5 0 055
+. 3,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 3,8 0 072
+; 4,8,2 0 073
+< 8,7 0 074 &lt;
+= 9,6 0 075
+eq "
+> 8,7 0 076 &gt;
+? 8,11 0 077
+@ 13,11,1 0 0100
+at "
+A 9,11 0 0101
+B 9,11 0 0102
+C 10,11 0 0103
+D 10,11 0 0104
+E 9,11 0 0105
+F 8,11 0 0106
+G 11,11 0 0107
+H 10,11 0 0110
+I 4,11 0 0111
+J 7,11 0 0112
+K 9,11 0 0113
+L 8,11 0 0114
+M 12,11 0 0115
+N 10,11 0 0116
+O 11,11 0 0117
+P 9,11 0 0120
+Q 11,11 0 0121
+R 10,11 0 0122
+S 9,11 0 0123
+T 9,11 0 0124
+U 10,11 0 0125
+V 9,11 0 0126
+W 13,11 0 0127
+X 9,11 0 0130
+Y 9,11 0 0131
+Z 9,11 0 0132
+[ 4,11,3 0 0133
+lB "
+\ 4,11 0 0134
+rs "
+] 4,11,3 0 0135
+rB "
+^ 7,11 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 3,11 0 0140
+oq "
+a 8,8 0 0141
+b 7,11 0 0142
+c 7,8 0 0143
+d 8,11 0 0144
+e 8,8 0 0145
+f 4,11 0 0146
+g 8,8,3 0 0147
+h 8,11 0 0150
+i 3,11 0 0151
+j 3,11,3 0 0152
+k 7,11 0 0153
+l 3,11 0 0154
+m 11,8 0 0155
+n 8,8 0 0156
+o 8,8 0 0157
+p 8,8,3 0 0160
+q 8,8,3 0 0161
+r 5,8 0 0162
+s 7,8 0 0163
+t 4,10 0 0164
+u 7,8 0 0165
+v 7,8 0 0166
+w 10,8 0 0167
+x 7,8 0 0170
+y 7,8,3 0 0171
+z 7,8 0 0172
+{ 5,11,3 0 0173
+lC "
+| 3,11,3 0 0174
+or "
+ba "
+} 5,11,3 0 0175
+rC "
+~ 8,6 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241 &iexcl;
+¡ "
+ct 8,9,1 0 0242 &cent;
+¢ "
+Po 8,11 0 0243 &pound;
+£ "
+Cs 8,8 0 0244 &curren;
+¤ "
+Ye 7,11 0 0245 &yen;
+¥ "
+bb 3,11,3 0 0246 &brvbar;
+¦ "
+sc 8,11,3 0 0247 &sect;
+§ "
+ad 5,10 0 0250 &uml;
+¨ "
+co 12,11 0 0251 &copy;
+© "
+Of 6,11 0 0252 &ordf;
+ª "
+Fo 8,7 0 0253 &laquo;
+« "
+no 9,6 0 0254 &not;
+¬ "
+- 4,5 0 055 &shy;
+hy " &shy;
+­ "
+rg 12,11 0 0256 &reg;
+® "
+a- 4,10 0 0257 &macr;
+¯ "
+de 6,11 0 0260 &deg;
+° "
++- 9,9 0 0261 &plusmn;
+± "
+S2 5,11 0 0262 &sup2;
+² "
+S3 5,11 0 0263 &sup3;
+³ "
+aa 5,11 0 0264 &acute;
+´ "
+µ 8,8,3 0 0265 &micro;
+ps 8,11,3 0 0266 &para;
+¶ "
+md 4,5 0 0267 &middot;
+· "
+ac 5,0,3 0 0270 &cedil;
+¸ "
+S1 5,11 0 0271 &sup1;
+¹ "
+Om 6,11 0 0272 &ordm;
+º "
+Fc 8,7 0 0273 &raquo;
+» "
+14 12,11 0 0274 &frac14;
+¼ "
+12 12,11 0 0275 &frac12;
+½ "
+34 12,11 0 0276 &frac34;
+¾ "
+r? 8,8,3 0 0277 &iquest;
+¿ "
+`A 9,14 0 0300 &Agrave;
+À "
+'A 9,14 0 0301 &Aacute;
+Á "
+^A 9,14 0 0302 &Acirc;
+Â "
+~A 9,13 0 0303 &Atilde;
+Ã "
+:A 9,14 0 0304 &Auml;
+Ä "
+oA 9,14 0 0305 &Aring;
+Å "
+AE 14,11 0 0306 &AElig;
+Æ "
+,C 10,11,3 0 0307 &Ccedil;
+Ç "
+`E 9,14 0 0310 &Egrave;
+È "
+'E 9,14 0 0311 &Eacute;
+É "
+^E 9,14 0 0312 &Ecirc;
+Ê "
+:E 9,13 0 0313 &Euml;
+Ë "
+`I 4,14 0 0314 &Igrave;
+Ì "
+'I 4,14 0 0315 &Iacute;
+Í "
+^I 4,14 0 0316 &Icirc;
+Î "
+:I 4,13 0 0317 &Iuml;
+Ï "
+-D 10,11 0 0320 &ETH;
+Ð "
+~N 10,14 0 0321 &Ntilde;
+Ñ "
+`O 11,14 0 0322 &Ograve;
+Ò "
+'O 11,14 0 0323 &Oacute;
+Ó "
+^O 11,14 0 0324 &Ocirc;
+Ô "
+~O 11,14 0 0325 &Otilde;
+Õ "
+:O 11,13 0 0326 &Ouml;
+Ö "
+mu 9,8 0 0327 &times;
+× "
+/O 11,11 0 0330 &Oslash;
+Ø "
+`U 10,14 0 0331 &Ugrave;
+Ù "
+'U 10,14 0 0332 &Uacute;
+Ú "
+^U 10,14 0 0333 &Ucirc;
+Û "
+:U 10,13 0 0334 &Uuml;
+Ü "
+'Y 9,14 0 0335 &Yacute;
+Ý "
+TP 9,11 0 0336 &THORN;
+Þ "
+ss 7,11 0 0337 &szlig;
+ß "
+`a 8,11 0 0340 &agrave;
+à "
+'a 8,11 0 0341 &aacute;
+á "
+^a 8,11 0 0342 &acirc;
+â "
+~a 8,11 0 0343 &atilde;
+ã "
+:a 8,11 0 0344 &auml;
+ä "
+oa 8,12 0 0345 &aring;
+å "
+ae 13,8 0 0346 &aelig;
+æ "
+,c 8,8,3 0 0347 &ccedil;
+ç "
+`e 8,11 0 0350 &egrave;
+è "
+'e 8,11 0 0351 &eacute;
+é "
+^e 8,11 0 0352 &ecirc;
+ê "
+:e 8,11 0 0353 &euml;
+ë "
+`i 3,11 0 0354 &igrave;
+ì "
+'i 3,11 0 0355 &iacute;
+í "
+^i 3,11 0 0356 &icirc;
+î "
+:i 3,11 0 0357 &iuml;
+ï "
+Sd 8,11 0 0360 &eth;
+ð "
+~n 8,11 0 0361 &ntilde;
+ñ "
+`o 8,11 0 0362 &ograve;
+ò "
+'o 8,11 0 0363 &oacute;
+ó "
+^o 8,11 0 0364 &ocirc;
+ô "
+~o 8,11 0 0365 &otilde;
+õ "
+:o 8,11 0 0366 &ouml;
+ö "
+di 9,8 0 0367 &divide;
+÷ "
+/o 8,8 0 0370 &oslash;
+ø "
+`u 8,11 0 0371 &ugrave;
+ù "
+'u 8,11 0 0372 &uacute;
+ú "
+^u 8,11 0 0373 &ucirc;
+û "
+:u 8,11 0 0374 &uuml;
+ü "
+'y 7,11,3 0 0375 &yacute;
+ý "
+Tp 8,11,3 0 0376 &thorn;
+þ "
+:y 7,10,3 0 0377 &yuml;
+ÿ "
diff --git a/font/devhtml/Makefile.sub b/font/devhtml/Makefile.sub
new file mode 100644
index 00000000..57c9f44d
--- /dev/null
+++ b/font/devhtml/Makefile.sub
@@ -0,0 +1,2 @@
+DEV=html
+DEVFILES=DESC TR TI TB TBI CR CI CB CBI HR HI HB HBI NR NI NB NBI S
diff --git a/font/devhtml/NB b/font/devhtml/NB
new file mode 100755
index 00000000..82f8ca62
--- /dev/null
+++ b/font/devhtml/NB
@@ -0,0 +1,306 @@
+name NB
+spacewidth 11
+charset
+--- 11,1 0 040
+! 4,11 0 041
+" 5,11 0 042 &quot;
+# 8,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11 0 045
+& 13,11 0 046 &amp;
+' 4,11 0 047
+( 5,11,2 0 050
+) 5,11,2 0 051
+* 6,11 0 052
++ 8,8 0 053
+, 4,3,2 0 054
+\- 8,5 0 055
+. 4,3 0 056
+/ 5,11 0 057
+sl "
+0 8,11 0 060
+1 6,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 8,8 0 074 &lt;
+= 8,6 0 075
+eq "
+> 8,8 0 076 &gt;
+? 7,11 0 077
+@ 14,11 0 0100
+at "
+A 11,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 12,11 0 0104
+E 10,11 0 0105
+F 10,11 0 0106
+G 12,11 0 0107
+H 12,11 0 0110
+I 7,11 0 0111
+J 9,11 0 0112
+K 12,11 0 0113
+L 10,11 0 0114
+M 14,11 0 0115
+N 12,11 0 0116
+O 12,11 0 0117
+P 10,11 0 0120
+Q 12,11,3 0 0121
+R 12,11 0 0122
+S 10,11 0 0123
+T 11,11 0 0124
+U 12,11 0 0125
+V 11,11 0 0126
+W 14,11 0 0127
+X 12,11 0 0130
+Y 11,11 0 0131
+Z 9,11 0 0132
+[ 5,11,2 0 0133
+lB "
+\ 7,11 0 0134
+rs "
+] 5,11,2 0 0135
+rB "
+^ 8,11 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 4,11 0 0140
+oq "
+a 9,7 0 0141
+b 10,11 0 0142
+c 8,7 0 0143
+d 10,11 0 0144
+e 9,7 0 0145
+f 6,11 0 0146
+g 8,8,3 0 0147
+h 10,11 0 0150
+i 5,10 0 0151
+j 5,10,3 0 0152
+k 9,11 0 0153
+l 5,11 0 0154
+m 15,7 0 0155
+n 10,7 0 0156
+o 9,7 0 0157
+p 10,7,3 0 0160
+q 9,7,3 0 0161
+r 7,7 0 0162
+s 7,7 0 0163
+t 6,10 0 0164
+u 10,7 0 0165
+v 7,7 0 0166
+w 12,7 0 0167
+x 9,7 0 0170
+y 7,7,3 0 0171
+z 7,7 0 0172
+{ 6,11,2 0 0173
+lC "
+| 8,11 0 0174
+or "
+ba "
+} 6,11,2 0 0175
+rC "
+~ 8,6 0 0176
+a~ "
+ap "
+ti "
+r! 5,8,3 0 0241 &iexcl;
+¡ "
+ct 8,8,1 0 0242 &cent;
+¢ "
+Po 9,11 0 0243 &pound;
+£ "
+Cs 9,10 0 0244 &curren;
+¤ "
+Ye 11,11 0 0245 &yen;
+¥ "
+bb 8,11 0 0246 &brvbar;
+¦ "
+sc 7,11,2 0 0247 &sect;
+§ "
+ad 7,10 0 0250 &uml;
+¨ "
+co 12,11 0 0251 &copy;
+© "
+Of 6,11 0 0252 &ordf;
+ª "
+Fo 8,6 0 0253 &laquo;
+« "
+no 8,6 0 0254 &not;
+¬ "
+- 5,5 0 055 &shy;
+hy " &shy;
+­ "
+rg 12,11 0 0256 &reg;
+® "
+a- 7,9 0 0257 &macr;
+¯ "
+de 6,11 0 0260 &deg;
+° "
++- 8,8 0 0261 &plusmn;
+± "
+S2 5,11 0 0262 &sup2;
+² "
+S3 5,11 0 0263 &sup3;
+³ "
+aa 6,11 0 0264 &acute;
+´ "
+µ 10,7,3 0 0265 &micro;
+ps 10,11 0 0266 &para;
+¶ "
+md 5,6 0 0267 &middot;
+· "
+ac 5,0,3 0 0270 &cedil;
+¸ "
+S1 5,11 0 0271 &sup1;
+¹ "
+Om 6,11 0 0272 &ordm;
+º "
+Fc 8,6 0 0273 &raquo;
+» "
+14 12,11 0 0274 &frac14;
+¼ "
+12 12,11 0 0275 &frac12;
+½ "
+34 12,11 0 0276 &frac34;
+¾ "
+r? 7,8,3 0 0277 &iquest;
+¿ "
+`A 11,15 0 0300 &Agrave;
+À "
+'A 11,15 0 0301 &Aacute;
+Á "
+^A 11,15 0 0302 &Acirc;
+Â "
+~A 11,14 0 0303 &Atilde;
+Ã "
+:A 11,14 0 0304 &Auml;
+Ä "
+oA 11,15 0 0305 &Aring;
+Å "
+AE 15,11 0 0306 &AElig;
+Æ "
+,C 11,11,3 0 0307 &Ccedil;
+Ç "
+`E 10,15 0 0310 &Egrave;
+È "
+'E 10,15 0 0311 &Eacute;
+É "
+^E 10,15 0 0312 &Ecirc;
+Ê "
+:E 10,14 0 0313 &Euml;
+Ë "
+`I 7,15 0 0314 &Igrave;
+Ì "
+'I 7,15 0 0315 &Iacute;
+Í "
+^I 7,15 0 0316 &Icirc;
+Î "
+:I 7,14 0 0317 &Iuml;
+Ï "
+-D 12,11 0 0320 &ETH;
+Ð "
+~N 12,14 0 0321 &Ntilde;
+Ñ "
+`O 12,15 0 0322 &Ograve;
+Ò "
+'O 12,15 0 0323 &Oacute;
+Ó "
+^O 12,15 0 0324 &Ocirc;
+Ô "
+~O 12,14 0 0325 &Otilde;
+Õ "
+:O 12,14 0 0326 &Ouml;
+Ö "
+mu 8,8 0 0327 &times;
+× "
+/O 12,11 0 0330 &Oslash;
+Ø "
+`U 12,15 0 0331 &Ugrave;
+Ù "
+'U 12,15 0 0332 &Uacute;
+Ú "
+^U 12,15 0 0333 &Ucirc;
+Û "
+:U 12,14 0 0334 &Uuml;
+Ü "
+'Y 11,14 0 0335 &Yacute;
+Ý "
+TP 10,11 0 0336 &THORN;
+Þ "
+ss 9,11 0 0337 &szlig;
+ß "
+`a 9,11 0 0340 &agrave;
+à "
+'a 9,11 0 0341 &aacute;
+á "
+^a 9,11 0 0342 &acirc;
+â "
+~a 9,10 0 0343 &atilde;
+ã "
+:a 9,10 0 0344 &auml;
+ä "
+oa 9,11 0 0345 &aring;
+å "
+ae 14,7 0 0346 &aelig;
+æ "
+,c 8,7,3 0 0347 &ccedil;
+ç "
+`e 9,11 0 0350 &egrave;
+è "
+'e 9,11 0 0351 &eacute;
+é "
+^e 9,11 0 0352 &ecirc;
+ê "
+:e 9,10 0 0353 &euml;
+ë "
+`i 5,11 0 0354 &igrave;
+ì "
+'i 5,11 0 0355 &iacute;
+í "
+^i 5,11 0 0356 &icirc;
+î "
+:i 5,10 0 0357 &iuml;
+ï "
+Sd 9,11 0 0360 &eth;
+ð "
+~n 10,10 0 0361 &ntilde;
+ñ "
+`o 9,11 0 0362 &ograve;
+ò "
+'o 9,11 0 0363 &oacute;
+ó "
+^o 9,11 0 0364 &ocirc;
+ô "
+~o 9,10 0 0365 &otilde;
+õ "
+:o 9,10 0 0366 &ouml;
+ö "
+di 8,8 0 0367 &divide;
+÷ "
+/o 9,8,1 0 0370 &oslash;
+ø "
+`u 10,11 0 0371 &ugrave;
+ù "
+'u 10,11 0 0372 &uacute;
+ú "
+^u 10,11 0 0373 &ucirc;
+û "
+:u 10,10 0 0374 &uuml;
+ü "
+'y 7,11,3 0 0375 &yacute;
+ý "
+Tp 10,11,3 0 0376 &thorn;
+þ "
+:y 7,10,3 0 0377 &yuml;
+ÿ "
diff --git a/font/devhtml/NBI b/font/devhtml/NBI
new file mode 100755
index 00000000..c288f693
--- /dev/null
+++ b/font/devhtml/NBI
@@ -0,0 +1,306 @@
+name NBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+" 6,11 0 042 &quot;
+# 8,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11,1 0 045
+& 13,11 0 046 &amp;
+' 4,11 0 047
+( 5,11,2 0 050
+) 6,11,2 0 051
+* 7,11 0 052
++ 8,8 0 053
+, 4,2,3 0 054
+\- 8,5 0 055
+. 4,2 0 056
+/ 5,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,7 0 072
+; 5,7,3 0 073
+< 9,9 0 074 &lt;
+= 9,7 0 075
+eq "
+> 9,9 0 076 &gt;
+? 7,11 0 077
+@ 13,11 0 0100
+at "
+A 11,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 12,11 0 0104
+E 10,11 0 0105
+F 10,11 0 0106
+G 11,11 0 0107
+H 12,11 0 0110
+I 6,11 0 0111
+J 8,11 0 0112
+K 12,11 0 0113
+L 10,11 0 0114
+M 15,11 0 0115
+N 13,11 0 0116
+O 12,11 0 0117
+P 11,11 0 0120
+Q 12,11,2 0 0121
+R 12,11 0 0122
+S 10,11 0 0123
+T 11,11 0 0124
+U 12,11 0 0125
+V 11,11 0 0126
+W 15,11 0 0127
+X 11,11 0 0130
+Y 9,11 0 0131
+Z 10,11 0 0132
+[ 7,11,2 0 0133
+lB "
+\ 9,11 0 0134
+rs "
+] 7,11,2 0 0135
+rB "
+^ 8,11 0 0136
+a^ "
+ha "
+_ 9,0,2 0 0137
+` 4,11 0 0140
+oq "
+a 10,7 0 0141
+b 8,11 0 0142
+c 8,7 0 0143
+d 10,11 0 0144
+e 8,7 0 0145
+f 5,11,3 0 0146
+g 8,9,3 0 0147
+h 10,11 0 0150
+i 5,10 0 0151
+j 4,10,3 0 0152
+k 9,11 0 0153
+l 5,11 0 0154
+m 15,7 0 0155
+n 10,7 0 0156
+o 8,7 0 0157
+p 8,7,3 0 0160
+q 9,7,3 0 0161
+r 7,7 0 0162
+s 8,7 0 0163
+t 5,9 0 0164
+u 10,7 0 0165
+v 8,7 0 0166
+w 13,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 6,11,2 0 0173
+lC "
+| 9,11 0 0174
+or "
+ba "
+} 6,11,2 0 0175
+rC "
+~ 11,6 0 0176
+a~ "
+ap "
+ti "
+r! 5,8,3 0 0241 &iexcl;
+¡ "
+ct 8,8,1 0 0242 &cent;
+¢ "
+Po 10,11 0 0243 &pound;
+£ "
+Cs 8,9 0 0244 &curren;
+¤ "
+Ye 10,11 0 0245 &yen;
+¥ "
+bb 8,11 0 0246 &brvbar;
+¦ "
+sc 9,11,2 0 0247 &sect;
+§ "
+ad 6,10 0 0250 &uml;
+¨ "
+co 12,11 0 0251 &copy;
+© "
+Of 8,11 0 0252 &ordf;
+ª "
+Fo 10,7 0 0253 &laquo;
+« "
+no 9,7 0 0254 &not;
+¬ "
+- 5,5 0 055 &shy;
+hy " &shy;
+­ "
+rg 12,11 0 0256 &reg;
+® "
+a- 6,9 0 0257 &macr;
+¯ "
+de 6,11 0 0260 &deg;
+° "
++- 8,8 0 0261 &plusmn;
+± "
+S2 5,11 0 0262 &sup2;
+² "
+S3 5,11 0 0263 &sup3;
+³ "
+aa 5,11 0 0264 &acute;
+´ "
+µ 10,7,3 0 0265 &micro;
+ps 9,11 0 0266 &para;
+¶ "
+md 5,6 0 0267 &middot;
+· "
+ac 5,0,3 0 0270 &cedil;
+¸ "
+S1 5,11 0 0271 &sup1;
+¹ "
+Om 8,11 0 0272 &ordm;
+º "
+Fc 10,7 0 0273 &raquo;
+» "
+14 12,11 0 0274 &frac14;
+¼ "
+12 12,11 0 0275 &frac12;
+½ "
+34 12,11 0 0276 &frac34;
+¾ "
+r? 7,8,3 0 0277 &iquest;
+¿ "
+`A 11,15 0 0300 &Agrave;
+À "
+'A 11,15 0 0301 &Aacute;
+Á "
+^A 11,15 0 0302 &Acirc;
+Â "
+~A 11,14 0 0303 &Atilde;
+Ã "
+:A 11,14 0 0304 &Auml;
+Ä "
+oA 11,15 0 0305 &Aring;
+Å "
+AE 14,11 0 0306 &AElig;
+Æ "
+,C 11,11,3 0 0307 &Ccedil;
+Ç "
+`E 10,15 0 0310 &Egrave;
+È "
+'E 10,15 0 0311 &Eacute;
+É "
+^E 10,15 0 0312 &Ecirc;
+Ê "
+:E 10,14 0 0313 &Euml;
+Ë "
+`I 6,15 0 0314 &Igrave;
+Ì "
+'I 6,15 0 0315 &Iacute;
+Í "
+^I 6,15 0 0316 &Icirc;
+Î "
+:I 6,14 0 0317 &Iuml;
+Ï "
+-D 12,11 0 0320 &ETH;
+Ð "
+~N 13,14 0 0321 &Ntilde;
+Ñ "
+`O 12,15 0 0322 &Ograve;
+Ò "
+'O 12,15 0 0323 &Oacute;
+Ó "
+^O 12,15 0 0324 &Ocirc;
+Ô "
+~O 12,14 0 0325 &Otilde;
+Õ "
+:O 12,14 0 0326 &Ouml;
+Ö "
+mu 8,8 0 0327 &times;
+× "
+/O 12,11 0 0330 &Oslash;
+Ø "
+`U 12,15 0 0331 &Ugrave;
+Ù "
+'U 12,15 0 0332 &Uacute;
+Ú "
+^U 12,15 0 0333 &Ucirc;
+Û "
+:U 12,14 0 0334 &Uuml;
+Ü "
+'Y 9,15 0 0335 &Yacute;
+Ý "
+TP 11,11 0 0336 &THORN;
+Þ "
+ss 10,11,3 0 0337 &szlig;
+ß "
+`a 10,11 0 0340 &agrave;
+à "
+'a 10,11 0 0341 &aacute;
+á "
+^a 10,11 0 0342 &acirc;
+â "
+~a 10,10 0 0343 &atilde;
+ã "
+:a 10,10 0 0344 &auml;
+ä "
+oa 10,11 0 0345 &aring;
+å "
+ae 13,7 0 0346 &aelig;
+æ "
+,c 8,7,3 0 0347 &ccedil;
+ç "
+`e 8,11 0 0350 &egrave;
+è "
+'e 8,11 0 0351 &eacute;
+é "
+^e 8,11 0 0352 &ecirc;
+ê "
+:e 8,10 0 0353 &euml;
+ë "
+`i 5,11 0 0354 &igrave;
+ì "
+'i 5,11 0 0355 &iacute;
+í "
+^i 5,11 0 0356 &icirc;
+î "
+:i 5,10 0 0357 &iuml;
+ï "
+Sd 8,11 0 0360 &eth;
+ð "
+~n 10,10 0 0361 &ntilde;
+ñ "
+`o 8,11 0 0362 &ograve;
+ò "
+'o 8,11 0 0363 &oacute;
+ó "
+^o 8,11 0 0364 &ocirc;
+ô "
+~o 8,10 0 0365 &otilde;
+õ "
+:o 8,10 0 0366 &ouml;
+ö "
+di 8,8 0 0367 &divide;
+÷ "
+/o 8,7 0 0370 &oslash;
+ø "
+`u 10,11 0 0371 &ugrave;
+ù "
+'u 10,11 0 0372 &uacute;
+ú "
+^u 10,11 0 0373 &ucirc;
+û "
+:u 10,10 0 0374 &uuml;
+ü "
+'y 9,11,3 0 0375 &yacute;
+ý "
+Tp 8,11,3 0 0376 &thorn;
+þ "
+:y 9,10,3 0 0377 &yuml;
+ÿ "
diff --git a/font/devhtml/NI b/font/devhtml/NI
new file mode 100755
index 00000000..21e7263a
--- /dev/null
+++ b/font/devhtml/NI
@@ -0,0 +1,306 @@
+name NI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+" 6,11 0 042 &quot;
+# 11,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 12,11,1 0 045
+& 11,11 0 046 &amp;
+' 4,11 0 047
+( 5,11,2 0 050
+) 5,11,2 0 051
+* 6,11 0 052
++ 8,8 0 053
+, 4,2,2 0 054
+\- 9,5 0 055
+. 4,2 0 056
+/ 9,11,3 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 9,8 0 074 &lt;
+= 8,6 0 075
+eq "
+> 9,8 0 076 &gt;
+? 6,11 0 077
+@ 12,11 0 0100
+at "
+A 11,11 0 0101
+B 9,11 0 0102
+C 10,11 0 0103
+D 11,11 0 0104
+E 9,11 0 0105
+F 8,11 0 0106
+G 10,11 0 0107
+H 11,11 0 0110
+I 7,11 0 0111
+J 8,11 0 0112
+K 10,11 0 0113
+L 9,11 0 0114
+M 14,11 0 0115
+N 12,11 0 0116
+O 10,11 0 0117
+P 10,11 0 0120
+Q 10,11,2 0 0121
+R 11,11 0 0122
+S 10,11 0 0123
+T 10,11 0 0124
+U 12,11 0 0125
+V 10,11 0 0126
+W 13,11 0 0127
+X 10,11 0 0130
+Y 9,11 0 0131
+Z 10,11 0 0132
+[ 6,11,2 0 0133
+lB "
+\ 8,11 0 0134
+rs "
+] 6,11,2 0 0135
+rB "
+^ 6,11 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 4,11 0 0140
+oq "
+a 9,7 0 0141
+b 7,11 0 0142
+c 6,7 0 0143
+d 9,11 0 0144
+e 6,7 0 0145
+f 5,11,3 0 0146
+g 7,8,3 0 0147
+h 9,11 0 0150
+i 4,11 0 0151
+j 4,11,3 0 0152
+k 8,11 0 0153
+l 4,11 0 0154
+m 14,7 0 0155
+n 9,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 8,7,3 0 0161
+r 7,7 0 0162
+s 7,7 0 0163
+t 5,9 0 0164
+u 9,7 0 0165
+v 7,7 0 0166
+w 11,7 0 0167
+x 8,7 0 0170
+y 7,7,3 0 0171
+z 8,7 0 0172
+{ 6,11,2 0 0173
+lC "
+| 9,11 0 0174
+or "
+ba "
+} 6,11,2 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241 &iexcl;
+¡ "
+ct 8,9,2 0 0242 &cent;
+¢ "
+Po 9,11 0 0243 &pound;
+£ "
+Cs 8,9 0 0244 &curren;
+¤ "
+Ye 9,11 0 0245 &yen;
+¥ "
+bb 8,11 0 0246 &brvbar;
+¦ "
+sc 7,11,2 0 0247 &sect;
+§ "
+ad 7,10 0 0250 &uml;
+¨ "
+co 13,11 0 0251 &copy;
+© "
+Of 6,11 0 0252 &ordf;
+ª "
+Fo 8,7 0 0253 &laquo;
+« "
+no 8,6 0 0254 &not;
+¬ "
+- 5,5 0 055 &shy;
+hy " &shy;
+­ "
+rg 13,11 0 0256 &reg;
+® "
+a- 6,9 0 0257 &macr;
+¯ "
+de 6,11 0 0260 &deg;
+° "
++- 8,8 0 0261 &plusmn;
+± "
+S2 5,11 0 0262 &sup2;
+² "
+S3 5,11 0 0263 &sup3;
+³ "
+aa 4,11 0 0264 &acute;
+´ "
+µ 9,7,3 0 0265 &micro;
+ps 9,11 0 0266 &para;
+¶ "
+md 5,6 0 0267 &middot;
+· "
+ac 5,0,3 0 0270 &cedil;
+¸ "
+S1 5,11 0 0271 &sup1;
+¹ "
+Om 6,11 0 0272 &ordm;
+º "
+Fc 8,7 0 0273 &raquo;
+» "
+14 12,11 0 0274 &frac14;
+¼ "
+12 12,11 0 0275 &frac12;
+½ "
+34 12,11 0 0276 &frac34;
+¾ "
+r? 6,8,3 0 0277 &iquest;
+¿ "
+`A 11,14 0 0300 &Agrave;
+À "
+'A 11,14 0 0301 &Aacute;
+Á "
+^A 11,14 0 0302 &Acirc;
+Â "
+~A 11,14 0 0303 &Atilde;
+Ã "
+:A 11,14 0 0304 &Auml;
+Ä "
+oA 11,14 0 0305 &Aring;
+Å "
+AE 14,11 0 0306 &AElig;
+Æ "
+,C 10,11,3 0 0307 &Ccedil;
+Ç "
+`E 9,14 0 0310 &Egrave;
+È "
+'E 9,14 0 0311 &Eacute;
+É "
+^E 9,14 0 0312 &Ecirc;
+Ê "
+:E 9,14 0 0313 &Euml;
+Ë "
+`I 7,14 0 0314 &Igrave;
+Ì "
+'I 7,14 0 0315 &Iacute;
+Í "
+^I 7,14 0 0316 &Icirc;
+Î "
+:I 7,14 0 0317 &Iuml;
+Ï "
+-D 11,11 0 0320 &ETH;
+Ð "
+~N 12,14 0 0321 &Ntilde;
+Ñ "
+`O 10,14 0 0322 &Ograve;
+Ò "
+'O 10,14 0 0323 &Oacute;
+Ó "
+^O 10,14 0 0324 &Ocirc;
+Ô "
+~O 10,14 0 0325 &Otilde;
+Õ "
+:O 10,14 0 0326 &Ouml;
+Ö "
+mu 8,8 0 0327 &times;
+× "
+/O 10,11 0 0330 &Oslash;
+Ø "
+`U 12,14 0 0331 &Ugrave;
+Ù "
+'U 12,14 0 0332 &Uacute;
+Ú "
+^U 12,14 0 0333 &Ucirc;
+Û "
+:U 12,14 0 0334 &Uuml;
+Ü "
+'Y 9,14 0 0335 &Yacute;
+Ý "
+TP 10,11 0 0336 &THORN;
+Þ "
+ss 8,11,3 0 0337 &szlig;
+ß "
+`a 9,11 0 0340 &agrave;
+à "
+'a 9,11 0 0341 &aacute;
+á "
+^a 9,11 0 0342 &acirc;
+â "
+~a 9,10 0 0343 &atilde;
+ã "
+:a 9,10 0 0344 &auml;
+ä "
+oa 9,11 0 0345 &aring;
+å "
+ae 10,7 0 0346 &aelig;
+æ "
+,c 6,7,3 0 0347 &ccedil;
+ç "
+`e 6,11 0 0350 &egrave;
+è "
+'e 6,11 0 0351 &eacute;
+é "
+^e 6,11 0 0352 &ecirc;
+ê "
+:e 6,10 0 0353 &euml;
+ë "
+`i 4,11 0 0354 &igrave;
+ì "
+'i 4,11 0 0355 &iacute;
+í "
+^i 4,11 0 0356 &icirc;
+î "
+:i 4,10 0 0357 &iuml;
+ï "
+Sd 7,11 0 0360 &eth;
+ð "
+~n 9,10 0 0361 &ntilde;
+ñ "
+`o 7,11 0 0362 &ograve;
+ò "
+'o 7,11 0 0363 &oacute;
+ó "
+^o 7,11 0 0364 &ocirc;
+ô "
+~o 7,10 0 0365 &otilde;
+õ "
+:o 7,10 0 0366 &ouml;
+ö "
+di 8,8 0 0367 &divide;
+÷ "
+/o 7,8,1 0 0370 &oslash;
+ø "
+`u 9,11 0 0371 &ugrave;
+ù "
+'u 9,11 0 0372 &uacute;
+ú "
+^u 9,11 0 0373 &ucirc;
+û "
+:u 9,10 0 0374 &uuml;
+ü "
+'y 7,11,3 0 0375 &yacute;
+ý "
+Tp 7,11,3 0 0376 &thorn;
+þ "
+:y 7,10,3 0 0377 &yuml;
+ÿ "
diff --git a/font/devhtml/NR b/font/devhtml/NR
new file mode 100755
index 00000000..8741cf49
--- /dev/null
+++ b/font/devhtml/NR
@@ -0,0 +1,306 @@
+name NR
+spacewidth 4
+charset
+--- 4,1 0 040
+! 3,11 0 041
+" 5,11 0 042 &quot;
+# 8,11 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 12,11 0 045
+& 13,11 0 046 &amp;
+' 4,11 0 047
+( 5,11,2 0 050
+) 6,11,2 0 051
+* 7,11 0 052
++ 9,7 0 053
+, 4,2,2 0 054
+\- 9,4 0 055
+. 4,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 10,7 0 074 &lt;
+= 9,6 0 075
+eq "
+> 10,7 0 076 &gt;
+? 6,11 0 077
+@ 13,11 0 0100
+at "
+A 10,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 11,11 0 0104
+E 10,11 0 0105
+F 10,11 0 0106
+G 11,11 0 0107
+H 12,11 0 0110
+I 6,11 0 0111
+J 7,11 0 0112
+K 11,11 0 0113
+L 10,11 0 0114
+M 16,11 0 0115
+N 13,11 0 0116
+O 11,11 0 0117
+P 10,11 0 0120
+Q 11,11,2 0 0121
+R 11,11 0 0122
+S 8,11 0 0123
+T 10,11 0 0124
+U 13,11 0 0125
+V 10,11 0 0126
+W 16,11 0 0127
+X 13,11 0 0130
+Y 10,11 0 0131
+Z 9,11 0 0132
+[ 4,11,2 0 0133
+lB "
+\ 8,11 0 0134
+rs "
+] 4,11,2 0 0135
+rB "
+^ 7,11 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 4,11 0 0140
+oq "
+a 8,7 0 0141
+b 7,11 0 0142
+c 7,7 0 0143
+d 8,11 0 0144
+e 7,7 0 0145
+f 5,11 0 0146
+g 8,7,3 0 0147
+h 9,11 0 0150
+i 4,10 0 0151
+j 4,10,3 0 0152
+k 9,11 0 0153
+l 4,11 0 0154
+m 14,7 0 0155
+n 9,7 0 0156
+o 7,7 0 0157
+p 8,7,3 0 0160
+q 7,7,3 0 0161
+r 7,7 0 0162
+s 6,7 0 0163
+t 5,9 0 0164
+u 9,7 0 0165
+v 8,7 0 0166
+w 12,7 0 0167
+x 8,7 0 0170
+y 8,7,3 0 0171
+z 7,7 0 0172
+{ 4,11,2 0 0173
+lC "
+| 9,11 0 0174
+or "
+ba "
+} 5,11,2 0 0175
+rC "
+~ 9,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241 &iexcl;
+¡ "
+ct 8,9,2 0 0242 &cent;
+¢ "
+Po 8,11 0 0243 &pound;
+£ "
+Cs 8,9 0 0244 &curren;
+¤ "
+Ye 8,11 0 0245 &yen;
+¥ "
+bb 9,11 0 0246 &brvbar;
+¦ "
+sc 7,11,2 0 0247 &sect;
+§ "
+ad 6,10 0 0250 &uml;
+¨ "
+co 14,11 0 0251 &copy;
+© "
+Of 6,11 0 0252 &ordf;
+ª "
+Fo 7,6 0 0253 &laquo;
+« "
+no 9,5 0 0254 &not;
+¬ "
+- 5,4 0 055 &shy;
+hy " &shy;
+­ "
+rg 14,11 0 0256 &reg;
+® "
+a- 5,9 0 0257 &macr;
+¯ "
+de 6,11 0 0260 &deg;
+° "
++- 9,7 0 0261 &plusmn;
+± "
+S2 5,11 0 0262 &sup2;
+² "
+S3 5,11 0 0263 &sup3;
+³ "
+aa 5,11 0 0264 &acute;
+´ "
+µ 9,7,3 0 0265 &micro;
+ps 9,11,2 0 0266 &para;
+¶ "
+md 4,5 0 0267 &middot;
+· "
+ac 5,1,3 0 0270 &cedil;
+¸ "
+S1 5,11 0 0271 &sup1;
+¹ "
+Om 5,11 0 0272 &ordm;
+º "
+Fc 7,6 0 0273 &raquo;
+» "
+14 12,11 0 0274 &frac14;
+¼ "
+12 12,11 0 0275 &frac12;
+½ "
+34 12,11 0 0276 &frac34;
+¾ "
+r? 6,8,3 0 0277 &iquest;
+¿ "
+`A 10,14 0 0300 &Agrave;
+À "
+'A 10,14 0 0301 &Aacute;
+Á "
+^A 10,14 0 0302 &Acirc;
+Â "
+~A 10,14 0 0303 &Atilde;
+Ã "
+:A 10,13 0 0304 &Auml;
+Ä "
+oA 10,14 0 0305 &Aring;
+Å "
+AE 15,11 0 0306 &AElig;
+Æ "
+,C 11,11,3 0 0307 &Ccedil;
+Ç "
+`E 10,14 0 0310 &Egrave;
+È "
+'E 10,14 0 0311 &Eacute;
+É "
+^E 10,14 0 0312 &Ecirc;
+Ê "
+:E 10,14 0 0313 &Euml;
+Ë "
+`I 6,14 0 0314 &Igrave;
+Ì "
+'I 6,14 0 0315 &Iacute;
+Í "
+^I 6,14 0 0316 &Icirc;
+Î "
+:I 6,14 0 0317 &Iuml;
+Ï "
+-D 11,11 0 0320 &ETH;
+Ð "
+~N 13,14 0 0321 &Ntilde;
+Ñ "
+`O 11,14 0 0322 &Ograve;
+Ò "
+'O 11,14 0 0323 &Oacute;
+Ó "
+^O 11,14 0 0324 &Ocirc;
+Ô "
+~O 11,14 0 0325 &Otilde;
+Õ "
+:O 11,14 0 0326 &Ouml;
+Ö "
+mu 9,7 0 0327 &times;
+× "
+/O 11,11 0 0330 &Oslash;
+Ø "
+`U 13,14 0 0331 &Ugrave;
+Ù "
+'U 13,14 0 0332 &Uacute;
+Ú "
+^U 13,14 0 0333 &Ucirc;
+Û "
+:U 13,14 0 0334 &Uuml;
+Ü "
+'Y 10,14 0 0335 &Yacute;
+Ý "
+TP 10,11 0 0336 &THORN;
+Þ "
+ss 8,11 0 0337 &szlig;
+ß "
+`a 8,11 0 0340 &agrave;
+à "
+'a 8,11 0 0341 &aacute;
+á "
+^a 8,11 0 0342 &acirc;
+â "
+~a 8,10 0 0343 &atilde;
+ã "
+:a 8,10 0 0344 &auml;
+ä "
+oa 8,11 0 0345 &aring;
+å "
+ae 12,7 0 0346 &aelig;
+æ "
+,c 7,7,3 0 0347 &ccedil;
+ç "
+`e 7,11 0 0350 &egrave;
+è "
+'e 7,11 0 0351 &eacute;
+é "
+^e 7,11 0 0352 &ecirc;
+ê "
+:e 7,10 0 0353 &euml;
+ë "
+`i 4,11 0 0354 &igrave;
+ì "
+'i 4,11 0 0355 &iacute;
+í "
+^i 4,11 0 0356 &icirc;
+î "
+:i 4,10 0 0357 &iuml;
+ï "
+Sd 7,11 0 0360 &eth;
+ð "
+~n 9,10 0 0361 &ntilde;
+ñ "
+`o 7,11 0 0362 &ograve;
+ò "
+'o 7,11 0 0363 &oacute;
+ó "
+^o 7,11 0 0364 &ocirc;
+ô "
+~o 7,10 0 0365 &otilde;
+õ "
+:o 7,10 0 0366 &ouml;
+ö "
+di 9,7 0 0367 &divide;
+÷ "
+/o 7,8,1 0 0370 &oslash;
+ø "
+`u 9,11 0 0371 &ugrave;
+ù "
+'u 9,11 0 0372 &uacute;
+ú "
+^u 9,11 0 0373 &ucirc;
+û "
+:u 9,10 0 0374 &uuml;
+ü "
+'y 8,11,3 0 0375 &yacute;
+ý "
+Tp 8,11,3 0 0376 &thorn;
+þ "
+:y 8,10,3 0 0377 &yuml;
+ÿ "
diff --git a/font/devhtml/S b/font/devhtml/S
new file mode 100755
index 00000000..59af889e
--- /dev/null
+++ b/font/devhtml/S
@@ -0,0 +1,226 @@
+name S
+special
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,10 0 041
+fa 9,10 0 042
+# 7,10 0 043
+sh "
+te 8,10 0 044
+% 12,10 0 045
+& 11,10 0 046
+st 6,7 0 047
+( 5,10,3 0 050
+) 5,10,3 0 051
+** 7,8 0 052
++ 8,7 0 053
+pl "
+, 3,2,2 0 054
+\- 8,4 0 055
+mi "
+. 3,2 0 056
+/ 4,10 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 8,7 0 074
+= 8,5 0 075
+eq "
+> 8,7 0 076
+? 6,10 0 077
+=~ 8,7 0 0100
+*A 11,10 0 0101
+*B 9,10 0 0102
+*X 11,10 0 0103
+*D 9,10 0 0104
+*E 9,10 0 0105
+*F 11,10 0 0106
+*G 9,10 0 0107
+*Y 11,10 0 0110
+*I 5,10 0 0111
++h 9,10 0 0112
+*K 10,10 0 0113
+*L 10,10 0 0114
+*M 13,10 0 0115
+*N 11,10 0 0116
+*O 10,10 0 0117
+*P 11,10 0 0120
+*H 10,10 0 0121
+*R 8,10 0 0122
+*S 9,10 0 0123
+*T 9,10 0 0124
+--- 9,10 0 0125
+ts 7,7,3 0 0126
+*W 11,10 0 0127
+*C 9,10 0 0130
+*Q 11,10 0 0131
+*Z 9,10 0 0132
+[ 5,10,3 0 0133
+lB "
+tf 10,7 0 0134
+3d "
+] 5,10,3 0 0135
+rB "
+pp 10,10 0 0136
+_ 7,0,3 0 0137
+radicalex 7,12 0 0140
+*a 9,7 0 0141
+*b 8,11,3 0 0142
+*x 8,7,3 0 0143
+*d 7,11 0 0144
+*e 6,7 0 0145
+*f 9,10,3 0 0146
+*g 6,7,3 0 0147
+*y 8,7,3 0 0150
+*i 5,7 0 0151
++f 9,7,3 0 0152
+*k 8,7 0 0153
+*l 8,10 0 0154
+*m 8,7,2 0 0155
+µ "
+*n 8,7 0 0156
+*o 8,7 0 0157
+*p 8,7 0 0160
+*h 7,10 0 0161
+*r 8,7,3 0 0162
+*s 8,7 0 0163
+*t 6,7 0 0164
+*u 8,7 0 0165
++p 11,8 0 0166
+*w 11,7 0 0167
+*c 7,12,3 0 0170
+*q 9,7,3 0 0171
+*z 7,11,3 0 0172
+lC 7,10,3 0 0173
+{ "
+ba 3,10,3 0 0174
+or "
+| "
+rC 7,10,3 0 0175
+} "
+ap 8,5 0 0176
+*U 9,10 0 0241
+fm 4,10 0 0242
+<= 8,9 0 0243
+f/ 4,10 0 0244
+if 10,6 0 0245
+Fn 7,10,3 0 0246
+CL 11,7 0 0247
+DI 11,7 0 0250
+HE 11,7 0 0251
+SP 11,7 0 0252
+<> 15,7 0 0253
+<- 14,7 0 0254
+ua 9,12,3 0 0255
+arrowverttp "
+-> 14,7 0 0256
+da 9,12,3 0 0257
+arrowvertbt "
+de 6,10 0 0260
+° "
++- 8,9 0 0261
+± "
+sd 6,10 0 0262
+>= 8,9 0 0263
+mu 8,7 0 0264
+× "
+pt 10,6 0 0265
+pd 7,11 0 0266
+bu 7,6 0 0267
+di 8,7 0 0270
+÷ "
+!= 8,7 0 0271
+== 8,6 0 0272
+~= 8,7 0 0273
+~~ "
+--- 15,2 0 0274
+arrowvertex 9,12,3 0 0275
+an 15,4 0 0276
+CR 10,9 0 0277
+Ah 12,10 0 0300
+Im 10,11,1 0 0301
+Re 12,11 0 0302
+wp 12,9,3 0 0303
+c* 11,9 0 0304
+c+ 11,9 0 0305
+es 12,11 0 0306
+ca 10,7 0 0307
+cu 10,7 0 0310
+sp 10,7 0 0311
+ip 10,7,2 0 0312
+--- 10,8,1 0 0313
+sb 10,7 0 0314
+ib 10,7,2 0 0315
+mo 10,7 0 0316
+nm 10,8,1 0 0317
+/_ 11,10 0 0320
+gr 10,11 0 0321
+rg 12,10 0 0322
+co 12,10 0 0323
+tm 11,10 0 0324
+--- 12,11,1 0 0325
+sr 8,12 0 0326
+md 4,5 0 0327
+no 10,5 0 0330
+¬ "
+AN 9,7 0 0331
+OR 9,7 0 0332
+hA 15,7 0 0333
+lA 14,7 0 0334
+uA 9,12 0 0335
+rA 14,7 0 0336
+dA 9,12 0 0337
+lz 7,11 0 0340
+la 5,12,3 0 0341
+--- 12,10 0 0342
+--- 12,10 0 0343
+--- 11,10 0 0344
+--- 10,11,1 0 0345
+parenlefttp 6,12,3 0 0346
+parenleftex 6,12,3 0 0347
+parenleftbt 6,12,3 0 0350
+bracketlefttp 6,12,3 0 0351
+lc "
+bracketleftex 6,12,3 0 0352
+bracketleftbt 6,12,3 0 0353
+lf "
+bracelefttp 7,12,3 0 0354
+lt "
+braceleftmid 7,12,3 0 0355
+lk "
+braceleftbt 7,12,3 0 0356
+lb "
+bracerightex 7,12,3 0 0357
+braceleftex "
+bv "
+--- 12,12 0 0360
+ra 5,12,3 0 0361
+is 4,12,1 0 0362
+--- 10,12,3 0 0363
+--- 10,12,3 0 0364
+--- 10,12,3 0 0365
+parenrighttp 6,12,3 0 0366
+parenrightex 6,12,3 0 0367
+parenrightbt 6,12,3 0 0370
+bracketrighttp 6,12,3 0 0371
+rc "
+bracketrightex 6,12,3 0 0372
+bracketrightbt 6,12,3 0 0373
+rf "
+bracerighttp 7,12,3 0 0374
+rt "
+bracerightmid 7,12,3 0 0375
+rk "
+bracerightbt 7,12,3 0 0376
+rb "
diff --git a/font/devhtml/TB b/font/devhtml/TB
new file mode 100755
index 00000000..0c31f24d
--- /dev/null
+++ b/font/devhtml/TB
@@ -0,0 +1,306 @@
+name TB
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,10 0 041
+" 7,10 0 042 &quot;
+# 7,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 14,10 0 045
+& 12,10 0 046 &amp;
+' 4,10 0 047
+( 5,10,3 0 050
+) 5,10,3 0 051
+* 7,10 0 052
++ 8,7 0 053
+, 3,2,2 0 054
+\- 9,4 0 055
+. 3,2 0 056
+/ 4,10 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 8,7 0 074 &lt;
+= 8,5 0 075
+eq "
+> 8,7 0 076 &gt;
+? 7,10 0 077
+@ 14,10,2 0 0100
+at "
+A 10,10 0 0101
+B 9,10 0 0102
+C 10,10 0 0103
+D 10,10 0 0104
+E 9,10 0 0105
+F 8,10 0 0106
+G 11,10 0 0107
+H 11,10 0 0110
+I 5,10 0 0111
+J 7,10,1 0 0112
+K 11,10 0 0113
+L 9,10 0 0114
+M 13,10 0 0115
+N 10,10 0 0116
+O 11,10 0 0117
+P 9,10 0 0120
+Q 11,10,3 0 0121
+R 10,10 0 0122
+S 8,10 0 0123
+T 9,10 0 0124
+U 10,10 0 0125
+V 10,10 0 0126
+W 14,10 0 0127
+X 10,10 0 0130
+Y 10,10 0 0131
+Z 9,10 0 0132
+[ 5,10,3 0 0133
+lB "
+\ 4,10 0 0134
+rs "
+] 5,10,3 0 0135
+rB "
+^ 8,10 0 0136
+a^ "
+ha "
+_ 7,0,3 0 0137
+` 4,10 0 0140
+oq "
+a 7,7 0 0141
+b 8,10 0 0142
+c 6,7 0 0143
+d 7,10 0 0144
+e 6,7 0 0145
+f 5,10 0 0146
+g 7,7,3 0 0147
+h 8,10 0 0150
+i 4,10 0 0151
+j 4,10,3 0 0152
+k 8,10 0 0153
+l 4,10 0 0154
+m 12,7 0 0155
+n 8,7 0 0156
+o 7,7 0 0157
+p 8,7,3 0 0160
+q 7,7,3 0 0161
+r 6,7 0 0162
+s 6,7 0 0163
+t 5,9 0 0164
+u 7,7 0 0165
+v 7,7 0 0166
+w 10,7 0 0167
+x 7,7 0 0170
+y 7,7,3 0 0171
+z 6,7 0 0172
+{ 7,10,3 0 0173
+lC "
+| 3,10,2 0 0174
+or "
+ba "
+} 7,10,3 0 0175
+rC "
+~ 8,7 0 0176
+a~ "
+ap "
+ti "
+r! 4,7,3 0 0241 &iexcl;
+¡ "
+ct 7,9,2 0 0242 &cent;
+¢ "
+Po 8,10 0 0243 &pound;
+£ "
+Cs 8,8 0 0244 &curren;
+¤ "
+Ye 8,10 0 0245 &yen;
+¥ "
+bb 3,10,2 0 0246 &brvbar;
+¦ "
+sc 7,10,2 0 0247 &sect;
+§ "
+ad 5,10 0 0250 &uml;
+¨ "
+co 12,10 0 0251 &copy;
+© "
+Of 5,10 0 0252 &ordf;
+ª "
+Fo 9,6 0 0253 &laquo;
+« "
+no 9,5 0 0254 &not;
+¬ "
+- 4,4 0 055 &shy;
+hy " &shy;
+­ "
+rg 12,10 0 0256 &reg;
+® "
+a- 5,9 0 0257 &macr;
+¯ "
+de 6,10 0 0260 &deg;
+° "
++- 8,9 0 0261 &plusmn;
+± "
+S2 4,10 0 0262 &sup2;
+² "
+S3 4,10 0 0263 &sup3;
+³ "
+aa 5,11 0 0264 &acute;
+´ "
+µ 7,7,3 0 0265 &micro;
+ps 8,10,3 0 0266 &para;
+¶ "
+md 4,6 0 0267 &middot;
+· "
+ac 5,0,3 0 0270 &cedil;
+¸ "
+S1 4,10 0 0271 &sup1;
+¹ "
+Om 5,10 0 0272 &ordm;
+º "
+Fc 9,6 0 0273 &raquo;
+» "
+14 10,10 0 0274 &frac14;
+¼ "
+12 10,10 0 0275 &frac12;
+½ "
+34 10,10 0 0276 &frac34;
+¾ "
+r? 7,7,3 0 0277 &iquest;
+¿ "
+`A 10,14 0 0300 &Agrave;
+À "
+'A 10,14 0 0301 &Aacute;
+Á "
+^A 10,14 0 0302 &Acirc;
+Â "
+~A 10,13 0 0303 &Atilde;
+Ã "
+:A 10,13 0 0304 &Auml;
+Ä "
+oA 10,14 0 0305 &Aring;
+Å "
+AE 14,10 0 0306 &AElig;
+Æ "
+,C 10,10,3 0 0307 &Ccedil;
+Ç "
+`E 9,14 0 0310 &Egrave;
+È "
+'E 9,14 0 0311 &Eacute;
+É "
+^E 9,14 0 0312 &Ecirc;
+Ê "
+:E 9,13 0 0313 &Euml;
+Ë "
+`I 5,14 0 0314 &Igrave;
+Ì "
+'I 5,14 0 0315 &Iacute;
+Í "
+^I 5,14 0 0316 &Icirc;
+Î "
+:I 5,13 0 0317 &Iuml;
+Ï "
+-D 11,10 0 0320 &ETH;
+Ð "
+~N 10,13 0 0321 &Ntilde;
+Ñ "
+`O 11,14 0 0322 &Ograve;
+Ò "
+'O 11,14 0 0323 &Oacute;
+Ó "
+^O 11,14 0 0324 &Ocirc;
+Ô "
+~O 11,13 0 0325 &Otilde;
+Õ "
+:O 11,13 0 0326 &Ouml;
+Ö "
+mu 8,7 0 0327 &times;
+× "
+/O 11,11,1 0 0330 &Oslash;
+Ø "
+`U 10,14 0 0331 &Ugrave;
+Ù "
+'U 10,14 0 0332 &Uacute;
+Ú "
+^U 10,14 0 0333 &Ucirc;
+Û "
+:U 10,13 0 0334 &Uuml;
+Ü "
+'Y 10,14 0 0335 &Yacute;
+Ý "
+TP 9,10 0 0336 &THORN;
+Þ "
+ss 8,10 0 0337 &szlig;
+ß "
+`a 7,11 0 0340 &agrave;
+à "
+'a 7,11 0 0341 &aacute;
+á "
+^a 7,11 0 0342 &acirc;
+â "
+~a 7,10 0 0343 &atilde;
+ã "
+:a 7,10 0 0344 &auml;
+ä "
+oa 7,11 0 0345 &aring;
+å "
+ae 11,7 0 0346 &aelig;
+æ "
+,c 7,7,3 0 0347 &ccedil;
+ç "
+`e 7,11 0 0350 &egrave;
+è "
+'e 7,11 0 0351 &eacute;
+é "
+^e 7,11 0 0352 &ecirc;
+ê "
+:e 7,10 0 0353 &euml;
+ë "
+`i 4,11 0 0354 &igrave;
+ì "
+'i 4,11 0 0355 &iacute;
+í "
+^i 4,11 0 0356 &icirc;
+î "
+:i 4,10 0 0357 &iuml;
+ï "
+Sd 7,10 0 0360 &eth;
+ð "
+~n 8,10 0 0361 &ntilde;
+ñ "
+`o 7,11 0 0362 &ograve;
+ò "
+'o 7,11 0 0363 &oacute;
+ó "
+^o 7,11 0 0364 &ocirc;
+ô "
+~o 7,10 0 0365 &otilde;
+õ "
+:o 7,10 0 0366 &ouml;
+ö "
+di 8,7 0 0367 &divide;
+÷ "
+/o 7,8,1 0 0370 &oslash;
+ø "
+`u 7,11 0 0371 &ugrave;
+ù "
+'u 7,11 0 0372 &uacute;
+ú "
+^u 7,11 0 0373 &ucirc;
+û "
+:u 7,10 0 0374 &uulm;
+ü "
+'y 7,11,3 0 0375 &yacute;
+ý "
+Tp 8,10,3 0 0376 &thorn;
+þ "
+:y 7,10,3 0 0377 &yuml;
+ÿ "
diff --git a/font/devhtml/TBI b/font/devhtml/TBI
new file mode 100755
index 00000000..56c55cf3
--- /dev/null
+++ b/font/devhtml/TBI
@@ -0,0 +1,306 @@
+name TBI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 7,10 0 041
+" 7,10 0 042
+# 8,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 14,10 0 045
+& 10,10 0 046
+' 5,10 0 047
+( 6,10,3 0 050
+) 6,10,3 0 051
+* 7,10 0 052
++ 9,7 0 053
+, 4,2,2 0 054
+\- 9,4 0 055
+. 3,2 0 056
+/ 6,10 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 5,7 0 072
+; 4,7,2 0 073
+< 8,6 0 074
+= 10,5 0 075
+eq "
+> 8,6 0 076
+? 8,10 0 077
+@ 15,10,2 0 0100
+at "
+A 9,10 0 0101
+B 9,10 0 0102
+C 9,10 0 0103
+D 10,10 0 0104
+E 10,10 0 0105
+F 9,10 0 0106
+G 10,10 0 0107
+H 11,10 0 0110
+I 5,10 0 0111
+J 7,10,1 0 0112
+K 11,10 0 0113
+L 9,10 0 0114
+M 13,10 0 0115
+N 11,10 0 0116
+O 10,10 0 0117
+P 9,10 0 0120
+Q 10,10,3 0 0121
+R 10,10 0 0122
+S 8,10 0 0123
+T 10,10 0 0124
+U 10,10 0 0125
+V 10,10 0 0126
+W 13,10 0 0127
+X 9,10 0 0130
+Y 8,10 0 0131
+Z 8,10 0 0132
+[ 6,10,3 0 0133
+lB "
+\ 6,10 0 0134
+rs "
+] 5,10,3 0 0135
+rB "
+^ 8,10 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 5,10 0 0140
+oq "
+a 8,7 0 0141
+b 7,10 0 0142
+c 6,7 0 0143
+d 7,10 0 0144
+e 7,7 0 0145
+f 5,10,3 0 0146
+g 6,7,3 0 0147
+h 8,10 0 0150
+i 4,10 0 0151
+j 4,10,3 0 0152
+k 7,10 0 0153
+l 4,10 0 0154
+m 11,7 0 0155
+n 8,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 6,7 0 0162
+s 6,7 0 0163
+t 4,9 0 0164
+u 7,7 0 0165
+v 6,7 0 0166
+w 9,7 0 0167
+x 6,7 0 0170
+y 6,7,3 0 0171
+z 6,7 0 0172
+{ 7,10,3 0 0173
+lC "
+| 4,10 0 0174
+or "
+ba "
+} 7,10,3 0 0175
+rC "
+~ 10,5 0 0176
+a~ "
+ap "
+ti "
+r! 7,7,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 7,10 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 7,10 0 0245
+¥ "
+bb 4,10 0 0246
+¦ "
+sc 8,10,3 0 0247
+§ "
+ad 6,9 0 0250
+¨ "
+co 12,10 0 0251
+© "
+Of 6,10 0 0252
+ª "
+Fo 8,6 0 0253
+« "
+no 9,5 0 0254
+¬ "
+- 5,4 0 055
+hy "
+­ "
+rg 12,10 0 0256
+® "
+a- 6,9 0 0257
+¯ "
+de 6,10 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 4,10 0 0262
+² "
+S3 4,10 0 0263
+³ "
+aa 6,10 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 8,10,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 4,10 0 0271
+¹ "
+Om 6,10 0 0272
+º "
+Fc 8,6 0 0273
+» "
+14 10,10 0 0274
+¼ "
+12 10,10 0 0275
+½ "
+34 10,10 0 0276
+¾ "
+r? 8,7,3 0 0277
+¿ "
+`A 9,13 0 0300
+À "
+'A 9,13 0 0301
+Á "
+^A 9,13 0 0302
+Â "
+~A 9,13 0 0303
+Ã "
+:A 9,13 0 0304
+Ä "
+oA 9,13 0 0305
+Å "
+AE 14,10 0 0306
+Æ "
+,C 9,10,3 0 0307
+Ç "
+`E 10,13 0 0310
+È "
+'E 10,13 0 0311
+É "
+^E 10,13 0 0312
+Ê "
+:E 10,13 0 0313
+Ë "
+`I 5,13 0 0314
+Ì "
+'I 5,13 0 0315
+Í "
+^I 5,13 0 0316
+Î "
+:I 5,13 0 0317
+Ï "
+-D 10,10 0 0320
+Ð "
+~N 11,13 0 0321
+Ñ "
+`O 10,13 0 0322
+Ò "
+'O 10,13 0 0323
+Ó "
+^O 10,13 0 0324
+Ô "
+~O 10,13 0 0325
+Õ "
+:O 10,13 0 0326
+Ö "
+mu 9,7 0 0327
+× "
+/O 10,11,1 0 0330
+Ø "
+`U 10,13 0 0331
+Ù "
+'U 10,13 0 0332
+Ú "
+^U 10,13 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 8,13 0 0335
+Ý "
+TP 9,10 0 0336
+Þ "
+ss 7,10,3 0 0337
+ß "
+`a 8,10 0 0340
+à "
+'a 8,10 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,10 0 0343
+ã "
+:a 8,10 0 0344
+ä "
+oa 8,11 0 0345
+å "
+ae 11,7 0 0346
+æ "
+,c 6,7,3 0 0347
+ç "
+`e 7,10 0 0350
+è "
+'e 7,10 0 0351
+é "
+^e 7,11 0 0352
+ê "
+:e 7,10 0 0353
+ë "
+`i 4,10 0 0354
+ì "
+'i 4,10 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,10 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 8,10 0 0361
+ñ "
+`o 7,10 0 0362
+ò "
+'o 7,10 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,10 0 0366
+ö "
+di 9,7 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 7,10 0 0371
+ù "
+'u 7,10 0 0372
+ú "
+^u 7,11 0 0373
+û "
+:u 7,10 0 0374
+ü "
+'y 6,10,2 0 0375
+ý "
+Tp 7,10,3 0 0376
+þ "
+:y 6,10,2 0 0377
+ÿ "
diff --git a/font/devhtml/TI b/font/devhtml/TI
new file mode 100755
index 00000000..c400a0ef
--- /dev/null
+++ b/font/devhtml/TI
@@ -0,0 +1,306 @@
+name TI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 5,10 0 041
+" 6,10 0 042 &quot;
+# 7,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 12,10 0 045
+& 11,10 0 046 &amp;
+' 5,10 0 047
+( 5,10,3 0 050
+) 5,10,3 0 051
+* 7,10 0 052
++ 10,7 0 053
+, 4,2,1 0 054
+\- 9,4 0 055
+. 3,2 0 056
+/ 4,10 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 4,7 0 072
+; 4,7,1 0 073
+< 10,7,1 0 074 &lt;
+= 10,5 0 075
+eq "
+> 10,7,1 0 076 &gt;
+? 7,10 0 077
+@ 13,10,3 0 0100
+at "
+A 9,10 0 0101
+B 8,10 0 0102
+C 9,10 0 0103
+D 10,10 0 0104
+E 9,10 0 0105
+F 9,10 0 0106
+G 10,10 0 0107
+H 10,10 0 0110
+I 5,10 0 0111
+J 6,10 0 0112
+K 10,10 0 0113
+L 8,10 0 0114
+M 12,10 0 0115
+N 11,10 0 0116
+O 10,10 0 0117
+P 9,10 0 0120
+Q 10,10,3 0 0121
+R 9,10 0 0122
+S 7,10 0 0123
+T 8,10 0 0124
+U 10,10 0 0125
+V 9,10 0 0126
+W 11,10 0 0127
+X 9,10 0 0130
+Y 8,10 0 0131
+Z 8,10 0 0132
+[ 6,10,3 0 0133
+lB "
+\ 4,10 0 0134
+rs "
+] 6,10,3 0 0135
+rB "
+^ 6,10 0 0136
+a^ "
+ha "
+_ 7,0,4 0 0137
+` 5,10 0 0140
+oq "
+a 7,7 0 0141
+b 7,10 0 0142
+c 6,7 0 0143
+d 7,10 0 0144
+e 7,7 0 0145
+f 5,10,3 0 0146
+g 6,7,3 0 0147
+h 7,10 0 0150
+i 4,10 0 0151
+j 4,10,3 0 0152
+k 7,10 0 0153
+l 4,10 0 0154
+m 10,7 0 0155
+n 7,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 5,7 0 0162
+s 6,7 0 0163
+t 5,9 0 0164
+u 7,7 0 0165
+v 6,7 0 0166
+w 9,7 0 0167
+x 7,7 0 0170
+y 7,7,3 0 0171
+z 6,7 0 0172
+{ 6,10,3 0 0173
+lC "
+| 4,10,3 0 0174
+or "
+ba "
+} 6,10,3 0 0175
+rC "
+~ 8,5 0 0176
+a~ "
+ap "
+ti "
+r! 6,7,3 0 0241 &iexcl;
+¡ "
+ct 7,9,2 0 0242 &cent;
+¢ "
+Po 7,10 0 0243 &pound;
+£ "
+Cs 7,8 0 0244 &curren;
+¤ "
+Ye 7,10 0 0245 &yen;
+¥ "
+bb 4,10,3 0 0246 &brvbar;
+¦ "
+sc 7,11,2 0 0247 &sect;
+§ "
+ad 5,10 0 0250 &uml;
+¨ "
+co 12,10 0 0251 &copy;
+© "
+Of 5,10 0 0252 &ordf;
+ª "
+Fo 7,6 0 0253 &laquo;
+« "
+no 9,6 0 0254 &not;
+¬ "
+- 5,4 0 055 &shy;
+hy " &shy;
+­ "
+rg 12,10 0 0256 &reg;
+® "
+a- 5,10 0 0257 &macr;
+¯ "
+de 6,10 0 0260 &deg;
+° "
++- 10,9 0 0261 &plusmn;
+± "
+S2 4,10 0 0262 &sup2;
+² "
+S3 4,10 0 0263 &sup3;
+³ "
+aa 4,10 0 0264 &acute;
+´ "
+µ 7,7,3 0 0265 &micro;
+ps 8,10,3 0 0266 &para;
+¶ "
+md 4,4 0 0267 &middot;
+· "
+ac 5,0,3 0 0270 &cedil;
+¸ "
+S1 4,10 0 0271 &sup1;
+¹ "
+Om 5,10 0 0272 &ordm;
+º "
+Fc 7,6 0 0273 &raquo;
+» "
+14 10,10 0 0274 &frac14;
+¼ "
+12 10,10 0 0275 &frac12;
+½ "
+34 10,10 0 0276 &frac34;
+¾ "
+r? 7,7,3 0 0277 &iquest;
+¿ "
+`A 9,13 0 0300 &Agrave;
+À "
+'A 9,13 0 0301 &Aacute;
+Á "
+^A 9,13 0 0302 &Acirc;
+Â "
+~A 9,13 0 0303 &Atilde;
+Ã "
+:A 9,12 0 0304 &Auml;
+Ä "
+oA 9,13 0 0305 &Aring;
+Å "
+AE 13,10 0 0306 &AElig;
+Æ "
+,C 9,10,3 0 0307 &Ccedil;
+Ç "
+`E 9,13 0 0310 &Egrave;
+È "
+'E 9,13 0 0311 &Eacute;
+É "
+^E 9,13 0 0312 &Ecirc;
+Ê "
+:E 9,12 0 0313 &Euml;
+Ë "
+`I 5,13 0 0314 &Igrave;
+Ì "
+'I 5,13 0 0315 &Iacute;
+Í "
+^I 5,13 0 0316 &Icirc;
+Î "
+:I 5,12 0 0317 &Iuml;
+Ï "
+-D 10,10 0 0320 &ETH;
+Ð "
+~N 11,13 0 0321 &Ntilde;
+Ñ "
+`O 10,13 0 0322 &Ograve;
+Ò "
+'O 10,13 0 0323 &Oacute;
+Ó "
+^O 10,13 0 0324 &Ocirc;
+Ô "
+~O 10,13 0 0325 &Otilde;
+Õ "
+:O 10,12 0 0326 &Ouml;
+Ö "
+mu 10,7 0 0327 &times;
+× "
+/O 10,11,1 0 0330 &Oslash;
+Ø "
+`U 10,13 0 0331 &Ugrave;
+Ù "
+'U 10,13 0 0332 &Uacute;
+Ú "
+^U 10,13 0 0333 &Ucirc;
+Û "
+:U 10,12 0 0334 &Uuml;
+Ü "
+'Y 8,13 0 0335 &Yacute;
+Ý "
+TP 9,10 0 0336 &THORN;
+Þ "
+ss 7,10,3 0 0337 &szlig;
+ß "
+`a 7,10 0 0340 &agrave;
+à "
+'a 7,10 0 0341 &aacute;
+á "
+^a 7,11 0 0342 &acirc;
+â "
+~a 7,10 0 0343 &atilde;
+ã "
+:a 7,9 0 0344 &auml;
+ä "
+oa 7,10 0 0345 &aring;
+å "
+ae 10,7 0 0346 &aelig;
+æ "
+,c 6,7,3 0 0347 &ccedil;
+ç "
+`e 7,10 0 0350 &egrave;
+è "
+'e 7,10 0 0351 &eacute;
+é "
+^e 7,11 0 0352 &ecirc;
+ê "
+:e 7,9 0 0353 &euml;
+ë "
+`i 4,10 0 0354 &igrave;
+ì "
+'i 4,10 0 0355 &iacute;
+í "
+^i 4,11 0 0356 &icirc;
+î "
+:i 4,9 0 0357 &iuml;
+ï "
+Sd 7,10 0 0360 &eth;
+ð "
+~n 7,10 0 0361 &ntilde;
+ñ "
+`o 7,10 0 0362 &ograve;
+ò "
+'o 7,10 0 0363 &oacute;
+ó "
+^o 7,11 0 0364 &ocirc;
+ô "
+~o 7,10 0 0365 &otilde;
+õ "
+:o 7,9 0 0366 &ouml;
+ö "
+di 10,7 0 0367 &divide;
+÷ "
+/o 7,8,1 0 0370 &oslash;
+ø "
+`u 7,10 0 0371 &ugrave;
+ù "
+'u 7,10 0 0372 &uacute;
+ú "
+^u 7,11 0 0373 &ucirc;
+û "
+:u 7,9 0 0374 &uulm;
+ü "
+'y 7,10,3 0 0375 &yacute;
+ý "
+Tp 7,10,3 0 0376 &thorn;
+þ "
+:y 7,9,3 0 0377 &yuml;
+ÿ "
diff --git a/font/devhtml/TR b/font/devhtml/TR
new file mode 100755
index 00000000..ff1076ff
--- /dev/null
+++ b/font/devhtml/TR
@@ -0,0 +1,306 @@
+name TR
+spacewidth 3
+charset
+--- 3,1 0 040
+! 5,10 0 041
+" 6,10 0 042 &quot;
+# 7,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 12,10 0 045
+& 11,10 0 046 &amp;
+' 4,10 0 047
+( 5,10,3 0 050
+) 5,10,3 0 051
+* 7,10 0 052
++ 8,7 0 053
+, 4,1,2 0 054
+\- 9,4 0 055
+. 4,1 0 056
+/ 4,10,2 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 8,7 0 074 &lt;
+= 8,5 0 075
+eq "
+> 8,7 0 076 &gt;
+? 6,10 0 077
+@ 13,10,2 0 0100
+at "
+A 11,10 0 0101
+B 9,10 0 0102
+C 10,10 0 0103
+D 10,10 0 0104
+E 9,10 0 0105
+F 8,10 0 0106
+G 11,10 0 0107
+H 10,10 0 0110
+I 5,10 0 0111
+J 6,10 0 0112
+K 10,10 0 0113
+L 9,10 0 0114
+M 13,10 0 0115
+N 11,10 0 0116
+O 10,10 0 0117
+P 8,10 0 0120
+Q 10,10,3 0 0121
+R 9,10 0 0122
+S 8,10 0 0123
+T 9,10 0 0124
+U 10,10 0 0125
+V 9,10 0 0126
+W 13,10 0 0127
+X 10,10 0 0130
+Y 9,10 0 0131
+Z 8,10 0 0132
+[ 5,10,3 0 0133
+lB "
+\ 4,10 0 0134
+rs "
+] 5,10,3 0 0135
+rB "
+^ 7,10 0 0136
+a^ "
+ha "
+_ 7,0,3 0 0137
+` 4,10 0 0140
+oq "
+a 7,7 0 0141
+b 7,10 0 0142
+c 7,7 0 0143
+d 7,10 0 0144
+e 7,7 0 0145
+f 4,10 0 0146
+g 7,7,3 0 0147
+h 7,10 0 0150
+i 3,10 0 0151
+j 4,10,3 0 0152
+k 7,10 0 0153
+l 3,10 0 0154
+m 11,7 0 0155
+n 7,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 5,7 0 0162
+s 6,7 0 0163
+t 4,8 0 0164
+u 7,7 0 0165
+v 7,7 0 0166
+w 11,7 0 0167
+x 7,7 0 0170
+y 7,7,3 0 0171
+z 6,7 0 0172
+{ 7,10,3 0 0173
+lC "
+| 3,10 0 0174
+or "
+ba "
+} 7,10,3 0 0175
+rC "
+~ 8,5 0 0176
+a~ "
+ap "
+ti "
+r! 5,7,3 0 0241 &iexcl;
+¡ "
+ct 7,8,1 0 0242 &cent;
+¢ "
+Po 8,10 0 0243 &pound;
+£ "
+Cs 7,8 0 0244 &curren;
+¤ "
+Ye 7,10 0 0245 &yen;
+¥ "
+bb 3,10 0 0246 &brvbar;
+¦ "
+sc 7,10,3 0 0247 &sect;
+§ "
+ad 5,10 0 0250 &uml;
+¨ "
+co 12,10 0 0251 &copy;
+© "
+Of 4,10 0 0252 &ordf;
+ª "
+Fo 7,6 0 0253 &laquo;
+« "
+no 9,6 0 0254 &not;
+¬ "
+- 4,4 0 0255 &shy;
+hy 4,4 0 0255 &shy;
+­ "
+rg 12,10 0 0256 &reg;
+® "
+a- 4,9 0 0257 &macr;
+¯ "
+de 6,10 0 0260 &deg;
+° "
++- 8,7 0 0261 &plusmn;
+± "
+S2 4,10 0 0262 &sup2;
+² "
+S3 4,10 0 0263 &sup3;
+³ "
+aa 5,11 0 0264 &acute;
+´ "
+µ 7,7,3 0 0265 &micro;
+ps 7,10,3 0 0266 &para;
+¶ "
+md 4,5 0 0267 &middot;
+· "
+ac 5,0,3 0 0270 &cedil;
+¸ "
+S1 4,10 0 0271 &sup1;
+¹ "
+Om 5,10 0 0272 &ordm;
+º "
+Fc 7,6 0 0273 &raquo;
+» "
+14 10,10 0 0274 &frac14;
+¼ "
+12 10,10 0 0275 &frac12;
+½ "
+34 10,10 0 0276 &frac34;
+¾ "
+r? 6,7,3 0 0277 &iquest;
+¿ "
+`A 11,14 0 0300 &Agrave;
+À "
+'A 11,14 0 0301 &Aacute;
+Á "
+^A 11,14 0 0302 &Acirc;
+Â "
+~A 11,14 0 0303 &Atilde;
+Ã "
+:A 11,13 0 0304 &Auml;
+Ä "
+oA 11,14 0 0305 &Aring;
+Å "
+AE 13,10 0 0306 &AElig;
+Æ "
+,C 10,10,3 0 0307 &Ccedil;
+Ç "
+`E 9,14 0 0310 &Egrave;
+È "
+'E 9,14 0 0311 &Eacute;
+É "
+^E 9,14 0 0312 &Ecirc;
+Ê "
+:E 9,13 0 0313 &Euml;
+Ë "
+`I 5,14 0 0314 &Igrave;
+Ì "
+'I 5,14 0 0315 &Iacute;
+Í "
+^I 5,14 0 0316 &Icirc;
+Î "
+:I 5,13 0 0317 &Iuml;
+Ï "
+-D 10,10 0 0320 &ETH;
+Ð "
+~N 11,14 0 0321 &Ntilde;
+Ñ "
+`O 10,14 0 0322 &Ograve;
+Ò "
+'O 10,14 0 0323 &Oacute;
+Ó "
+^O 10,14 0 0324 &Ocirc;
+Ô "
+~O 10,14 0 0325 &Otilde;
+Õ "
+:O 10,13 0 0326 &Ouml;
+Ö "
+mu 8,7 0 0327 &times;
+× "
+/O 10,11,1 0 0330 &Oslash;
+Ø "
+`U 10,14 0 0331 &Ugrave;
+Ù "
+'U 10,14 0 0332 &Uacute;
+Ú "
+^U 10,14 0 0333 &Ucirc;
+Û "
+:U 10,13 0 0334 &Uuml;
+Ü "
+'Y 9,14 0 0335 &Yacute;
+Ý "
+TP 8,10 0 0336 &THORN;
+Þ "
+ss 7,10 0 0337 &szlig;
+ß "
+`a 7,11 0 0340 &agrave;
+à "
+'a 7,11 0 0341 &aacute;
+á "
+^a 7,11 0 0342 &acirc;
+â "
+~a 7,11 0 0343 &atilde;
+ã "
+:a 7,10 0 0344 &auml;
+ä "
+oa 7,11 0 0345 &aring;
+å "
+ae 11,7 0 0346 &aelig;
+æ "
+,c 7,7,3 0 0347 &ccedil;
+ç "
+`e 7,11 0 0350 &egrave;
+è "
+'e 7,11 0 0351 &eacute;
+é "
+^e 7,11 0 0352 &ecirc;
+ê "
+:e 7,10 0 0353 &euml;
+ë "
+`i 3,11 0 0354 &igrave;
+ì "
+'i 3,11 0 0355 &iacute;
+í "
+^i 3,11 0 0356 &icirc;
+î "
+:i 3,10 0 0357 &iuml;
+ï "
+Sd 7,10 0 0360 &eth;
+ð "
+~n 7,11 0 0361 &ntilde;
+ñ "
+`o 7,11 0 0362 &ograve;
+ò "
+'o 7,11 0 0363 &oacute;
+ó "
+^o 7,11 0 0364 &ocirc;
+ô "
+~o 7,11 0 0365 &otilde;
+õ "
+:o 7,10 0 0366 &ouml;
+ö "
+di 8,7 0 0367 &divide;
+÷ "
+/o 7,8,1 0 0370 &oslash;
+ø "
+`u 7,11 0 0371 &ugrave;
+ù "
+'u 7,11 0 0372 &uacute;
+ú "
+^u 7,11 0 0373 &ucirc;
+û "
+:u 7,10 0 0374 &uuml;
+ü "
+'y 7,11,3 0 0375 &yacute;
+ý "
+Tp 7,10,3 0 0376 &thorn;
+þ "
+:y 7,10,3 0 0377 &yuml;
+ÿ "
diff --git a/font/devlatin1/DESC.proto b/font/devlatin1/DESC.proto
new file mode 100644
index 00000000..88399ab1
--- /dev/null
+++ b/font/devlatin1/DESC.proto
@@ -0,0 +1,8 @@
+res 240
+hor 24
+vert 40
+unitwidth 10
+sizes 10 0
+fonts 4 R I B BI
+tcommand
+postpro grotty
diff --git a/font/devlatin1/Makefile.sub b/font/devlatin1/Makefile.sub
new file mode 100644
index 00000000..25de3f77
--- /dev/null
+++ b/font/devlatin1/Makefile.sub
@@ -0,0 +1,32 @@
+DEV=latin1
+FONTS=R I B BI
+DEVFILES=$(FONTS) DESC
+CLEANADD=$(FONTS) DESC
+
+RES=240
+CPI=10
+LPI=6
+
+$(FONTS): R.proto
+ @echo Making $@
+ @-rm -f $@
+ @(charwidth=`expr $(RES) / $(CPI)` ; \
+ sed -e "s/^name [A-Z]*$$/name $@/" \
+ -e "s/^\\([^ ]*\\) [0-9]+ /\\1 $$charwidth /" \
+ -e "s/^spacewidth [0-9]+$$/spacewidth $$charwidth/" \
+ -e "s/^internalname .*$$/internalname $@/" \
+ -e "/^internalname/s/BI/3/" \
+ -e "/^internalname/s/B/2/" \
+ -e "/^internalname/s/I/1/" \
+ -e "/^internalname .*[^ 0-9]/d" \
+ $(srcdir)/R.proto >$@)
+
+DESC: DESC.proto
+ @echo Making $@
+ @-rm -f $@
+ @sed -e "s/^res .*$$/res $(RES)/" \
+ -e "s/^hor .*$$/hor `expr $(RES) / $(CPI)`/" \
+ -e "s/^vert .*$$/vert `expr $(RES) / $(LPI)`/" \
+ -e "s/^fonts .*$$/fonts `set $(FONTS); echo $$#` $(FONTS)/" \
+ $(srcdir)/DESC.proto >$@
+
diff --git a/font/devlatin1/R.proto b/font/devlatin1/R.proto
new file mode 100644
index 00000000..29a88754
--- /dev/null
+++ b/font/devlatin1/R.proto
@@ -0,0 +1,353 @@
+name R
+internalname 0
+spacewidth 24
+charset
+! 24 0 0041
+" 24 0 0042
+lq "
+rq "
+# 24 0 0043
+sh "
+$ 24 0 0044
+Do "
+% 24 0 0045
+& 24 0 0046
+' 24 0 0047
+fm "
+aq "
+( 24 0 0050
+) 24 0 0051
+* 24 0 0052
+** "
++ 24 0 0053
+pl "
+, 24 0 0054
+\- 24 0 0055
+mi "
+- "
+hy "
+en "
+. 24 0 0056
+/ 24 0 0057
+sl "
+f/ "
+0 24 0 0060
+1 24 0 0061
+2 24 0 0062
+3 24 0 0063
+4 24 0 0064
+5 24 0 0065
+6 24 0 0066
+7 24 0 0067
+8 24 0 0070
+9 24 0 0071
+: 24 0 0072
+; 24 0 0073
+< 24 0 0074
+la "
+fo "
+= 24 0 0075
+eq "
+> 24 0 0076
+ra "
+fc "
+? 24 0 0077
+@ 24 0 0100
+at "
+A 24 0 0101
+*A "
+B 24 0 0102
+*B "
+C 24 0 0103
+D 24 0 0104
+E 24 0 0105
+*E "
+F 24 0 0106
+G 24 0 0107
+H 24 0 0110
+*Y "
+I 24 0 0111
+*I "
+J 24 0 0112
+K 24 0 0113
+*K "
+L 24 0 0114
+M 24 0 0115
+*M "
+N 24 0 0116
+*N "
+O 24 0 0117
+ci "
+*O "
+P 24 0 0120
+*R "
+Q 24 0 0121
+R 24 0 0122
+S 24 0 0123
+T 24 0 0124
+*T "
+U 24 0 0125
+V 24 0 0126
+W 24 0 0127
+X 24 0 0130
+*X "
+Y 24 0 0131
+*U "
+Z 24 0 0132
+*Z "
+[ 24 0 0133
+lB "
+\ 24 0 0134
+rs "
+] 24 0 0135
+rB "
+a^ 24 0 0136
+^ "
+ha "
+_ 24 0 0137
+ru "
+ul "
+` 24 0 0140
+oq "
+ga "
+a 24 0 0141
+b 24 0 0142
+c 24 0 0143
+d 24 0 0144
+e 24 0 0145
+f 24 0 0146
+g 24 0 0147
+h 24 0 0150
+i 24 0 0151
+.i "
+j 24 0 0152
+k 24 0 0153
+l 24 0 0154
+m 24 0 0155
+n 24 0 0156
+o 24 0 0157
+*o "
+p 24 0 0160
+q 24 0 0161
+r 24 0 0162
+s 24 0 0163
+t 24 0 0164
+u 24 0 0165
+v 24 0 0166
+w 24 0 0167
+x 24 0 0170
+y 24 0 0171
+z 24 0 0172
+lC 24 0 0173
+{ "
+ba 24 0 0174
+or "
+bv "
+br "
+| "
+lb "
+lc "
+lf "
+lk "
+lt "
+rb "
+rc "
+rf "
+rk "
+rt "
+rC 24 0 0175
+} "
+a~ 24 0 0176
+~ "
+ap "
+ti "
+r! 24 0 0241
+char161 "
+ct 24 0 0242
+char162 "
+Po 24 0 0243
+char163 "
+Cs 24 0 0244
+char164 "
+Ye 24 0 0245
+char165 "
+bb 24 0 0246
+char166 "
+sc 24 0 0247
+char167 "
+ad 24 0 0250
+char168 "
+co 24 0 0251
+char169 "
+Of 24 0 0252
+char170 "
+Fo 24 0 0253
+char171 "
+no 24 0 0254
+char172 "
+char173 24 0 0255
+rg 24 0 0256
+char174 "
+a- 24 0 0257
+char175 "
+de 24 0 0260
+char176 "
+ao "
++- 24 0 0261
+char177 "
+S2 24 0 0262
+char178 "
+S3 24 0 0263
+char179 "
+aa 24 0 0264
+char180 "
+*m 24 0 0265
+char181 "
+ps 24 0 0266
+char182 "
+md 24 0 0267
+char183 "
+ac 24 0 0270
+char184 "
+S1 24 0 0271
+char185 "
+Om 24 0 0272
+char186 "
+Fc 24 0 0273
+char187 "
+14 24 0 0274
+char188 "
+12 24 0 0275
+char189 "
+34 24 0 0276
+char190 "
+r? 24 0 0277
+char191 "
+`A 24 0 0300
+char192 "
+'A 24 0 0301
+char193 "
+^A 24 0 0302
+char194 "
+~A 24 0 0303
+char195 "
+:A 24 0 0304
+char196 "
+oA 24 0 0305
+char197 "
+AE 24 0 0306
+char198 "
+,C 24 0 0307
+char199 "
+`E 24 0 0310
+char200 "
+'E 24 0 0311
+char201 "
+^E 24 0 0312
+char202 "
+:E 24 0 0313
+char203 "
+`I 24 0 0314
+char204 "
+'I 24 0 0315
+char205 "
+^I 24 0 0316
+char206 "
+:I 24 0 0317
+char207 "
+-D 24 0 0320
+char208 "
+~N 24 0 0321
+char209 "
+`O 24 0 0322
+char210 "
+'O 24 0 0323
+char211 "
+^O 24 0 0324
+char212 "
+~O 24 0 0325
+char213 "
+:O 24 0 0326
+char214 "
+mu 24 0 0327
+char215 "
+/O 24 0 0330
+char216 "
+`U 24 0 0331
+char217 "
+'U 24 0 0332
+char218 "
+^U 24 0 0333
+char219 "
+:U 24 0 0334
+char220 "
+'Y 24 0 0335
+char221 "
+TP 24 0 0336
+char222 "
+ss 24 0 0337
+char223 "
+`a 24 0 0340
+char224 "
+'a 24 0 0341
+char225 "
+^a 24 0 0342
+char226 "
+~a 24 0 0343
+char227 "
+:a 24 0 0344
+char228 "
+oa 24 0 0345
+char229 "
+ae 24 0 0346
+char230 "
+,c 24 0 0347
+char231 "
+`e 24 0 0350
+char232 "
+'e 24 0 0351
+char233 "
+^e 24 0 0352
+char234 "
+:e 24 0 0353
+char235 "
+`i 24 0 0354
+char236 "
+'i 24 0 0355
+char237 "
+^i 24 0 0356
+char238 "
+:i 24 0 0357
+char239 "
+Sd 24 0 0360
+char240 "
+~n 24 0 0361
+char241 "
+`o 24 0 0362
+char242 "
+'o 24 0 0363
+char243 "
+^o 24 0 0364
+char244 "
+~o 24 0 0365
+char245 "
+:o 24 0 0366
+char246 "
+di 24 0 0367
+char247 "
+/o 24 0 0370
+char248 "
+`u 24 0 0371
+char249 "
+'u 24 0 0372
+char250 "
+^u 24 0 0373
+char251 "
+:u 24 0 0374
+char252 "
+'y 24 0 0375
+char253 "
+Tp 24 0 0376
+char254 "
+:y 24 0 0377
+char255 "
diff --git a/font/devlj4/ALBB b/font/devlj4/ALBB
new file mode 100644
index 00000000..0d1ea4ec
--- /dev/null
+++ b/font/devlj4/ALBB
@@ -0,0 +1,773 @@
+name ALBB
+spacewidth 9759
+pcltypeface 4362
+pclproportional 1
+pclweight 4
+pclstyle 0
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -2925
+P . -4389
+P , -4389
+V A -3414
+A V -3414
+T o -3414
+T r -3414
+T c -3414
+T e -3414
+T d -3414
+T s -3414
+T y -3414
+T a -3414
+T w -3414
+T u -3414
+L T -2925
+L Y -2925
+Y o -2925
+Y e -2925
+Y a -2925
+A W -2925
+W A -2925
+T A -3414
+V o -2925
+V e -2925
+V a -2439
+Y A -2925
+F A -1950
+F . -3903
+F , -3903
+A T -3414
+A Y -2925
+v . -2439
+v , -2439
+y . -2439
+y , -2439
+T . -3414
+T , -3414
+L W -2925
+P A -2439
+V . -3903
+V , -3903
+Y . -2925
+Y , -2925
+W o -2439
+W e -2439
+W a -1950
+W . -2925
+W , -2925
+r . -2925
+r , -2925
+w . -2439
+w , -2439
+Y u -1950
+A v -1461
+A y -1461
+A w -1461
+o . -975
+o , -975
+p . -1950
+p , -1950
+e . -975
+e , -975
+b . -1950
+b , -1950
+O T -2439
+O V -1950
+O Y -2439
+O . -2439
+O , -2439
+L y -975
+L O -975
+L G -486
+L C -486
+L Q -486
+P J -486
+V y -1461
+V u -1461
+V O -1950
+V G -1461
+V C -1461
+V Q -1461
+D T -2439
+D V -1461
+D Y -1950
+D . -2439
+D , -2439
+Y O -2439
+Y G -1950
+Y C -1950
+Y Q -1950
+F o -975
+F e -975
+F a -975
+O A -1461
+O W -1461
+L U -486
+R T -1461
+R V -1461
+R Y -1461
+R W -1461
+G T -486
+P o -1461
+P g -975
+P e -1461
+P a -975
+D A -975
+D W -975
+B T -1950
+B Y -1950
+B . -1950
+B , -1950
+A O -1461
+A G -975
+A C -975
+A U -975
+A Q -975
+W r -975
+W y -975
+W u -975
+W O -1461
+W G -975
+W C -975
+W Q -975
+U A -975
+U . -1950
+U , -1950
+Q A -975
+Q W -975
+f . -486
+f , -486
+T O -2439
+T G -2439
+T C -2439
+T Q -2439
+O X -1950
+L o -486
+L e -486
+L q -486
+G V -486
+G Y -486
+G W -486
+G . -486
+G , -486
+P T -486
+P V -486
+P Y -486
+D X -1461
+B V -1461
+B X -1461
+B A -975
+B W -975
+S . -1461
+S , -1461
+F O -486
+X o -1461
+X e -1461
+X y -1461
+X O -1950
+X G -1461
+X C -1461
+X Q -1461
+A o -975
+A e -975
+Q X -1461
+K o -975
+K e -975
+K y -975
+K w -975
+K O -1461
+K G -975
+K C -975
+K Q -975
+o v -486
+o y -486
+o x -486
+o w -486
+h v -486
+h y -486
+m v -486
+m y -486
+r g -975
+g . -975
+g , -975
+p v -486
+p y -486
+p x -486
+v o -486
+v g -486
+v c -486
+v d -486
+v a -486
+v q -486
+e v -486
+e y -486
+b v -486
+b y -486
+b w -486
+s . -975
+s , -975
+y o -486
+y g -486
+y c -486
+y d -486
+y a -486
+y q -486
+f g -486
+x o -486
+x c -486
+x e -486
+x d -486
+x q -486
+a v -486
+a y -486
+a w -486
+w o -486
+w g -486
+w c -486
+w d -486
+w a -486
+w q -486
+T S -1461
+R o -975
+R y -975
+R O -1461
+R G -975
+R C -975
+R U -975
+R Q -975
+G X -486
+G A -486
+P s -975
+P Z -486
+P X -486
+P W -486
+V S -1461
+S A -975
+Y S -1461
+X u -1461
+A t -975
+A c -975
+A d -975
+A u -975
+A q -975
+W S -975
+K c -975
+K u -975
+h w -486
+m w -486
+r o -975
+r c -975
+r e -975
+r d -975
+r a -975
+r q -975
+g g -486
+p w -486
+v e -486
+v s -486
+e x -486
+e w -486
+y e -486
+y s -486
+f o -486
+f c -486
+f e -486
+f d -486
+f s -486
+f a -486
+f q -486
+w e -486
+w s -486
+k o -486
+k c -486
+k v -486
+k e -486
+k d -486
+k y -486
+k w -486
+k q -486
+O Z -975
+O J -975
+L J -486
+R e -975
+R u -975
+G Z -486
+P O -486
+E O -486
+Z o -486
+Z e -486
+Z d -486
+Z y -486
+Z w -486
+Z u -486
+Z O -975
+Z G -486
+Z C -486
+Z Q -486
+D Z -486
+D J -486
+B Z -486
+B J -486
+A J -486
+J O -486
+K J -486
+t o -486
+t c -486
+t e -486
+t d -486
+t q -486
+o z -486
+r s -975
+g o -486
+g c -486
+g e -486
+g d -486
+g s -486
+g a -486
+g q -486
+p z -486
+e z -486
+z o -486
+z c -486
+z e -486
+z d -486
+z q -486
+b z -486
+k t -486
+k u -486
+O g -486
+O j -486
+R J -486
+G J -486
+C O -486
+B O -486
+U O -486
+K T -486
+K V -486
+K Y -486
+K W -486
+K U -486
+L ' -975
+T char173 -3414
+T hy -3414
+T - -3414
+T en -3414
+T em -3414
+A ' -1461
+char173 T -3414
+hy T -3414
+- T -3414
+en T -3414
+em T -3414
+Y char173 -1950
+Y hy -1950
+Y - -1950
+Y en -1950
+Y em -1950
+p ' -486
+e ' -486
+b ' -486
+a ' -486
+V char173 -1461
+V hy -1461
+V - -1461
+V en -1461
+V em -1461
+h ' -486
+m ' -486
+R ' -975
+W char173 -975
+W hy -975
+W - -975
+W en -975
+W em -975
+' d -1950
+L char173 -486
+L hy -486
+L - -486
+L en -486
+L em -486
+X char173 -1461
+X hy -1461
+X - -1461
+X en -1461
+X em -1461
+A char173 -975
+A hy -975
+A - -975
+A en -975
+A em -975
+K char173 -975
+K hy -975
+K - -975
+K en -975
+K em -975
+' s -975
+char173 X -1461
+hy X -1461
+- X -1461
+char173 A -975
+hy A -975
+- A -975
+en X -1461
+en A -975
+em X -1461
+R char173 -975
+R hy -975
+R - -975
+R en -975
+R em -975
+K ' -486
+k ' -486
+O ' -486
+Z char173 -486
+Z hy -486
+Z - -486
+Z en -486
+Z em -486
+k char173 -486
+k hy -486
+k - -486
+k en -486
+k em -486
+charset
+! 9759,20130,300 2 3617
+" 15126,20130 2 3618
+sh 17565,20430,300 2 3619
+# "
+Do 17565,21630,2370 2 3620
+$ "
+% 25857,20430,300 2 3621
+& 23907,17037,300 0 3622
+' 9759,20130 2 51751
+( 13173,20130,4365 3 3624
+) 13173,20130,4365 3 3625
+* 17565,20130 2 3626
++ 25857,15465 0 3627
+, 9759,5025,3885 0 3628
+char173 9759,10515 0 3629
+hy "
+- "
+. 9759,5430,300 0 3630
+sl 13173,20130 2 3631
+/ "
+0 17565,20430,300 2 3632
+1 17565,20430 2 3633
+2 17565,20430 2 3634
+3 17565,20130,300 2 3635
+4 17565,20130 2 3636
+5 17565,20130,300 2 3637
+6 17565,20130,300 2 3638
+7 17565,20130 2 3639
+8 17565,20430,300 2 3640
+9 17565,20430 2 3641
+: 9759,14376,300 0 3642
+; 9759,14376,3885 0 3643
+< 26346,16068 0 3644
+= 25857,13644 0 3645
+> 26346,16068 0 3646
+? 12684,20430,300 2 3647
+at 25857,21057,2679 2 3648
+@ "
+A 20490,20130 2 3649
+B 18540,20130 2 3650
+C 19029,20430,300 2 3651
+D 20490,20130 2 3652
+E 16101,20130 2 3653
+F 15126,20130 2 3654
+G 20490,20430,300 2 3655
+H 21468,20130 2 3656
+I 10245,20130 2 3657
+J 11709,20130,4380 3 3658
+K 19515,20130 2 3659
+L 15126,20130 2 3660
+M 25857,20130 2 3661
+N 22443,20130 2 3662
+O 23907,20430,300 2 3663
+P 17076,20130 2 3664
+Q 23907,20430,4095 2 3665
+R 18540,20130 2 3666
+S 14148,20430,300 2 3667
+T 16587,20130 2 3668
+U 21468,20130,300 2 3669
+V 20004,20130 2 3670
+W 25857,20130 2 3671
+X 20004,20130 2 3672
+Y 17565,20130 2 3673
+Z 17565,20130 2 3674
+lB 13173,20130,3960 2 3675
+[ "
+rs 13173,20130 2 3676
+\ "
+rB 13173,20130,3960 2 3677
+] "
+ha 13173,19758 2 51875
+_ 13173,191367,6588 3 3679
+oq 9759,20130 2 51808
+` "
+a 13173,14310,300 0 3681
+b 16101,20025 2 3682
+c 12684,14310,300 0 3683
+d 15612,20025,300 2 3684
+e 13662,14310,300 0 3685
+f 9759,20130 2 3686
+g 14637,14310,4650 1 3687
+h 15612,20025 2 3688
+i 7806,20940 2 3689
+j 7806,20940,4365 3 3690
+k 16587,20025 2 3691
+l 7806,20025 2 3692
+m 23418,14310 0 3693
+n 15612,14310 0 3694
+o 16101,14310,300 0 3695
+p 15612,14310,4365 1 3696
+q 15612,14310,4365 1 3697
+r 11220,14310 0 3698
+s 11220,14310,300 0 3699
+t 10734,17100,300 0 3700
+u 15612,14010,300 0 3701
+v 14637,14010 0 3702
+w 20979,14010 0 3703
+x 16587,14010 0 3704
+y 14637,14010,4365 1 3705
+z 12198,14010 0 3706
+lC 13173,20130,6075 3 3707
+{ "
+ba 13173,19758,6588 3 3708
+| "
+rC 13173,20130,6075 3 3709
+} "
+ti 26346,9435 0 51876
+char192 20490,25170 2 3776
+`A "
+char194 20490,25170 2 3778
+^A "
+char200 16101,25170 2 3784
+`E "
+char202 16101,25170 2 3786
+^E "
+char203 16101,26130 2 3787
+:E "
+char206 10245,25170 2 3790
+^I "
+char207 10245,26130 2 3791
+:I "
+char180 17565,20250 2 3764
+aa "
+ga 17565,20250 2 3680
+a^ 17565,20250 2 3678
+^ "
+char168 17565,20190 2 3752
+ad "
+a~ 17565,19035 2 3710
+~ "
+char217 21468,25170,300 2 3801
+`U "
+char219 21468,25170,300 2 3803
+^U "
+char221 17565,25170 2 3805
+'Y "
+char253 14637,20250,4365 3 3837
+'y "
+char176 14637,20430 2 3760
+de "
+char199 19029,20430,6270 3 3783
+,C "
+char231 12684,14310,6000 1 3815
+,c "
+char209 22443,25101 2 3793
+~N "
+char241 15612,19035 2 3825
+~n "
+char161 9759,14376,6054 1 3745
+r! "
+char191 12684,14526,6204 1 3775
+r? "
+char164 17565,15834 0 3748
+Cs "
+char163 17565,20430 2 3747
+Po "
+char165 17565,20130 2 3749
+Ye "
+char167 17565,20430,4365 3 3751
+sc "
+Fn 17565,20130 2 51871
+char162 17565,19911 2 3746
+ct "
+char226 13173,20250,300 2 3810
+^a "
+char234 13662,20250,300 2 3818
+^e "
+char244 16101,20250,300 2 3828
+^o "
+char251 15612,20250,300 2 3835
+^u "
+char225 13173,20250,300 2 3809
+'a "
+char233 13662,20250,300 2 3817
+'e "
+char243 16101,20250,300 2 3827
+'o "
+char250 15612,20250,300 2 3834
+'u "
+char224 13173,20250,300 2 3808
+`a "
+char232 13662,20250,300 2 3816
+`e "
+char242 16101,20250,300 2 3826
+`o "
+char249 15612,20250,300 2 3833
+`u "
+char228 13173,20190,300 2 3812
+:a "
+char235 13662,20190,300 2 3819
+:e "
+char246 16101,20190,300 2 3830
+:o "
+char252 15612,20190,300 2 3836
+:u "
+char197 20490,26508 2 3781
+oA "
+char238 7806,20250 2 3822
+^i "
+char216 23907,20601,366 2 3800
+/O "
+char198 26835,20130 2 3782
+AE "
+char229 13173,20655,300 2 3813
+oa "
+char237 7806,20250 2 3821
+'i "
+char248 16101,14373,330 0 3832
+/o "
+char230 20004,14310,300 0 3814
+ae "
+char196 20490,26130 2 3780
+:A "
+char236 7806,20250 2 3820
+`i "
+char214 23907,26130,300 2 3798
+:O "
+char220 21468,26130,300 2 3804
+:U "
+char201 16101,25170 2 3785
+'E "
+char239 7806,20190 2 3823
+:i "
+char223 17076,20130,300 2 3807
+ss "
+char212 23907,25170,300 2 3796
+^O "
+char193 20490,25170 2 3777
+'A "
+char195 20490,25101 2 3779
+~A "
+char227 13173,19035,300 2 3811
+~a "
+char208 21468,20130 2 3792
+-D "
+char240 16101,20025,300 2 3824
+Sd "
+char205 10245,25170 2 3789
+'I "
+char204 10245,25170 2 3788
+`I "
+char211 23907,25170,300 2 3795
+'O "
+char210 23907,25170,300 2 3794
+`O "
+char213 23907,25101,300 2 3797
+~O "
+char245 16101,19035,300 2 3829
+~o "
+vS 14148,25170,300 2 51795
+vs 11220,20250,300 2 51827
+char218 21468,25170,300 2 3802
+'U "
+:Y 17565,26130 2 51801
+char255 14637,20190,4365 3 3839
+:y "
+char222 17076,20130 2 3806
+TP "
+char254 15612,20025,4365 3 3838
+Tp "
+char181 15612,12630,4680 1 3765
+char182 17565,19635,4200 3 3766
+ps "
+char190 25857,20430,300 2 3774
+34 "
+\- 25857,10380 0 51757
+char188 25857,20430,300 2 3772
+14 "
+char189 25857,20430,300 2 3773
+12 "
+char170 12198,20430 2 3754
+Of "
+char186 12198,20430 2 3770
+Om "
+char171 13662,12450 0 3755
+Fo "
+char187 13662,12450 0 3771
+Fc "
+char177 25857,15465,6855 1 3761
+char166 13173,19083,5916 3 3750
+bb "
+char169 13173,19635 2 3753
+co "
+char172 25857,12210 0 3756
+no "
+char174 13173,19635 2 3758
+rg "
+char178 12198,20340 2 3762
+S2 "
+char179 12198,20130 2 3763
+S3 "
+char184 17565,0,6000 1 3768
+ac "
+char185 12198,20340 2 3769
+S1 "
+char215 25857,15282 0 3799
+char247 25857,16380,885 0 3831
+char183 9759,13080 0 3767
+fm 9759,20130 2 51873
+sd 15612,20130 2 51874
+dg 17565,20130,4365 3 51755
+tm 16101,17850 0 51796
+ah 17565,20250 2 51935
+ao 17565,20655 2 51930
+f/ 3903,20430,300 2 51759
+em 25857,10095 0 51789
+en 17565,10095 0 51790
+dd 17565,20130,4365 3 51773
+.i 7806,14010 0 51957
+aq 9759,20130 2 3623
+bu 13173,14226 0 51889
+'C 19029,25170,300 2 20166
+'c 12684,20250,300 2 20198
+lq 17076,20130 2 51838
+rq 17076,20130 2 51746
+Bq 17076,5025,3885 0 51772
+vz 12198,20250 2 51834
+fi 16587,20130 2 51881
+fl 16587,20130 2 51882
+ff 18540,20130 2 51883
+Fi 25371,20130 2 51884
+Fl 25371,20130 2 51885
+ij 15612,20940,4365 3 51958
+bq 9759,5025,3885 0 51756
+%0 33663,20430,300 2 51901
+char175 17565,19020 2 3759
+a- "
+ab 17565,19260 2 51926
+a. 17565,20190 2 51927
+oe 23418,14310,300 0 51823
+OE 31224,20430,300 2 51791
+fo 7806,12450 0 51886
+fc 7806,12450 0 51887
+sq 19029,15624 0 51899
+/L 16587,20130 2 51944
+/l 12684,20025 2 51960
+a" 17565,20250 2 51933
+ho 17565,348,5838 1 51934
+vZ 17565,25170 2 51802
+IJ 21954,20130,4380 3 51942
diff --git a/font/devlj4/ALBR b/font/devlj4/ALBR
new file mode 100644
index 00000000..4e384ded
--- /dev/null
+++ b/font/devlj4/ALBR
@@ -0,0 +1,788 @@
+name ALBR
+spacewidth 8295
+pcltypeface 4362
+pclproportional 1
+pclweight 1
+pclstyle 0
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -2925
+P . -4389
+P , -4389
+V A -4389
+A V -4389
+T o -3903
+T r -3903
+T c -3903
+T e -3903
+T d -3903
+T s -3903
+T y -3903
+T a -3903
+T w -3903
+T u -3903
+L T -2925
+L Y -2925
+Y o -3903
+Y e -3903
+Y a -2925
+A W -3414
+W A -3414
+T A -3903
+V o -2925
+V e -2925
+V a -2925
+Y A -3903
+F A -2925
+F . -3903
+F , -3903
+A T -3903
+A Y -3903
+v . -3414
+v , -3414
+y . -3414
+y , -3414
+T . -3903
+T , -3903
+L W -2925
+P A -2925
+V . -3903
+V , -3903
+Y . -3903
+Y , -3903
+W o -2439
+W e -2439
+W a -2439
+W . -3414
+W , -3414
+r . -2925
+r , -2925
+w . -3414
+w , -3414
+Y u -1950
+A v -2439
+A y -2439
+A w -2439
+o . -1950
+o , -1950
+p . -1950
+p , -1950
+e . -975
+e , -975
+b . -1950
+b , -1950
+O T -2439
+O V -2439
+O Y -2439
+O . -2439
+O , -2439
+L y -1461
+L O -1461
+L G -975
+L C -975
+L Q -975
+P J -486
+V y -1950
+V u -1950
+V O -2439
+V G -1950
+V C -1950
+V Q -1950
+D T -2439
+D V -1950
+D Y -1950
+D . -2439
+D , -2439
+Y O -2439
+Y G -1950
+Y C -1950
+Y Q -1950
+F o -975
+F e -975
+F a -975
+O A -2439
+O W -1950
+L U -975
+R T -1461
+R V -1461
+R Y -1461
+R W -1461
+G T -1461
+P o -1461
+P g -975
+P e -1461
+P a -975
+D A -1950
+D W -1461
+B T -1950
+B Y -1950
+B . -1950
+B , -1950
+A O -2439
+A G -1950
+A C -1950
+A U -1950
+A Q -1950
+W r -1461
+W y -1461
+W u -1461
+W O -1950
+W G -1461
+W C -1461
+W Q -1461
+Q A -1950
+Q W -1461
+f . -486
+f , -486
+T O -2439
+T G -2439
+T C -2439
+T Q -2439
+O X -1461
+L o -975
+L e -975
+L q -975
+G V -1461
+G Y -1461
+G W -1461
+G . -486
+G , -486
+P T -486
+P V -486
+P Y -486
+D X -975
+B V -1950
+B X -975
+B A -1950
+B W -1461
+S . -1461
+S , -1461
+F O -486
+X o -975
+X e -975
+X y -975
+X O -1461
+X G -975
+X C -975
+X Q -975
+A o -1950
+A e -1950
+Q X -975
+K o -975
+K e -975
+K y -975
+K w -975
+K O -1461
+K G -975
+K C -975
+K Q -975
+o v -486
+o y -486
+o x -486
+o w -486
+h v -486
+h y -486
+n v -486
+n y -486
+m v -486
+m y -486
+r g -975
+g . -975
+g , -975
+p v -486
+p y -486
+p x -486
+v o -486
+v g -486
+v c -486
+v d -486
+v a -486
+v q -486
+e v -486
+e y -486
+b v -486
+b y -486
+b w -486
+s . -975
+s , -975
+y o -486
+y g -486
+y c -486
+y d -486
+y a -486
+y q -486
+f g -486
+x o -486
+x c -486
+x e -486
+x d -486
+x a -486
+x q -486
+a v -486
+a y -486
+a w -486
+w o -486
+w g -486
+w c -486
+w d -486
+w a -486
+w q -486
+T S -1461
+L a -975
+R o -975
+R y -975
+R O -1461
+R G -975
+R C -975
+R U -975
+R Q -975
+G X -486
+G A -486
+P Z -486
+P X -486
+P W -486
+V S -1461
+S T -975
+S V -975
+S Y -975
+S X -975
+S A -1461
+S W -975
+Y S -1461
+X a -975
+X u -975
+A t -975
+A c -1950
+A d -1950
+A a -975
+A u -1950
+A q -1950
+W S -1461
+K c -975
+K u -975
+o f -486
+h w -486
+n w -486
+m w -486
+r o -975
+r c -975
+r e -975
+r d -975
+r a -975
+r q -975
+g g -486
+p f -486
+p w -486
+v e -486
+e f -486
+e x -486
+e w -486
+b f -486
+y e -486
+f o -486
+f c -486
+f e -486
+f d -486
+f a -486
+f q -486
+w e -486
+k o -486
+k c -486
+k v -486
+k e -486
+k d -486
+k y -486
+k a -486
+k w -486
+k q -486
+O Z -975
+O J -975
+L J -486
+R e -975
+R a -975
+R u -975
+G Z -486
+P O -486
+E O -486
+Z o -486
+Z e -486
+Z d -486
+Z y -486
+Z a -486
+Z w -486
+Z u -486
+Z O -975
+Z G -486
+Z C -486
+Z Q -486
+D Z -486
+D J -486
+B Z -486
+B J -486
+S Z -486
+S J -486
+A J -486
+J O -486
+K a -975
+K J -486
+o z -486
+h f -486
+n f -486
+m f -486
+g o -486
+g c -486
+g e -486
+g d -486
+g a -486
+g q -486
+p z -486
+e z -486
+z o -486
+z c -486
+z e -486
+z d -486
+z a -486
+z q -486
+b z -486
+a f -486
+k t -486
+k f -486
+k u -486
+O g -486
+O j -486
+R J -486
+G J -486
+C O -486
+B O -486
+A f -486
+U O -486
+K T -486
+K V -486
+K Y -486
+K W -486
+K U -486
+L ' -2925
+T char173 -3903
+T hy -3903
+T - -3903
+T en -3903
+T em -3903
+A ' -2925
+char173 T -3903
+hy T -3903
+- T -3903
+en T -3903
+em T -3903
+Y char173 -1950
+Y hy -1950
+Y - -1950
+Y en -1950
+Y em -1950
+p ' -1950
+e ' -975
+b ' -1950
+a ' -1461
+V char173 -1950
+V hy -1950
+V - -1950
+V en -1950
+V em -1950
+h ' -1950
+n ' -1950
+m ' -1950
+R ' -975
+W char173 -1461
+W hy -1461
+W - -1461
+W en -1461
+W em -1461
+' d -1950
+L char173 -975
+L hy -975
+L - -975
+L en -975
+L em -975
+X char173 -975
+X hy -975
+X - -975
+X en -975
+X em -975
+A char173 -1950
+A hy -1950
+A - -1950
+A en -1950
+A em -1950
+K char173 -975
+K hy -975
+K - -975
+K en -975
+K em -975
+char173 X -975
+hy X -975
+- X -975
+char173 A -1950
+hy A -1950
+- A -1950
+en X -975
+en A -1950
+em X -975
+R char173 -975
+R hy -975
+R - -975
+R en -975
+R em -975
+K ' -486
+b f -486
+k ' -486
+O ' -486
+Z char173 -486
+Z hy -486
+Z - -486
+Z en -486
+Z em -486
+k char173 -486
+k hy -486
+k - -486
+k en -486
+k em -486
+charset
+! 8295,20130,300 2 3617
+" 13173,20130 2 3618
+sh 16587,20430,300 2 3619
+# "
+Do 16587,21909,2490 2 3620
+$ "
+% 24882,20430,300 2 3621
+& 22932,16869,300 0 3622
+' 8295,20130 2 51751
+( 10734,20130,4365 3 3624
+) 10734,20130,4365 3 3625
+* 16587,20130 2 3626
++ 24882,15420,60 0 3627
+, 8295,3945,5055 1 3628
+char173 8295,9795 0 3629
+hy "
+- "
+. 8295,4080,300 0 3630
+sl 11709,20130 2 3631
+/ "
+0 16587,20430,300 2 3632
+1 16587,20430 2 3633
+2 16587,20430 2 3634
+3 16587,20130,300 2 3635
+4 16587,20130 2 3636
+5 16587,20130,300 2 3637
+6 16587,20130,300 2 3638
+7 16587,20130 2 3639
+8 16587,20430,300 2 3640
+9 16587,20430 2 3641
+: 8295,12372,300 0 3642
+; 8295,12372,5055 1 3643
+< 26346,16068 0 3644
+= 24882,11880 0 3645
+> 26346,16068 0 3646
+? 12198,20430,300 2 3647
+at 24882,21030,2745 2 3648
+@ "
+A 20979,20430 2 3649
+B 15126,20130 2 3650
+C 18051,20430,300 2 3651
+D 18540,20130 2 3652
+E 14637,20130 2 3653
+F 13662,20130 2 3654
+G 20490,20430,300 2 3655
+H 20004,20130 2 3656
+I 8295,20130 2 3657
+J 10734,20130,4488 3 3658
+K 18051,20130 2 3659
+L 14148,20130 2 3660
+M 24396,20130 2 3661
+N 21468,20130 2 3662
+O 22932,20430,300 2 3663
+P 13662,20130 2 3664
+Q 22932,20430,4152 3 3665
+R 16587,20130 2 3666
+S 13662,20430,300 2 3667
+T 16587,20130 2 3668
+U 20979,20130,300 2 3669
+V 20490,20130 2 3670
+W 24882,20430 2 3671
+X 18051,20130 2 3672
+Y 17076,20130 2 3673
+Z 16101,20130 2 3674
+lB 11220,20130,4365 3 3675
+[ "
+rs 11709,20130 2 3676
+\ "
+rB 11220,20130,4365 3 3677
+] "
+ha 13173,19758 2 51875
+_ 13173,191367,6588 3 3679
+oq 8295,20130 2 51808
+` "
+a 12198,14310,300 0 3681
+b 14148,20025 2 3682
+c 12198,14310,300 0 3683
+d 14637,20025,300 2 3684
+e 12684,14310,300 0 3685
+f 8295,20130 2 3686
+g 12684,14310,4479 1 3687
+h 14148,20025 2 3688
+i 6342,19815 2 3689
+j 6342,19815,4365 3 3690
+k 12684,20025 2 3691
+l 6342,20025 2 3692
+m 21954,14310 0 3693
+n 14148,14310 0 3694
+o 14637,14310,300 0 3695
+p 14637,14310,4365 1 3696
+q 14148,14310,4365 1 3697
+r 9759,14310 0 3698
+s 9270,14310,300 0 3699
+t 8781,16950,300 0 3700
+u 14148,14010,300 0 3701
+v 12684,14010 0 3702
+w 18540,14010 0 3703
+x 12684,14010 0 3704
+y 13173,14010,4365 1 3705
+z 10245,14010 0 3706
+lC 11709,20130,6075 3 3707
+{ "
+ba 13173,19758,6588 3 3708
+| "
+rC 11709,20130,6075 3 3709
+} "
+ti 26346,8952 0 51876
+char192 20979,24960 2 3776
+`A "
+char194 20979,24960 2 3778
+^A "
+char200 14637,24960 2 3784
+`E "
+char202 14637,24960 2 3786
+^E "
+char203 14637,25020 2 3787
+:E "
+char206 8295,24960 2 3790
+^I "
+char207 8295,25020 2 3791
+:I "
+char180 16587,19785 2 3764
+aa "
+ga 16587,19785 2 3680
+a^ 16587,19785 2 3678
+^ "
+char168 16587,19140 2 3752
+ad "
+a~ 16587,18507 2 3710
+~ "
+char217 20979,24960,300 2 3801
+`U "
+char219 20979,24960,300 2 3803
+^U "
+char221 17076,24960 2 3805
+'Y "
+char253 13173,19785,4365 3 3837
+'y "
+char176 13662,20430 2 3760
+de "
+char199 18051,20430,6330 3 3783
+,C "
+char231 12198,14310,6006 1 3815
+,c "
+char209 21468,24783 2 3793
+~N "
+char241 14148,18507 2 3825
+~n "
+char161 8295,14346,6084 1 3745
+r! "
+char191 12198,14496,6234 1 3775
+r? "
+char164 16587,15684 0 3748
+Cs "
+char163 16587,20430 2 3747
+Po "
+char165 16587,20130 2 3749
+Ye "
+char167 16587,20430,4365 3 3751
+sc "
+Fn 16587,20130 2 51871
+char162 16587,19968 2 3746
+ct "
+char226 12198,19785,300 2 3810
+^a "
+char234 12684,19785,300 2 3818
+^e "
+char244 14637,19785,300 2 3828
+^o "
+char251 14148,19785,300 2 3835
+^u "
+char225 12198,19785,300 2 3809
+'a "
+char233 12684,19785,300 2 3817
+'e "
+char243 14637,19785,300 2 3827
+'o "
+char250 14148,19785,300 2 3834
+'u "
+char224 12198,19785,300 2 3808
+`a "
+char232 12684,19785,300 2 3816
+`e "
+char242 14637,19785,300 2 3826
+`o "
+char249 14148,19785,300 2 3833
+`u "
+char228 12198,19140,300 2 3812
+:a "
+char235 12684,19140,300 2 3819
+:e "
+char246 14637,19140,300 2 3830
+:o "
+char252 14148,19140,300 2 3836
+:u "
+char197 20979,26154 2 3781
+oA "
+char238 6342,19785 2 3822
+^i "
+char216 22932,20454,300 2 3800
+/O "
+char198 25857,20130 2 3782
+AE "
+char229 12198,20160,300 2 3813
+oa "
+char237 6342,19785 2 3821
+'i "
+char248 14637,14316,300 0 3832
+/o "
+char230 19515,14310,300 0 3814
+ae "
+char196 20979,25020 2 3780
+:A "
+char236 6342,19785 2 3820
+`i "
+char214 22932,25020,300 2 3798
+:O "
+char220 20979,25020,300 2 3804
+:U "
+char201 14637,24960 2 3785
+'E "
+char239 6342,19140 2 3823
+:i "
+char223 15612,20130,300 2 3807
+ss "
+char212 22932,24960,300 2 3796
+^O "
+char193 20979,24960 2 3777
+'A "
+char195 20979,24783 2 3779
+~A "
+char227 12198,18507,300 2 3811
+~a "
+char208 20004,20130 2 3792
+-D "
+char240 14637,20025,300 2 3824
+Sd "
+char205 8295,24960 2 3789
+'I "
+char204 8295,24960 2 3788
+`I "
+char211 22932,24960,300 2 3795
+'O "
+char210 22932,24960,300 2 3794
+`O "
+char213 22932,24783,300 2 3797
+~O "
+char245 14637,18507,300 2 3829
+~o "
+vS 13662,24960,300 2 51795
+vs 9270,19785,300 2 51827
+char218 20979,24960,300 2 3802
+'U "
+:Y 17076,25020 2 51801
+char255 13173,19140,4365 3 3839
+:y "
+char222 13662,20130 2 3806
+TP "
+char254 14637,20025,4365 3 3838
+Tp "
+char181 14637,12630,4350 1 3765
+char182 16587,19635,4200 3 3766
+ps "
+char190 24882,20430,300 2 3774
+34 "
+\- 24882,9405 0 51757
+char188 24882,20430,300 2 3772
+14 "
+char189 24882,20430,300 2 3773
+12 "
+char170 10245,20430 2 3754
+Of "
+char186 10245,20430 2 3770
+Om "
+char171 12198,12450 0 3755
+Fo "
+char187 12198,12450 0 3771
+Fc "
+char177 24882,15420,5175 1 3761
+char166 13173,19083,5916 3 3750
+bb "
+char169 13173,19635 2 3753
+co "
+char172 24882,12135 0 3756
+no "
+char174 13173,19635 2 3758
+rg "
+char178 10245,20340 2 3762
+S2 "
+char179 10245,20130 2 3763
+S3 "
+char184 16587,309,6006 1 3768
+ac "
+char185 10245,20340 2 3769
+S1 "
+char215 24882,15990,279 0 3799
+char247 24882,15090 0 3831
+char183 8295,12330 0 3767
+fm 8295,20130 2 51873
+sd 14148,20130 2 51874
+dg 16587,20130,4365 3 51755
+tm 16101,17850 0 51796
+ah 16587,19785 2 51935
+ao 16587,20160 2 51930
+f/ 3414,20430,300 2 51759
+em 24882,9525 0 51789
+en 16587,9525 0 51790
+dd 16587,20130,4365 3 51773
+.i 6342,14010 0 51957
+aq 8295,20130 2 3623
+bu 13173,14226 0 51889
+'C 18051,24960,300 2 20166
+'c 12198,19785,300 2 20198
+lq 14148,20130 2 51838
+rq 14148,20130 2 51746
+Bq 14148,3900,5100 1 51772
+vz 10245,19785 2 51834
+fi 14148,20130 2 51881
+fl 14148,20130 2 51882
+ff 15612,20130 2 51883
+Fi 21468,20130 2 51884
+Fl 21468,20130 2 51885
+ij 12684,19815,4365 3 51958
+bq 8295,3900,5100 1 51756
+%0 33177,20430,300 2 51901
+char175 16587,18603 2 3759
+a- "
+ab 16587,19110 2 51926
+a. 16587,19140 2 51927
+oe 22443,14310,300 0 51823
+OE 26346,20430,300 2 51791
+fo 6831,12450 0 51886
+fc 6831,12450 0 51887
+sq 19029,15624 0 51899
+/L 16101,20130 2 51944
+/l 9270,20025 2 51960
+a" 16587,19785 2 51933
+ho 16587,297,6417 1 51934
+vZ 16101,24960 2 51802
+IJ 18051,20130,4488 3 51942
diff --git a/font/devlj4/AOB b/font/devlj4/AOB
new file mode 100644
index 00000000..954d8afb
--- /dev/null
+++ b/font/devlj4/AOB
@@ -0,0 +1,744 @@
+name AOB
+spacewidth 8781
+pcltypeface 4168
+pclproportional 1
+pclweight 3
+pclstyle 0
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -1461
+P . -5364
+P , -5364
+V A -1950
+A V -1950
+T o -2439
+T c -1950
+T e -1950
+T d -1950
+T s -1461
+T a -1950
+T J -2925
+L T -2925
+L Y -3414
+Y o -3414
+Y e -2925
+Y a -2925
+Y J -2925
+A W -1461
+W A -1461
+T A -2439
+V o -1461
+V e -1461
+V a -1461
+Y A -2925
+F A -486
+F . -3903
+F , -3903
+A T -2439
+A Y -2925
+v . -2925
+v , -2925
+y . -3414
+y , -3414
+T . -3414
+T , -3414
+L W -975
+P A -975
+V J -2925
+V . -3414
+V , -3414
+Y . -3903
+Y , -3903
+W o -975
+W e -975
+W a -975
+W . -2439
+W , -2439
+r . -3414
+r , -3414
+w . -2925
+w , -2925
+Y u -975
+A v -1461
+A y -1461
+A w -1461
+o . -2439
+o , -2439
+p . -1950
+p , -1950
+e . -1461
+e , -1461
+b . -2439
+b , -2439
+O T -486
+O V -975
+O Y -1461
+O . -1950
+O , -1950
+L y -975
+P J -2925
+V y -486
+V u -486
+V O -975
+V G -975
+V C -975
+V Q -975
+D T -486
+D V -975
+D Y -1461
+D . -1950
+D , -1950
+Y O -1461
+Y G -1461
+Y C -1461
+Y Q -1461
+c . -1461
+c , -1461
+O A -486
+O W -975
+R V -486
+R Y -975
+R W -486
+G T -486
+P o -486
+P g -486
+P e -486
+P a -486
+C . -486
+C , -486
+D A -486
+D W -975
+B Y -975
+B . -1461
+B , -1461
+F J -2925
+A O -486
+A G -486
+A C -486
+A U -486
+A Q -486
+W r -486
+W y -486
+W u -486
+W O -975
+W G -975
+W C -975
+W J -1950
+W Q -975
+J A -486
+J . -1950
+J , -1950
+U A -486
+U . -1950
+U , -1950
+Q A -486
+Q W -975
+f . -1461
+f , -1461
+T O -486
+T G -486
+T C -486
+T Q -486
+O X -486
+G V -975
+G Y -1461
+G W -975
+G . -1950
+G , -1950
+P V -486
+P Y -975
+C V -486
+C Y -975
+D X -486
+B V -486
+B X -486
+B A -486
+B W -486
+S . -1461
+S , -1461
+X o -486
+X e -486
+X y -486
+X O -486
+X G -486
+X C -486
+X Q -486
+A o -486
+A e -486
+Q X -486
+K o -486
+K e -486
+K y -486
+K w -486
+K O -486
+K G -486
+K C -486
+K Q -486
+o v -975
+o y -975
+o x -486
+o w -975
+h v -975
+h y -975
+n v -975
+n y -975
+m v -975
+m y -975
+g . -486
+g , -486
+p v -975
+p y -975
+p x -486
+c v -975
+c y -975
+c w -975
+v o -975
+v g -975
+v c -975
+v d -975
+v a -975
+v q -975
+e v -975
+e y -975
+b v -975
+b y -975
+b w -975
+s . -975
+s , -975
+y o -975
+y g -975
+y c -975
+y d -975
+y a -975
+y q -975
+x o -486
+x g -486
+x c -486
+x e -486
+x d -486
+x a -486
+x q -486
+a v -975
+a y -975
+a w -975
+w o -975
+w g -975
+w c -975
+w d -975
+w a -975
+w q -975
+R o -1461
+R O -486
+R G -486
+R C -486
+R Q -486
+G X -486
+G A -486
+P s -486
+P X -486
+P W -486
+C W -486
+V S -486
+S V -486
+S Y -975
+S X -486
+S A -486
+S W -486
+Y S -975
+X a -486
+X u -486
+X S -486
+A t -486
+A g -486
+A c -486
+A d -486
+A a -486
+A u -486
+A q -486
+A S -486
+W S -486
+K c -486
+K u -486
+K S -486
+t . -486
+t , -486
+h w -975
+h . -486
+h , -486
+n w -975
+n . -486
+n , -486
+m w -975
+m . -486
+m , -486
+l . -486
+l , -486
+i . -486
+i , -486
+p w -975
+c x -486
+v e -975
+v s -975
+e x -486
+e w -975
+z . -486
+z , -486
+d . -486
+d , -486
+s v -975
+s y -975
+s x -486
+s w -975
+y e -975
+y s -975
+x s -486
+x . -486
+x , -486
+a . -486
+a , -486
+w e -975
+w s -975
+j . -486
+j , -486
+u . -486
+k o -486
+k g -486
+k c -486
+k e -486
+k d -486
+k a -486
+k q -486
+k . -486
+k , -486
+O Z -486
+O J -1461
+H . -486
+H , -486
+N . -486
+N , -486
+M . -486
+M , -486
+L . -486
+L , -486
+R e -1461
+R a -975
+R . -486
+R , -486
+G Z -486
+I . -486
+I , -486
+P O -486
+P G -486
+P C -486
+P Q -486
+E . -486
+E , -486
+Z o -1950
+Z e -1950
+Z d -1950
+Z s -486
+Z a -975
+Z O -486
+Z G -486
+Z C -486
+Z Q -486
+Z . -486
+Z , -486
+D Z -486
+D J -1461
+B J -975
+S J -975
+X . -486
+X , -486
+A s -486
+A . -486
+A , -486
+J J -1461
+U J -1461
+K a -486
+K . -486
+K , -486
+k s -486
+G J -1461
+A f -486
+A ' -486
+Y char173 -975
+Y hy -975
+Y - -975
+Y en -975
+Y em -975
+V char173 -486
+V hy -486
+V - -486
+V en -486
+V em -486
+W char173 -486
+W hy -486
+W - -486
+W en -486
+W em -486
+X char173 -486
+X hy -486
+X - -486
+X en -486
+X em -486
+A char173 -486
+A hy -486
+A - -486
+A en -486
+A em -486
+K char173 -486
+K hy -486
+K - -486
+K en -486
+K em -486
+char173 X -486
+hy X -486
+- X -486
+char173 A -486
+hy A -486
+- A -486
+en X -486
+en A -486
+em X -486
+charset
+! 9759,20205,450 2 3617
+" 12198,19755 2 3618
+sh 17565,20730,3630 3 3619
+# "
+Do 17565,22980,3855 3 3620
+$ "
+% 30249,20505,450 2 3621
+& 21468,20205,450 2 3622
+' 6831,19755 2 51751
+( 8781,19755 2 3624
+) 8781,19755 2 3625
+* 17565,20205 2 3626
++ 30249,15450,600 0 3627
+, 8781,4080,4710 1 3628
+char173 8781,10965 0 3629
+hy "
+- "
+. 8781,4170,450 0 3630
+sl 10734,20820,450 2 3631
+/ "
+0 17565,20505,450 2 3632
+1 17565,20055 2 3633
+2 17565,20505 2 3634
+3 17565,20055,450 2 3635
+4 17565,20055 2 3636
+5 17565,20055,450 2 3637
+6 17565,20505,450 2 3638
+7 17565,20055 2 3639
+8 17565,20505,450 2 3640
+9 17565,20505,450 2 3641
+: 8781,15783,450 0 3642
+; 8781,15783,4710 1 3643
+< 26346,16068 0 3644
+= 30249,12984 0 3645
+> 26346,16068 0 3646
+? 16101,20205,450 2 3647
+at 30249,21057,2679 2 3648
+@ "
+A 20004,19755 2 3649
+B 18051,19755 2 3650
+C 17076,20205,450 2 3651
+D 19515,19755 2 3652
+E 16101,19755 2 3653
+F 16101,19755 2 3654
+G 18540,20205,450 2 3655
+H 19515,19755 2 3656
+I 8295,19755 2 3657
+J 13662,19755,450 2 3658
+K 18540,19755 2 3659
+L 14637,19755 2 3660
+M 24396,19755 2 3661
+N 20004,19755 2 3662
+O 20004,20205,450 2 3663
+P 18540,19755 2 3664
+Q 20004,20205,3075 2 3665
+R 18051,19755 2 3666
+S 15612,20205,450 2 3667
+T 17076,19755 2 3668
+U 19029,19755,450 2 3669
+V 19029,19755 2 3670
+W 27321,19755 2 3671
+X 19029,19755 2 3672
+Y 19029,19755 2 3673
+Z 17565,19755 2 3674
+lB 8781,19755 2 3675
+[ "
+rs 10734,20820,450 2 3676
+\ "
+rB 8781,19755 2 3677
+] "
+ha 13173,19758 2 51875
+_ 13173,191367,6588 3 3679
+oq 6831,19755 2 51808
+` "
+a 17076,17205,450 0 3681
+b 19029,20820,450 2 3682
+c 15612,17205,450 0 3683
+d 19029,20820,450 2 3684
+e 17565,17205,450 0 3685
+f 13662,20820 2 3686
+g 19029,17205,3930 1 3687
+h 19029,20820 2 3688
+i 8781,21855 2 3689
+j 8781,21855,3930 3 3690
+k 17076,20820 2 3691
+l 8295,20820 2 3692
+m 27810,17205 0 3693
+n 19029,17205 0 3694
+o 18540,17205,450 0 3695
+p 19029,17205,3930 1 3696
+q 19029,17205,3930 1 3697
+r 13662,17205 0 3698
+s 14637,17205,450 0 3699
+t 14148,20970,450 2 3700
+u 18540,16755,450 0 3701
+v 17565,16755 0 3702
+w 26346,16755 0 3703
+x 17565,16755 0 3704
+y 17565,16755,3930 1 3705
+z 15126,16755 0 3706
+lC 13173,20130,6075 3 3707
+{ "
+ba 13173,19758,6588 3 3708
+| "
+rC 13173,20130,6075 3 3709
+} "
+ti 26346,9435 0 51876
+char192 20004,24930 2 3776
+`A "
+char194 20004,24930 2 3778
+^A "
+char200 16101,24930 2 3784
+`E "
+char202 16101,24930 2 3786
+^E "
+char203 16101,25050 2 3787
+:E "
+char206 8295,24930 2 3790
+^I "
+char207 8295,25050 2 3791
+:I "
+char180 17565,22125 2 3764
+aa "
+ga 17565,22125 2 3680
+a^ 17565,22125 2 3678
+^ "
+char168 17565,22125 2 3752
+ad "
+a~ 17565,22521 2 3710
+~ "
+char217 19029,24930,450 2 3801
+`U "
+char219 19029,24930,450 2 3803
+^U "
+char221 19029,24930 2 3805
+'Y "
+char253 17565,22125,3930 3 3837
+'y "
+char176 17565,20505 2 3760
+de "
+char199 17076,20205,5988 3 3783
+,C "
+char231 15612,17205,5988 1 3815
+,c "
+char209 20004,25161 2 3793
+~N "
+char241 19029,22521 2 3825
+~n "
+char161 9759,17115,3540 1 3745
+r! "
+char191 16101,17106,3549 1 3775
+r? "
+char164 17565,15834 0 3748
+Cs "
+char163 17565,20505 2 3747
+Po "
+char165 17565,20055 2 3749
+Ye "
+char167 17565,20205,3930 3 3751
+sc "
+Fn 17565,20820 2 51871
+char162 17565,21603,1890 2 3746
+ct "
+char226 17076,22125,450 2 3810
+^a "
+char234 17565,22125,450 2 3818
+^e "
+char244 18540,22125,450 2 3828
+^o "
+char251 18540,22125,450 2 3835
+^u "
+char225 17076,22125,450 2 3809
+'a "
+char233 17565,22125,450 2 3817
+'e "
+char243 18540,22125,450 2 3827
+'o "
+char250 18540,22125,450 2 3834
+'u "
+char224 17076,22125,450 2 3808
+`a "
+char232 17565,22125,450 2 3816
+`e "
+char242 18540,22125,450 2 3826
+`o "
+char249 18540,22125,450 2 3833
+`u "
+char228 17076,22125,450 2 3812
+:a "
+char235 17565,22125,450 2 3819
+:e "
+char246 18540,22125,450 2 3830
+:o "
+char252 18540,22125,450 2 3836
+:u "
+char197 20004,27354 2 3781
+oA "
+char238 8781,22125 2 3822
+^i "
+char216 20004,20205,450 2 3800
+/O "
+char198 30249,19755 2 3782
+AE "
+char229 17076,24825,450 2 3813
+oa "
+char237 8781,22125 2 3821
+'i "
+char248 18540,17205,450 0 3832
+/o "
+char230 27321,17205,450 0 3814
+ae "
+char196 20004,25050 2 3780
+:A "
+char236 8781,22125 2 3820
+`i "
+char214 20004,25050,450 2 3798
+:O "
+char220 19029,25050,450 2 3804
+:U "
+char201 16101,24930 2 3785
+'E "
+char239 8781,22125 2 3823
+:i "
+char223 18540,20820,450 2 3807
+ss "
+char212 20004,24930,450 2 3796
+^O "
+char193 20004,24930 2 3777
+'A "
+char195 20004,25161 2 3779
+~A "
+char227 17076,22521,450 2 3811
+~a "
+char208 19515,19755 2 3792
+-D "
+char240 18540,21666,450 2 3824
+Sd "
+char205 8295,24930 2 3789
+'I "
+char204 8295,24930 2 3788
+`I "
+char211 20004,24930,450 2 3795
+'O "
+char210 20004,24930,450 2 3794
+`O "
+char213 20004,25161,450 2 3797
+~O "
+char245 18540,22521,450 2 3829
+~o "
+vS 15612,24930,450 2 51795
+vs 14637,22125,450 2 51827
+char218 19029,24930,450 2 3802
+'U "
+:Y 19029,25050 2 51801
+char255 17565,22125,3930 3 3839
+:y "
+char222 18540,19755 2 3806
+TP "
+char254 19029,20820,3930 3 3838
+Tp "
+char181 15612,12630,4680 1 3765
+char182 17565,19635,4200 1 3766
+ps "
+char190 30249,20610,555 2 3774
+34 "
+\- 30249,9375 0 51757
+char188 30249,20610,555 2 3772
+14 "
+char189 30249,20610,555 2 3773
+12 "
+char170 14637,20505 2 3754
+Of "
+char186 14637,20505 2 3770
+Om "
+char171 15612,14025 0 3755
+Fo "
+char187 15612,14025 0 3771
+Fc "
+char177 30249,15450,5895 1 3761
+char166 13173,19083,5916 1 3750
+bb "
+char169 13173,19635 0 3753
+co "
+char172 30249,11274 0 3756
+no "
+char174 13173,19635 0 3758
+rg "
+char178 11709,20385 2 3762
+S2 "
+char179 11709,20055 2 3763
+S3 "
+char184 17565,507,5988 1 3768
+ac "
+char185 11709,20055 2 3769
+S1 "
+char215 30249,15225,585 0 3799
+char247 30249,15885,1035 0 3831
+char183 8781,12759 0 3767
+fm 8781,20055 2 51873
+sd 17565,20055 2 51874
+dg 17565,20205,4095 3 51755
+tm 16101,17850 0 51796
+ah 17565,22125 2 51935
+ao 17565,24825 2 51930
+f/ 5367,20610,555 2 51759
+em 30249,10440 0 51789
+en 17565,10440 0 51790
+dd 17565,20205,4095 3 51773
+.i 8781,16755 0 51957
+aq 6831,19755 2 3623
+bu 13173,14226 0 51889
+'C 17076,24930,450 2 20166
+'c 15612,22125,450 2 20198
+lq 11220,19755 2 51838
+rq 11220,19755 2 51746
+Bq 11220,4038,3672 1 51772
+vz 15126,22125 2 51834
+fi 21954,21855 2 51881
+fl 21954,20820 2 51882
+ff 25371,20820 2 51883
+Fi 33177,21855 2 51884
+Fl 33177,20820 2 51885
+ij 17565,21855,3930 3 51958
+bq 6831,4038,3672 1 51756
+%0 34152,20505,450 2 51901
+char175 17565,21675 2 3759
+a- "
+ab 17565,22200 2 51926
+a. 17565,22590 2 51927
+oe 28785,17205,450 0 51823
+OE 28785,20205,450 2 51791
+fo 9270,14025 0 51886
+fc 9270,14025 0 51887
+sq 19029,15624 0 51899
+/L 14148,19755 2 51944
+/l 9270,20820 2 51960
+a" 17565,22125 2 51933
+ho 17565,1095,4155 1 51934
+vZ 17565,24930 2 51802
+IJ 21954,19755,450 2 51942
diff --git a/font/devlj4/AOI b/font/devlj4/AOI
new file mode 100644
index 00000000..f1b9ca71
--- /dev/null
+++ b/font/devlj4/AOI
@@ -0,0 +1,797 @@
+name AOI
+spacewidth 7806
+slant 11.150000
+pcltypeface 4168
+pclproportional 1
+pclweight 0
+pclstyle 1
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -2439
+P . -4878
+P , -4878
+V A -2439
+A V -1950
+T o -2925
+T r -1461
+T c -2925
+T e -2925
+T d -2925
+T s -2439
+T y -1461
+T a -2925
+T w -1461
+T u -1461
+T J -2925
+L T -2925
+L Y -2925
+Y o -2925
+Y e -2925
+Y a -2439
+Y J -2925
+A W -1461
+W A -1461
+T A -2925
+V o -1461
+V e -1461
+V a -1461
+Y A -2925
+F A -1461
+F . -3903
+F , -3903
+A T -2439
+A Y -2439
+v . -2439
+v , -2439
+y . -2925
+y , -2925
+T . -3414
+T , -3414
+L W -1461
+P A -975
+V J -2925
+V . -3414
+V , -3414
+Y . -3414
+Y , -3414
+W o -975
+W e -975
+W a -975
+W . -1950
+W , -1950
+r . -1950
+r , -1950
+w . -2439
+w , -2439
+Y u -975
+A v -1461
+A y -1461
+A w -975
+o . -2439
+o , -2439
+p . -2439
+p , -2439
+e . -1461
+e , -1461
+b . -2439
+b , -2439
+O T -1461
+O V -975
+O Y -1461
+O . -2439
+O , -2439
+L y -1950
+L O -2439
+L G -2439
+L C -2439
+L Q -2439
+P J -2925
+V y -975
+V u -975
+V O -975
+V G -975
+V C -975
+V Q -975
+D T -1461
+D V -975
+D Y -1461
+D . -2439
+D , -2439
+Y O -975
+Y G -975
+Y C -975
+Y Q -975
+F o -486
+F e -486
+F a -486
+c . -1461
+c , -1461
+O A -975
+O W -486
+L U -1950
+R T -975
+R V -975
+R Y -975
+R W -486
+G T -1461
+C A -486
+C . -975
+C , -975
+D A -975
+D W -486
+B T -1461
+B Y -1461
+B . -1461
+B , -1461
+F J -2925
+A O -975
+A G -975
+A C -975
+A U -975
+A Q -975
+W r -486
+W y -486
+W u -486
+W O -486
+W G -486
+W C -486
+W J -1461
+W Q -486
+J A -486
+J . -975
+J , -975
+U A -975
+U . -2439
+U , -2439
+Q W -486
+f . -2439
+f , -2439
+T O -1461
+T G -1461
+T C -1461
+T Q -1461
+O X -975
+L o -2925
+L e -2439
+L q -1950
+G V -975
+G Y -1461
+G W -486
+G . -1950
+G , -1950
+P T -1461
+P V -975
+P Y -1461
+C T -975
+C V -975
+C Y -975
+D X -975
+B V -975
+B X -975
+B A -975
+B W -486
+S . -1950
+S , -1950
+X o -975
+X e -975
+X y -975
+X O -975
+X G -975
+X C -975
+X Q -975
+A o -975
+A e -975
+K o -1461
+K e -1461
+K y -975
+K w -975
+K O -975
+K G -975
+K C -975
+K Q -975
+o v -486
+o y -486
+o x -975
+h v -486
+h y -486
+n v -486
+n y -486
+m v -486
+m y -486
+r g -486
+g . -486
+g , -486
+p v -486
+p y -486
+p x -975
+c v -486
+c y -486
+v o -486
+v g -486
+v c -486
+v d -486
+v a -486
+v q -486
+e v -486
+e y -486
+b v -975
+b y -975
+b w -486
+s . -975
+s , -975
+y o -486
+y g -486
+y c -486
+y d -486
+y a -486
+y q -486
+f g -486
+x o -975
+x c -975
+x e -975
+x d -975
+x a -975
+x q -975
+a v -486
+a y -486
+w o -486
+w g -486
+w c -486
+w d -486
+w a -486
+w q -486
+T S -1461
+L a -975
+L S -1461
+G X -975
+G A -975
+P X -975
+P W -486
+C X -486
+C W -486
+C J -486
+V S -975
+S T -1461
+S V -975
+S Y -1461
+S X -975
+S A -975
+S W -486
+Y S -975
+X a -975
+X u -975
+X S -975
+A t -975
+A c -975
+A d -975
+A a -975
+A u -975
+A q -975
+A S -975
+W S -486
+K c -1461
+K u -975
+K S -975
+t . -486
+t , -486
+h . -486
+h , -486
+n . -486
+n , -486
+m . -486
+m , -486
+l . -486
+l , -486
+r o -486
+r c -486
+r e -486
+r d -486
+r a -486
+r q -486
+i . -486
+i , -486
+c x -975
+v e -486
+v s -486
+e x -975
+z . -486
+z , -486
+d . -486
+d , -486
+b f -486
+s v -486
+s y -486
+s x -486
+y e -486
+y s -486
+f o -486
+f c -486
+f e -486
+f d -486
+f s -486
+f a -486
+f q -486
+x s -486
+x . -486
+x , -486
+a . -486
+a , -486
+w e -486
+w s -486
+j . -486
+j , -486
+u . -486
+k o -975
+k c -975
+k e -975
+k d -975
+k a -975
+k q -975
+k . -486
+k , -486
+O J -1950
+H . -486
+H , -486
+N . -486
+N , -486
+M . -486
+M , -486
+L . -486
+L , -486
+R . -486
+R , -486
+I . -486
+I , -486
+E . -486
+E , -486
+Z o -1461
+Z e -1461
+Z d -1461
+Z s -486
+Z a -975
+Z . -486
+Z , -486
+D J -1950
+B J -975
+S J -1461
+X . -486
+X , -486
+A s -486
+A . -486
+A , -486
+J J -486
+U J -1950
+K a -975
+K . -486
+K , -486
+o z -975
+r s -486
+p z -975
+c z -975
+v f -486
+e z -975
+z o -975
+z c -975
+z e -975
+z d -975
+z s -486
+z a -975
+z q -975
+b t -486
+b g -486
+b z -1461
+b j -486
+s z -486
+y f -486
+w f -486
+k s -486
+G J -1461
+L ' -3414
+T char173 -1461
+T hy -1461
+T - -1461
+T en -1461
+T em -1461
+A ' -1950
+char173 T -1461
+hy T -1461
+- T -1461
+en T -1461
+em T -1461
+Y char173 -975
+Y hy -975
+Y - -975
+Y en -975
+Y em -975
+p ' -1950
+c ' -975
+e ' -1950
+b ' -1950
+a ' -1950
+V char173 -975
+V hy -975
+V - -975
+V en -975
+V em -975
+h ' -1950
+n ' -1950
+m ' -1950
+W char173 -486
+W hy -486
+W - -486
+W en -486
+W em -486
+' d -1950
+s ' -975
+L char173 -1950
+L hy -1950
+L - -1950
+L en -1950
+L em -1950
+X char173 -975
+X hy -975
+X - -975
+X en -975
+X em -975
+A char173 -975
+A hy -975
+A - -975
+A en -975
+A em -975
+K char173 -975
+K hy -975
+K - -975
+K en -975
+K em -975
+' s -975
+char173 X -975
+hy X -975
+- X -975
+char173 A -975
+hy A -975
+- A -975
+en X -975
+en A -975
+em X -975
+b f -486
+charset
+! 7806,20160,405,1176,798,880 2 3617
+" 11709,19755,0,504,-2439,504 2 3618
+sh 15612,20460,4296,0,-936 3 3619
+# "
+Do 15612,22065,2295,1062,258,880 2 3620
+$ "
+% 26346,20460,405,0,-1734 2 3621
+& 17565,20160,405,414,381,414 2 3622
+' 7806,19755,0,744,-1851,744 2 51751
+( 7806,19755,405,3360,-270,880 2 3624
+) 7806,19755,405,618,2472,618 2 3625
+* 15612,20160,0,0,-2880 2 3626
++ 26346,15255,585,0,-3894 0 3627
+, 7806,2910,4320,0,2160 1 3628
+char173 7806,10230,0,654,468,654 0 3629
+hy "
+- "
+. 7806,2925,405,0,684 0 3630
+sl 7806,20820,405,4203,3111,880 2 3631
+/ "
+0 15612,20460,405,1371,450,880 2 3632
+1 15612,20055,0,0,-879 2 3633
+2 15612,20460,0,1173,1140,880 2 3634
+3 15612,20055,405,1743,621,880 2 3635
+4 15612,20055,0,1101,1074,880 2 3636
+5 15612,20055,405,1530,453,880 2 3637
+6 15612,20460,405,1863,-6,880 2 3638
+7 15612,20055,0,2184,-213,880 2 3639
+8 15612,20460,405,1362,708,880 2 3640
+9 15612,20460,405,1032,828,880 2 3641
+: 7806,13515,405,0,684 0 3642
+; 7806,13515,4320,0,2160 1 3643
+< 26346,16068,0,0,-3981 0 3644
+= 26346,10800,0,0,-3921 0 3645
+> 26346,16068,0,0,-3981 0 3646
+? 14148,20160,405,1497,-1323,880 2 3647
+at 26346,21030,2745,0,-1083 2 3648
+@ "
+A 18051,19755,0,0,2478 2 3649
+B 16587,19755,0,1230,765,880 2 3650
+C 16101,20160,405,1941,-36,880 2 3651
+D 19029,19755,0,516,657,516 2 3652
+E 15612,19755,0,1971,858,880 2 3653
+F 15126,19755,0,2244,807,880 2 3654
+G 18051,20160,405,1218,-144,880 2 3655
+H 19515,19755,0,1179,558,880 2 3656
+I 6831,19755,0,1557,909,880 2 3657
+J 12198,19755,405,1518,2154,880 2 3658
+K 16101,19755,0,3612,717,880 2 3659
+L 12684,19755,0,0,783 2 3660
+M 22932,19755,0,1287,729,880 2 3661
+N 19515,19755,0,1344,735,880 2 3662
+O 19029,20160,405,732,-39,732 2 3663
+P 16587,19755,0,1425,699,880 2 3664
+Q 19029,20160,993,849,-243,849 2 3665
+R 16101,19755,0,1494,744,880 2 3666
+S 14637,20160,405,1374,888,880 2 3667
+T 14637,19755,0,3165,-825,880 2 3668
+U 18540,19755,405,1449,-453,880 2 3669
+V 17076,19755,0,2931,-1407,880 2 3670
+W 25371,19755,0,3333,-1341,880 2 3671
+X 16587,19755,0,3177,2418,880 2 3672
+Y 16587,19755,0,3216,-1296,880 2 3673
+Z 16101,19755,0,2199,1347,880 2 3674
+lB 7806,19755,405,2646,699,880 2 3675
+[ "
+rs 7806,20820,405,0,-1671 2 3676
+\ "
+rB 7806,19755,405,1341,2004,880 2 3677
+] "
+ha 13173,19758,0,36,36,36 2 51875
+_ 13173,191367,6588,1317,1317,880 3 3679
+oq 7806,19755,0,1062,-2169,880 2 51808
+` "
+a 16101,17160,405,0,621 0 3681
+b 18051,20820,405,0,735 2 3682
+c 15126,17160,405,1257,114,880 0 3683
+d 18051,20820,405,1623,207,880 2 3684
+e 16587,17160,405,546,-6,546 0 3685
+f 11220,20820,0,3024,114,880 2 3686
+g 18051,17160,3930,654,102,654 1 3687
+h 18051,20820,0,0,573 2 3688
+i 6831,21105,0,2052,918,880 2 3689
+j 7317,21105,3930,1986,4662,880 3 3690
+k 14637,20820,0,2835,738,880 2 3691
+l 6831,20820,0,1794,891,880 2 3692
+m 26835,17160,0,0,735 0 3693
+n 18051,17160,0,0,567 0 3694
+o 17565,17160,405,90,-30,90 0 3695
+p 18051,17160,3930,51,1440,51 1 3696
+q 18051,17160,3930,855,216,855 1 3697
+r 11220,17160,0,2286,816,880 0 3698
+s 12684,17160,405,1206,1044,880 0 3699
+t 12198,20985,405,2229,-525,880 2 3700
+u 18051,16755,405,603,-237,603 0 3701
+v 16101,16755,0,1950,-618,880 0 3702
+w 24396,16755,0,1749,-735,880 0 3703
+x 15126,16755,0,2667,2142,880 0 3704
+y 15612,16755,3930,2085,-378,880 1 3705
+z 13662,16755,0,1953,1530,880 0 3706
+lC 11709,20130,6075,2580,-1005,880 3 3707
+{ "
+ba 13173,19758,6588,0,-4596 3 3708
+| "
+rC 11709,20130,6075,0,3153 3 3709
+} "
+ti 26346,8952,0,0,-4029 0 51876
+char192 18051,25005,0,0,2478 2 3776
+`A "
+char194 18051,25005,0,0,2478 2 3778
+^A "
+char200 15612,25005,0,1971,858,880 2 3784
+`E "
+char202 15612,25005,0,1971,858,880 2 3786
+^E "
+char203 15612,24645,0,1971,858,880 2 3787
+:E "
+char206 6831,25005,0,4425,909,880 2 3790
+^I "
+char207 6831,24645,0,4878,909,880 2 3791
+:I "
+char180 15612,22080,0,2073,-6261,880 2 3764
+aa "
+ga 15612,22080,0,0,-3054 2 3680
+a^ 15612,22080,0,0,-4680 2 3678
+^ "
+char168 15612,21795,0,0,-4674 2 3752
+ad "
+a~ 15612,21819,0,1443,-2550,880 2 3710
+~ "
+char217 18540,25005,405,1449,-453,880 2 3801
+`U "
+char219 18540,25005,405,1449,-453,880 2 3803
+^U "
+char221 16587,25005,0,3216,-1296,880 2 3805
+'Y "
+char253 15612,22080,3930,2085,-378,880 3 3837
+'y "
+char176 15612,20460,0,0,-2748 2 3760
+de "
+char199 16101,20160,6285,1941,-36,880 3 3783
+,C "
+char231 15126,17160,6285,1257,114,880 1 3815
+,c "
+char209 19515,24744,0,1344,735,880 2 3793
+~N "
+char241 18051,21819,0,222,567,222 2 3825
+~n "
+char161 7806,17157,3408,714,1260,714 0 3745
+r! "
+char191 14148,17175,3390,0,1623 0 3775
+r? "
+char164 15612,15684,0,96,-528,96 0 3748
+Cs "
+char163 15612,20460,0,2118,1011,880 2 3747
+Po "
+char165 15612,20055,0,3255,-999,880 2 3749
+Ye "
+char167 15612,20160,4095,0,-1920 3 3751
+sc "
+Fn 15612,20820,0,1578,-2127,880 2 51871
+char162 15612,20547,498,1389,-540,880 2 3746
+ct "
+char226 16101,22080,405,0,621 2 3810
+^a "
+char234 16587,22080,405,546,-6,546 2 3818
+^e "
+char244 17565,22080,405,90,-30,90 2 3828
+^o "
+char251 18051,22080,405,603,-237,603 2 3835
+^u "
+char225 16101,22080,405,1827,621,880 2 3809
+'a "
+char233 16587,22080,405,1584,-6,880 2 3817
+'e "
+char243 17565,22080,405,1095,-30,880 2 3827
+'o "
+char250 18051,22080,405,852,-237,852 2 3834
+'u "
+char224 16101,22080,405,0,621 2 3808
+`a "
+char232 16587,22080,405,546,-6,546 2 3816
+`e "
+char242 17565,22080,405,90,-30,90 2 3826
+`o "
+char249 18051,22080,405,603,-237,603 2 3833
+`u "
+char228 16101,21795,405,0,621 2 3812
+:a "
+char235 16587,21795,405,546,-6,546 2 3819
+:e "
+char246 17565,21795,405,90,-30,90 2 3830
+:o "
+char252 18051,21795,405,603,-237,603 2 3836
+:u "
+char197 18051,26850,0,0,2478 2 3781
+oA "
+char238 6831,22080,0,3831,921,880 2 3822
+^i "
+char216 19029,20205,450,2472,1920,880 2 3800
+/O "
+char198 28299,19755,0,2715,2868,880 2 3782
+AE "
+char229 16101,24390,405,0,621 2 3813
+oa "
+char237 6831,22080,0,6462,921,880 2 3821
+'i "
+char248 17565,17232,474,1710,1614,880 0 3832
+/o "
+char230 25857,17160,405,591,780,591 0 3814
+ae "
+char196 18051,24645,0,0,2478 2 3780
+:A "
+char236 6831,22080,0,1335,1338,880 2 3820
+`i "
+char214 19029,24645,405,732,-39,732 2 3798
+:O "
+char220 18540,24645,405,1449,-453,880 2 3804
+:U "
+char201 15612,25005,0,2739,858,880 2 3785
+'E "
+char239 6831,21795,0,4275,921,880 2 3823
+:i "
+char223 16101,20820,405,57,780,57 2 3807
+ss "
+char212 19029,25005,405,732,-39,732 2 3796
+^O "
+char193 18051,25005,0,1518,2478,880 2 3777
+'A "
+char195 18051,24744,0,1263,2478,880 2 3779
+~A "
+char227 16101,21819,405,1197,621,880 2 3811
+~a "
+char208 19029,19755,0,516,690,516 2 3792
+-D "
+char240 17565,21426,405,66,-36,66 2 3824
+Sd "
+char205 6831,25005,0,7128,909,880 2 3789
+'I "
+char204 6831,25005,0,2073,909,880 2 3788
+`I "
+char211 19029,25005,405,1029,-39,880 2 3795
+'O "
+char210 19029,25005,405,732,-39,732 2 3794
+`O "
+char213 19029,24744,405,774,-39,774 2 3797
+~O "
+char245 17565,21819,405,465,-30,465 2 3829
+~o "
+vS 14637,25005,405,1374,888,880 2 51795
+vs 12684,22080,405,1596,1044,880 2 51827
+char218 18540,25005,405,1449,-453,880 2 3802
+'U "
+:Y 16587,24645,0,3216,-1296,880 2 51801
+char255 15612,21795,3930,2085,-378,880 3 3839
+:y "
+char222 16587,19755,0,675,753,675 2 3806
+TP "
+char254 18051,20820,3930,51,1440,51 3 3838
+Tp "
+char181 14637,12630,4350,1122,2931,880 1 3765
+char182 15612,19635,4200,0,-1344 3 3766
+ps "
+char190 26346,20610,555,0,-1806 2 3774
+34 "
+\- 26346,8295,0,0,-3891 0 51757
+char188 26346,20610,555,0,-1755 2 3772
+14 "
+char189 26346,20610,555,0,-1998 2 3773
+12 "
+char170 15612,20460,0,0,-2658 2 3754
+Of "
+char186 15612,20460,0,0,-2451 2 3770
+Om "
+char171 13662,14145,0,2082,-45,880 0 3755
+Fo "
+char187 13662,14145,0,267,1770,267 0 3771
+Fc "
+char177 26346,15255,3900,0,-3906 1 3761
+char166 13173,19083,5916,0,-4596 3 3750
+bb "
+char169 13173,19635,0,3903,-2112,880 2 3753
+co "
+char172 26346,11679,0,0,-3984 0 3756
+no "
+char174 13173,19635,0,3903,-2112,880 2 3758
+rg "
+char178 10245,20385,0,2097,-225,880 2 3762
+S2 "
+char179 10245,20055,0,2064,-186,880 2 3763
+S3 "
+char184 15612,375,6285,0,-2349 1 3768
+ac "
+char185 10245,20055,0,0,-495 2 3769
+S1 "
+char215 26346,15189,579,0,-3957 0 3799
+char247 26346,12780,0,0,-3894 0 3831
+char183 7806,11760,0,0,-1131 0 3767
+fm 7806,20055,0,1680,-2322,880 2 51873
+sd 15612,20055,0,0,-2322 2 51874
+dg 15612,20160,4095,0,-1632 3 51755
+tm 16101,17850,0,1443,-1980,880 0 51796
+ah 15612,22080,0,132,-5370,132 2 51935
+ao 15612,24390,0,0,-6087 2 51930
+f/ 4392,20610,555,7662,7350,880 2 51759
+em 26346,9840,0,462,330,462 0 51789
+en 15612,9840,0,528,336,528 0 51790
+dd 15612,20160,4095,0,-1611 3 51773
+.i 6831,16755,0,975,921,880 0 51957
+aq 7806,19755,0,672,-2604,672 2 3623
+bu 13173,14226,0,0,-498 0 51889
+'C 16101,25005,405,2718,-36,880 2 20166
+'c 15126,22080,405,2466,114,880 2 20198
+lq 11709,19755,0,1344,-2424,880 2 51838
+rq 11709,19755,0,756,-1836,756 2 51746
+Bq 11709,2970,3315,0,1494 0 51772
+vz 13662,22080,0,1953,1530,880 2 51834
+fi 17076,21105,0,2268,-153,880 2 51881
+fl 17076,20820,0,1668,57,880 2 51882
+ff 20490,20820,0,3111,42,880 2 51883
+Fi 26346,21105,0,2331,-201,880 2 51884
+Fl 26346,20820,0,1692,48,880 2 51885
+ij 13173,21105,3930,1986,918,880 3 51958
+bq 7806,2970,3315,0,1089 0 51756
+%0 34152,20460,405,684,-159,684 2 51901
+char175 15612,21210,0,0,-5265 2 3759
+a- "
+ab 15612,22230,0,0,-5238 2 51926
+a. 15612,21795,0,0,-7032 2 51927
+oe 28299,17160,405,768,270,768 0 51823
+OE 25857,20160,405,2463,-27,880 2 51791
+fo 8781,14145,0,1689,279,880 0 51886
+fc 8781,14145,0,324,1644,324 0 51887
+sq 19029,15624,0,0,-2022 0 51899
+/L 13173,19755,0,21,1839,21 2 51944
+/l 7806,20820,0,3030,2109,880 2 51960
+a" 15612,22080,0,4503,-3531,880 2 51933
+ho 15612,765,3990,0,-6564 1 51934
+vZ 16101,25005,0,2199,1347,880 2 51802
+IJ 18540,19755,405,1518,909,880 2 51942
diff --git a/font/devlj4/AOR b/font/devlj4/AOR
new file mode 100644
index 00000000..2f2b6d79
--- /dev/null
+++ b/font/devlj4/AOR
@@ -0,0 +1,720 @@
+name AOR
+spacewidth 7806
+pcltypeface 4168
+pclproportional 1
+pclweight 0
+pclstyle 0
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -2439
+P . -4878
+P , -4878
+V A -2439
+A V -1950
+T o -2439
+T r -975
+T c -2439
+T e -2439
+T d -2925
+T s -1950
+T y -975
+T a -1950
+T w -975
+T u -975
+T J -2439
+L T -2439
+L Y -3414
+Y o -2925
+Y e -2925
+Y a -1950
+Y J -2925
+A W -1950
+W A -1950
+T A -2439
+V o -975
+V e -975
+V a -975
+Y A -3414
+F A -1950
+F . -3903
+F , -3903
+A T -2439
+A Y -3414
+v . -2925
+v , -2925
+y . -2925
+y , -2925
+T . -2925
+T , -2925
+L W -1950
+P A -1461
+V J -2439
+V . -2925
+V , -2925
+Y . -3903
+Y , -3903
+W o -975
+W e -975
+W a -975
+W . -2439
+W , -2439
+r . -3903
+r , -3903
+w . -2439
+w , -2439
+Y u -975
+A v -1461
+A y -1950
+A w -1461
+o . -2439
+o , -2439
+p . -2439
+p , -2439
+e . -1950
+e , -1950
+b . -2439
+b , -2439
+O T -975
+O Y -975
+O . -2439
+O , -2439
+L y -2439
+L O -1461
+L G -1461
+L C -1461
+L Q -1461
+P J -2925
+D T -975
+D Y -975
+D . -1950
+D , -1950
+Y O -975
+Y G -975
+Y C -975
+Y Q -975
+F o -486
+F e -486
+F a -486
+c . -1461
+c , -1461
+O A -1461
+L U -1461
+R T -486
+R Y -486
+G T -486
+C A -975
+C . -1461
+C , -1461
+D A -1461
+B T -975
+B Y -975
+B . -1461
+B , -1461
+F J -2925
+A O -975
+A G -975
+A C -975
+A U -975
+A Q -975
+W J -1950
+J A -1461
+J . -1950
+J , -1950
+U A -1461
+U . -1950
+U , -1950
+f . -2925
+f , -2925
+T O -975
+T G -975
+T C -975
+T Q -975
+L o -1461
+L e -1461
+L q -1461
+G Y -486
+G . -1461
+G , -1461
+P T -975
+P Y -975
+C T -486
+C Y -486
+B A -975
+S . -1461
+S , -1461
+X o -1950
+X e -1950
+A o -975
+A e -975
+K o -975
+K e -975
+K y -975
+K w -975
+K O -975
+K G -975
+K C -975
+K Q -975
+o v -486
+o y -975
+o x -486
+o w -486
+h v -486
+h y -975
+n v -486
+n y -975
+m v -486
+m y -975
+r g -486
+g . -486
+g , -486
+p v -486
+p y -975
+p x -486
+c v -486
+c y -975
+c w -486
+v o -486
+v g -486
+v c -486
+v d -975
+v a -486
+v q -486
+e v -486
+e y -975
+b v -1461
+b y -1950
+b w -1461
+s . -1461
+s , -1461
+y o -486
+y g -486
+y c -486
+y d -975
+y a -486
+y q -486
+x o -486
+x g -486
+x c -486
+x e -486
+x d -975
+x a -486
+x q -486
+a v -486
+a y -975
+a w -486
+w o -486
+w g -486
+w c -486
+w d -975
+w a -486
+w q -486
+T S -975
+L a -486
+L S -975
+R o -1950
+G A -975
+C J -975
+S T -975
+S Y -975
+S A -975
+Y S -975
+X a -486
+A t -486
+A g -975
+A c -975
+A d -1461
+A a -486
+A u -975
+A q -975
+A S -975
+K c -975
+K u -975
+K S -975
+t . -486
+t , -486
+h w -486
+h . -486
+h , -486
+n w -486
+n . -486
+n , -486
+m w -486
+m . -486
+m , -486
+l . -486
+l , -486
+r o -486
+r c -486
+r e -486
+r d -975
+r a -486
+r q -486
+i . -486
+i , -486
+p w -486
+c x -486
+v e -486
+v s -486
+e x -486
+e w -486
+z . -486
+z , -486
+d . -486
+d , -486
+b f -975
+y e -486
+y s -486
+f d -486
+x . -486
+x , -486
+a . -486
+a , -486
+w e -486
+w s -486
+j . -486
+j , -486
+u . -486
+k o -975
+k g -975
+k c -975
+k e -975
+k d -1461
+k a -486
+k q -975
+k . -486
+k , -486
+O J -1950
+H . -486
+H , -486
+N . -486
+N , -486
+M . -486
+M , -486
+L . -486
+L , -486
+R e -1950
+R a -486
+R . -486
+R , -486
+I . -486
+I , -486
+E d -486
+E . -486
+E , -486
+Z o -1950
+Z e -1950
+Z d -1950
+Z a -486
+Z . -486
+Z , -486
+D J -1461
+B J -975
+S J -975
+X . -486
+X , -486
+A . -486
+A , -486
+J J -1461
+U J -1461
+K a -486
+K . -486
+K , -486
+t d -486
+r s -486
+g d -486
+z d -486
+b t -975
+b g -975
+b z -975
+b j -975
+G J -975
+A f -486
+U d -486
+L ' -3903
+T char173 -975
+T hy -975
+T - -975
+T en -975
+T em -975
+A ' -2439
+char173 T -975
+hy T -975
+- T -975
+en T -975
+em T -975
+Y char173 -975
+Y hy -975
+Y - -975
+Y en -975
+Y em -975
+p ' -1950
+c ' -975
+e ' -1950
+b ' -1950
+a ' -1461
+h ' -1950
+n ' -1461
+m ' -1461
+' d -1950
+L char173 -1461
+L hy -1461
+L - -1461
+L en -1461
+L em -1461
+A char173 -975
+A hy -975
+A - -975
+A en -975
+A em -975
+K char173 -975
+K hy -975
+K - -975
+K en -975
+K em -975
+' s -975
+char173 A -1461
+hy A -1461
+- A -1461
+en A -1461
+b f -975
+charset
+! 8295,20160,405 2 3617
+" 11220,19755 2 3618
+sh 15612,20460,4296 3 3619
+# "
+Do 15612,21960,2265 2 3620
+$ "
+% 26835,20460,405 2 3621
+& 19029,20160,405 2 3622
+' 6831,19755 2 51751
+( 7806,19755,405 2 3624
+) 7806,19755,405 2 3625
+* 15612,20160 2 3626
++ 26835,15255,585 0 3627
+, 7806,2910,4320 1 3628
+char173 7806,10200 0 3629
+hy "
+- "
+. 7806,2925,405 0 3630
+sl 8295,20820,405 2 3631
+/ "
+0 15612,20460,405 2 3632
+1 15612,20055 2 3633
+2 15612,20460 2 3634
+3 15612,20055,405 2 3635
+4 15612,20055 2 3636
+5 15612,20055,405 2 3637
+6 15612,20460,405 2 3638
+7 15612,20055 2 3639
+8 15612,20460,405 2 3640
+9 15612,20460,405 2 3641
+: 7806,13647,405 0 3642
+; 7806,13647,4320 1 3643
+< 26346,16068 0 3644
+= 26835,10800 0 3645
+> 26346,16068 0 3646
+? 15126,20160,405 2 3647
+at 26835,21030,2745 2 3648
+@ "
+A 18540,19755 2 3649
+B 17565,19755 2 3650
+C 16101,20160,405 2 3651
+D 18540,19755 2 3652
+E 15612,19755 2 3653
+F 15126,19755 2 3654
+G 18051,20160,405 2 3655
+H 19515,19755 2 3656
+I 7317,19755 2 3657
+J 12198,19755,405 2 3658
+K 16587,19755 2 3659
+L 13662,19755 2 3660
+M 23418,19755 2 3661
+N 19515,19755 2 3662
+O 19029,20160,405 2 3663
+P 16587,19755 2 3664
+Q 19029,20160,636 2 3665
+R 16587,19755 2 3666
+S 14148,20160,405 2 3667
+T 15126,19755 2 3668
+U 19029,19755,405 2 3669
+V 16587,19755 2 3670
+W 25857,19755 2 3671
+X 16587,19755 2 3672
+Y 16587,19755 2 3673
+Z 16101,19755 2 3674
+lB 7806,19755,405 2 3675
+[ "
+rs 8295,20820,405 2 3676
+\ "
+rB 7806,19755,405 2 3677
+] "
+ha 13173,19758 2 51875
+_ 13173,191367,6588 3 3679
+oq 6831,19755 2 51808
+` "
+a 15126,17160,405 0 3681
+b 18540,20820,405 2 3682
+c 14637,17160,405 0 3683
+d 18540,20820,405 2 3684
+e 16587,17160,405 0 3685
+f 11709,20820 2 3686
+g 17565,17160,3930 1 3687
+h 18051,20820 2 3688
+i 7806,21105 2 3689
+j 7806,21105,3930 3 3690
+k 15126,20820 2 3691
+l 7317,20820 2 3692
+m 27321,17160 0 3693
+n 18051,17160 0 3694
+o 18051,17160,405 0 3695
+p 18540,17160,3930 1 3696
+q 18540,17160,3930 1 3697
+r 12198,17160 0 3698
+s 12198,17160,405 0 3699
+t 12198,20925,405 2 3700
+u 17565,16755,405 0 3701
+v 15612,16755 0 3702
+w 23907,16755 0 3703
+x 14637,16755 0 3704
+y 15612,16755,3930 1 3705
+z 13662,16755 0 3706
+lC 11709,20130,6075 3 3707
+{ "
+ba 13173,19758,6588 3 3708
+| "
+rC 11709,20130,6075 3 3709
+} "
+ti 26346,8952 0 51876
+char192 18540,25005 2 3776
+`A "
+char194 18540,25005 2 3778
+^A "
+char200 15612,25005 2 3784
+`E "
+char202 15612,25005 2 3786
+^E "
+char203 15612,24690 2 3787
+:E "
+char206 7317,25005 2 3790
+^I "
+char207 7317,24690 2 3791
+:I "
+char180 15612,22080 2 3764
+aa "
+ga 15612,22080 2 3680
+a^ 15612,22080 2 3678
+^ "
+char168 15612,21840 2 3752
+ad "
+a~ 15612,21873 2 3710
+~ "
+char217 19029,25005,405 2 3801
+`U "
+char219 19029,25005,405 2 3803
+^U "
+char221 16587,25005 2 3805
+'Y "
+char253 15612,22080,3930 3 3837
+'y "
+char176 15612,20460 2 3760
+de "
+char199 16101,20160,4896 3 3783
+,C "
+char231 14637,17160,4896 1 3815
+,c "
+char209 19515,24915 2 3793
+~N "
+char241 18051,21873 2 3825
+~n "
+char161 8295,17124,3441 0 3745
+r! "
+char191 15126,17124,3441 0 3775
+r? "
+char164 15612,15684 0 3748
+Cs "
+char163 15612,20460 2 3747
+Po "
+char165 15612,20055 2 3749
+Ye "
+char167 15612,20160,4095 3 3751
+sc "
+Fn 15612,20820 2 51871
+char162 15612,20526,537 2 3746
+ct "
+char226 15126,22080,405 2 3810
+^a "
+char234 16587,22080,405 2 3818
+^e "
+char244 18051,22080,405 2 3828
+^o "
+char251 17565,22080,405 2 3835
+^u "
+char225 15126,22080,405 2 3809
+'a "
+char233 16587,22080,405 2 3817
+'e "
+char243 18051,22080,405 2 3827
+'o "
+char250 17565,22080,405 2 3834
+'u "
+char224 15126,22080,405 2 3808
+`a "
+char232 16587,22080,405 2 3816
+`e "
+char242 18051,22080,405 2 3826
+`o "
+char249 17565,22080,405 2 3833
+`u "
+char228 15126,21840,405 2 3812
+:a "
+char235 16587,21840,405 2 3819
+:e "
+char246 18051,21840,405 2 3830
+:o "
+char252 17565,21840,405 2 3836
+:u "
+char197 18540,26850 2 3781
+oA "
+char238 7806,22080 2 3822
+^i "
+char216 19029,20187,501 2 3800
+/O "
+char198 30738,19755 2 3782
+AE "
+char229 15126,24390,405 2 3813
+oa "
+char237 7806,22080 2 3821
+'i "
+char248 18051,17163,432 0 3832
+/o "
+char230 26346,17160,405 0 3814
+ae "
+char196 18540,24690 2 3780
+:A "
+char236 7806,22080 2 3820
+`i "
+char214 19029,24690,405 2 3798
+:O "
+char220 19029,24690,405 2 3804
+:U "
+char201 15612,25005 2 3785
+'E "
+char239 7806,21840 2 3823
+:i "
+char223 16587,20820,405 2 3807
+ss "
+char212 19029,25005,405 2 3796
+^O "
+char193 18540,25005 2 3777
+'A "
+char195 18540,24915 2 3779
+~A "
+char227 15126,21873,405 2 3811
+~a "
+char208 18540,19755 2 3792
+-D "
+char240 18051,22695,405 2 3824
+Sd "
+char205 7317,25005 2 3789
+'I "
+char204 7317,25005 2 3788
+`I "
+char211 19029,25005,405 2 3795
+'O "
+char210 19029,25005,405 2 3794
+`O "
+char213 19029,24915,405 2 3797
+~O "
+char245 18051,21873,405 2 3829
+~o "
+vS 14148,25005,405 2 51795
+vs 12198,22080,405 2 51827
+char218 19029,25005,405 2 3802
+'U "
+:Y 16587,24690 2 51801
+char255 15612,21840,3930 3 3839
+:y "
+char222 16587,19755 2 3806
+TP "
+char254 18540,20820,3930 3 3838
+Tp "
+char181 14637,12630,4350 1 3765
+char182 15612,19635,4200 3 3766
+ps "
+char190 26835,20610,555 2 3774
+34 "
+\- 26835,8295 0 51757
+char188 26835,20610,555 2 3772
+14 "
+char189 26835,20610,555 2 3773
+12 "
+char170 15612,20460 2 3754
+Of "
+char186 15612,20460 2 3770
+Om "
+char171 14148,13950 0 3755
+Fo "
+char187 14148,13950 0 3771
+Fc "
+char177 26835,15255,3900 1 3761
+char166 13173,19083,5916 3 3750
+bb "
+char169 13173,19635 2 3753
+co "
+char172 26835,11331 0 3756
+no "
+char174 13173,19635 2 3758
+rg "
+char178 10245,20385 2 3762
+S2 "
+char179 10245,20055 2 3763
+S3 "
+char184 15612,324,4896 1 3768
+ac "
+char185 10245,20055 2 3769
+S1 "
+char215 26835,15189,579 0 3799
+char247 26835,12780 0 3831
+char183 7806,11781 0 3767
+fm 7806,20055 2 51873
+sd 15612,20055 2 51874
+dg 15612,20160,4095 3 51755
+tm 16101,17850 0 51796
+ah 15612,22080 2 51935
+ao 15612,24390 2 51930
+f/ 4392,20610,555 2 51759
+em 26835,9840 0 51789
+en 15612,9840 0 51790
+dd 15612,20160,4095 3 51773
+.i 7806,16755 0 51957
+aq 6831,19755 2 3623
+bu 13173,14226 0 51889
+'C 16101,25005,405 2 20166
+'c 14637,22080,405 2 20198
+lq 10245,19755 2 51838
+rq 10245,19755 2 51746
+Bq 10245,2868,3417 0 51772
+vz 13662,22080 2 51834
+fi 18051,21105 2 51881
+fl 18051,20820 2 51882
+ff 20979,20820 2 51883
+Fi 27321,21105 2 51884
+Fl 27321,20820 2 51885
+ij 15126,21105,3930 3 51958
+bq 6831,2868,3417 0 51756
+%0 34152,20460,405 2 51901
+char175 15612,21306 2 3759
+a- "
+ab 15612,22155 2 51926
+a. 15612,21840 2 51927
+oe 29274,17160,405 0 51823
+OE 26346,20160,405 2 51791
+fo 9270,13950 0 51886
+fc 9270,13950 0 51887
+sq 19029,15624 0 51899
+/L 13662,19755 2 51944
+/l 7317,20820 2 51960
+a" 15612,22080 2 51933
+ho 15612,747,4143 1 51934
+vZ 16101,25005 2 51802
+IJ 19029,19755,405 2 51942
diff --git a/font/devlj4/CB b/font/devlj4/CB
new file mode 100644
index 00000000..3d060f34
--- /dev/null
+++ b/font/devlj4/CB
@@ -0,0 +1,347 @@
+name CB
+spacewidth 15873
+pcltypeface 4099
+pclproportional 0
+pclweight 3
+pclstyle 0
+charset
+! 15873,15060,330 0 3617
+" 15873,15060 0 3618
+sh 15873,17091,1389 2 3619
+# "
+Do 15873,17010,3306 2 3620
+$ "
+% 15873,16275,900 2 3621
+& 15873,14244,330 0 3622
+' 15873,15060 0 51751
+( 15873,16935,2295 2 3624
+) 15873,16935,2295 2 3625
+* 15873,15060 0 3626
++ 15873,11535 0 3627
+, 15873,4305,2655 0 3628
+char173 15873,7440 0 3629
+hy "
+- "
+. 15873,4035,330 0 3630
+sl 15873,18300,3525 2 3631
+/ "
+0 15873,16155,330 2 3632
+1 15873,16155 2 3633
+2 15873,16155 2 3634
+3 15873,16155,330 2 3635
+4 15873,16155 2 3636
+5 15873,15825,330 2 3637
+6 15873,16155,330 2 3638
+7 15873,15825 2 3639
+8 15873,16155,330 2 3640
+9 15873,16155,330 2 3641
+: 15873,10635,330 0 3642
+; 15873,10635,2655 0 3643
+< 15873,11667,243 0 3644
+= 15873,8886 0 3645
+> 15873,11667,243 0 3646
+? 15873,15390,330 2 3647
+at 15873,15276,489 2 3648
+@ "
+A 15873,15060 0 3649
+B 15873,15060 0 3650
+C 15873,15390,330 2 3651
+D 15873,15060 0 3652
+E 15873,15060 0 3653
+F 15873,15060 0 3654
+G 15873,15390,330 2 3655
+H 15873,15060 0 3656
+I 15873,15060 0 3657
+J 15873,15060,330 0 3658
+K 15873,15060 0 3659
+L 15873,15060 0 3660
+M 15873,15060 0 3661
+N 15873,15060,330 0 3662
+O 15873,15390,330 2 3663
+P 15873,15060 0 3664
+Q 15873,15390,3801 2 3665
+R 15873,15060 0 3666
+S 15873,15390,330 2 3667
+T 15873,15060 0 3668
+U 15873,15060,330 0 3669
+V 15873,15060 0 3670
+W 15873,15060 0 3671
+X 15873,15060 0 3672
+Y 15873,15060 0 3673
+Z 15873,15060 0 3674
+lB 15873,16935,2295 2 3675
+[ "
+rs 15873,18300,3525 2 3676
+\ "
+rB 15873,16935,2295 2 3677
+] "
+ha 15873,19758 2 51875
+_ 15873,191367,6588 3 3679
+oq 15873,15060 0 51808
+` "
+a 15873,11775,330 0 3681
+b 15873,16350,330 2 3682
+c 15873,11775,330 0 3683
+d 15873,16350,330 2 3684
+e 15873,11775,330 0 3685
+f 15873,16350 2 3686
+g 15873,11775,4845 1 3687
+h 15873,16350 2 3688
+i 15873,16920 2 3689
+j 15873,16920,4845 3 3690
+k 15873,16350 2 3691
+l 15873,16350 2 3692
+m 15873,11775 0 3693
+n 15873,11775 0 3694
+o 15873,11775,330 0 3695
+p 15873,11775,4845 1 3696
+q 15873,11775,4845 1 3697
+r 15873,11775 0 3698
+s 15873,11775,330 0 3699
+t 15873,14940,330 0 3700
+u 15873,11445,330 0 3701
+v 15873,11445 0 3702
+w 15873,11445 0 3703
+x 15873,11445 0 3704
+y 15873,11445,4845 1 3705
+z 15873,11445 0 3706
+lC 15873,20130,6075 3 3707
+{ "
+ba 15873,19758,6588 3 3708
+| "
+rC 15873,20130,6075 3 3709
+} "
+ti 15873,8160 0 51876
+char192 15873,21375 2 3776
+`A "
+char194 15873,21375 2 3778
+^A "
+char200 15873,21375 2 3784
+`E "
+char202 15873,21375 2 3786
+^E "
+char203 15873,20790 2 3787
+:E "
+char206 15873,21375 2 3790
+^I "
+char207 15873,20790 2 3791
+:I "
+char180 15873,17880 2 3764
+aa "
+ga 15873,17880 2 3680
+a^ 15873,17880 2 3678
+^ "
+char168 15873,16890 2 3752
+ad "
+a~ 15873,16959 2 3710
+~ "
+char217 15873,21375,330 2 3801
+`U "
+char219 15873,21375,330 2 3803
+^U "
+char221 15873,21375 2 3805
+'Y "
+char253 15873,17880,4845 3 3837
+'y "
+char176 15873,16155 2 3760
+de "
+char199 15873,15390,5457 3 3783
+,C "
+char231 15873,11775,5469 1 3815
+,c "
+char209 15873,20490,330 2 3793
+~N "
+char241 15873,16959 2 3825
+~n "
+char161 15873,11784,3606 0 3745
+r! "
+char191 15873,11751,3969 0 3775
+r? "
+char164 15873,15834 2 3748
+Cs "
+char163 15873,16155,741 2 3747
+Po "
+char165 15873,15825 2 3749
+Ye "
+char167 15873,15390,1692 2 3751
+sc "
+Fn 15873,16350,3114 2 51871
+char162 15873,15966,1419 2 3746
+ct "
+char226 15873,17880,330 2 3810
+^a "
+char234 15873,17880,330 2 3818
+^e "
+char244 15873,17880,330 2 3828
+^o "
+char251 15873,17880,330 2 3835
+^u "
+char225 15873,17880,330 2 3809
+'a "
+char233 15873,17880,330 2 3817
+'e "
+char243 15873,17880,330 2 3827
+'o "
+char250 15873,17880,330 2 3834
+'u "
+char224 15873,17880,330 2 3808
+`a "
+char232 15873,17880,330 2 3816
+`e "
+char242 15873,17880,330 2 3826
+`o "
+char249 15873,17880,330 2 3833
+`u "
+char228 15873,16890,330 2 3812
+:a "
+char235 15873,16890,330 2 3819
+:e "
+char246 15873,16890,330 2 3830
+:o "
+char252 15873,16890,330 2 3836
+:u "
+char197 15873,21780 2 3781
+oA "
+char238 15873,17880 2 3822
+^i "
+char216 15873,15432,492 2 3800
+/O "
+char198 15873,15060 0 3782
+AE "
+char229 15873,18900,330 2 3813
+oa "
+char237 15873,17880 2 3821
+'i "
+char248 15873,11913,600 0 3832
+/o "
+char230 15873,11775,330 0 3814
+ae "
+char196 15873,20790 2 3780
+:A "
+char236 15873,17880 2 3820
+`i "
+char214 15873,20790,330 2 3798
+:O "
+char220 15873,20790,330 2 3804
+:U "
+char201 15873,21375 2 3785
+'E "
+char239 15873,16890 2 3823
+:i "
+char223 15873,16350,330 2 3807
+ss "
+char212 15873,21375,330 2 3796
+^O "
+char193 15873,21375 2 3777
+'A "
+char195 15873,20490 2 3779
+~A "
+char227 15873,16959,330 2 3811
+~a "
+char208 15873,15060 0 3792
+-D "
+char240 15873,18249,330 2 3824
+Sd "
+char205 15873,21375 2 3789
+'I "
+char204 15873,21375 2 3788
+`I "
+char211 15873,21375,330 2 3795
+'O "
+char210 15873,21375,330 2 3794
+`O "
+char213 15873,20490,330 2 3797
+~O "
+char245 15873,16959,330 2 3829
+~o "
+vS 15873,21375,330 2 51795
+vs 15873,17880,330 2 51827
+char218 15873,21375,330 2 3802
+'U "
+:Y 15873,20790 2 51801
+char255 15873,16890,4845 3 3839
+:y "
+char222 15873,15060 0 3806
+TP "
+char254 15873,16350,4845 3 3838
+Tp "
+char181 15873,11445,5580 1 3765
+char182 15873,19635,4080 2 3766
+ps "
+char190 15873,16545,2415 2 3774
+34 "
+\- 15873,7020 0 51757
+char188 15873,16545,2415 2 3772
+14 "
+char189 15873,16545,2415 2 3773
+12 "
+char170 15873,16155 2 3754
+Of "
+char186 15873,16155 2 3770
+Om "
+char171 15873,11595 0 3755
+Fo "
+char187 15873,11595 0 3771
+Fc "
+char177 15873,11535,3360 0 3761
+char166 15873,19083,5916 3 3750
+bb "
+char169 15873,19635 2 3753
+co "
+char172 15873,9420 0 3756
+no "
+char174 15873,19635 2 3758
+rg "
+char178 15873,16035 2 3762
+S2 "
+char179 15873,16035 2 3763
+S3 "
+char184 15873,0,5469 1 3768
+ac "
+char185 15873,16035 2 3769
+S1 "
+char215 15873,11340 0 3799
+char247 15873,11190 0 3831
+char183 15873,10176 0 3767
+fm 15873,15825 2 51873
+sd 15873,15825 2 51874
+dg 15873,15060,1185 0 51755
+tm 15873,17850 2 51796
+ah 15873,17880 2 51935
+ao 15873,18900 2 51930
+f/ 15873,16695,2265 2 51759
+em 15873,7440 0 51789
+en 15873,7440 0 51790
+dd 15873,15060,1185 0 51773
+.i 15873,11445 0 51957
+aq 15873,15060 0 3623
+bu 15873,12714 0 51889
+'C 15873,21375,330 2 20166
+'c 15873,17880,330 2 20198
+lq 15873,15060 0 51838
+rq 15873,15060 0 51746
+Bq 15873,4602,2358 0 51772
+vz 15873,17880 2 51834
+fi 15873,16920 2 51881
+fl 15873,16350 2 51882
+ff 15873,16350 2 51883
+Fi 15873,16350 2 51884
+Fl 15873,16350 2 51885
+ij 15873,16920,4845 3 51958
+bq 15873,4605,2355 0 51756
+%0 15873,16275,900 2 51901
+char175 15873,15567 2 3759
+a- "
+ab 15873,17310 2 51926
+a. 15873,16890 2 51927
+oe 15873,11775,330 0 51823
+OE 15873,15060 0 51791
+fo 15873,11085 0 51886
+fc 15873,11085 0 51887
+sq 15873,14106 0 51899
+/L 15873,15060 0 51944
+/l 15873,16350 2 51960
+a" 15873,18720 2 51933
+ho 15873,573,4680 1 51934
+vZ 15873,21375 2 51802
+IJ 15873,15060,3837 0 51942
diff --git a/font/devlj4/CBI b/font/devlj4/CBI
new file mode 100644
index 00000000..14f2aa95
--- /dev/null
+++ b/font/devlj4/CBI
@@ -0,0 +1,348 @@
+name CBI
+spacewidth 15873
+slant 11.300000
+pcltypeface 4099
+pclproportional 0
+pclweight 3
+pclstyle 1
+charset
+! 15873,15060,330,0,-3018 0 3617
+" 15873,15060,0,0,-2661 0 3618
+sh 15873,17091,1389,279,363,279 2 3619
+# "
+Do 15873,17007,3306,0,279 2 3620
+$ "
+% 15873,16275,900,0,-396 2 3621
+& 15873,14238,330,0,426 0 3622
+' 15873,15060,0,0,-2745 0 51751
+( 15873,16935,2295,0,-3093 2 3624
+) 15873,16935,2295,0,-1824 2 3625
+* 15873,15060,0,0,-1497 0 3626
++ 15873,11535,0,0,-891 0 3627
+, 15873,4305,2655,0,-1506 0 3628
+char173 15873,8805,0,0,-2319 0 3629
+hy "
+- "
+. 15873,3675,330,0,-2805 0 3630
+sl 15873,18300,3525,1224,1512,614 2 3631
+/ "
+0 15873,16155,330,0,-927 2 3632
+1 15873,16155,0,0,324 2 3633
+2 15873,16155,0,0,1044 2 3634
+3 15873,16155,330,0,891 2 3635
+4 15873,16155,0,0,345 2 3636
+5 15873,15825,330,0,621 2 3637
+6 15873,16155,330,342,-762,342 2 3638
+7 15873,15825,0,0,-1227 2 3639
+8 15873,16155,330,0,-465 2 3640
+9 15873,16155,330,0,297 2 3641
+: 15873,10572,330,0,-2802 0 3642
+; 15873,10572,2655,0,-831 0 3643
+< 15873,11667,243,0,-600 0 3644
+= 15873,8886,0,0,-951 0 3645
+> 15873,11667,243,0,-1524 0 3646
+? 15873,15390,330,0,-2031 2 3647
+at 15873,15273,489,1020,1203,614 2 3648
+@ "
+A 15873,15060,0,69,2868,69 0 3649
+B 15873,15060,0,0,1992 0 3650
+C 15873,15390,330,903,228,614 2 3651
+D 15873,15060,0,369,2277,369 0 3652
+E 15873,15060,0,1254,1719,614 0 3653
+F 15873,15060,0,1527,1293,614 0 3654
+G 15873,15390,330,1224,585,614 2 3655
+H 15873,15060,0,1878,2172,614 0 3656
+I 15873,15060,0,321,615,321 0 3657
+J 15873,15060,330,2331,1152,614 0 3658
+K 15873,15060,0,1890,1569,614 0 3659
+L 15873,15060,0,27,1602,27 0 3660
+M 15873,15060,0,2508,3099,614 0 3661
+N 15873,15060,330,2625,2439,614 0 3662
+O 15873,15390,330,447,633,447 2 3663
+P 15873,15060,0,816,774,614 0 3664
+Q 15873,15390,3408,453,678,453 2 3665
+R 15873,15060,0,0,1977 0 3666
+S 15873,15390,330,0,1386 2 3667
+T 15873,15060,0,1578,210,614 0 3668
+U 15873,15060,330,2124,75,614 0 3669
+V 15873,15060,0,2718,504,614 0 3670
+W 15873,15060,0,2757,552,614 0 3671
+X 15873,15060,0,1509,2286,614 0 3672
+Y 15873,15060,0,2043,-168,614 0 3673
+Z 15873,15060,0,159,1026,159 0 3674
+lB 15873,16935,2295,0,-1995 2 3675
+[ "
+rs 15873,18300,3525,0,-2523 2 3676
+\ "
+rB 15873,16935,2295,0,-1632 2 3677
+] "
+ha 15873,19758,0,0,-1314 2 51875
+_ 15873,191367,6588,1317,1317,614 3 3679
+oq 15873,15060,0,0,-3345 0 51808
+` "
+a 15873,11775,330,0,837 0 3681
+b 15873,16350,330,390,1974,390 2 3682
+c 15873,11775,330,0,282 0 3683
+d 15873,16350,330,183,1038,183 2 3684
+e 15873,11775,330,0,228 0 3685
+f 15873,16350,0,1308,39,614 2 3686
+g 15873,11775,4845,1260,1542,614 1 3687
+h 15873,16350,0,0,2550 2 3688
+i 15873,16920,0,0,606 2 3689
+j 15873,16920,4845,0,1428 3 3690
+k 15873,16350,0,0,2061 2 3691
+l 15873,16350,0,0,570 2 3692
+m 15873,11775,0,417,3222,417 0 3693
+n 15873,11775,0,0,2292 0 3694
+o 15873,11775,330,0,858 0 3695
+p 15873,11775,4845,330,3072,330 1 3696
+q 15873,11775,4845,1644,810,614 1 3697
+r 15873,11775,0,735,1257,614 0 3698
+s 15873,11775,330,0,798 0 3699
+t 15873,14985,330,0,-1245 0 3700
+u 15873,11445,330,0,432 0 3701
+v 15873,11445,0,1554,936,614 0 3702
+w 15873,11445,0,1896,1278,614 0 3703
+x 15873,11445,0,894,2469,614 0 3704
+y 15873,11445,4845,1887,2409,614 1 3705
+z 15873,11445,0,0,498 0 3706
+lC 15873,20130,6075,1548,-2004,614 3 3707
+{ "
+ba 15873,19758,6588,0,-5946 3 3708
+| "
+rC 15873,20130,6075,0,996 3 3709
+} "
+ti 15873,8160,0,0,-792 0 51876
+char192 15873,21495,0,69,2868,69 2 3776
+`A "
+char194 15873,21495,0,69,2868,69 2 3778
+^A "
+char200 15873,21495,0,1254,1719,614 2 3784
+`E "
+char202 15873,21495,0,1254,1719,614 2 3786
+^E "
+char203 15873,20520,0,1254,1719,614 2 3787
+:E "
+char206 15873,21495,0,609,615,609 2 3790
+^I "
+char207 15873,20520,0,321,615,321 2 3791
+:I "
+char180 15873,18000,0,0,-3249 2 3764
+aa "
+ga 15873,18000,0,0,-2835 2 3680
+a^ 15873,18000,0,9,-2343,9 2 3678
+^ "
+char168 15873,16890,0,0,-4020 2 3752
+ad "
+a~ 15873,16959,0,594,-2031,594 2 3710
+~ "
+char217 15873,21495,330,2124,75,614 2 3801
+`U "
+char219 15873,21495,330,2124,75,614 2 3803
+^U "
+char221 15873,21495,0,2043,-168,614 2 3805
+'Y "
+char253 15873,18000,4845,1887,2409,614 3 3837
+'y "
+char176 15873,16155,0,0,-3120 2 3760
+de "
+char199 15873,15390,5721,903,228,614 3 3783
+,C "
+char231 15873,11775,5562,0,282 1 3815
+,c "
+char209 15873,20487,330,2625,2439,614 2 3793
+~N "
+char241 15873,16959,0,594,2292,594 2 3825
+~n "
+char161 15873,11904,3486,0,-3411 0 3745
+r! "
+char191 15873,11868,3852,0,-747 0 3775
+r? "
+char164 15873,15834,0,345,348,345 2 3748
+Cs "
+char163 15873,16155,603,192,-108,192 2 3747
+Po "
+char165 15873,15825,0,2160,-342,614 2 3749
+Ye "
+char167 15873,15390,1692,0,-1332 2 3751
+sc "
+Fn 15873,16350,3135,12,1572,12 2 51871
+char162 15873,15978,1419,0,-1068 2 3746
+ct "
+char226 15873,18000,330,9,837,9 2 3810
+^a "
+char234 15873,18000,330,9,228,9 2 3818
+^e "
+char244 15873,18000,330,9,858,9 2 3828
+^o "
+char251 15873,18000,330,9,432,9 2 3835
+^u "
+char225 15873,18000,330,0,837 2 3809
+'a "
+char233 15873,18000,330,0,228 2 3817
+'e "
+char243 15873,18000,330,0,858 2 3827
+'o "
+char250 15873,18000,330,0,432 2 3834
+'u "
+char224 15873,18000,330,0,837 2 3808
+`a "
+char232 15873,18000,330,0,228 2 3816
+`e "
+char242 15873,18000,330,0,858 2 3826
+`o "
+char249 15873,18000,330,0,432 2 3833
+`u "
+char228 15873,16890,330,0,837 2 3812
+:a "
+char235 15873,16890,330,0,228 2 3819
+:e "
+char246 15873,16890,330,0,858 2 3830
+:o "
+char252 15873,16890,330,0,432 2 3836
+:u "
+char197 15873,21780,0,69,2868,69 2 3781
+oA "
+char238 15873,18000,0,9,606,9 2 3822
+^i "
+char216 15873,15501,528,1206,1434,614 2 3800
+/O "
+char198 15873,15060,0,2391,2655,614 0 3782
+AE "
+char229 15873,18381,330,0,837 2 3813
+oa "
+char237 15873,18000,0,0,606 2 3821
+'i "
+char248 15873,11901,591,486,1311,486 0 3832
+/o "
+char230 15873,11775,330,654,2010,614 0 3814
+ae "
+char196 15873,20520,0,69,2868,69 2 3780
+:A "
+char236 15873,18000,0,0,606 2 3820
+`i "
+char214 15873,20520,330,447,633,447 2 3798
+:O "
+char220 15873,20520,330,2124,75,614 2 3804
+:U "
+char201 15873,21495,0,1254,1719,614 2 3785
+'E "
+char239 15873,16890,0,0,606 2 3823
+:i "
+char223 15873,16350,330,0,2220 2 3807
+ss "
+char212 15873,21495,330,609,633,609 2 3796
+^O "
+char193 15873,21495,0,69,2868,69 2 3777
+'A "
+char195 15873,20487,0,174,2868,174 2 3779
+~A "
+char227 15873,16959,330,594,837,594 2 3811
+~a "
+char208 15873,15060,0,366,2280,366 0 3792
+-D "
+char240 15873,18222,330,0,171 2 3824
+Sd "
+char205 15873,21495,0,321,615,321 2 3789
+'I "
+char204 15873,21495,0,321,615,321 2 3788
+`I "
+char211 15873,21495,330,591,633,591 2 3795
+'O "
+char210 15873,21495,330,447,633,447 2 3794
+`O "
+char213 15873,20487,330,1986,633,614 2 3797
+~O "
+char245 15873,16959,330,594,858,594 2 3829
+~o "
+vS 15873,21495,330,984,1386,614 2 51795
+vs 15873,18000,330,9,798,9 2 51827
+char218 15873,21495,330,2124,75,614 2 3802
+'U "
+:Y 15873,20520,0,2043,-168,614 2 51801
+char255 15873,16890,4845,1887,2409,614 3 3839
+:y "
+char222 15873,15060,0,222,2166,222 0 3806
+TP "
+char254 15873,16350,4845,330,3075,330 3 3838
+Tp "
+char181 15873,11445,5580,114,-12,114 1 3765
+char182 15873,19635,4080,0,-1308 2 3766
+ps "
+char190 15873,16674,2286,4155,1086,614 2 3774
+34 "
+\- 15873,7020,0,0,-951 0 51757
+char188 15873,16674,2286,4458,1638,614 2 3772
+14 "
+char189 15873,16674,2286,3384,1857,614 2 3773
+12 "
+char170 15873,16155,0,0,-3528 2 3754
+Of "
+char186 15873,16155,0,0,-3588 2 3770
+Om "
+char171 15873,11625,0,354,1047,354 0 3755
+Fo "
+char187 15873,11625,0,0,1605 0 3771
+Fc "
+char177 15873,11535,3360,0,-891 0 3761
+char166 15873,19083,5916,0,-5946 3 3750
+bb "
+char169 15873,19635,0,225,-1134,225 2 3753
+co "
+char172 15873,9420,0,0,-951 0 3756
+no "
+char174 15873,19635,0,225,-1134,225 2 3758
+rg "
+char178 15873,16170,0,0,-3063 2 3762
+S2 "
+char179 15873,16170,0,0,-3162 2 3763
+S3 "
+char184 15873,0,5562,0,-2265 1 3768
+ac "
+char185 15873,16170,0,0,-3066 2 3769
+S1 "
+char215 15873,11646,0,0,-798 0 3799
+char247 15873,11190,0,0,-1110 0 3831
+char183 15873,10128,0,0,-4290 0 3767
+fm 15873,15825,0,0,-5124 2 51873
+sd 15873,15825,0,0,-2748 2 51874
+dg 15873,15060,1185,0,-1776 0 51755
+tm 15873,17850,0,108,-417,108 2 51796
+ah 15873,18000,0,9,-2343,9 2 51935
+ao 15873,18381,0,0,-5319 2 51930
+f/ 15873,16695,2265,2712,2529,614 2 51759
+em 15873,8805,0,1707,1929,614 0 51789
+en 15873,8805,0,0,-363 0 51790
+dd 15873,15060,1185,0,-1776 0 51773
+.i 15873,11445,0,0,606 0 51957
+aq 15873,15060,0,0,-4983 0 3623
+bu 15873,12714,0,0,-1848 0 51889
+'C 15873,21495,330,903,228,614 2 20166
+'c 15873,18000,330,0,282 2 20198
+lq 15873,15060,0,387,-741,387 0 51838
+rq 15873,15060,0,0,-144 0 51746
+Bq 15873,4596,2364,0,1314 0 51772
+vz 15873,18000,0,9,498,9 2 51834
+fi 15873,16920,0,438,2340,438 2 51881
+fl 15873,16350,0,336,2337,336 2 51882
+ff 15873,16350,0,4086,2349,614 2 51883
+Fi 15873,16350,0,2229,2946,614 2 51884
+Fl 15873,16350,0,1425,2949,614 2 51885
+ij 15873,16920,4845,738,1320,614 3 51958
+bq 15873,4596,2364,0,-1647 0 51756
+%0 15873,16275,900,3066,3417,614 2 51901
+char175 15873,16032,0,537,-2187,537 2 3759
+a- "
+ab 15873,17340,0,993,-2841,614 2 51926
+a. 15873,16890,0,0,-6186 2 51927
+oe 15873,11775,330,1284,1977,614 0 51823
+OE 15873,15060,0,2781,1740,614 0 51791
+fo 15873,11070,0,0,-2004 0 51886
+fc 15873,11070,0,0,-1389 0 51887
+sq 15873,14106,0,0,-444 0 51899
+/L 15873,15060,0,27,1602,27 0 51944
+/l 15873,16350,0,0,570 2 51960
+a" 15873,18720,0,2916,-4083,614 2 51933
+ho 15873,564,4665,0,-4917 1 51934
+vZ 15873,21495,0,984,1026,614 2 51802
+IJ 15873,15060,3849,1506,1941,614 0 51942
diff --git a/font/devlj4/CI b/font/devlj4/CI
new file mode 100644
index 00000000..5e87918b
--- /dev/null
+++ b/font/devlj4/CI
@@ -0,0 +1,348 @@
+name CI
+spacewidth 15873
+slant 11.300000
+pcltypeface 4099
+pclproportional 0
+pclweight 0
+pclstyle 1
+charset
+! 15873,15060,330,0,-5232 0 3617
+" 15873,15060,0,0,-4632 0 3618
+sh 15873,16827,2046,1710,-1473,610 2 3619
+# "
+Do 15873,17259,3642,954,-1644,610 2 3620
+$ "
+% 15873,16380,330,1140,-2169,610 2 3621
+& 15873,14169,330,1563,-1911,610 0 3622
+' 15873,15060,0,0,-5217 0 51751
+( 15873,17070,2580,1185,-7563,610 2 3624
+) 15873,17070,2580,0,-2013 2 3625
+* 15873,15060,0,174,-3273,174 0 3626
++ 15873,11385,0,252,-2151,252 0 3627
+, 15873,3195,3420,0,-3000 0 3628
+char173 15873,6570,0,0,-3741 0 3629
+hy "
+- "
+. 15873,3105,330,0,-5040 0 3630
+sl 15873,18465,3765,2349,-699,610 2 3631
+/ "
+0 15873,15390,330,399,-2832,399 0 3632
+1 15873,15060,0,0,-1494 0 3633
+2 15873,15390,0,423,-786,423 0 3634
+3 15873,15390,330,0,-1113 0 3635
+4 15873,15060,0,0,-1548 0 3636
+5 15873,15060,330,882,-1170,610 0 3637
+6 15873,15390,330,1530,-2436,610 0 3638
+7 15873,15060,0,954,-2829,610 0 3639
+8 15873,15390,330,624,-2226,610 0 3640
+9 15873,15390,330,684,-1659,610 0 3641
+: 15873,9975,330,0,-5043 0 3642
+; 15873,9975,3420,0,-3177 0 3643
+< 15873,10647,3,0,-1155 0 3644
+= 15873,8451,0,252,-2151,252 0 3645
+> 15873,10647,3,0,-1959 0 3646
+? 15873,15390,330,483,-4173,483 0 3647
+at 15873,14391,363,2031,-1359,610 0 3648
+@ "
+A 15873,15060,0,1470,1092,610 0 3649
+B 15873,15060,0,1383,171,610 0 3650
+C 15873,15390,330,2835,-1689,610 0 3651
+D 15873,15060,0,2061,537,610 0 3652
+E 15873,15060,0,2724,-153,610 0 3653
+F 15873,15060,0,3120,-471,610 0 3654
+G 15873,15390,330,2259,-957,610 0 3655
+H 15873,15060,0,3483,285,610 0 3656
+I 15873,15060,0,1764,-1188,610 0 3657
+J 15873,15060,330,3729,-369,610 0 3658
+K 15873,15060,0,3453,-210,610 0 3659
+L 15873,15060,0,1512,-135,610 0 3660
+M 15873,15060,0,4218,1107,610 0 3661
+N 15873,15060,0,4182,738,610 0 3662
+O 15873,15390,330,2058,-1137,610 0 3663
+P 15873,15060,0,2262,-786,610 0 3664
+Q 15873,15390,3357,2037,-1074,610 0 3665
+R 15873,15060,0,1248,234,610 0 3666
+S 15873,15390,330,1893,-804,610 0 3667
+T 15873,15060,0,3183,-1968,610 0 3668
+U 15873,15060,330,4095,-2097,610 0 3669
+V 15873,15060,0,4191,-1725,610 0 3670
+W 15873,15060,0,4260,-1671,610 0 3671
+X 15873,15060,0,3177,522,610 0 3672
+Y 15873,15060,0,3672,-2262,610 0 3673
+Z 15873,15060,0,1707,-807,610 0 3674
+lB 15873,17070,2580,1815,-6345,610 2 3675
+[ "
+rs 15873,18465,3765,0,-4674 2 3676
+\ "
+rB 15873,17070,2580,0,-1221 2 3677
+] "
+ha 15873,19758,0,0,-1314 2 51875
+_ 15873,191367,6588,1317,1317,610 3 3679
+oq 15873,15060,0,0,-6267 0 51808
+` "
+a 15873,11775,330,531,-696,531 0 3681
+b 15873,16500,330,1602,723,610 2 3682
+c 15873,11775,330,1542,-1617,610 0 3683
+d 15873,16500,330,2148,-1143,610 2 3684
+e 15873,11775,330,1269,-1611,610 0 3685
+f 15873,16500,0,2262,-1173,610 2 3686
+g 15873,11775,5145,2622,-96,610 1 3687
+h 15873,16500,0,1179,387,610 2 3688
+i 15873,17235,0,0,-1260 2 3689
+j 15873,17235,5145,0,81 3 3690
+k 15873,16500,0,1857,24,610 2 3691
+l 15873,16500,0,0,-1131 2 3692
+m 15873,11775,0,1746,1188,610 0 3693
+n 15873,11775,0,960,585,610 0 3694
+o 15873,11775,330,1443,-1140,610 0 3695
+p 15873,11775,5145,1500,1920,610 1 3696
+q 15873,11775,5145,3354,-984,610 1 3697
+r 15873,11775,0,2475,-597,610 0 3698
+s 15873,11775,330,915,-1356,610 0 3699
+t 15873,14760,330,738,-3216,610 0 3700
+u 15873,11445,330,726,-1404,610 0 3701
+v 15873,11445,0,3342,-1224,610 0 3702
+w 15873,11445,0,3735,-831,610 0 3703
+x 15873,11445,0,2502,648,610 0 3704
+y 15873,11445,5145,3123,903,610 1 3705
+z 15873,11445,0,1101,-1368,610 0 3706
+lC 15873,20130,6075,2940,-5529,610 3 3707
+{ "
+ba 15873,19758,6588,0,-5946 3 3708
+| "
+rC 15873,20130,6075,0,-1059 3 3709
+} "
+ti 15873,7233,0,0,-1089 0 51876
+char192 15873,21255,0,1470,1092,610 2 3776
+`A "
+char194 15873,21255,0,1707,1092,610 2 3778
+^A "
+char200 15873,21255,0,2724,-153,610 2 3784
+`E "
+char202 15873,21255,0,2724,-153,610 2 3786
+^E "
+char203 15873,20670,0,2724,-153,610 2 3787
+:E "
+char206 15873,21255,0,2157,-1188,610 2 3790
+^I "
+char207 15873,20670,0,1764,-1188,610 2 3791
+:I "
+char180 15873,17640,0,1401,-6675,610 2 3764
+aa "
+ga 15873,17640,0,0,-4491 2 3680
+a^ 15873,17640,0,1257,-4491,610 2 3678
+^ "
+char168 15873,16905,0,0,-6489 2 3752
+ad "
+a~ 15873,16818,0,1788,-4146,610 2 3710
+~ "
+char217 15873,21255,330,4095,-2097,610 2 3801
+`U "
+char219 15873,21255,330,4095,-2097,610 2 3803
+^U "
+char221 15873,21255,0,3672,-2262,610 2 3805
+'Y "
+char253 15873,17640,5145,3123,903,610 3 3837
+'y "
+char176 15873,15390,0,0,-4464 0 3760
+de "
+char199 15873,15390,4815,2835,-1689,610 1 3783
+,C "
+char231 15873,11775,4815,1542,-1617,610 1 3815
+,c "
+char209 15873,20580,0,4182,738,610 2 3793
+~N "
+char241 15873,16818,0,1788,585,610 2 3825
+~n "
+char161 15873,11946,3444,0,-5715 0 3745
+r! "
+char191 15873,11946,3774,0,-2577 0 3775
+r? "
+char164 15873,15684,0,1560,-2253,610 2 3748
+Cs "
+char163 15873,15390,474,1797,-2232,610 0 3747
+Po "
+char165 15873,15060,0,3741,-2178,610 0 3749
+Ye "
+char167 15873,15390,1905,0,-3360 0 3751
+sc "
+Fn 15873,15090,4350,1704,-774,610 0 51871
+char162 15873,16083,1536,900,-3015,610 2 3746
+ct "
+char226 15873,17640,330,1257,-696,610 2 3810
+^a "
+char234 15873,17640,330,1269,-1611,610 2 3818
+^e "
+char244 15873,17640,330,1443,-1140,610 2 3828
+^o "
+char251 15873,17640,330,1257,-1404,610 2 3835
+^u "
+char225 15873,17640,330,1401,-696,610 2 3809
+'a "
+char233 15873,17640,330,1401,-1611,610 2 3817
+'e "
+char243 15873,17640,330,1443,-1140,610 2 3827
+'o "
+char250 15873,17640,330,1401,-1404,610 2 3834
+'u "
+char224 15873,17640,330,531,-696,531 2 3808
+`a "
+char232 15873,17640,330,1269,-1611,610 2 3816
+`e "
+char242 15873,17640,330,1443,-1140,610 2 3826
+`o "
+char249 15873,17640,330,726,-1404,610 2 3833
+`u "
+char228 15873,16905,330,531,-696,531 2 3812
+:a "
+char235 15873,16905,330,1269,-1611,610 2 3819
+:e "
+char246 15873,16905,330,1443,-1140,610 2 3830
+:o "
+char252 15873,16905,330,726,-1404,610 2 3836
+:u "
+char197 15873,21690,0,1470,1092,610 2 3781
+oA "
+char238 15873,17640,0,1257,-1260,610 2 3822
+^i "
+char216 15873,15390,453,2697,-333,610 0 3800
+/O "
+char198 15873,15060,0,2871,855,610 0 3782
+AE "
+char229 15873,17997,330,531,-696,531 2 3813
+oa "
+char237 15873,17640,0,1401,-1260,610 2 3821
+'i "
+char248 15873,11793,330,2241,-291,610 0 3832
+/o "
+char230 15873,11775,330,2148,-189,610 0 3814
+ae "
+char196 15873,20670,0,1470,1092,610 2 3780
+:A "
+char236 15873,17640,0,0,-1260 2 3820
+`i "
+char214 15873,20670,330,2058,-1137,610 2 3798
+:O "
+char220 15873,20670,330,4095,-2097,610 2 3804
+:U "
+char201 15873,21255,0,2724,-153,610 2 3785
+'E "
+char239 15873,16905,0,0,-1260 2 3823
+:i "
+char223 15873,16500,330,1746,-66,610 2 3807
+ss "
+char212 15873,21255,330,2157,-1137,610 2 3796
+^O "
+char193 15873,21255,0,2217,1092,610 2 3777
+'A "
+char195 15873,20580,0,2445,1092,610 2 3779
+~A "
+char227 15873,16818,330,1788,-696,610 2 3811
+~a "
+char208 15873,15060,0,2061,537,610 0 3792
+-D "
+char240 15873,18297,330,1614,-1143,610 2 3824
+Sd "
+char205 15873,21255,0,2217,-1188,610 2 3789
+'I "
+char204 15873,21255,0,1764,-1188,610 2 3788
+`I "
+char211 15873,21255,330,2217,-1137,610 2 3795
+'O "
+char210 15873,21255,330,2058,-1137,610 2 3794
+`O "
+char213 15873,20580,330,2895,-1137,610 2 3797
+~O "
+char245 15873,16818,330,1788,-1140,610 2 3829
+~o "
+vS 15873,21255,330,2157,-804,610 2 51795
+vs 15873,17640,330,1257,-1356,610 2 51827
+char218 15873,21255,330,4095,-2097,610 2 3802
+'U "
+:Y 15873,20670,0,3672,-2262,610 2 51801
+char255 15873,16905,5145,3123,903,610 3 3839
+:y "
+char222 15873,15060,0,2421,-756,610 0 3806
+TP "
+char254 15873,16500,5145,1380,2037,610 3 3838
+Tp "
+char181 15873,11445,5595,0,-321 1 3765
+char182 15873,19635,4080,150,-2508,150 2 3766
+ps "
+char190 15873,15498,2655,4026,15,610 0 3774
+34 "
+\- 15873,6435,0,252,-2151,252 0 51757
+char188 15873,15498,2655,4626,-30,610 0 3772
+14 "
+char189 15873,15498,2655,3426,615,610 0 3773
+12 "
+char170 15873,15390,0,0,-5310 0 3754
+Of "
+char186 15873,15390,0,0,-5274 0 3770
+Om "
+char171 15873,11010,0,1230,-2184,610 0 3755
+Fo "
+char187 15873,11010,0,330,-1284,330 0 3771
+Fc "
+char177 15873,11385,2835,252,-2151,252 0 3761
+char166 15873,19083,5916,0,-5946 3 3750
+bb "
+char169 15873,19635,0,2121,-3030,610 2 3753
+co "
+char172 15873,8865,0,252,-2151,252 0 3756
+no "
+char174 15873,19635,0,1839,-2748,610 2 3758
+rg "
+char178 15873,15240,0,0,-4467 0 3762
+S2 "
+char179 15873,15240,0,0,-4548 0 3763
+S3 "
+char184 15873,0,4815,0,-4626 1 3768
+ac "
+char185 15873,15060,0,0,-4830 0 3769
+S1 "
+char215 15873,11340,0,252,-2151,252 0 3799
+char247 15873,10530,0,306,-2205,306 0 3831
+char183 15873,9657,0,0,-6252 0 3767
+fm 15873,15060,0,0,-7596 0 51873
+sd 15873,15060,0,0,-5274 0 51874
+dg 15873,15060,1290,0,-4491 0 51755
+tm 15873,17850,0,1896,-2205,610 2 51796
+ah 15873,17640,0,1257,-4491,610 2 51935
+ao 15873,17997,0,0,-7365 2 51930
+f/ 15873,15498,2655,3126,915,610 0 51759
+em 15873,6570,0,3141,264,610 0 51789
+en 15873,6570,0,606,-2142,606 0 51790
+dd 15873,15060,1290,0,-4491 0 51773
+.i 15873,11445,0,0,-1260 0 51957
+aq 15873,15060,0,0,-6936 0 3623
+bu 15873,12714,0,0,-1848 0 51889
+'C 15873,21255,330,2835,-1689,610 2 20166
+'c 15873,17640,330,1542,-1617,610 2 20198
+lq 15873,15060,0,861,-3495,610 0 51838
+rq 15873,15060,0,1011,-3645,610 0 51746
+Bq 15873,3495,3120,0,-1491 0 51772
+vz 15873,17640,0,1257,-1368,610 2 51834
+fi 15873,17235,0,1983,1185,610 2 51881
+fl 15873,16500,0,1806,1185,610 2 51882
+ff 15873,16500,0,5799,1212,610 2 51883
+Fi 15873,16500,0,3705,846,610 2 51884
+Fl 15873,16500,0,2208,852,610 2 51885
+ij 15873,17235,5145,2958,1278,610 3 51958
+bq 15873,3495,3120,0,-3498 0 51756
+%0 15873,16380,330,2361,-471,610 2 51901
+char175 15873,15666,0,1914,-3453,610 2 3759
+a- "
+ab 15873,16395,0,2325,-5001,610 2 51926
+a. 15873,16905,0,0,-8292 2 51927
+oe 15873,11775,330,2334,30,610 0 51823
+OE 15873,15060,0,2799,-390,610 0 51791
+fo 15873,10365,0,0,-4143 0 51886
+fc 15873,10365,0,0,-3543 0 51887
+sq 15873,14106,0,0,-444 0 51899
+/L 15873,15060,0,1515,-135,610 0 51944
+/l 15873,16500,0,0,-1185 2 51960
+a" 15873,18420,0,2355,-6834,610 2 51933
+ho 15873,0,4263,0,-7344 0 51934
+vZ 15873,21255,0,2157,-807,610 2 51802
+IJ 15873,15060,2904,3021,-207,610 0 51942
diff --git a/font/devlj4/CLARENDON b/font/devlj4/CLARENDON
new file mode 100644
index 00000000..f5936b59
--- /dev/null
+++ b/font/devlj4/CLARENDON
@@ -0,0 +1,348 @@
+name CLARENDON
+spacewidth 5856
+pcltypeface 4140
+pclproportional 1
+pclweight 3
+pclstyle 4
+ligatures fi fl ff ffi ffl 0
+charset
+! 6342,18300 2 3617
+" 11709,18645 2 3618
+sh 11709,18300 2 3619
+# "
+Do 11709,18309,306 2 3620
+$ "
+% 17565,18645,345 2 3621
+& 16587,18645,345 2 3622
+' 5856,18645 2 51751
+( 5856,18300,6870 3 3624
+) 5856,18300,6870 3 3625
+* 11709,18645 2 3626
++ 17565,16545 0 3627
+, 5856,3945,3375 0 3628
+char173 5856,8295 0 3629
+hy "
+- "
+. 5856,3945 0 3630
+sl 5856,18645,345 2 3631
+/ "
+0 11709,18645,345 2 3632
+1 11709,18300 2 3633
+2 11709,18645,345 2 3634
+3 11709,18645,345 2 3635
+4 11709,18300 2 3636
+5 11709,18300,345 2 3637
+6 11709,18645,345 2 3638
+7 11709,18300 2 3639
+8 11709,18645,345 2 3640
+9 11709,18645,345 2 3641
+: 5856,13965 0 3642
+; 5856,13965,3375 0 3643
+< 26346,16068 0 3644
+= 17565,12540 0 3645
+> 26346,16068 0 3646
+? 11709,18300 2 3647
+at 26346,16950,4131 2 3648
+@ "
+A 13662,18300 2 3649
+B 13662,18300 2 3650
+C 12684,18645,345 2 3651
+D 13662,18300 2 3652
+E 13662,18285 2 3653
+F 13173,18300 2 3654
+G 13662,18645,345 2 3655
+H 15126,18300 2 3656
+I 7806,18300 2 3657
+J 11220,18300,345 2 3658
+K 14637,18300 2 3659
+L 12198,18300 2 3660
+M 18051,18300 2 3661
+N 14637,18300 2 3662
+O 13662,18645,345 2 3663
+P 13173,18300 2 3664
+Q 14148,18645,2553 2 3665
+R 15126,18300,345 2 3666
+S 12198,18645,345 2 3667
+T 13662,18300 2 3668
+U 13173,18300,345 2 3669
+V 14148,18300 2 3670
+W 19515,18300 2 3671
+X 13662,18300 2 3672
+Y 13173,18300 2 3673
+Z 12198,18300 2 3674
+lB 5856,18300,5085 3 3675
+[ "
+rs 5856,18645,345 2 3676
+\ "
+rB 5856,18300,5085 3 3677
+] "
+ha 13173,19758 2 51875
+_ 13173,191367,6588 3 3679
+oq 5856,18645 2 51808
+` "
+a 13662,14250,345 0 3681
+b 12684,18300,345 2 3682
+c 11220,14250,345 0 3683
+d 12684,18300,345 2 3684
+e 11709,14250,345 0 3685
+f 8781,18645 2 3686
+g 13662,15165,4605 1 3687
+h 13173,18300 2 3688
+i 6831,18705 2 3689
+j 8295,18705,4605 3 3690
+k 13173,18300 2 3691
+l 6831,18300 2 3692
+m 19515,14250 0 3693
+n 13173,14250 0 3694
+o 12198,14250,345 0 3695
+p 12684,14250,4290 1 3696
+q 12684,14250,4290 1 3697
+r 9759,14250 0 3698
+s 11220,14250,345 0 3699
+t 8295,17265,345 2 3700
+u 13173,13905,345 0 3701
+v 11709,13905 0 3702
+w 17565,13905 0 3703
+x 12198,13905 0 3704
+y 12198,13905,4605 1 3705
+z 10245,13905 0 3706
+lC 13173,19935,6210 3 3707
+{ "
+ba 13173,19758,6588 3 3708
+| "
+rC 13173,19935,6210 3 3709
+} "
+ti 26346,9435 0 51876
+char192 13662,23355 2 3776
+`A "
+char194 13662,22755 2 3778
+^A "
+char200 13662,23355 2 3784
+`E "
+char202 13662,22755 2 3786
+^E "
+char203 13662,23325 2 3787
+:E "
+char206 7806,22755 2 3790
+^I "
+char207 7806,23325 2 3791
+:I "
+char180 11709,19305 2 3764
+aa "
+ga 11709,19305 2 3680
+a^ 11709,18180 2 3678
+^ "
+char168 11709,18750 2 3752
+ad "
+a~ 11709,18654 2 3710
+~ "
+char217 13173,23355,345 2 3801
+`U "
+char219 13173,22755,345 2 3803
+^U "
+char221 13173,23355 2 3805
+'Y "
+char253 12198,19305,4605 3 3837
+'y "
+char176 11709,18645 2 3760
+de "
+char199 12684,18645,4725 3 3783
+,C "
+char231 11220,14250,4737 1 3815
+,c "
+char209 14637,23229 2 3793
+~N "
+char241 13173,18654 2 3825
+~n "
+char161 6342,13956,4344 1 3745
+r! "
+char191 11709,13956,4344 1 3775
+r? "
+char164 17565,15834 0 3748
+Cs "
+char163 11709,18645,345 2 3747
+Po "
+char165 11709,18300 2 3749
+Ye "
+char167 11709,19605,6420 3 3751
+sc "
+Fn 11709,18645 2 51871
+char162 11709,16917 2 3746
+ct "
+char226 13662,18180,345 2 3810
+^a "
+char234 11709,18180,345 2 3818
+^e "
+char244 12198,18180,345 2 3828
+^o "
+char251 13173,18180,345 2 3835
+^u "
+char225 13662,19305,345 2 3809
+'a "
+char233 11709,19305,345 2 3817
+'e "
+char243 12198,19305,345 2 3827
+'o "
+char250 13173,19305,345 2 3834
+'u "
+char224 13662,19305,345 2 3808
+`a "
+char232 11709,19305,345 2 3816
+`e "
+char242 12198,19305,345 2 3826
+`o "
+char249 13173,19305,345 2 3833
+`u "
+char228 13662,18750,345 2 3812
+:a "
+char235 11709,18750,345 2 3819
+:e "
+char246 12198,18750,345 2 3830
+:o "
+char252 13173,18750,345 2 3836
+:u "
+char197 13662,25200 2 3781
+oA "
+char238 6831,18180 2 3822
+^i "
+char216 13662,18645,345 2 3800
+/O "
+char198 22932,18285 2 3782
+AE "
+char229 13662,21195,345 2 3813
+oa "
+char237 6831,19305 2 3821
+'i "
+char248 12198,14250,345 0 3832
+/o "
+char230 18051,14250,345 0 3814
+ae "
+char196 13662,23325 2 3780
+:A "
+char236 6831,19305 2 3820
+`i "
+char214 13662,23325,345 2 3798
+:O "
+char220 13173,23325,345 2 3804
+:U "
+char201 13662,23355 2 3785
+'E "
+char239 6831,18750 2 3823
+:i "
+char223 13173,18645 2 3807
+ss "
+char212 13662,22755,345 2 3796
+^O "
+char193 13662,23355 2 3777
+'A "
+char195 13662,23229 2 3779
+~A "
+char227 13662,18654,345 2 3811
+~a "
+char208 13662,18300 2 3792
+-D "
+char240 12198,19083,345 2 3824
+Sd "
+char205 7806,23355 2 3789
+'I "
+char204 7806,23355 2 3788
+`I "
+char211 13662,23355,345 2 3795
+'O "
+char210 13662,23355,345 2 3794
+`O "
+char213 13662,23229,345 2 3797
+~O "
+char245 12198,18654,345 2 3829
+~o "
+vS 12198,22755,345 2 51795
+vs 11220,18180,345 2 51827
+char218 13173,23355,345 2 3802
+'U "
+:Y 13173,23325 2 51801
+char255 12198,18750,4605 3 3839
+:y "
+char222 13173,18300 2 3806
+TP "
+char254 12684,18300,4290 3 3838
+Tp "
+char181 14637,10800,5193 1 3765
+char182 12198,19635,4200 3 3766
+ps "
+char190 17565,18645,345 2 3774
+34 "
+\- 17565,10200 0 51757
+char188 17565,18645,345 2 3772
+14 "
+char189 17565,18645,345 2 3773
+12 "
+char170 11709,18645 2 3754
+Of "
+char186 11709,18645 2 3770
+Om "
+char171 12198,12195 0 3755
+Fo "
+char187 12198,12195 0 3771
+Fc "
+char177 17565,16500 0 3761
+char166 13173,19083,5916 3 3750
+bb "
+char169 13173,19725 2 3753
+co "
+char172 17565,13479 0 3756
+no "
+char174 13173,19725 2 3758
+rg "
+char178 7806,18480 2 3762
+S2 "
+char179 7806,18480 2 3763
+S3 "
+char184 11709,108,4737 1 3768
+ac "
+char185 7806,18300 2 3769
+S1 "
+char215 17565,16782 0 3799
+char247 17565,15045 0 3831
+char183 5856,11745 0 3767
+fm 5856,18645 2 51873
+sd 10245,18645 2 51874
+dg 11709,18300,4575 3 51755
+tm 16101,17550 2 51796
+ah 11709,18180 2 51935
+ao 11709,21195 2 51930
+f/ 3903,18645,345 2 51759
+em 17565,8295 0 51789
+en 11709,8295 0 51790
+dd 11709,18300,4575 3 51773
+.i 6831,13905 0 51957
+aq 5856,18645 2 3623
+bu 13173,14226 0 51889
+'C 12684,23355,345 2 20166
+'c 11220,19305,345 2 20198
+lq 10734,18645 2 51838
+rq 10734,18645 2 51746
+Bq 10734,3615,3705 0 51772
+vz 10245,18180 2 51834
+fi 15612,18705 2 51881
+fl 15612,18645 2 51882
+ff 17076,18645 2 51883
+Fi 24396,18705 2 51884
+Fl 24396,18645 2 51885
+ij 14637,18705,4605 3 51958
+bq 5856,3615,3705 0 51756
+%0 23418,18645,345 2 51901
+char175 11709,16920 2 3759
+a- "
+ab 11709,19080 2 51926
+a. 11709,18750 2 51927
+oe 18051,14250,345 0 51823
+OE 20979,18645,345 2 51791
+fo 7806,12195 0 51886
+fc 7806,12195 0 51887
+sq 19029,15624 0 51899
+/L 12198,18300 2 51944
+/l 6831,18300 2 51960
+a" 11709,19305 2 51933
+ho 11709,1062,4353 1 51934
+vZ 12198,22755 2 51802
+IJ 19029,18300,345 2 51942
diff --git a/font/devlj4/CORONET b/font/devlj4/CORONET
new file mode 100644
index 00000000..e892e18c
--- /dev/null
+++ b/font/devlj4/CORONET
@@ -0,0 +1,348 @@
+name CORONET
+spacewidth 13227
+slant 12.000000
+pcltypeface 4102
+pclproportional 0
+pclweight 0
+pclstyle 1
+charset
+! 13227,18990,330 2 3617
+" 13227,18990 2 3618
+sh 13227,21309,2451 2 3619
+# "
+Do 13227,19320,1074 2 3620
+$ "
+% 13227,19320,330 2 3621
+& 13227,19320,330 2 3622
+' 13227,19320 2 51751
+( 13227,19320,1935 2 3624
+) 13227,19320,1935 2 3625
+* 13227,18990 2 3626
++ 13227,15075 0 3627
+, 13227,1785,2250 0 3628
+char173 13227,7995 0 3629
+hy "
+- "
+. 13227,2100,330 0 3630
+sl 13227,19545,330 2 3631
+/ "
+0 13227,19320,330 2 3632
+1 13227,19320 2 3633
+2 13227,19320 2 3634
+3 13227,19320,330 2 3635
+4 13227,19320 2 3636
+5 13227,18990,330 2 3637
+6 13227,19320,330 2 3638
+7 13227,18990 2 3639
+8 13227,19320,330 2 3640
+9 13227,19320,330 2 3641
+: 13227,12492,330 0 3642
+; 13227,12492,2250 0 3643
+< 13227,15063 0 3644
+= 13227,11721 0 3645
+> 13227,15063 0 3646
+? 13227,19320,330 2 3647
+at 13227,19320,330 2 3648
+@ "
+A 13227,18990 2 3649
+B 13227,18990 2 3650
+C 13227,19320,330 2 3651
+D 13227,18990 2 3652
+E 13227,18990 2 3653
+F 13227,18990 2 3654
+G 13227,19320,330 2 3655
+H 13227,18990 2 3656
+I 13227,18990 2 3657
+J 13227,18990,330 2 3658
+K 13227,18990 2 3659
+L 13227,18990 2 3660
+M 13227,18990 2 3661
+N 13227,18990 2 3662
+O 13227,19320,330 2 3663
+P 13227,18990 2 3664
+Q 13227,19320,2778 2 3665
+R 13227,18990 2 3666
+S 13227,19320,330 2 3667
+T 13227,18990 2 3668
+U 13227,18990,330 2 3669
+V 13227,18990 2 3670
+W 13227,18990 2 3671
+X 13227,18990 2 3672
+Y 13227,18990 2 3673
+Z 13227,18990 2 3674
+lB 13227,18990,2940 2 3675
+[ "
+rs 13227,19545,330 2 3676
+\ "
+rB 13227,18990,2940 2 3677
+] "
+ha 13227,19758 2 51875
+_ 13227,191367,6588 3 3679
+oq 13227,19326 2 51808
+` "
+a 13227,14355,330 0 3681
+b 13227,19545,330 2 3682
+c 13227,14355,330 0 3683
+d 13227,19545,330 2 3684
+e 13227,14355,330 0 3685
+f 13227,19335 2 3686
+g 13227,14355,4350 0 3687
+h 13227,19545 2 3688
+i 13227,18780 2 3689
+j 13227,18780,4350 2 3690
+k 13227,19545 2 3691
+l 13227,19545 2 3692
+m 13227,14355 0 3693
+n 13227,14355 0 3694
+o 13227,14355,330 0 3695
+p 13227,14355,5475 1 3696
+q 13227,14355,5475 1 3697
+r 13227,14355 0 3698
+s 13227,14355,330 0 3699
+t 13227,18495,330 2 3700
+u 13227,14025,330 0 3701
+v 13227,14025 0 3702
+w 13227,14025 0 3703
+x 13227,14025 0 3704
+y 13227,14025,4350 0 3705
+z 13227,14025 0 3706
+lC 13227,20130,6075 3 3707
+{ "
+ba 13227,19758,6588 3 3708
+| "
+rC 13227,20130,6075 3 3709
+} "
+ti 13227,10485 0 51876
+char192 13227,24630 2 3776
+`A "
+char194 13227,24810 2 3778
+^A "
+char200 13227,24630 2 3784
+`E "
+char202 13227,24810 2 3786
+^E "
+char203 13227,23115 2 3787
+:E "
+char206 13227,24810 2 3790
+^I "
+char207 13227,23115 2 3791
+:I "
+char180 13227,19725 2 3764
+aa "
+ga 13227,19725 2 3680
+a^ 13227,19905 2 3678
+^ "
+char168 13227,18195 2 3752
+ad "
+a~ 13227,18873 2 3710
+~ "
+char217 13227,24630,330 2 3801
+`U "
+char219 13227,24810,330 2 3803
+^U "
+char221 13227,24630 2 3805
+'Y "
+char253 13227,19725,4350 2 3837
+'y "
+char176 13227,19320 2 3760
+de "
+char199 13227,19320,5325 3 3783
+,C "
+char231 13227,14355,5295 1 3815
+,c "
+char209 13227,23814 2 3793
+~N "
+char241 13227,18873 2 3825
+~n "
+char161 13227,14271,5049 1 3745
+r! "
+char191 13227,14214,5436 1 3775
+r? "
+char164 13227,15684 0 3748
+Cs "
+char163 13227,19320,330 2 3747
+Po "
+char165 13227,18990 2 3749
+Ye "
+char167 13227,19320,1344 2 3751
+sc "
+Fn 13227,19335,3540 2 51871
+char162 13227,19320,330 2 3746
+ct "
+char226 13227,19905,330 2 3810
+^a "
+char234 13227,19905,330 2 3818
+^e "
+char244 13227,19905,330 2 3828
+^o "
+char251 13227,19905,330 2 3835
+^u "
+char225 13227,19725,330 2 3809
+'a "
+char233 13227,19725,330 2 3817
+'e "
+char243 13227,19725,330 2 3827
+'o "
+char250 13227,19725,330 2 3834
+'u "
+char224 13227,19725,330 2 3808
+`a "
+char232 13227,19725,330 2 3816
+`e "
+char242 13227,19725,330 2 3826
+`o "
+char249 13227,19725,330 2 3833
+`u "
+char228 13227,18195,330 2 3812
+:a "
+char235 13227,18195,330 2 3819
+:e "
+char246 13227,18195,330 2 3830
+:o "
+char252 13227,18195,330 2 3836
+:u "
+char197 13227,24810 2 3781
+oA "
+char238 13227,19905 2 3822
+^i "
+char216 13227,19320,342 2 3800
+/O "
+char198 13227,18990 2 3782
+AE "
+char229 13227,19905,330 2 3813
+oa "
+char237 13227,19725 2 3821
+'i "
+char248 13227,14895,735 0 3832
+/o "
+char230 13227,14355,330 0 3814
+ae "
+char196 13227,23115 2 3780
+:A "
+char236 13227,19725 2 3820
+`i "
+char214 13227,23115,330 2 3798
+:O "
+char220 13227,23115,330 2 3804
+:U "
+char201 13227,24630 2 3785
+'E "
+char239 13227,18195 2 3823
+:i "
+char223 13227,19335,330 2 3807
+ss "
+char212 13227,24810,330 2 3796
+^O "
+char193 13227,24630 2 3777
+'A "
+char195 13227,23814 2 3779
+~A "
+char227 13227,18873,330 2 3811
+~a "
+char208 13227,18990 2 3792
+-D "
+char240 13227,19545,330 2 3824
+Sd "
+char205 13227,24630 2 3789
+'I "
+char204 13227,24630 2 3788
+`I "
+char211 13227,24630,330 2 3795
+'O "
+char210 13227,24630,330 2 3794
+`O "
+char213 13227,23814,330 2 3797
+~O "
+char245 13227,18873,330 2 3829
+~o "
+vS 13227,24810,330 2 51795
+vs 13227,19905,330 2 51827
+char218 13227,24630,330 2 3802
+'U "
+:Y 13227,23115 2 51801
+char255 13227,18195,4350 2 3839
+:y "
+char222 13227,18990 2 3806
+TP "
+char254 13227,19545,5475 3 3838
+Tp "
+char181 13227,14025,4350 0 3765
+char182 13227,19635,4200 2 3766
+ps "
+char190 13227,19110,3825 2 3774
+34 "
+\- 13227,9945 0 51757
+char188 13227,19110,3825 2 3772
+14 "
+char189 13227,19110,3825 2 3773
+12 "
+char170 13227,19320 2 3754
+Of "
+char186 13227,19320 2 3770
+Om "
+char171 13227,13710 0 3755
+Fo "
+char187 13227,13710 0 3771
+Fc "
+char177 13227,15075 0 3761
+char166 13227,19083,5916 3 3750
+bb "
+char169 13227,19635 2 3753
+co "
+char172 13227,12501 0 3756
+no "
+char174 13227,19635 2 3758
+rg "
+char178 13227,19110 2 3762
+S2 "
+char179 13227,19110 2 3763
+S3 "
+char184 13227,0,5295 1 3768
+ac "
+char185 13227,19110 2 3769
+S1 "
+char215 13227,14814 0 3799
+char247 13227,14655 0 3831
+char183 13227,11007 0 3767
+fm 13227,18990 2 51873
+sd 13227,18990 2 51874
+dg 13227,18990 2 51755
+tm 13227,17850 2 51796
+ah 13227,19905 2 51935
+ao 13227,19905 2 51930
+f/ 13227,15675,777 0 51759
+em 13227,7710 0 51789
+en 13227,7710 0 51790
+dd 13227,18990 2 51773
+.i 13227,14025 0 51957
+aq 13227,18990 2 3623
+bu 13227,12714 0 51889
+'C 13227,24630,330 2 20166
+'c 13227,19725,330 2 20198
+lq 13227,19326 2 51838
+rq 13227,19320 2 51746
+Bq 13227,2214,2091 0 51772
+vz 13227,19905 2 51834
+fi 13227,19335 2 51881
+fl 13227,19335 2 51882
+ff 13227,19335 2 51883
+Fi 13227,19335 2 51884
+Fl 13227,19335 2 51885
+ij 13227,18780,4350 2 51958
+bq 13227,2214,2091 0 51756
+%0 13227,19320,330 2 51901
+char175 13227,18051 2 3759
+a- "
+ab 13227,19350 2 51926
+a. 13227,18195 2 51927
+oe 13227,14355,330 0 51823
+OE 13227,19320,330 2 51791
+fo 13227,13710 0 51886
+fc 13227,13710 0 51887
+sq 13227,14106 0 51899
+/L 13227,18990 2 51944
+/l 13227,19545 2 51960
+a" 13227,19725 2 51933
+ho 13227,735,4086 0 51934
+vZ 13227,24810 2 51802
+IJ 13227,18990,330 2 51942
diff --git a/font/devlj4/CR b/font/devlj4/CR
new file mode 100644
index 00000000..9a87b1a3
--- /dev/null
+++ b/font/devlj4/CR
@@ -0,0 +1,347 @@
+name CR
+spacewidth 15873
+pcltypeface 4099
+pclproportional 0
+pclweight 0
+pclstyle 0
+charset
+! 15873,15060,330 0 3617
+" 15873,15060 0 3618
+sh 15873,16827,2040 2 3619
+# "
+Do 15873,17247,3642 2 3620
+$ "
+% 15873,16380,330 2 3621
+& 15873,14187,330 0 3622
+' 15873,15060 0 51751
+( 15873,17070,2580 2 3624
+) 15873,17070,2580 2 3625
+* 15873,15060 0 3626
++ 15873,11385 0 3627
+, 15873,3195,3420 0 3628
+char173 15873,7275 0 3629
+hy "
+- "
+. 15873,2805,330 0 3630
+sl 15873,18465,3765 2 3631
+/ "
+0 15873,15390,330 0 3632
+1 15873,15060 0 3633
+2 15873,15390 0 3634
+3 15873,15390,330 0 3635
+4 15873,15060 0 3636
+5 15873,15060,330 0 3637
+6 15873,15390,330 0 3638
+7 15873,15060 0 3639
+8 15873,15390,330 0 3640
+9 15873,15390,330 0 3641
+: 15873,9705,393 0 3642
+; 15873,9705,3420 0 3643
+< 15873,10647,3 0 3644
+= 15873,8451 0 3645
+> 15873,10647,3 0 3646
+? 15873,15390,330 0 3647
+at 15873,14391,363 0 3648
+@ "
+A 15873,15060 0 3649
+B 15873,15060 0 3650
+C 15873,15390,330 0 3651
+D 15873,15060 0 3652
+E 15873,15060 0 3653
+F 15873,15060 0 3654
+G 15873,15390,330 0 3655
+H 15873,15060 0 3656
+I 15873,15060 0 3657
+J 15873,15060,330 0 3658
+K 15873,15060 0 3659
+L 15873,15060 0 3660
+M 15873,15060 0 3661
+N 15873,15060 0 3662
+O 15873,15390,330 0 3663
+P 15873,15060 0 3664
+Q 15873,15390,3360 0 3665
+R 15873,15060 0 3666
+S 15873,15390,330 0 3667
+T 15873,15060 0 3668
+U 15873,15060,330 0 3669
+V 15873,15060 0 3670
+W 15873,15060 0 3671
+X 15873,15060 0 3672
+Y 15873,15060 0 3673
+Z 15873,15060 0 3674
+lB 15873,17070,2580 2 3675
+[ "
+rs 15873,18465,3765 2 3676
+\ "
+rB 15873,17070,2580 2 3677
+] "
+ha 15873,19758 2 51875
+_ 15873,191367,6588 3 3679
+oq 15873,15060 0 51808
+` "
+a 15873,11775,330 0 3681
+b 15873,16500,330 2 3682
+c 15873,11775,330 0 3683
+d 15873,16500,330 2 3684
+e 15873,11775,330 0 3685
+f 15873,16500 2 3686
+g 15873,11775,5145 1 3687
+h 15873,16500 2 3688
+i 15873,17235 2 3689
+j 15873,17235,5145 3 3690
+k 15873,16500 2 3691
+l 15873,16500 2 3692
+m 15873,11775 0 3693
+n 15873,11775 0 3694
+o 15873,11775,330 0 3695
+p 15873,11775,5145 1 3696
+q 15873,11775,5145 1 3697
+r 15873,11775 0 3698
+s 15873,11775,330 0 3699
+t 15873,14826,330 0 3700
+u 15873,11445,330 0 3701
+v 15873,11445 0 3702
+w 15873,11445 0 3703
+x 15873,11445 0 3704
+y 15873,11445,5145 1 3705
+z 15873,11445 0 3706
+lC 15873,20130,6075 3 3707
+{ "
+ba 15873,19758,6588 3 3708
+| "
+rC 15873,20130,6075 3 3709
+} "
+ti 15873,7233 0 51876
+char192 15873,21180 2 3776
+`A "
+char194 15873,21180 2 3778
+^A "
+char200 15873,21180 2 3784
+`E "
+char202 15873,21180 2 3786
+^E "
+char203 15873,20670 2 3787
+:E "
+char206 15873,21180 2 3790
+^I "
+char207 15873,20670 2 3791
+:I "
+char180 15873,17565 2 3764
+aa "
+ga 15873,17565 2 3680
+a^ 15873,17565 2 3678
+^ "
+char168 15873,16905 2 3752
+ad "
+a~ 15873,16830 2 3710
+~ "
+char217 15873,21180,330 2 3801
+`U "
+char219 15873,21180,330 2 3803
+^U "
+char221 15873,21180 2 3805
+'Y "
+char253 15873,17565,5145 3 3837
+'y "
+char176 15873,15390 0 3760
+de "
+char199 15873,15390,5175 1 3783
+,C "
+char231 15873,11775,4815 1 3815
+,c "
+char209 15873,20571 2 3793
+~N "
+char241 15873,16830 2 3825
+~n "
+char161 15873,11880,3510 0 3745
+r! "
+char191 15873,11898,3822 0 3775
+r? "
+char164 15873,15684 2 3748
+Cs "
+char163 15873,15390,330 0 3747
+Po "
+char165 15873,15060 0 3749
+Ye "
+char167 15873,15390,1905 0 3751
+sc "
+Fn 15873,15090,4350 0 51871
+char162 15873,16179,1431 2 3746
+ct "
+char226 15873,17565,330 2 3810
+^a "
+char234 15873,17565,330 2 3818
+^e "
+char244 15873,17565,330 2 3828
+^o "
+char251 15873,17565,330 2 3835
+^u "
+char225 15873,17565,330 2 3809
+'a "
+char233 15873,17565,330 2 3817
+'e "
+char243 15873,17565,330 2 3827
+'o "
+char250 15873,17565,330 2 3834
+'u "
+char224 15873,17565,330 2 3808
+`a "
+char232 15873,17565,330 2 3816
+`e "
+char242 15873,17565,330 2 3826
+`o "
+char249 15873,17565,330 2 3833
+`u "
+char228 15873,16905,330 2 3812
+:a "
+char235 15873,16905,330 2 3819
+:e "
+char246 15873,16905,330 2 3830
+:o "
+char252 15873,16905,330 2 3836
+:u "
+char197 15873,21690 2 3781
+oA "
+char238 15873,17565 2 3822
+^i "
+char216 15873,15591,612 2 3800
+/O "
+char198 15873,15060 0 3782
+AE "
+char229 15873,17997,330 2 3813
+oa "
+char237 15873,17565 2 3821
+'i "
+char248 15873,11856,459 0 3832
+/o "
+char230 15873,11775,330 0 3814
+ae "
+char196 15873,20670 2 3780
+:A "
+char236 15873,17565 2 3820
+`i "
+char214 15873,20670,330 2 3798
+:O "
+char220 15873,20670,330 2 3804
+:U "
+char201 15873,21180 2 3785
+'E "
+char239 15873,16905 2 3823
+:i "
+char223 15873,16500,330 2 3807
+ss "
+char212 15873,21180,330 2 3796
+^O "
+char193 15873,21180 2 3777
+'A "
+char195 15873,20571 2 3779
+~A "
+char227 15873,16830,330 2 3811
+~a "
+char208 15873,15060 0 3792
+-D "
+char240 15873,18015,330 2 3824
+Sd "
+char205 15873,21180 2 3789
+'I "
+char204 15873,21180 2 3788
+`I "
+char211 15873,21180,330 2 3795
+'O "
+char210 15873,21180,330 2 3794
+`O "
+char213 15873,20571,330 2 3797
+~O "
+char245 15873,16830,330 2 3829
+~o "
+vS 15873,21180,330 2 51795
+vs 15873,17565,330 2 51827
+char218 15873,21180,330 2 3802
+'U "
+:Y 15873,20670 2 51801
+char255 15873,16905,5145 3 3839
+:y "
+char222 15873,15060 0 3806
+TP "
+char254 15873,16500,5145 3 3838
+Tp "
+char181 15873,11445,5595 1 3765
+char182 15873,19635,4080 2 3766
+ps "
+char190 15873,15519,2673 2 3774
+34 "
+\- 15873,6435 0 51757
+char188 15873,15519,2673 2 3772
+14 "
+char189 15873,15519,2673 2 3773
+12 "
+char170 15873,15390 0 3754
+Of "
+char186 15873,15390 0 3770
+Om "
+char171 15873,11490 0 3755
+Fo "
+char187 15873,11490 0 3771
+Fc "
+char177 15873,11385,2835 0 3761
+char166 15873,19083,5916 3 3750
+bb "
+char169 15873,19635 2 3753
+co "
+char172 15873,8865 0 3756
+no "
+char174 15873,19635 2 3758
+rg "
+char178 15873,15240 0 3762
+S2 "
+char179 15873,15240 0 3763
+S3 "
+char184 15873,0,4815 1 3768
+ac "
+char185 15873,15060 0 3769
+S1 "
+char215 15873,11340 0 3799
+char247 15873,10530 0 3831
+char183 15873,8931 0 3767
+fm 15873,15060 0 51873
+sd 15873,15060 0 51874
+dg 15873,15060,1290 0 51755
+tm 15873,17850 2 51796
+ah 15873,17565 2 51935
+ao 15873,17997 2 51930
+f/ 15873,15519,2673 2 51759
+em 15873,7275 0 51789
+en 15873,7275 0 51790
+dd 15873,15060,1290 0 51773
+.i 15873,11445 0 51957
+aq 15873,15060 0 3623
+bu 15873,12714 0 51889
+'C 15873,21180,330 2 20166
+'c 15873,17565,330 2 20198
+lq 15873,15060 0 51838
+rq 15873,15060 0 51746
+Bq 15873,3495,3120 0 51772
+vz 15873,17565 2 51834
+fi 15873,17235 2 51881
+fl 15873,16500 2 51882
+ff 15873,16500 2 51883
+Fi 15873,16500 2 51884
+Fl 15873,16500 2 51885
+ij 15873,17235,5145 3 51958
+bq 15873,3495,3120 0 51756
+%0 15873,16380,330 2 51901
+char175 15873,15726 2 3759
+a- "
+ab 15873,16725 2 51926
+a. 15873,16905 2 51927
+oe 15873,11775,330 0 51823
+OE 15873,15060 0 51791
+fo 15873,10845 0 51886
+fc 15873,10845 0 51887
+sq 15873,14106 0 51899
+/L 15873,15060 0 51944
+/l 15873,16500 2 51960
+a" 15873,18195 2 51933
+ho 15873,0,4263 0 51934
+vZ 15873,21180 2 51802
+IJ 15873,15060,2850 0 51942
diff --git a/font/devlj4/DESC.in b/font/devlj4/DESC.in
new file mode 100644
index 00000000..b726647f
--- /dev/null
+++ b/font/devlj4/DESC.in
@@ -0,0 +1,9 @@
+hor 1
+vert 1
+sizescale 4
+sizes 1-3999 0
+styles R I B BI
+fonts 6 0 0 0 0 0 S
+family T
+tcommand
+postpro grolj4
diff --git a/font/devlj4/GB b/font/devlj4/GB
new file mode 100644
index 00000000..3c704551
--- /dev/null
+++ b/font/devlj4/GB
@@ -0,0 +1,732 @@
+name GB
+spacewidth 7317
+pcltypeface 4197
+pclproportional 1
+pclweight 3
+pclstyle 0
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -2925
+P . -3903
+P , -3903
+V A -3414
+A V -4389
+T o -4389
+T r -2925
+T c -3903
+T e -3903
+T d -3903
+T s -2925
+T y -3414
+T a -2925
+T w -3414
+T u -2925
+L T -2925
+L Y -2925
+Y o -3903
+Y e -3414
+Y a -3414
+A W -4389
+W A -3414
+T A -2925
+V o -3414
+V e -2925
+V a -2925
+Y A -3414
+F A -2439
+F . -3903
+F , -3903
+A T -2925
+A Y -3414
+v . -2439
+v , -2439
+y . -2439
+y , -2439
+T . -2925
+T , -2925
+L W -2925
+P A -2439
+V . -3903
+V , -3903
+Y . -3414
+Y , -3414
+W o -3414
+W e -2925
+W a -2925
+W . -3903
+W , -3903
+r . -1950
+r , -1950
+w . -975
+w , -975
+Y u -2439
+A v -1950
+A y -1950
+A w -1950
+o . -1461
+o , -1461
+p . -1461
+p , -1461
+e . -975
+e , -975
+b . -1461
+b , -1461
+O T -1950
+O V -1950
+O Y -1950
+O . -1950
+O , -1950
+L y -975
+V y -1950
+V u -1950
+V O -1950
+V G -1950
+V C -1950
+V Q -1950
+D T -1950
+D V -1950
+D Y -1950
+D . -1950
+D , -1950
+Y O -1950
+Y G -1950
+Y C -1950
+Y Q -1950
+F o -1461
+F e -975
+F a -975
+O A -975
+O W -1950
+L U -486
+R T -1950
+R V -1950
+R Y -1950
+R W -1950
+G T -486
+P o -1461
+P g -975
+P e -975
+P a -975
+D A -975
+D W -1950
+B T -975
+B Y -975
+B . -975
+B , -975
+A O -975
+A G -975
+A C -975
+A U -1461
+A Q -975
+W r -1950
+W y -1950
+W u -1950
+W O -1950
+W G -1950
+W C -1950
+W Q -1950
+J A -486
+J . -486
+J , -486
+U A -1461
+U . -1950
+U , -1950
+Q A -975
+Q W -1950
+T O -1950
+T G -1950
+T C -1950
+T Q -1950
+O X -1461
+L o -486
+G V -486
+G Y -486
+G W -486
+G . -486
+G , -486
+P T -975
+P V -975
+P Y -975
+D X -1461
+B V -975
+B X -975
+B A -975
+B W -975
+S . -975
+S , -975
+X o -1461
+X e -975
+X y -1461
+X O -1461
+X G -1461
+X C -1461
+X Q -1461
+A o -1461
+A e -975
+Q X -1461
+K o -1461
+K e -975
+K y -975
+K w -975
+K O -975
+K G -975
+K C -975
+K Q -975
+o v -1461
+o y -1461
+o x -1461
+o w -1461
+h v -975
+h y -975
+n v -975
+n y -975
+m v -975
+m y -975
+r g -975
+p v -975
+p y -975
+p x -975
+v o -1461
+v g -975
+v c -975
+v d -975
+v a -975
+v q -975
+e v -486
+e y -486
+b v -975
+b y -975
+b w -975
+s . -486
+s , -486
+y o -1461
+y g -975
+y c -975
+y d -975
+y a -975
+y q -975
+x o -1461
+x c -975
+x e -975
+x d -975
+x q -975
+a v -975
+a y -975
+a w -975
+w o -1461
+w g -975
+w c -975
+w d -975
+w a -975
+w q -975
+T S -975
+R o -1461
+R y -1461
+R O -1461
+R G -1461
+R C -1461
+R U -1461
+R Q -1461
+G X -486
+G A -486
+P s -486
+P Z -975
+P X -975
+P W -975
+V S -975
+S A -975
+Y S -975
+A t -486
+A c -975
+A d -975
+A q -975
+W S -975
+K c -975
+o f -486
+h w -975
+n w -975
+m w -975
+r o -1461
+r c -975
+r e -975
+r d -975
+r a -975
+r q -975
+p w -975
+v e -975
+v s -486
+e x -486
+e w -486
+y e -975
+y s -486
+f o -1461
+f c -975
+f e -975
+f d -975
+f q -975
+w e -975
+w s -486
+k o -975
+k c -486
+k e -486
+k d -486
+k q -486
+O Z -975
+R e -975
+G Z -486
+E o -486
+E v -975
+E y -975
+E w -975
+Z o -486
+Z y -975
+Z w -975
+D Z -975
+B Z -975
+J o -486
+U g -486
+t o -975
+t c -486
+t e -486
+t d -486
+t q -486
+o t -486
+o g -486
+o z -975
+o j -486
+r s -486
+g o -975
+g c -486
+g e -486
+g d -486
+g q -486
+p z -486
+e z -486
+z o -975
+z c -486
+z e -486
+z d -486
+z q -486
+b z -486
+C o -486
+C y -975
+B o -486
+B y -486
+B S -486
+B U -486
+U o -975
+U c -486
+U e -486
+U d -486
+U s -486
+U a -486
+U q -486
+L ' -2925
+T char173 -3414
+T hy -3414
+T - -3414
+T en -3414
+T em -3414
+A ' -2925
+char173 T -3414
+hy T -3414
+- T -3414
+en T -3414
+em T -3414
+Y char173 -2439
+Y hy -2439
+Y - -2439
+Y en -2439
+Y em -2439
+p ' -1461
+e ' -486
+b ' -975
+a ' -975
+V char173 -1950
+V hy -1950
+V - -1950
+V en -1950
+V em -1950
+h ' -975
+n ' -975
+m ' -975
+R ' -1461
+W char173 -1950
+W hy -1950
+W - -1950
+W en -1950
+W em -1950
+' d -1461
+X char173 -1461
+X hy -1461
+X - -1461
+X en -1461
+X em -1461
+A char173 -975
+A hy -975
+A - -975
+A en -975
+A em -975
+K char173 -975
+K hy -975
+K - -975
+K en -975
+K em -975
+' s -486
+char173 X -1461
+hy X -1461
+- X -1461
+char173 A -975
+hy A -975
+- A -975
+en X -1461
+en A -975
+em X -1461
+R char173 -1461
+R hy -1461
+R - -1461
+R en -1461
+R em -1461
+G ' -486
+B ' -486
+charset
+! 7317,18948,390 2 3617
+" 10734,18987 2 3618
+sh 13173,17805,390 0 3619
+# "
+Do 13173,19584,1779 2 3620
+$ "
+% 21954,17805,390 0 3621
+& 22443,18165,390 0 3622
+' 6831,18555 2 51751
+( 8295,20250,6705 3 3624
+) 8295,20250,6705 3 3625
+* 13173,18555 2 3626
++ 21954,13467,87 0 3627
+, 7317,3972,4152 0 3628
+char173 7317,7575 0 3629
+hy "
+- "
+. 7317,3915,390 0 3630
+sl 13173,20250,300 2 3631
+/ "
+0 13173,17805,390 0 3632
+1 13173,17805,150 0 3633
+2 13173,17805,150 0 3634
+3 13173,17805,390 0 3635
+4 13173,17805 0 3636
+5 13173,17490,390 0 3637
+6 13173,17805,390 0 3638
+7 13173,17415,390 0 3639
+8 13173,17805,390 0 3640
+9 13173,17805,390 0 3641
+: 7317,11940,390 0 3642
+; 7317,11940,4152 0 3643
+< 26346,16068 0 3644
+= 21954,9654 0 3645
+> 26346,16068 0 3646
+? 10245,18948,390 2 3647
+at 21954,16950,4131 0 3648
+@ "
+A 20004,18939,150 2 3649
+B 17565,18315,150 2 3650
+C 20004,18555,390 2 3651
+D 21954,18555,150 2 3652
+E 16587,18315,150 2 3653
+F 16587,18315,150 2 3654
+G 21468,18555,390 2 3655
+H 23418,18315,150 2 3656
+I 10245,18315,150 2 3657
+J 9759,18315,6363 3 3658
+K 19515,18315,150 2 3659
+L 16101,18315,150 2 3660
+M 24882,18315,390 2 3661
+N 22443,18315,612 2 3662
+O 22932,18555,390 2 3663
+P 16587,18555,150 2 3664
+Q 22932,18555,5253 2 3665
+R 19515,18315,150 2 3666
+S 14148,18555,390 2 3667
+T 17565,19500,138 2 3668
+U 21468,18315,390 2 3669
+V 19515,18315,390 2 3670
+W 26346,18315,390 2 3671
+X 20004,18315,150 2 3672
+Y 18540,18315,150 2 3673
+Z 17565,19500,150 2 3674
+lB 8295,18165,4905 0 3675
+[ "
+rs 13173,20250,300 2 3676
+\ "
+rB 8295,18165,4905 0 3677
+] "
+ha 13173,19758 2 51875
+_ 13173,191367,6588 3 3679
+oq 6831,18555 2 51808
+` "
+a 12198,12420,390 0 3681
+b 14637,20250,390 2 3682
+c 11220,12420,390 0 3683
+d 14637,20250,390 2 3684
+e 11709,12420,390 0 3685
+f 9270,20250,150 2 3686
+g 14148,12420,6705 1 3687
+h 15612,20250,150 2 3688
+i 7806,19329,150 2 3689
+j 7317,19329,6705 3 3690
+k 14637,20250,150 2 3691
+l 7806,20250,150 2 3692
+m 22932,12420,150 0 3693
+n 15612,12420,150 0 3694
+o 14148,12420,390 0 3695
+p 14637,12420,6855 1 3696
+q 14637,12420,6855 1 3697
+r 11220,12420,150 0 3698
+s 9759,12420,390 0 3699
+t 9759,15585,390 0 3700
+u 15612,12420,390 0 3701
+v 14148,12180,390 0 3702
+w 20004,12180,390 0 3703
+x 14148,12180,150 0 3704
+y 13662,12180,6705 1 3705
+z 12684,12870,150 0 3706
+lC 13173,19935,6210 3 3707
+{ "
+ba 13173,19758,6588 3 3708
+| "
+rC 13173,19935,6210 3 3709
+} "
+ti 26346,9435 0 51876
+char192 20004,24810,150 2 3776
+`A "
+char194 20004,24810,150 2 3778
+^A "
+char200 16587,24810,150 2 3784
+`E "
+char202 16587,24810,150 2 3786
+^E "
+char203 16587,23505,150 2 3787
+:E "
+char206 10245,24810,150 2 3790
+^I "
+char207 10245,23505,150 2 3791
+:I "
+char180 13173,20475 2 3764
+aa "
+ga 13173,20475 2 3680
+a^ 13173,20475 2 3678
+^ "
+char168 13173,18090 0 3752
+ad "
+a~ 13173,18324 2 3710
+~ "
+char217 21468,24810,390 2 3801
+`U "
+char219 21468,24810,390 2 3803
+^U "
+char221 18540,24810,150 2 3805
+'Y "
+char253 13662,20475,6705 3 3837
+'y "
+char176 13173,17415 0 3760
+de "
+char199 20004,18555,6405 3 3783
+,C "
+char231 11220,12420,5694 0 3815
+,c "
+char209 22443,23973,612 2 3793
+~N "
+char241 15612,18324,150 2 3825
+~n "
+char161 7317,12330,7008 1 3745
+r! "
+char191 10245,12330,7008 1 3775
+r? "
+char164 13173,15834 0 3748
+Cs "
+char163 13173,17805,390 0 3747
+Po "
+char165 13173,18315,150 2 3749
+Ye "
+char167 13173,18555,6705 3 3751
+sc "
+Fn 13173,20250,6705 3 51871
+char162 13173,18012,57 0 3746
+ct "
+char226 12198,20475,390 2 3810
+^a "
+char234 11709,20475,390 2 3818
+^e "
+char244 14148,20475,390 2 3828
+^o "
+char251 15612,20475,390 2 3835
+^u "
+char225 12198,20475,390 2 3809
+'a "
+char233 11709,20475,390 2 3817
+'e "
+char243 14148,20475,390 2 3827
+'o "
+char250 15612,20475,390 2 3834
+'u "
+char224 12198,20475,390 2 3808
+`a "
+char232 11709,20475,390 2 3816
+`e "
+char242 14148,20475,390 2 3826
+`o "
+char249 15612,20475,390 2 3833
+`u "
+char228 12198,18090,390 0 3812
+:a "
+char235 11709,18090,390 0 3819
+:e "
+char246 14148,18090,390 0 3830
+:o "
+char252 15612,18090,390 0 3836
+:u "
+char197 20004,25065,150 2 3781
+oA "
+char238 7806,20475,150 2 3822
+^i "
+char216 22932,18729,390 2 3800
+/O "
+char198 25857,18315,150 2 3782
+AE "
+char229 12198,19836,390 2 3813
+oa "
+char237 7806,20475,150 2 3821
+'i "
+char248 14148,12525,804 0 3832
+/o "
+char230 18051,12420,390 0 3814
+ae "
+char196 20004,23505,150 2 3780
+:A "
+char236 7806,20475,150 2 3820
+`i "
+char214 22932,23505,390 2 3798
+:O "
+char220 21468,23505,390 2 3804
+:U "
+char201 16587,24810,150 2 3785
+'E "
+char239 7806,18090,150 0 3823
+:i "
+char223 15612,20250,390 2 3807
+ss "
+char212 22932,24810,390 2 3796
+^O "
+char193 20004,24810,150 2 3777
+'A "
+char195 20004,23973,150 2 3779
+~A "
+char227 12198,18324,390 2 3811
+~a "
+char208 21954,18555,150 2 3792
+-D "
+char240 14148,20250,390 2 3824
+Sd "
+char205 10245,24810,150 2 3789
+'I "
+char204 10245,24810,150 2 3788
+`I "
+char211 22932,24810,390 2 3795
+'O "
+char210 22932,24810,390 2 3794
+`O "
+char213 22932,23973,390 2 3797
+~O "
+char245 14148,18324,390 2 3829
+~o "
+vS 14148,24810,390 2 51795
+vs 9759,20475,390 2 51827
+char218 21468,24810,390 2 3802
+'U "
+:Y 18540,23505,150 2 51801
+char255 13662,18090,6705 1 3839
+:y "
+char222 16587,18315,153 2 3806
+TP "
+char254 14637,20250,6855 3 3838
+Tp "
+char181 14637,10800,5193 0 3765
+char182 13173,19635,4200 2 3766
+ps "
+char190 21954,17805,390 0 3774
+34 "
+\- 21954,7755 0 51757
+char188 21954,17805,390 0 3772
+14 "
+char189 21954,17805,390 0 3773
+12 "
+char170 12198,17805 0 3754
+Of "
+char186 12198,17805 0 3770
+Om "
+char171 12684,10605 0 3755
+Fo "
+char187 12684,10605 0 3771
+Fc "
+char177 21954,13467,3354 0 3761
+char166 13173,19083,5916 2 3750
+bb "
+char169 13173,19725 2 3753
+co "
+char172 21954,10560 0 3756
+no "
+char174 13173,19725 2 3758
+rg "
+char178 9270,17805 0 3762
+S2 "
+char179 9270,17805 0 3763
+S3 "
+char184 13173,57,5694 0 3768
+ac "
+char185 9270,17805 0 3769
+S1 "
+char215 21954,13470,144 0 3799
+char247 21954,13383,3 0 3831
+char183 7317,10722 0 3767
+fm 13173,17805 0 51873
+sd 13173,17805 0 51874
+dg 13173,18555,6579 3 51755
+tm 16101,17550 0 51796
+ah 13173,20475 2 51935
+ao 13173,19836 2 51930
+f/ 2928,17805,390 0 51759
+em 21954,7185 0 51789
+en 13173,7185 0 51790
+dd 13173,18555,4905 2 51773
+.i 7806,12420,150 0 51957
+aq 6831,18987 2 3623
+bu 13173,14226 0 51889
+'C 20004,24810,390 2 20166
+'c 11220,20475,390 2 20198
+lq 12198,18555 2 51838
+rq 12198,18555 2 51746
+Bq 12198,3714,3519 0 51772
+vz 12684,20475,150 2 51834
+fi 15612,20250,150 2 51881
+fl 15612,20250,150 2 51882
+ff 17076,20250,150 2 51883
+Fi 23418,20250,150 2 51884
+Fl 23418,20250,150 2 51885
+ij 15126,19329,6705 3 51958
+bq 6831,3714,3519 0 51756
+%0 30249,17805,180 0 51901
+char175 13173,17088 0 3759
+a- "
+ab 13173,17079 0 51926
+a. 13173,18471 2 51927
+oe 20979,12420,390 0 51823
+OE 28299,18555,390 2 51791
+fo 8295,10605 0 51886
+fc 8295,10605 0 51887
+sq 19029,15624 0 51899
+/L 16101,18315,150 2 51944
+/l 7806,20250,150 2 51960
+a" 13173,20475 2 51933
+ho 13173,993,4317 0 51934
+vZ 17565,24810,150 2 51802
+IJ 20004,18315,6363 3 51942
diff --git a/font/devlj4/GBI b/font/devlj4/GBI
new file mode 100644
index 00000000..9a507ce8
--- /dev/null
+++ b/font/devlj4/GBI
@@ -0,0 +1,736 @@
+name GBI
+spacewidth 6831
+slant 16.300000
+pcltypeface 4197
+pclproportional 1
+pclweight 3
+pclstyle 1
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -4878
+P . -4389
+P , -4389
+V A -4389
+A V -4389
+T o -4389
+T r -3414
+T c -3903
+T e -3903
+T d -3903
+T s -3414
+T y -3903
+T a -3903
+T w -3903
+T u -3414
+L T -3414
+L Y -3903
+Y o -3903
+Y e -3903
+Y a -4389
+A W -4389
+W A -3414
+T A -3414
+V o -2925
+V e -2925
+V a -3414
+Y A -4389
+F A -2439
+F . -3903
+F , -3903
+A T -3414
+A Y -3903
+v . -1461
+v , -1461
+y . -975
+y , -975
+T . -3414
+T , -3414
+L W -4878
+P A -2925
+V . -3903
+V , -3903
+Y . -3903
+Y , -3903
+W o -2439
+W e -2439
+W a -2925
+W . -3414
+W , -3414
+r . -1950
+r , -1950
+w . -1461
+w , -1461
+Y u -2925
+A v -1950
+A y -1950
+A w -1950
+o . -975
+o , -975
+p . -975
+p , -975
+b . -1950
+b , -1950
+O T -1950
+O V -1950
+O Y -1950
+O . -975
+O , -975
+L y -2925
+L O -1950
+L G -1950
+L C -1950
+L Q -1950
+V y -1950
+V u -1950
+V O -975
+V G -975
+V C -975
+V Q -975
+D T -1950
+D V -1950
+D Y -1950
+D . -975
+D , -975
+Y O -975
+Y G -975
+Y C -975
+Y Q -975
+F o -975
+F e -975
+F a -975
+O A -975
+O W -1950
+L U -1950
+R T -1950
+R V -1950
+R Y -1950
+R W -1950
+G T -975
+P o -975
+P e -975
+P a -1461
+D A -975
+D W -1950
+B T -975
+B Y -975
+B . -975
+B , -975
+A O -1461
+A G -1461
+A C -1461
+A U -1950
+A Q -1461
+W r -1461
+W y -1461
+W u -1461
+W O -975
+W G -975
+W C -975
+W Q -975
+J A -486
+J . -486
+J , -486
+U A -1461
+U . -1461
+U , -1461
+Q A -975
+Q W -1950
+T O -975
+T G -975
+T C -975
+T Q -975
+O X -975
+L o -975
+L e -975
+L q -486
+G V -975
+G Y -975
+G W -975
+P T -975
+P V -975
+P Y -975
+C T -486
+C V -486
+C Y -486
+D X -975
+B V -975
+B X -975
+B A -975
+B W -975
+X o -975
+X e -975
+X y -1461
+X O -975
+X G -975
+X C -975
+X Q -975
+A o -975
+A e -975
+Q X -975
+K o -975
+K e -975
+K y -1461
+K w -1461
+K O -975
+K G -975
+K C -975
+K Q -975
+o v -975
+o y -975
+o x -975
+o w -975
+h v -486
+h y -486
+n v -486
+n y -486
+m v -486
+m y -486
+p v -486
+p y -486
+p x -486
+v o -486
+b v -486
+b y -486
+b w -486
+y o -486
+x o -975
+x c -486
+x e -486
+x d -486
+x a -486
+x q -486
+w o -975
+w g -486
+w c -486
+w d -486
+w a -486
+w q -486
+T i -975
+L a -486
+R o -975
+R y -975
+R O -975
+R G -975
+R C -975
+R U -975
+R Q -975
+P Z -975
+P X -975
+P W -975
+C W -486
+V i -975
+Y i -975
+X a -486
+A g -486
+A c -975
+A d -975
+A a -486
+A q -486
+W i -975
+K c -975
+o f -486
+h w -486
+h . -486
+h , -486
+n w -486
+n . -486
+n , -486
+m w -486
+m . -486
+m , -486
+r o -975
+r c -975
+r e -975
+r d -975
+r a -975
+r q -975
+p w -486
+f o -486
+w e -486
+w s -486
+k o -486
+O Z -975
+L J -486
+R e -975
+R a -486
+E o -486
+E v -486
+E y -486
+E w -486
+Z o -975
+Z e -975
+Z d -975
+Z y -1461
+Z a -486
+Z w -1461
+Z O -975
+Z G -975
+Z C -975
+Z Q -975
+D Z -975
+B Z -975
+A J -486
+J o -486
+K a -486
+t o -486
+o t -486
+o g -486
+o z -486
+o j -486
+g o -486
+v y -486
+v x -486
+v w -486
+z o -486
+w t -486
+w h -486
+w n -486
+w m -486
+w l -486
+w r -486
+w i -486
+w p -486
+w v -486
+w z -486
+w b -486
+w y -486
+w f -486
+w x -486
+w w -486
+w j -486
+w u -486
+w k -486
+R J -486
+C o -486
+E T -486
+E V -486
+E Y -486
+E W -486
+E U -486
+B o -486
+B y -486
+B U -486
+U o -486
+L ' -4878
+T char173 -3903
+T hy -3903
+T - -3903
+T en -3903
+T em -3903
+A ' -2439
+char173 T -3903
+hy T -3903
+- T -3903
+en T -3903
+em T -3903
+Y char173 -2925
+Y hy -2925
+Y - -2925
+Y en -2925
+Y em -2925
+p ' -486
+b ' -975
+V char173 -1950
+V hy -1950
+V - -1950
+V en -1950
+V em -1950
+h ' -486
+n ' -486
+m ' -486
+R ' -975
+W char173 -1461
+W hy -1461
+W - -1461
+W en -1461
+W em -1461
+' d -975
+L char173 -1950
+L hy -1950
+L - -1950
+L en -1950
+L em -1950
+X char173 -1461
+X hy -1461
+X - -1461
+X en -1461
+X em -1461
+A char173 -1461
+A hy -1461
+A - -1461
+A en -1461
+A em -1461
+K char173 -975
+K hy -975
+K - -975
+K en -975
+K em -975
+char173 X -1461
+hy X -1461
+- X -1461
+char173 A -1461
+hy A -1461
+- A -1461
+en X -1461
+en A -1461
+em X -1461
+R char173 -975
+R hy -975
+R - -975
+R en -975
+R em -975
+v ' -486
+w ' -486
+E ' -486
+Z char173 -1461
+Z hy -1461
+Z - -1461
+Z en -1461
+Z em -1461
+B ' -486
+w char173 -486
+w hy -486
+w - -486
+w en -486
+w em -486
+charset
+! 6831,18717,390,2859,345,962 2 3617
+" 11220,18555,0,1827,-2346,962 2 3618
+sh 13173,17415,390,1542,33,962 0 3619
+# "
+Do 13173,19182,2292,1161,255,962 2 3620
+$ "
+% 21954,17805,582,0,-1386 0 3621
+& 18540,18555,390,1743,-672,962 2 3622
+' 6831,18555,0,2763,-1368,962 2 51751
+( 7806,20172,6930,4779,306,962 3 3624
+) 7806,20172,6930,822,4263,822 3 3625
+* 13173,18555,0,1908,-1731,962 2 3626
++ 21954,13467,87,0,-2871 0 3627
+, 6831,3381,4077,0,687 0 3628
+char173 6831,7575,0,882,558,882 0 3629
+hy "
+- "
+. 6831,3486,390,0,-270 0 3630
+sl 13173,18594,390,4080,1101,962 2 3631
+/ "
+0 13173,17805,390,1212,-213,962 0 3632
+1 13173,17805,150,279,-567,279 0 3633
+2 13173,17805,150,1017,1179,962 0 3634
+3 13173,17805,390,336,1731,336 0 3635
+4 13173,17805,0,1485,699,962 0 3636
+5 13173,17415,390,1881,-714,962 0 3637
+6 13173,17805,390,1575,111,962 0 3638
+7 13173,17415,390,2856,-1332,962 0 3639
+8 13173,17805,390,1428,21,962 0 3640
+9 13173,17805,390,1536,72,962 0 3641
+: 6831,12177,390,1032,-270,962 0 3642
+; 6831,12177,4077,1032,687,962 0 3643
+< 26346,16068,0,0,-3981 0 3644
+= 21954,9654,0,0,-2877 0 3645
+> 26346,16068,0,0,-3981 0 3646
+? 10245,18705,390,2250,-1023,962 2 3647
+at 21954,16950,4131,1743,1035,962 0 3648
+@ "
+A 19515,18555,195,15,1764,15 2 3649
+B 16587,18555,195,1047,1806,962 2 3650
+C 19515,18555,390,2028,-837,962 2 3651
+D 20490,18555,195,1566,1323,962 2 3652
+E 16587,18360,195,1848,1476,962 2 3653
+F 15126,18360,195,3372,1542,962 2 3654
+G 20979,18555,390,1476,-1074,962 2 3655
+H 21468,18360,195,3429,1671,962 2 3656
+I 10245,18360,195,3429,1542,962 2 3657
+J 9270,18360,6219,3918,4407,962 3 3658
+K 19029,18360,195,2877,1482,962 2 3659
+L 16587,18360,195,900,1431,900 2 3660
+M 22932,18360,195,2907,2571,962 2 3661
+N 20979,18360,195,3810,1401,962 2 3662
+O 21954,18555,390,1014,-807,962 2 3663
+P 16587,18555,195,1896,1236,962 2 3664
+Q 21954,18555,6639,1014,-807,962 3 3665
+R 19515,18555,195,63,1344,63 2 3666
+S 13173,18555,390,2022,732,962 2 3667
+T 18051,19425,195,4188,-1452,962 2 3668
+U 21468,18360,390,3498,-1761,962 2 3669
+V 19515,18360,390,3597,-1551,962 2 3670
+W 26346,18360,390,4203,-1437,962 2 3671
+X 19029,18360,195,3300,1851,962 2 3672
+Y 19515,18360,195,3228,-2169,962 2 3673
+Z 17565,19425,195,1575,285,962 2 3674
+lB 7806,18165,4614,4290,2805,962 0 3675
+[ "
+rs 13173,18717,390,0,-2868 2 3676
+\ "
+rB 7806,18165,4614,3402,3693,962 0 3677
+] "
+ha 13173,19758,0,36,36,36 2 51875
+_ 13173,191367,6588,1317,1317,962 3 3679
+oq 6831,18555,0,3195,-1800,962 2 51808
+` "
+a 13662,13143,390,1143,663,962 0 3681
+b 14637,20250,390,714,351,714 2 3682
+c 11220,12420,390,1695,438,962 0 3683
+d 14637,20250,390,2610,417,962 2 3684
+e 11220,12420,390,1365,429,962 0 3685
+f 7806,20250,6705,5985,4074,962 3 3686
+g 12684,12420,6705,2031,2331,962 1 3687
+h 14637,20250,390,555,657,555 2 3688
+i 8295,18765,390,1344,498,962 2 3689
+j 7806,18765,6705,2169,3789,962 3 3690
+k 14148,20250,390,858,426,858 2 3691
+l 7806,20250,390,2595,252,962 2 3692
+m 21468,12420,390,291,255,291 0 3693
+n 14637,12420,390,486,57,486 0 3694
+o 12684,12420,390,459,339,459 0 3695
+p 14637,13893,6735,639,3318,639 1 3696
+q 14148,12420,6900,1143,501,962 1 3697
+r 10245,12420,0,2187,390,962 0 3698
+s 8781,12420,390,873,903,873 0 3699
+t 8295,14937,390,2001,312,962 0 3700
+u 14148,12420,390,813,111,813 0 3701
+v 15126,12420,390,759,324,759 0 3702
+w 20490,12420,390,1065,462,962 0 3703
+x 12684,12420,390,1731,1635,962 0 3704
+y 13173,12420,6705,1029,1767,962 1 3705
+z 11220,12885,195,2064,2046,962 0 3706
+lC 13173,19935,6210,3339,-972,962 2 3707
+{ "
+ba 13173,19758,6588,0,-4596 3 3708
+| "
+rC 13173,19935,6210,63,2304,63 2 3709
+} "
+ti 26346,9435,0,0,-4029 0 51876
+char192 19515,24843,195,15,1764,15 2 3776
+`A "
+char194 19515,25182,195,15,1764,15 2 3778
+^A "
+char200 16587,24843,195,1848,1476,962 2 3784
+`E "
+char202 16587,25182,195,1848,1476,962 2 3786
+^E "
+char203 16587,23439,195,1848,1476,962 2 3787
+:E "
+char206 10245,25182,195,4377,1542,962 2 3790
+^I "
+char207 10245,23439,195,3792,1542,962 2 3791
+:I "
+char180 13173,19668,0,1317,-6054,962 2 3764
+aa "
+ga 13173,19668,0,0,-2961 2 3680
+a^ 13173,20514,0,285,-3393,285 2 3678
+^ "
+char168 13173,18057,0,1161,-3669,962 0 3752
+ad "
+a~ 13173,18468,0,1074,-3600,962 2 3710
+~ "
+char217 21468,24843,390,3498,-1761,962 2 3801
+`U "
+char219 21468,25182,390,3498,-1761,962 2 3803
+^U "
+char221 19515,24843,195,3228,-2169,962 2 3805
+'Y "
+char253 13173,19668,6705,1317,1767,962 3 3837
+'y "
+char176 13173,17415,0,600,-1974,600 0 3760
+de "
+char199 19515,18555,6060,2028,-837,962 2 3783
+,C "
+char231 11220,12420,4776,1695,438,962 0 3815
+,c "
+char209 20979,24255,195,3810,1401,962 2 3793
+~N "
+char241 14637,18468,390,486,57,486 2 3825
+~n "
+char161 6831,12411,6696,834,2370,834 1 3745
+r! "
+char191 10245,12405,6690,0,1686 1 3775
+r? "
+char164 13173,15834,0,2349,1044,962 0 3748
+Cs "
+char163 13173,17262,390,951,1173,951 0 3747
+Po "
+char165 13173,18090,150,3885,-1269,962 0 3749
+Ye "
+char167 13173,18555,6705,525,-69,525 3 3751
+sc "
+Fn 13173,20250,6705,3279,1419,962 3 51871
+char162 13173,17613,417,1263,-1290,962 0 3746
+ct "
+char226 13662,20514,390,1143,663,962 2 3810
+^a "
+char234 11220,20514,390,1365,429,962 2 3818
+^e "
+char244 12684,20514,390,531,339,531 2 3828
+^o "
+char251 14148,20514,390,813,111,813 2 3835
+^u "
+char225 13662,19668,390,1143,663,962 2 3809
+'a "
+char233 11220,19668,390,2295,429,962 2 3817
+'e "
+char243 12684,19668,390,1563,339,962 2 3827
+'o "
+char250 14148,19668,390,831,111,831 2 3834
+'u "
+char224 13662,19668,390,1143,663,962 2 3808
+`a "
+char232 11220,19668,390,1365,429,962 2 3816
+`e "
+char242 12684,19668,390,459,339,459 2 3826
+`o "
+char249 14148,19668,390,813,111,813 2 3833
+`u "
+char228 13662,18057,390,1143,663,962 0 3812
+:a "
+char235 11220,18057,390,2139,429,962 0 3819
+:e "
+char246 12684,18057,390,1407,339,962 0 3830
+:o "
+char252 14148,18057,390,813,111,813 0 3836
+:u "
+char197 19515,24900,195,15,1764,15 2 3781
+oA "
+char238 8295,20514,390,2724,459,962 2 3822
+^i "
+char216 21954,18555,390,1125,-696,962 2 3800
+/O "
+char198 25857,18360,195,870,2910,870 2 3782
+AE "
+char229 13662,18861,390,1377,663,962 2 3813
+oa "
+char237 8295,19668,390,3756,459,962 2 3821
+'i "
+char248 12684,12420,390,552,444,552 0 3832
+/o "
+char230 18540,13047,390,1296,477,962 0 3814
+ae "
+char196 19515,23439,195,15,1764,15 2 3780
+:A "
+char236 8295,19668,390,663,459,663 2 3820
+`i "
+char214 21954,23439,390,1014,-807,962 2 3798
+:O "
+char220 21468,23439,390,3498,-1761,962 2 3804
+:U "
+char201 16587,24843,195,1848,1476,962 2 3785
+'E "
+char239 8295,18057,390,3600,459,962 0 3823
+:i "
+char223 14148,20250,6705,2916,4902,962 3 3807
+ss "
+char212 21954,25182,390,1014,-807,962 2 3796
+^O "
+char193 19515,24843,195,15,1764,15 2 3777
+'A "
+char195 19515,24255,195,648,1764,648 2 3779
+~A "
+char227 13662,18468,390,1143,663,962 2 3811
+~a "
+char208 20490,18555,342,1557,1314,962 2 3792
+-D "
+char240 12684,20250,390,600,339,600 2 3824
+Sd "
+char205 10245,24843,195,3540,1542,962 2 3789
+'I "
+char204 10245,24843,195,3429,1542,962 2 3788
+`I "
+char211 21954,24843,390,1014,-807,962 2 3795
+'O "
+char210 21954,24843,390,1014,-807,962 2 3794
+`O "
+char213 21954,24255,390,1014,-807,962 2 3797
+~O "
+char245 12684,18468,390,1320,339,962 2 3829
+~o "
+vS 13173,24657,390,3903,732,962 2 51795
+vs 8781,20526,390,4242,903,962 2 51827
+char218 21468,24843,390,3498,-1761,962 2 3802
+'U "
+:Y 19515,23439,195,3228,-2169,962 2 51801
+char255 13173,18057,6705,1161,1767,962 1 3839
+:y "
+char222 16587,18360,195,846,1221,846 2 3806
+TP "
+char254 14637,20250,6900,663,3342,663 3 3838
+Tp "
+char181 14637,10800,5193,582,756,582 0 3765
+char182 13173,19635,4200,1032,-690,962 2 3766
+ps "
+char190 21954,17805,180,0,-627 0 3774
+34 "
+\- 21954,7755,0,0,-2892 0 51757
+char188 21954,17625,180,0,-1242 0 3772
+14 "
+char189 21954,17625,180,0,-1317 0 3773
+12 "
+char170 11220,17805,0,1833,-1338,962 0 3754
+Of "
+char186 11220,17805,0,1218,-1776,962 0 3770
+Om "
+char171 11220,9906,0,837,609,837 0 3755
+Fo "
+char187 11220,9906,0,435,1011,435 0 3771
+Fc "
+char177 21954,13467,3354,0,-2865 0 3761
+char166 13173,19083,5916,0,-4596 2 3750
+bb "
+char169 13173,19725,0,5022,-3198,962 2 3753
+co "
+char172 21954,10560,0,0,-2565 0 3756
+no "
+char174 13173,19725,0,5022,-3198,962 2 3758
+rg "
+char178 8781,17805,0,2001,-606,962 0 3762
+S2 "
+char179 8781,17805,0,1881,-387,962 0 3763
+S3 "
+char184 13173,657,4776,0,-1791 0 3768
+ac "
+char185 8781,17625,0,1389,-1590,962 0 3769
+S1 "
+char215 21954,13530,192,0,-2934 0 3799
+char247 21954,13383,3,0,-2886 0 3831
+char183 6831,10533,0,336,-1116,336 0 3767
+fm 13173,17415,0,0,-1461 0 51873
+sd 13173,17415,0,1680,-1461,962 0 51874
+dg 13173,18555,6657,1035,186,962 3 51755
+tm 16101,17550,0,5508,-3159,962 0 51796
+ah 13173,20526,0,2367,-5475,962 2 51935
+ao 13173,18861,0,285,-5313,285 2 51930
+f/ 2928,17625,180,8301,6948,962 0 51759
+em 21954,7185,0,666,-45,666 0 51789
+en 13173,7185,0,537,-72,537 0 51790
+dd 13173,18555,4989,990,243,962 2 51773
+.i 8295,12420,390,288,459,288 0 51957
+aq 6831,18555,0,2289,-2826,962 2 3623
+bu 13173,14226,0,0,-498 0 51889
+'C 19515,24843,390,2028,-837,962 2 20166
+'c 11220,19668,390,1995,438,962 2 20198
+lq 11220,18555,0,4245,-1419,962 2 51838
+rq 11220,18555,0,3423,-597,962 2 51746
+Bq 11220,3456,4002,0,3399 0 51772
+vz 11220,20526,195,3345,2046,962 2 51834
+fi 14637,20250,6705,1566,3645,962 3 51881
+fl 14637,20250,6705,2934,3735,962 3 51882
+ff 14637,20250,6705,5373,3861,962 3 51883
+Fi 21468,20250,6705,1701,3675,962 3 51884
+Fl 21468,20250,6705,2832,3765,962 3 51885
+ij 14637,18765,6705,2169,498,962 3 51958
+bq 6831,3456,4002,0,2925 0 51756
+%0 30249,17805,450,0,-1386 0 51901
+char175 13173,16974,0,438,-4107,438 0 3759
+a- "
+ab 13173,17325,0,1386,-5277,962 0 51926
+a. 13173,18057,0,0,-6510 0 51927
+oe 19029,12420,390,1338,357,962 0 51823
+OE 27321,18555,390,1932,-528,962 2 51791
+fo 6831,9906,0,999,792,962 0 51886
+fc 6831,9906,0,423,1368,423 0 51887
+sq 19029,15624,0,0,-2022 0 51899
+/L 16587,18360,195,900,1431,900 2 51944
+/l 7806,20250,390,2580,444,962 2 51960
+a" 13173,19830,0,3630,-3816,962 2 51933
+ho 13173,711,4791,0,-4011 0 51934
+vZ 17565,24657,195,1707,285,962 2 51802
+IJ 19515,18360,6219,3918,1542,962 3 51942
diff --git a/font/devlj4/GI b/font/devlj4/GI
new file mode 100644
index 00000000..d8bb19d2
--- /dev/null
+++ b/font/devlj4/GI
@@ -0,0 +1,669 @@
+name GI
+spacewidth 6342
+slant 16.400000
+pcltypeface 4197
+pclproportional 1
+pclweight 0
+pclstyle 1
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -3903
+P . -4389
+P , -4389
+V A -3414
+A V -3414
+T o -4878
+T r -3414
+T c -4389
+T e -4389
+T d -4389
+T s -3414
+T y -4389
+T a -3903
+T w -4389
+T u -3414
+L T -3903
+L Y -3414
+Y o -3903
+Y e -3903
+Y a -3903
+A W -3414
+W A -3414
+T A -3414
+V o -2925
+V e -2925
+V a -2925
+Y A -3414
+F A -2439
+F . -3903
+F , -3903
+A T -3414
+A Y -3414
+v . -1461
+v , -1461
+y . -975
+y , -975
+T . -3414
+T , -3414
+L W -3414
+P A -2925
+V . -3903
+V , -3903
+Y . -3903
+Y , -3903
+W o -2925
+W e -2925
+W a -2925
+W . -3903
+W , -3903
+r . -1950
+r , -1950
+w . -1461
+w , -1461
+Y u -2439
+A v -1950
+A y -1950
+A w -1950
+o . -1461
+o , -1461
+p . -975
+p , -975
+b . -1950
+b , -1950
+O T -1950
+O V -1950
+O Y -1950
+O . -975
+O , -975
+V y -1461
+V u -1461
+V O -975
+V G -975
+V C -975
+V Q -975
+D T -1950
+D V -1950
+D Y -1950
+D . -975
+D , -975
+Y O -975
+Y G -975
+Y C -975
+Y Q -975
+F o -1461
+F e -975
+F a -975
+O A -975
+O W -1950
+R T -2925
+R V -2925
+R Y -2925
+R W -2925
+G T -975
+P o -1461
+P e -1461
+P a -1461
+D A -975
+D W -1950
+B T -975
+B Y -975
+B . -975
+B , -975
+A O -1950
+A G -1950
+A C -1950
+A U -1950
+A Q -1950
+W r -1461
+W y -1461
+W u -1461
+W O -975
+W G -975
+W C -975
+W Q -975
+U A -975
+U . -975
+U , -975
+Q A -975
+Q W -1950
+T O -975
+T G -975
+T C -975
+T Q -975
+O X -975
+L o -486
+G V -975
+G Y -975
+G W -975
+P T -975
+P V -975
+P Y -975
+D X -975
+B V -975
+B X -975
+B A -975
+B W -975
+F r -486
+F y -486
+F u -486
+F O -486
+F G -486
+F C -486
+F Q -486
+X o -1461
+X e -1461
+X y -1461
+X O -975
+X G -975
+X C -975
+X Q -975
+A o -1461
+A e -1461
+Q X -975
+K o -1461
+K e -975
+K y -975
+K w -975
+K O -975
+K G -975
+K C -975
+K Q -975
+o v -486
+o y -486
+o x -486
+o w -486
+v o -486
+y o -486
+x o -975
+x c -486
+x e -486
+x d -486
+x a -486
+x q -486
+w o -486
+R o -1461
+R y -1461
+R O -1461
+R G -1461
+R C -1461
+R U -1461
+R Q -1461
+P Z -975
+P X -975
+P W -975
+X a -486
+A t -975
+A g -486
+A c -1461
+A d -975
+A a -486
+A q -486
+K c -975
+o f -486
+h . -486
+h , -486
+n . -486
+n , -486
+m . -486
+m , -486
+r o -975
+r c -486
+r e -486
+r d -486
+r a -486
+r q -486
+f o -486
+k o -486
+O Z -975
+R e -1461
+R a -486
+G Z -975
+E o -486
+Z o -975
+Z e -486
+Z d -486
+Z y -486
+Z a -486
+Z w -486
+Z O -486
+Z G -486
+Z C -486
+Z Q -486
+D Z -975
+B Z -975
+J o -486
+K a -486
+t o -486
+o t -486
+o g -486
+o z -486
+o j -486
+g o -486
+z o -486
+C o -486
+E T -486
+E V -486
+E Z -486
+E Y -486
+E W -486
+B o -486
+U o -486
+L ' -4878
+T char173 -4389
+T hy -4389
+T - -4389
+T en -4389
+T em -4389
+A ' -2439
+char173 T -3414
+hy T -3414
+- T -3414
+en T -3414
+em T -3414
+Y char173 -2439
+Y hy -2439
+Y - -2439
+Y en -2439
+Y em -2439
+p ' -486
+b ' -975
+V char173 -1461
+V hy -1461
+V - -1461
+V en -1461
+V em -1461
+h ' -486
+n ' -486
+m ' -486
+R ' -1950
+W char173 -1461
+W hy -1461
+W - -1461
+W en -1461
+W em -1461
+' d -975
+F char173 -486
+F hy -486
+F - -486
+F en -486
+F em -486
+X char173 -1461
+X hy -1461
+X - -1461
+X en -1461
+X em -1461
+A char173 -1950
+A hy -1950
+A - -1950
+A en -1950
+A em -1950
+K char173 -975
+K hy -975
+K - -975
+K en -975
+K em -975
+char173 X -1461
+hy X -1461
+- X -1461
+char173 A -1461
+hy A -1461
+- A -1461
+en X -1461
+en A -1461
+em X -1461
+R char173 -1461
+R hy -1461
+R - -1461
+R en -1461
+R em -1461
+v ' -486
+w ' -486
+E ' -486
+Z ' -975
+Z char173 -486
+Z hy -486
+Z - -486
+Z en -486
+Z em -486
+B ' -486
+charset
+! 6342,18648,390,2823,786,910 2 3617
+" 11220,18555,0,2325,-3858,910 2 3618
+sh 12684,17805,390,1377,-72,910 0 3619
+# "
+Do 12684,19380,2415,1467,-54,910 2 3620
+$ "
+% 20490,17805,180,252,-1311,252 0 3621
+& 18051,18555,390,1461,9,910 2 3622
+' 6342,18555,0,2622,-1662,910 2 51751
+( 6342,20283,6705,5652,855,910 3 3624
+) 6342,20283,6705,1701,4806,910 3 3625
+* 12684,18555,0,2358,-2589,910 2 3626
++ 20490,13191,261,0,-2496 0 3627
+, 6342,3300,3891,0,1584 0 3628
+char173 6342,6960,0,438,183,438 0 3629
+hy "
+- "
+. 6342,2985,390,0,861 0 3630
+sl 13173,20250,225,4644,1500,910 2 3631
+/ "
+0 12684,17805,390,1482,-354,910 0 3632
+1 12684,17415,150,0,-843 0 3633
+2 12684,17805,0,633,216,633 0 3634
+3 12684,17805,390,588,1335,588 0 3635
+4 12684,17805,0,1158,18,910 0 3636
+5 12684,17415,390,780,-183,780 0 3637
+6 12684,17805,390,2220,-102,910 0 3638
+7 12684,17415,390,2988,-888,910 0 3639
+8 12684,17805,390,1620,-105,910 0 3640
+9 12684,17805,390,1731,-126,910 0 3641
+: 6342,11586,390,1044,861,910 0 3642
+; 6342,11586,3891,1251,1584,910 0 3643
+< 26346,16068,0,0,-3981 0 3644
+= 20490,8883,0,0,-2688 0 3645
+> 26346,16068,0,0,-3981 0 3646
+? 9270,18648,390,2514,-396,910 2 3647
+at 20619,16980,3654,2277,1044,910 0 3648
+@ "
+A 18540,18555,150,0,2757 2 3649
+B 15126,18555,150,1614,1335,910 2 3650
+C 18540,18555,390,2820,-795,910 2 3651
+D 20004,18555,150,1380,1872,910 2 3652
+E 15612,18315,150,1824,1827,910 2 3653
+F 13173,18315,150,3717,1683,910 2 3654
+G 20490,18555,390,1182,-873,910 2 3655
+H 20490,18315,150,3783,1785,910 2 3656
+I 8781,18315,150,3582,1641,910 2 3657
+J 8295,18315,5814,3522,4017,910 2 3658
+K 18051,18315,150,2922,1755,910 2 3659
+L 15612,18315,150,345,1536,345 2 3660
+M 20490,18315,150,3192,2418,910 2 3661
+N 19515,18315,150,3774,1101,910 2 3662
+O 20979,18555,390,1308,-624,910 2 3663
+P 14637,18555,150,2430,1737,910 2 3664
+Q 20979,18555,6027,1248,-684,910 2 3665
+R 18051,18555,150,0,1965 2 3666
+S 12198,18555,390,1974,759,910 2 3667
+T 16101,19185,150,4656,-1578,910 2 3668
+U 20004,18315,390,3312,-1641,910 2 3669
+V 19029,18315,390,5280,-2376,910 2 3670
+W 25371,18315,390,5025,-2190,910 2 3671
+X 18540,18315,150,3168,1833,910 2 3672
+Y 17565,18315,150,5103,-1386,910 2 3673
+Z 16587,19557,0,1626,78,910 2 3674
+lB 6342,18165,5160,4749,3360,910 0 3675
+[ "
+rs 13173,20250,225,0,-3234 2 3676
+\ "
+rB 6342,18165,5160,3387,4722,910 0 3677
+] "
+ha 13173,19758,0,36,36,36 2 51875
+_ 13173,191367,6588,1317,1317,910 3 3679
+oq 6342,18555,0,3606,-2646,910 2 51808
+` "
+a 12198,11670,390,687,1335,687 0 3681
+b 12684,20253,390,1776,216,910 2 3682
+c 9759,11670,390,1668,495,910 0 3683
+d 13173,20250,390,2223,915,910 2 3684
+e 9759,11670,390,1515,687,910 0 3685
+f 7317,20250,6705,6675,5391,910 3 3686
+g 11220,11670,6705,1806,1908,910 1 3687
+h 12684,20250,390,801,1086,801 2 3688
+i 7806,18495,390,1020,24,910 2 3689
+j 6342,18495,6705,2055,4209,910 3 3690
+k 13173,20250,390,657,957,657 2 3691
+l 7317,20250,390,1938,606,910 2 3692
+m 21468,11670,390,345,342,345 0 3693
+n 14637,11670,390,513,309,513 0 3694
+o 12198,11670,390,423,288,423 0 3695
+p 12198,13440,6855,963,3558,910 1 3696
+q 12684,11670,6855,1458,1005,910 1 3697
+r 10245,11670,0,2121,417,910 0 3698
+s 7806,11670,390,1242,1449,910 0 3699
+t 8295,13944,390,1638,75,910 0 3700
+u 13662,11670,390,576,381,576 0 3701
+v 13662,11670,390,1317,423,910 0 3702
+w 19029,11670,390,1209,393,910 0 3703
+x 12198,11670,390,936,1476,910 0 3704
+y 11709,11670,6705,867,2037,867 1 3705
+z 11220,12315,0,1359,1530,910 0 3706
+lC 11709,19935,6210,3360,-1692,910 3 3707
+{ "
+ba 13173,19758,6588,0,-4596 3 3708
+| "
+rC 11709,19935,6210,0,2232 3 3709
+} "
+ti 26346,8952,0,0,-4029 0 51876
+char192 18540,24930,150,0,2757 2 3776
+`A "
+char194 18540,24915,150,438,2757,438 2 3778
+^A "
+char200 15612,24930,150,1824,1827,910 2 3784
+`E "
+char202 15612,24915,150,1824,1827,910 2 3786
+^E "
+char203 15612,22620,150,1824,1827,910 2 3787
+:E "
+char206 8781,24915,150,4425,1641,910 2 3790
+^I "
+char207 8781,22620,150,4899,1641,910 2 3791
+:I "
+char180 12684,19590,0,1218,-5838,910 2 3764
+aa "
+ga 12684,19590,0,0,-3147 2 3680
+a^ 12684,19614,0,210,-3726,210 2 3678
+^ "
+char168 12684,17394,0,153,-3873,153 0 3752
+ad "
+a~ 12684,17481,0,1239,-3270,910 0 3710
+~ "
+char217 20004,24930,390,3312,-1641,910 2 3801
+`U "
+char219 20004,24915,390,3312,-1641,910 2 3803
+^U "
+char221 17565,24930,150,5103,-1386,910 2 3805
+'Y "
+char253 11709,19590,6705,2106,2037,910 3 3837
+'y "
+char176 12684,17805,0,828,-2298,828 0 3760
+de "
+char199 18540,18555,6018,2820,-795,910 2 3783
+,C "
+char231 9759,11670,4770,1668,516,910 0 3815
+,c "
+char209 19515,23727,150,3774,1101,910 2 3793
+~N "
+char241 14637,17481,390,513,309,513 0 3825
+~n "
+char161 6831,12000,7038,1113,2007,910 1 3745
+r! "
+char191 9270,12000,7038,0,2256 1 3775
+r? "
+char164 12684,15684,0,2205,291,910 0 3748
+Cs "
+char163 12684,17805,390,1413,1200,910 0 3747
+Po "
+char165 12684,18315,150,4137,-486,910 2 3749
+Ye "
+char167 12684,18555,5250,0,66 2 3751
+sc "
+Fn 12684,20250,6705,3483,3216,910 3 51871
+char162 12684,17568,186,795,-1197,795 0 3746
+ct "
+char226 12198,19614,390,687,1335,687 2 3810
+^a "
+char234 9759,19614,390,1671,687,910 2 3818
+^e "
+char244 12198,19614,390,453,288,453 2 3828
+^o "
+char251 13662,19614,390,576,381,576 2 3835
+^u "
+char225 12198,19590,390,1863,1335,910 2 3809
+'a "
+char233 9759,19590,390,3081,687,910 2 3817
+'e "
+char243 12198,19590,390,1863,288,910 2 3827
+'o "
+char250 13662,19590,390,1131,381,910 2 3834
+'u "
+char224 12198,19590,390,687,1335,687 2 3808
+`a "
+char232 9759,19590,390,1515,687,910 2 3816
+`e "
+char242 12198,19590,390,423,288,423 2 3826
+`o "
+char249 13662,19590,390,576,381,576 2 3833
+`u "
+char228 12198,17394,390,891,1335,891 0 3812
+:a "
+char235 9759,17394,390,2109,687,910 0 3819
+:e "
+char246 12198,17394,390,891,288,891 0 3830
+:o "
+char252 13662,17394,390,576,381,576 0 3836
+:u "
+char197 18540,24681,150,150,2757,150 2 3781
+oA "
+char238 7806,19614,390,2649,24,910 2 3822
+^i "
+char216 20979,18555,390,2475,1140,910 2 3800
+/O "
+char198 25371,18315,150,1821,2859,910 2 3782
+AE "
+char229 12198,19566,390,1257,1335,910 2 3813
+oa "
+char237 7806,19590,390,4059,24,910 2 3821
+'i "
+char248 12198,11670,390,2388,2475,910 0 3832
+/o "
+char230 16587,11670,390,1551,1377,910 0 3814
+ae "
+char196 18540,22620,150,1191,2757,910 2 3780
+:A "
+char236 7806,19590,390,966,24,910 2 3820
+`i "
+char214 20979,22620,390,1308,-624,910 2 3798
+:O "
+char220 20004,22620,390,3312,-1641,910 2 3804
+:U "
+char201 15612,24930,150,1824,1827,910 2 3785
+'E "
+char239 7806,17394,390,2562,24,910 0 3823
+:i "
+char223 13173,20250,6705,3594,6294,910 3 3807
+ss "
+char212 20979,24915,390,1308,-624,910 2 3796
+^O "
+char193 18540,24930,150,1083,2757,910 2 3777
+'A "
+char195 18540,23727,150,2175,2757,910 2 3779
+~A "
+char227 12198,17481,390,1482,1335,910 0 3811
+~a "
+char208 20004,18555,150,1380,1872,910 2 3792
+-D "
+char240 12198,20199,327,540,288,540 2 3824
+Sd "
+char205 8781,24930,150,5073,1641,910 2 3789
+'I "
+char204 8781,24930,150,3582,1641,910 2 3788
+`I "
+char211 20979,24930,390,1308,-624,910 2 3795
+'O "
+char210 20979,24930,390,1308,-624,910 2 3794
+`O "
+char213 20979,23727,390,1308,-624,910 2 3797
+~O "
+char245 12198,17481,390,1482,288,910 0 3829
+~o "
+vS 12198,24969,390,2829,759,910 2 51795
+vs 7806,19863,390,4191,1449,910 2 51827
+char218 20004,24930,390,3312,-1641,910 2 3802
+'U "
+:Y 17565,22620,150,5103,-1386,910 2 51801
+char255 11709,17394,6705,1134,2037,910 1 3839
+:y "
+char222 14637,18315,150,1383,1722,910 2 3806
+TP "
+char254 12198,20250,6855,963,3561,910 3 3838
+Tp "
+char181 14637,10800,5595,612,585,612 0 3765
+char182 12684,19635,4200,1812,-981,910 2 3766
+ps "
+char190 20490,17805,390,0,-1074 0 3774
+34 "
+\- 20490,7305,0,0,-2532 0 51757
+char188 20490,17625,390,0,-1143 0 3772
+14 "
+char189 20490,17625,390,33,-204,33 0 3773
+12 "
+char170 11709,17805,0,1590,-1725,910 0 3754
+Of "
+char186 11709,17805,0,936,-1989,910 0 3770
+Om "
+char171 10734,9945,0,759,-9,759 0 3755
+Fo "
+char187 10734,9945,0,204,546,204 0 3771
+Fc "
+char177 20490,13191,3105,0,-2502 0 3761
+char166 13173,19083,5916,0,-4596 2 3750
+bb "
+char169 13173,19725,0,5526,-3702,910 2 3753
+co "
+char172 20490,10029,0,0,-2055 0 3756
+no "
+char174 13173,19725,0,5526,-3702,910 2 3758
+rg "
+char178 8781,17805,0,1725,-690,910 0 3762
+S2 "
+char179 8781,17805,0,1746,-273,910 0 3763
+S3 "
+char184 12684,0,4770,0,-948 0 3768
+ac "
+char185 8781,17625,0,1257,-1230,910 0 3769
+S1 "
+char215 20490,12969,189,0,-2793 0 3799
+char247 20490,12966,36,0,-2424 0 3831
+char183 6342,10350,0,534,-1212,534 0 3767
+fm 12684,17805,0,0,-2970 0 51873
+sd 12684,17805,0,0,-1374 0 51874
+dg 12684,18555,5250,2079,-741,910 2 51755
+tm 16101,17550,0,6012,-3663,910 0 51796
+ah 12684,19863,0,1152,-4668,910 2 51935
+ao 12684,19566,0,570,-4965,570 2 51930
+f/ 2928,17415,390,8091,6480,910 0 51759
+em 20490,6960,0,651,420,651 0 51789
+en 12684,6960,0,756,357,756 0 51790
+dd 12684,18555,5250,1128,210,910 2 51773
+.i 7806,11670,390,657,24,657 0 51957
+aq 7317,18555,0,2418,-3858,910 2 3623
+bu 13173,14226,0,0,-498 0 51889
+'C 18540,24930,390,2820,-795,910 2 20166
+'c 9759,19590,390,3231,495,910 2 20198
+lq 10734,18555,0,3054,-1956,910 2 51838
+rq 10734,18555,0,2940,-1842,910 2 51746
+Bq 10734,2013,4437,0,2022 0 51772
+vz 11220,19863,0,2484,1530,910 2 51834
+fi 13173,20250,6705,1812,5289,910 3 51881
+fl 14148,20250,6705,1464,5172,910 3 51882
+ff 13662,20250,6705,6495,5286,910 3 51883
+Fi 19029,20250,6705,1914,5388,910 3 51884
+Fl 19515,20601,6705,2037,5289,910 3 51885
+ij 14148,18495,6705,2055,24,910 3 51958
+bq 6342,2013,4437,0,1680 0 51756
+%0 29760,17805,207,378,-1368,378 0 51901
+char175 12684,17328,0,609,-3933,609 0 3759
+a- "
+ab 12684,18054,0,918,-4341,910 0 51926
+a. 12684,17034,0,0,-6228 0 51927
+oe 18051,11670,390,1527,288,910 0 51823
+OE 27321,18555,390,1800,-636,910 2 51791
+fo 7806,9945,0,780,-672,780 0 51886
+fc 7806,9945,0,0,147 0 51887
+sq 19029,15624,0,0,-2022 0 51899
+/L 15612,18315,150,345,1536,345 2 51944
+/l 7317,20250,390,2265,660,910 2 51960
+a" 12684,19590,0,3705,-4452,910 2 51933
+ho 12684,420,4155,0,-3069 0 51934
+vZ 16587,24969,0,1626,78,910 2 51802
+IJ 17076,18315,5814,3522,1641,910 2 51942
diff --git a/font/devlj4/GR b/font/devlj4/GR
new file mode 100644
index 00000000..448d19a9
--- /dev/null
+++ b/font/devlj4/GR
@@ -0,0 +1,853 @@
+name GR
+spacewidth 6831
+pcltypeface 4197
+pclproportional 1
+pclweight 0
+pclstyle 0
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -3414
+P . -4389
+P , -4389
+V A -4389
+A V -4389
+T o -3903
+T r -2439
+T c -3414
+T e -3414
+T d -3414
+T s -2439
+T y -4389
+T a -2439
+T w -4389
+T u -3414
+L T -2925
+L Y -2925
+Y o -4389
+Y e -3903
+Y a -2925
+A W -4389
+W A -4389
+T A -2439
+V o -3414
+V e -3414
+V a -2925
+Y A -2925
+F A -2925
+F . -3903
+F , -3903
+A T -2925
+A Y -2925
+v . -2439
+v , -2439
+y . -2925
+y , -2925
+T . -2439
+T , -2439
+L W -3414
+P A -2925
+V . -3903
+V , -3903
+Y . -2925
+Y , -2925
+W o -3414
+W e -3414
+W a -2925
+W . -3903
+W , -3903
+r . -1461
+r , -1461
+w . -2925
+w , -2925
+Y u -3414
+A v -2439
+A y -2439
+A w -2925
+o . -1461
+o , -1461
+p . -1461
+p , -1461
+e . -486
+e , -486
+b . -1461
+b , -1461
+O T -1950
+O V -1950
+O Y -1950
+O . -1950
+O , -1950
+L y -2439
+L O -1950
+L G -1950
+L C -1950
+L Q -1950
+P J -975
+V y -1950
+V u -1950
+V O -1950
+V G -1950
+V C -1950
+V Q -1950
+D T -1950
+D V -1950
+D Y -1950
+D . -1950
+D , -1950
+Y O -1950
+Y G -1950
+Y C -1950
+Y Q -1950
+F o -1461
+F e -1461
+F a -975
+c . -486
+c , -486
+O A -1461
+O W -1950
+L U -1950
+R T -2925
+R V -2925
+R Y -2925
+R W -2925
+G T -486
+P o -1461
+P g -975
+P e -1461
+P a -975
+D A -1461
+D W -1950
+B T -1461
+B Y -1461
+B . -1461
+B , -1461
+A O -1461
+A G -1461
+A C -1461
+A U -1950
+A Q -1461
+W r -1950
+W y -1950
+W u -1950
+W O -1950
+W G -1950
+W C -1950
+W Q -1950
+J A -486
+J . -486
+J , -486
+U A -1950
+U . -1950
+U , -1950
+Q A -1461
+Q W -1950
+T O -1950
+T G -1950
+T C -1950
+T Q -1950
+O X -1461
+L o -1461
+L e -975
+L q -1461
+G V -486
+G Y -486
+G W -486
+P T -975
+P V -975
+P Y -975
+D X -1461
+B V -1461
+B X -1461
+B A -1461
+B W -1461
+S . -975
+S , -975
+X o -1461
+X e -975
+X y -1461
+X O -1461
+X G -1461
+X C -1461
+X Q -1461
+A o -1461
+A e -975
+Q X -1461
+K o -1461
+K e -975
+K y -1461
+K w -1461
+K O -1461
+K G -1461
+K C -1461
+K Q -1461
+o v -1461
+o y -1461
+o x -1461
+o w -1461
+h v -975
+h y -975
+n v -975
+n y -975
+m v -975
+m y -975
+r g -975
+p v -975
+p y -975
+p x -975
+v o -1461
+v g -975
+v c -975
+v d -975
+v a -975
+v q -975
+e v -486
+e y -486
+b v -975
+b y -975
+b w -1461
+s . -486
+s , -486
+y o -1461
+y g -975
+y c -1461
+y d -1461
+y a -975
+y q -1461
+x o -1461
+x c -975
+x e -975
+x d -975
+x q -975
+a v -486
+a y -486
+a w -486
+w o -1461
+w g -975
+w c -1461
+w d -1461
+w a -975
+w q -1461
+T S -975
+R o -1461
+R y -1950
+R O -1950
+R G -1950
+R C -1950
+R U -1950
+R Q -1950
+P s -486
+P Z -975
+P X -975
+P W -975
+V S -975
+S A -975
+Y S -975
+X u -975
+A t -975
+A c -975
+A d -975
+A u -975
+A q -1461
+W S -975
+J y -486
+K c -975
+K u -975
+o f -486
+h w -975
+n w -975
+m w -975
+r o -1461
+r c -975
+r e -975
+r d -975
+r a -975
+r q -975
+p w -975
+v e -975
+v s -486
+e x -486
+e w -486
+y e -1461
+y s -486
+f o -1461
+f c -975
+f e -975
+f d -975
+f q -975
+w e -1461
+w s -486
+k o -1461
+k c -975
+k e -975
+k d -975
+k q -975
+O Z -975
+O J -975
+L J -975
+R e -975
+R u -975
+P H -486
+P N -486
+P M -486
+P L -486
+P R -486
+P I -486
+P P -486
+P E -486
+P D -486
+P B -486
+P F -486
+P U -486
+P K -486
+E t -486
+E o -975
+E c -486
+E v -486
+E e -486
+E d -486
+E y -486
+E w -486
+E u -486
+E q -486
+E O -486
+E G -486
+E C -486
+E J -486
+E Q -486
+Z o -1461
+Z e -975
+Z d -975
+Z y -975
+Z w -975
+Z u -975
+Z O -975
+Z G -975
+Z C -975
+Z Q -975
+D Z -975
+D J -975
+B Z -975
+B J -975
+A J -975
+J o -975
+J e -486
+J a -486
+J u -486
+J O -486
+J G -486
+J C -486
+J S -486
+J Q -486
+U g -486
+K J -486
+t o -1461
+t c -975
+t e -975
+t d -975
+t q -975
+o t -486
+o g -486
+o z -975
+o j -486
+r s -486
+g o -975
+g c -486
+g e -486
+g d -486
+g q -486
+p z -486
+e z -486
+z o -975
+z c -486
+z e -486
+z d -486
+z q -486
+b z -486
+R J -975
+G J -486
+C o -486
+C y -975
+E T -486
+E V -486
+E Y -486
+E W -486
+E U -486
+B o -486
+B y -486
+B a -486
+B H -486
+B N -486
+B M -486
+B L -486
+B R -486
+B I -486
+B P -486
+B E -486
+B D -486
+B B -486
+B F -486
+B U -486
+B K -486
+U t -486
+U o -975
+U n -486
+U m -486
+U r -486
+U p -486
+U c -486
+U v -486
+U e -486
+U z -486
+U d -486
+U s -975
+U y -486
+U f -486
+U x -486
+U a -975
+U w -486
+U q -486
+U O -486
+U G -486
+U C -486
+U S -486
+U Q -486
+K T -486
+K V -486
+K Y -486
+K W -486
+K U -486
+L ' -3414
+T char173 -4389
+T hy -4389
+T - -4389
+T en -4389
+T em -4389
+A ' -2925
+char173 T -4389
+hy T -4389
+- T -4389
+en T -4389
+em T -4389
+Y char173 -3414
+Y hy -3414
+Y - -3414
+Y en -3414
+Y em -3414
+p ' -975
+e ' -486
+b ' -1461
+a ' -486
+V char173 -1950
+V hy -1950
+V - -1950
+V en -1950
+V em -1950
+h ' -975
+n ' -975
+m ' -975
+R ' -1950
+W char173 -1950
+W hy -1950
+W - -1950
+W en -1950
+W em -1950
+' d -1461
+L char173 -1950
+L hy -1950
+L - -1950
+L en -1950
+L em -1950
+X char173 -1461
+X hy -1461
+X - -1461
+X en -1461
+X em -1461
+A char173 -1461
+A hy -1461
+A - -1461
+A en -1461
+A em -1461
+K char173 -1461
+K hy -1461
+K - -1461
+K en -1461
+K em -1461
+' s -486
+char173 X -1461
+hy X -1461
+- X -1461
+char173 A -1461
+hy A -1461
+- A -1461
+en X -1461
+en A -1461
+em X -1461
+R char173 -1950
+R hy -1950
+R - -1950
+R en -1950
+R em -1950
+K ' -486
+G ' -486
+E ' -486
+E char173 -486
+E hy -486
+E - -486
+E en -486
+E em -486
+Z char173 -975
+Z hy -975
+Z - -975
+Z en -975
+Z em -975
+B ' -486
+J char173 -486
+J hy -486
+J - -486
+J en -486
+J em -486
+U char173 -486
+U hy -486
+U - -486
+U en -486
+U em -486
+charset
+! 6831,18837,390 2 3617
+" 11220,18555 2 3618
+sh 12684,17805,390 0 3619
+# "
+Do 12684,19122,1707 2 3620
+$ "
+% 21468,17415,390 0 3621
+& 21954,18165,390 0 3622
+' 7317,18555 2 51751
+( 7806,20250,6705 3 3624
+) 7806,20250,6705 3 3625
+* 12684,18555 2 3626
++ 21468,13191,261 0 3627
+, 6831,3096,4449 0 3628
+char173 6831,6960 0 3629
+hy "
+- "
+. 6831,2847,390 0 3630
+sl 12684,20250,480 2 3631
+/ "
+0 12684,17805,390 0 3632
+1 12684,17805,150 0 3633
+2 12684,17805,150 0 3634
+3 12684,17805,390 0 3635
+4 12684,17415,390 0 3636
+5 12684,17415,390 0 3637
+6 12684,17811,390 0 3638
+7 12684,17415,390 0 3639
+8 12684,17805,390 0 3640
+9 12684,17805,390 0 3641
+: 6831,10593,390 0 3642
+; 6831,10593,4449 0 3643
+< 26346,16068 0 3644
+= 21468,8883 0 3645
+> 26346,16068 0 3646
+? 9759,18837,390 2 3647
+at 21594,16980,3654 0 3648
+@ "
+A 20004,18555,150 2 3649
+B 16101,18315,150 2 3650
+C 19515,18555,390 2 3651
+D 20979,18555,150 2 3652
+E 16587,18315,150 2 3653
+F 15612,18315,150 2 3654
+G 20979,18555,390 2 3655
+H 22443,18315,150 2 3656
+I 8781,18315,150 2 3657
+J 9759,18315,6060 2 3658
+K 19029,18315,150 2 3659
+L 16101,18315,150 2 3660
+M 23907,18315,390 2 3661
+N 22443,18315,774 2 3662
+O 22443,18555,390 2 3663
+P 15612,18555,150 2 3664
+Q 22443,18555,6339 3 3665
+R 18540,18315,150 2 3666
+S 12684,18555,390 2 3667
+T 18051,19299,150 2 3668
+U 21468,18315,390 2 3669
+V 19029,18315,390 2 3670
+W 25857,18315,390 2 3671
+X 20004,18315,150 2 3672
+Y 19029,18315,150 2 3673
+Z 17565,19299 2 3674
+lB 7806,18165,4905 0 3675
+[ "
+rs 12684,20250,480 2 3676
+\ "
+rB 7806,18165,4905 0 3677
+] "
+ha 13173,19758 2 51875
+_ 13173,191367,6588 3 3679
+oq 7317,18555 2 51808
+` "
+a 11220,11670,390 0 3681
+b 14148,20265,390 2 3682
+c 11220,11670,390 0 3683
+d 13662,20250,390 2 3684
+e 11220,11670,390 0 3685
+f 8295,20250,150 2 3686
+g 12198,11670,6705 1 3687
+h 14637,20250,150 2 3688
+i 7317,19356,150 2 3689
+j 6831,19356,6705 3 3690
+k 14637,20250,150 2 3691
+l 7317,20262,150 2 3692
+m 21954,11670,153 0 3693
+n 14637,11673,150 0 3694
+o 14148,11670,390 0 3695
+p 14148,11679,6855 1 3696
+q 13662,11670,6855 1 3697
+r 10245,11670,150 0 3698
+s 9270,11670,390 0 3699
+t 8781,13677,390 0 3700
+u 14148,11280,390 0 3701
+v 13173,11430,390 0 3702
+w 20004,11430,390 0 3703
+x 13173,11430,150 0 3704
+y 14148,11430,6705 1 3705
+z 12198,12063 0 3706
+lC 11709,19935,6210 3 3707
+{ "
+ba 13173,19758,6588 3 3708
+| "
+rC 11709,19935,6210 3 3709
+} "
+ti 26346,8952 0 51876
+char192 20004,24846,150 2 3776
+`A "
+char194 20004,24600,150 2 3778
+^A "
+char200 16587,24846,150 2 3784
+`E "
+char202 16587,24600,150 2 3786
+^E "
+char203 16587,23751,150 2 3787
+:E "
+char206 8781,24600,150 2 3790
+^I "
+char207 8781,23751,150 2 3791
+:I "
+char180 12684,20460 2 3764
+aa "
+ga 12684,20460 2 3680
+a^ 12684,20460 2 3678
+^ "
+char168 12684,17244 0 3752
+ad "
+a~ 12684,18180 0 3710
+~ "
+char217 21468,24846,390 2 3801
+`U "
+char219 21468,24600,390 2 3803
+^U "
+char221 19029,24846,150 2 3805
+'Y "
+char253 14148,20460,6705 3 3837
+'y "
+char176 12684,17805 0 3760
+de "
+char199 19515,18555,5964 2 3783
+,C "
+char231 11220,11670,5553 0 3815
+,c "
+char209 22443,24498,774 2 3793
+~N "
+char241 14637,18180,150 0 3825
+~n "
+char161 6831,12096,7131 1 3745
+r! "
+char191 9759,12096,7131 1 3775
+r? "
+char164 12684,15684 0 3748
+Cs "
+char163 12684,17805,5424 0 3747
+Po "
+char165 12684,18315,150 2 3749
+Ye "
+char167 12684,18555,5250 2 3751
+sc "
+Fn 12684,20250,6705 3 51871
+char162 12684,17556,126 0 3746
+ct "
+char226 11220,20460,390 2 3810
+^a "
+char234 11220,20460,390 2 3818
+^e "
+char244 14148,20460,390 2 3828
+^o "
+char251 14148,20460,390 2 3835
+^u "
+char225 11220,20460,390 2 3809
+'a "
+char233 11220,20460,390 2 3817
+'e "
+char243 14148,20460,390 2 3827
+'o "
+char250 14148,20460,390 2 3834
+'u "
+char224 11220,20460,390 2 3808
+`a "
+char232 11220,20460,390 2 3816
+`e "
+char242 14148,20460,390 2 3826
+`o "
+char249 14148,20460,390 2 3833
+`u "
+char228 11220,17244,390 0 3812
+:a "
+char235 11220,17244,390 0 3819
+:e "
+char246 14148,17244,390 0 3830
+:o "
+char252 14148,17244,390 0 3836
+:u "
+char197 20004,24768,150 2 3781
+oA "
+char238 7317,20460,150 2 3822
+^i "
+char216 22443,18948,501 2 3800
+/O "
+char198 28299,18315,150 2 3782
+AE "
+char229 11220,19248,390 2 3813
+oa "
+char237 7317,20460,150 2 3821
+'i "
+char248 14148,11832,489 0 3832
+/o "
+char230 17076,11670,390 0 3814
+ae "
+char196 20004,23751,150 2 3780
+:A "
+char236 7317,20460,150 2 3820
+`i "
+char214 22443,23751,390 2 3798
+:O "
+char220 21468,23751,390 2 3804
+:U "
+char201 16587,24846,150 2 3785
+'E "
+char239 7317,17244,150 0 3823
+:i "
+char223 14637,20250,390 2 3807
+ss "
+char212 22443,24600,390 2 3796
+^O "
+char193 20004,24846,150 2 3777
+'A "
+char195 20004,24498,150 2 3779
+~A "
+char227 11220,18180,390 0 3811
+~a "
+char208 20979,18555,150 2 3792
+-D "
+char240 14148,20250,390 2 3824
+Sd "
+char205 8781,24846,150 2 3789
+'I "
+char204 8781,24846,150 2 3788
+`I "
+char211 22443,24846,390 2 3795
+'O "
+char210 22443,24846,390 2 3794
+`O "
+char213 22443,24498,390 2 3797
+~O "
+char245 14148,18180,390 0 3829
+~o "
+vS 12684,24612,390 2 51795
+vs 9270,20499,390 2 51827
+char218 21468,24846,390 2 3802
+'U "
+:Y 19029,23751,150 2 51801
+char255 14148,17244,6705 1 3839
+:y "
+char222 15612,18315,150 2 3806
+TP "
+char254 14148,20250,6855 3 3838
+Tp "
+char181 14637,10800,5595 0 3765
+char182 12684,19635,4200 2 3766
+ps "
+char190 21468,17805,288 0 3774
+34 "
+\- 21468,7305 0 51757
+char188 21468,17805,288 0 3772
+14 "
+char189 21468,17805,288 0 3773
+12 "
+char170 12684,17805 0 3754
+Of "
+char186 12684,17805 0 3770
+Om "
+char171 11220,9945 0 3755
+Fo "
+char187 11220,9945 0 3771
+Fc "
+char177 21468,13191,3105 0 3761
+char166 13173,19083,5916 2 3750
+bb "
+char169 13173,19725 2 3753
+co "
+char172 21468,10029 0 3756
+no "
+char174 13173,19725 2 3758
+rg "
+char178 8781,17805 0 3762
+S2 "
+char179 8781,17805 0 3763
+S3 "
+char184 12684,255,5553 0 3768
+ac "
+char185 8781,17805 0 3769
+S1 "
+char215 21468,12969,189 0 3799
+char247 21468,12966,36 0 3831
+char183 6831,10326 0 3767
+fm 12684,17805 0 51873
+sd 12684,17805 0 51874
+dg 12684,18555,5250 2 51755
+tm 16101,17550 0 51796
+ah 12684,20499 2 51935
+ao 12684,19248 2 51930
+f/ 2928,17805,288 0 51759
+em 21468,6960 0 51789
+en 12684,6960 0 51790
+dd 12684,18555,5250 2 51773
+.i 7317,11673,150 0 51957
+aq 7317,18555 2 3623
+bu 13173,14226 0 51889
+'C 19515,24846,390 2 20166
+'c 11220,20460,390 2 20198
+lq 11220,18555 2 51838
+rq 11220,18555 2 51746
+Bq 11220,2811,3939 0 51772
+vz 12198,20499 2 51834
+fi 14637,20250,150 2 51881
+fl 14637,20250,150 2 51882
+ff 15612,20250,150 2 51883
+Fi 21954,20250,150 2 51884
+Fl 21954,20250,150 2 51885
+ij 14148,19356,6705 3 51958
+bq 7317,2811,3939 0 51756
+%0 30738,17805,180 0 51901
+char175 12684,17367 0 3759
+a- "
+ab 12684,17796 0 51926
+a. 12684,17244 0 51927
+oe 20004,11670,390 0 51823
+OE 27321,18555,390 2 51791
+fo 7317,9945 0 51886
+fc 7317,9945 0 51887
+sq 19029,15624 0 51899
+/L 16101,18315,150 2 51944
+/l 7317,20262,150 2 51960
+a" 12684,20460 2 51933
+ho 12684,600,4653 0 51934
+vZ 17565,24612 2 51802
+IJ 18540,18315,6060 2 51942
diff --git a/font/devlj4/LGB b/font/devlj4/LGB
new file mode 100644
index 00000000..89c96915
--- /dev/null
+++ b/font/devlj4/LGB
@@ -0,0 +1,347 @@
+name LGB
+spacewidth 13227
+pcltypeface 4102
+pclproportional 0
+pclweight 3
+pclstyle 0
+charset
+! 13227,18990,330 2 3617
+" 13227,18990 2 3618
+sh 13227,21345,2391 2 3619
+# "
+Do 13227,19320,993 2 3620
+$ "
+% 13227,19320,330 2 3621
+& 13227,19320,330 2 3622
+' 13227,19320 2 51751
+( 13227,19320,2325 2 3624
+) 13227,19320,2325 2 3625
+* 13227,18990 2 3626
++ 13227,15645 0 3627
+, 13227,2925,2640 0 3628
+char173 13227,8775 0 3629
+hy "
+- "
+. 13227,3180,330 0 3630
+sl 13227,19545,330 2 3631
+/ "
+0 13227,19320,330 2 3632
+1 13227,19320 2 3633
+2 13227,19320 2 3634
+3 13227,19320,330 2 3635
+4 13227,19320 2 3636
+5 13227,18990,330 2 3637
+6 13227,19320,330 2 3638
+7 13227,18990 2 3639
+8 13227,19320,330 2 3640
+9 13227,19320,330 2 3641
+: 13227,12654,330 0 3642
+; 13227,12654,2640 0 3643
+< 13227,15312 0 3644
+= 13227,12534 0 3645
+> 13227,15312 0 3646
+? 13227,19320,330 2 3647
+at 13227,19320,330 2 3648
+@ "
+A 13227,18990 2 3649
+B 13227,18990 2 3650
+C 13227,19320,330 2 3651
+D 13227,18990 2 3652
+E 13227,18990 2 3653
+F 13227,18990 2 3654
+G 13227,19320,330 2 3655
+H 13227,18990 2 3656
+I 13227,18990 2 3657
+J 13227,18990,330 2 3658
+K 13227,18990 2 3659
+L 13227,18990 2 3660
+M 13227,18990 2 3661
+N 13227,18990 2 3662
+O 13227,19320,330 2 3663
+P 13227,18990 2 3664
+Q 13227,19320,2760 2 3665
+R 13227,18990 2 3666
+S 13227,19320,330 2 3667
+T 13227,18990 2 3668
+U 13227,18990,330 2 3669
+V 13227,18990 2 3670
+W 13227,18990 2 3671
+X 13227,18990 2 3672
+Y 13227,18990 2 3673
+Z 13227,18990 2 3674
+lB 13227,18990,3510 2 3675
+[ "
+rs 13227,19545,330 2 3676
+\ "
+rB 13227,18990,3510 2 3677
+] "
+ha 13227,19758 2 51875
+_ 13227,191367,6588 3 3679
+oq 13227,19320 2 51808
+` "
+a 13227,14355,330 0 3681
+b 13227,19545,330 2 3682
+c 13227,14355,330 0 3683
+d 13227,19545,330 2 3684
+e 13227,14355,330 0 3685
+f 13227,19335 2 3686
+g 13227,14355,4350 0 3687
+h 13227,19545 2 3688
+i 13227,19095 2 3689
+j 13227,19095,4350 2 3690
+k 13227,19545 2 3691
+l 13227,19545 2 3692
+m 13227,14355 0 3693
+n 13227,14355 0 3694
+o 13227,14355,330 0 3695
+p 13227,14355,5475 1 3696
+q 13227,14355,5475 1 3697
+r 13227,14355 0 3698
+s 13227,14355,330 0 3699
+t 13227,18300,330 2 3700
+u 13227,14025,330 0 3701
+v 13227,14025 0 3702
+w 13227,14025 0 3703
+x 13227,14025 0 3704
+y 13227,14025,4350 0 3705
+z 13227,14025 0 3706
+lC 13227,20130,6141 3 3707
+{ "
+ba 13227,19758,6588 3 3708
+| "
+rC 13227,20130,6141 3 3709
+} "
+ti 13227,11181 0 51876
+char192 13227,25155 2 3776
+`A "
+char194 13227,25080 2 3778
+^A "
+char200 13227,25155 2 3784
+`E "
+char202 13227,25080 2 3786
+^E "
+char203 13227,24000 2 3787
+:E "
+char206 13227,25080 2 3790
+^I "
+char207 13227,24000 2 3791
+:I "
+char180 13227,20745 2 3764
+aa "
+ga 13227,20745 2 3680
+a^ 13227,21015 2 3678
+^ "
+char168 13227,19125 2 3752
+ad "
+a~ 13227,19683 2 3710
+~ "
+char217 13227,25155,330 2 3801
+`U "
+char219 13227,25080,330 2 3803
+^U "
+char221 13227,25155 2 3805
+'Y "
+char253 13227,20745,4350 2 3837
+'y "
+char176 13227,19320 2 3760
+de "
+char199 13227,19320,5787 3 3783
+,C "
+char231 13227,14355,6060 1 3815
+,c "
+char209 13227,24552 2 3793
+~N "
+char241 13227,19683 2 3825
+~n "
+char161 13227,14319,5001 1 3745
+r! "
+char191 13227,14265,5385 1 3775
+r? "
+char164 13227,15885 0 3748
+Cs "
+char163 13227,18990,330 2 3747
+Po "
+char165 13227,18990 2 3749
+Ye "
+char167 13227,19320,1218 2 3751
+sc "
+Fn 13227,19335,3558 2 51871
+char162 13227,19320,330 2 3746
+ct "
+char226 13227,21015,330 2 3810
+^a "
+char234 13227,21015,330 2 3818
+^e "
+char244 13227,21015,330 2 3828
+^o "
+char251 13227,21015,330 2 3835
+^u "
+char225 13227,20745,330 2 3809
+'a "
+char233 13227,20745,330 2 3817
+'e "
+char243 13227,20745,330 2 3827
+'o "
+char250 13227,20745,330 2 3834
+'u "
+char224 13227,20745,330 2 3808
+`a "
+char232 13227,20745,330 2 3816
+`e "
+char242 13227,20745,330 2 3826
+`o "
+char249 13227,20745,330 2 3833
+`u "
+char228 13227,19125,330 2 3812
+:a "
+char235 13227,19125,330 2 3819
+:e "
+char246 13227,19125,330 2 3830
+:o "
+char252 13227,19125,330 2 3836
+:u "
+char197 13227,24882 2 3781
+oA "
+char238 13227,21015 2 3822
+^i "
+char216 13227,19320,459 2 3800
+/O "
+char198 13227,18990 2 3782
+AE "
+char229 13227,20790,330 2 3813
+oa "
+char237 13227,20745 2 3821
+'i "
+char248 13227,14901,957 0 3832
+/o "
+char230 13227,14355,330 0 3814
+ae "
+char196 13227,24000 2 3780
+:A "
+char236 13227,20745 2 3820
+`i "
+char214 13227,24000,330 2 3798
+:O "
+char220 13227,24000,330 2 3804
+:U "
+char201 13227,25155 2 3785
+'E "
+char239 13227,19125 2 3823
+:i "
+char223 13227,19335,330 2 3807
+ss "
+char212 13227,25080,330 2 3796
+^O "
+char193 13227,25155 2 3777
+'A "
+char195 13227,24552 2 3779
+~A "
+char227 13227,19683,330 2 3811
+~a "
+char208 13227,18990 2 3792
+-D "
+char240 13227,19656,330 2 3824
+Sd "
+char205 13227,25155 2 3789
+'I "
+char204 13227,25155 2 3788
+`I "
+char211 13227,25155,330 2 3795
+'O "
+char210 13227,25155,330 2 3794
+`O "
+char213 13227,24552,330 2 3797
+~O "
+char245 13227,19683,330 2 3829
+~o "
+vS 13227,25116,330 2 51795
+vs 13227,21015,330 2 51827
+char218 13227,25155,330 2 3802
+'U "
+:Y 13227,24000 2 51801
+char255 13227,19125,4350 2 3839
+:y "
+char222 13227,18990 2 3806
+TP "
+char254 13227,19545,5475 3 3838
+Tp "
+char181 13227,14025,4350 0 3765
+char182 13227,19635,4200 2 3766
+ps "
+char190 13227,19110,3825 2 3774
+34 "
+\- 13227,10425 0 51757
+char188 13227,19110,3825 2 3772
+14 "
+char189 13227,19110,3825 2 3773
+12 "
+char170 13227,19320 2 3754
+Of "
+char186 13227,19320 2 3770
+Om "
+char171 13227,14115 0 3755
+Fo "
+char187 13227,14115 0 3771
+Fc "
+char177 13227,15645,30 0 3761
+char166 13227,19083,5916 3 3750
+bb "
+char169 13227,19635 2 3753
+co "
+char172 13227,13020 0 3756
+no "
+char174 13227,19635 2 3758
+rg "
+char178 13227,19110 2 3762
+S2 "
+char179 13227,19110 2 3763
+S3 "
+char184 13227,0,6060 1 3768
+ac "
+char185 13227,19110 2 3769
+S1 "
+char215 13227,15549 0 3799
+char247 13227,15510 0 3831
+char183 13227,11376 0 3767
+fm 13227,18990 2 51873
+sd 13227,18990 2 51874
+dg 13227,18990 2 51755
+tm 13227,17850 2 51796
+ah 13227,21015 2 51935
+ao 13227,20790 2 51930
+f/ 13227,15675 0 51759
+em 13227,8430 0 51789
+en 13227,8430 0 51790
+dd 13227,18990 2 51773
+.i 13227,14025 0 51957
+aq 13227,18990 2 3623
+bu 13227,12714 0 51889
+'C 13227,25155,330 2 20166
+'c 13227,20745,330 2 20198
+lq 13227,19320 2 51838
+rq 13227,19320 2 51746
+Bq 13227,3486,2079 0 51772
+vz 13227,21015 2 51834
+fi 13227,19335 2 51881
+fl 13227,19335 2 51882
+ff 13227,19335 2 51883
+Fi 13227,19335 2 51884
+Fl 13227,19335 2 51885
+ij 13227,19095,4350 2 51958
+bq 13227,3486,2079 0 51756
+%0 13227,19320,330 2 51901
+char175 13227,19119 2 3759
+a- "
+ab 13227,19830 2 51926
+a. 13227,19125 2 51927
+oe 13227,14355,330 0 51823
+OE 13227,19320,330 2 51791
+fo 13227,14115 0 51886
+fc 13227,14115 0 51887
+sq 13227,14106 0 51899
+/L 13227,18990 2 51944
+/l 13227,19545 2 51960
+a" 13227,20745 2 51933
+ho 13227,1026,5109 1 51934
+vZ 13227,25116 2 51802
+IJ 13227,18990,330 2 51942
diff --git a/font/devlj4/LGI b/font/devlj4/LGI
new file mode 100644
index 00000000..492b52c0
--- /dev/null
+++ b/font/devlj4/LGI
@@ -0,0 +1,348 @@
+name LGI
+spacewidth 13227
+slant 12.000000
+pcltypeface 4102
+pclproportional 0
+pclweight 0
+pclstyle 1
+charset
+! 13227,18990,330,0,-2748 2 3617
+" 13227,18990,0,372,-3960,372 2 3618
+sh 13227,21309,2451,1827,1062,790 2 3619
+# "
+Do 13227,19320,1074,762,288,762 2 3620
+$ "
+% 13227,19320,330,2535,882,790 2 3621
+& 13227,19320,330,54,699,54 2 3622
+' 13227,19320,0,0,-5469 2 51751
+( 13227,19320,1935,318,-2952,318 2 3624
+) 13227,19320,1935,318,-2952,318 2 3625
+* 13227,18990,0,1995,-828,790 2 3626
++ 13227,15075,0,960,-93,790 0 3627
+, 13227,1785,2250,0,-2769 0 3628
+char173 13227,7995,0,0,-2511 0 3629
+hy "
+- "
+. 13227,2100,330,0,-3873 0 3630
+sl 13227,19545,330,0,-1410 2 3631
+/ "
+0 13227,19320,330,564,-456,564 2 3632
+1 13227,19320,0,0,60 2 3633
+2 13227,19320,0,1578,1365,790 2 3634
+3 13227,19320,330,420,888,420 2 3635
+4 13227,19320,0,585,750,585 2 3636
+5 13227,18990,330,1215,153,790 2 3637
+6 13227,19320,330,1800,-93,790 2 3638
+7 13227,18990,0,2184,-963,790 2 3639
+8 13227,19320,330,996,423,790 2 3640
+9 13227,19320,330,741,90,741 2 3641
+: 13227,12492,330,0,-3039 0 3642
+; 13227,12492,2250,0,-2772 0 3643
+< 13227,15063,0,390,387,390 0 3644
+= 13227,11721,0,1065,-288,790 0 3645
+> 13227,15063,0,390,387,390 0 3646
+? 13227,19320,330,981,-2730,790 2 3647
+at 13227,19320,330,993,87,790 2 3648
+@ "
+A 13227,18990,0,0,2541 2 3649
+B 13227,18990,0,1095,831,790 2 3650
+C 13227,19320,330,1524,-12,790 2 3651
+D 13227,18990,0,1089,1263,790 2 3652
+E 13227,18990,0,1995,642,790 2 3653
+F 13227,18990,0,2535,594,790 2 3654
+G 13227,19320,330,1350,519,790 2 3655
+H 13227,18990,0,2316,1050,790 2 3656
+I 13227,18990,0,558,-663,558 2 3657
+J 13227,18990,330,2118,-39,790 2 3658
+K 13227,18990,0,1590,765,790 2 3659
+L 13227,18990,0,0,153 2 3660
+M 13227,18990,0,2853,1941,790 2 3661
+N 13227,18990,0,2097,882,790 2 3662
+O 13227,19320,330,1485,273,790 2 3663
+P 13227,18990,0,1152,771,790 2 3664
+Q 13227,19320,2778,1485,273,790 2 3665
+R 13227,18990,0,987,981,790 2 3666
+S 13227,19320,330,1608,1134,790 2 3667
+T 13227,18990,0,3171,-1431,790 2 3668
+U 13227,18990,330,2220,108,790 2 3669
+V 13227,18990,0,2217,-2733,790 2 3670
+W 13227,18990,0,3045,702,790 2 3671
+X 13227,18990,0,2355,1296,790 2 3672
+Y 13227,18990,0,2553,-2397,790 2 3673
+Z 13227,18990,0,1956,1203,790 2 3674
+lB 13227,18990,2940,1110,-33,790 2 3675
+[ "
+rs 13227,19545,330,0,-3072 2 3676
+\ "
+rB 13227,18990,2940,342,735,342 2 3677
+] "
+ha 13227,19758,0,9,9,9 2 51875
+_ 13227,191367,6588,1317,1317,790 3 3679
+oq 13227,19326,0,0,-6222 2 51808
+` "
+a 13227,14355,330,0,105 0 3681
+b 13227,19545,330,312,1671,312 2 3682
+c 13227,14355,330,810,261,790 0 3683
+d 13227,19545,330,2121,363,790 2 3684
+e 13227,14355,330,387,303,387 0 3685
+f 13227,19335,0,3231,-1785,790 2 3686
+g 13227,14355,4350,1545,1053,790 0 3687
+h 13227,19545,0,168,723,168 2 3688
+i 13227,18780,0,0,-2319 2 3689
+j 13227,18780,4350,906,936,790 2 3690
+k 13227,19545,0,495,504,495 2 3691
+l 13227,19545,0,0,-3603 2 3692
+m 13227,14355,0,1770,2205,790 0 3693
+n 13227,14355,0,267,774,267 0 3694
+o 13227,14355,330,372,252,372 0 3695
+p 13227,14355,5475,213,2205,213 1 3696
+q 13227,14355,5475,1668,318,790 1 3697
+r 13227,14355,0,684,-81,684 0 3698
+s 13227,14355,330,57,480,57 0 3699
+t 13227,18495,330,0,-933 2 3700
+u 13227,14025,330,714,249,714 0 3701
+v 13227,14025,0,1437,-1767,790 0 3702
+w 13227,14025,0,2574,279,790 0 3703
+x 13227,14025,0,1050,2112,790 0 3704
+y 13227,14025,4350,1986,3579,790 0 3705
+z 13227,14025,0,984,1395,790 0 3706
+lC 13227,20130,6075,1170,-2529,790 3 3707
+{ "
+ba 13227,19758,6588,0,-4623 3 3708
+| "
+rC 13227,20130,6075,0,975 3 3709
+} "
+ti 13227,10485,0,825,822,790 0 51876
+char192 13227,24630,0,0,2541 2 3776
+`A "
+char194 13227,24810,0,2133,2541,790 2 3778
+^A "
+char200 13227,24630,0,1995,642,790 2 3784
+`E "
+char202 13227,24810,0,2133,642,790 2 3786
+^E "
+char203 13227,23115,0,1995,642,790 2 3787
+:E "
+char206 13227,24810,0,2133,-663,790 2 3790
+^I "
+char207 13227,23115,0,1143,-663,790 2 3791
+:I "
+char180 13227,19725,0,753,-5706,753 2 3764
+aa "
+ga 13227,19725,0,0,-4728 2 3680
+a^ 13227,19905,0,1089,-3117,790 2 3678
+^ "
+char168 13227,18195,0,0,-4341 2 3752
+ad "
+a~ 13227,18873,0,1833,-2406,790 2 3710
+~ "
+char217 13227,24630,330,2220,108,790 2 3801
+`U "
+char219 13227,24810,330,2220,108,790 2 3803
+^U "
+char221 13227,24630,0,2553,-2397,790 2 3805
+'Y "
+char253 13227,19725,4350,1986,3579,790 2 3837
+'y "
+char176 13227,19320,0,0,-2637 2 3760
+de "
+char199 13227,19320,5325,1524,-12,790 3 3783
+,C "
+char231 13227,14355,5295,810,261,790 1 3815
+,c "
+char209 13227,23814,0,3201,882,790 2 3793
+~N "
+char241 13227,18873,0,1833,774,790 2 3825
+~n "
+char161 13227,14271,5049,0,-1647 1 3745
+r! "
+char191 13227,14214,5436,0,-126 1 3775
+r? "
+char164 13227,15684,0,1425,528,790 0 3748
+Cs "
+char163 13227,19320,330,2433,234,790 2 3747
+Po "
+char165 13227,18990,0,2712,-1056,790 2 3749
+Ye "
+char167 13227,19320,1344,66,-891,66 2 3751
+sc "
+Fn 13227,19335,3540,231,-492,231 2 51871
+char162 13227,19320,330,891,-780,790 2 3746
+ct "
+char226 13227,19905,330,1089,105,790 2 3810
+^a "
+char234 13227,19905,330,1089,303,790 2 3818
+^e "
+char244 13227,19905,330,1089,252,790 2 3828
+^o "
+char251 13227,19905,330,1089,249,790 2 3835
+^u "
+char225 13227,19725,330,753,105,753 2 3809
+'a "
+char233 13227,19725,330,753,303,753 2 3817
+'e "
+char243 13227,19725,330,753,252,753 2 3827
+'o "
+char250 13227,19725,330,753,249,753 2 3834
+'u "
+char224 13227,19725,330,0,105 2 3808
+`a "
+char232 13227,19725,330,387,303,387 2 3816
+`e "
+char242 13227,19725,330,372,252,372 2 3826
+`o "
+char249 13227,19725,330,714,249,714 2 3833
+`u "
+char228 13227,18195,330,0,105 2 3812
+:a "
+char235 13227,18195,330,387,303,387 2 3819
+:e "
+char246 13227,18195,330,372,252,372 2 3830
+:o "
+char252 13227,18195,330,714,249,714 2 3836
+:u "
+char197 13227,24810,0,0,2541 2 3781
+oA "
+char238 13227,19905,0,0,-1917 2 3822
+^i "
+char216 13227,19320,342,2895,1743,790 2 3800
+/O "
+char198 13227,18990,0,4059,2670,790 2 3782
+AE "
+char229 13227,19905,330,0,105 2 3813
+oa "
+char237 13227,19725,0,3,-2319,3 2 3821
+'i "
+char248 13227,14895,735,1119,1086,790 0 3832
+/o "
+char230 13227,14355,330,1530,1950,790 0 3814
+ae "
+char196 13227,23115,0,1143,2541,790 2 3780
+:A "
+char236 13227,19725,0,0,-2319 2 3820
+`i "
+char214 13227,23115,330,1485,273,790 2 3798
+:O "
+char220 13227,23115,330,2220,108,790 2 3804
+:U "
+char201 13227,24630,0,1995,642,790 2 3785
+'E "
+char239 13227,18195,0,0,-2319 2 3823
+:i "
+char223 13227,19335,330,570,270,570 2 3807
+ss "
+char212 13227,24810,330,2133,273,790 2 3796
+^O "
+char193 13227,24630,0,1389,2541,790 2 3777
+'A "
+char195 13227,23814,0,3201,2541,790 2 3779
+~A "
+char227 13227,18873,330,1833,105,790 2 3811
+~a "
+char208 13227,18990,0,1389,963,790 2 3792
+-D "
+char240 13227,19545,330,192,237,192 2 3824
+Sd "
+char205 13227,24630,0,1389,-663,790 2 3789
+'I "
+char204 13227,24630,0,558,-663,558 2 3788
+`I "
+char211 13227,24630,330,1485,273,790 2 3795
+'O "
+char210 13227,24630,330,1485,273,790 2 3794
+`O "
+char213 13227,23814,330,3201,273,790 2 3797
+~O "
+char245 13227,18873,330,1833,252,790 2 3829
+~o "
+vS 13227,24810,330,2433,1134,790 2 51795
+vs 13227,19905,330,1539,480,790 2 51827
+char218 13227,24630,330,2220,108,790 2 3802
+'U "
+:Y 13227,23115,0,2553,-2397,790 2 51801
+char255 13227,18195,4350,1986,3579,790 2 3839
+:y "
+char222 13227,18990,0,378,771,378 2 3806
+TP "
+char254 13227,19545,5475,231,2223,231 3 3838
+Tp "
+char181 13227,14025,4350,765,1659,765 0 3765
+char182 13227,19635,4200,696,-408,696 2 3766
+ps "
+char190 13227,19110,3825,1413,627,790 2 3774
+34 "
+\- 13227,9945,0,1065,-288,790 0 51757
+char188 13227,19110,3825,918,873,790 2 3772
+14 "
+char189 13227,19110,3825,1269,1023,790 2 3773
+12 "
+char170 13227,19320,0,0,-3066 2 3754
+Of "
+char186 13227,19320,0,0,-3330 2 3770
+Om "
+char171 13227,13710,0,2418,1104,790 0 3755
+Fo "
+char187 13227,13710,0,1107,2415,790 0 3771
+Fc "
+char177 13227,15075,0,1110,-243,790 0 3761
+char166 13227,19083,5916,0,-4623 3 3750
+bb "
+char169 13227,19635,0,3927,-2190,790 2 3753
+co "
+char172 13227,12501,0,1065,-288,790 0 3756
+no "
+char174 13227,19635,0,3927,-2190,790 2 3758
+rg "
+char178 13227,19110,0,0,-2379 2 3762
+S2 "
+char179 13227,19110,0,0,-2073 2 3763
+S3 "
+char184 13227,0,5295,0,-1200 1 3768
+ac "
+char185 13227,19110,0,0,-2727 2 3769
+S1 "
+char215 13227,14814,0,897,-483,790 0 3799
+char247 13227,14655,0,1104,-252,790 0 3831
+char183 13227,11007,0,0,-4590 0 3767
+fm 13227,18990,0,0,-3444 2 51873
+sd 13227,18990,0,0,-3444 2 51874
+dg 13227,18990,0,0,-2019 2 51755
+tm 13227,17850,0,4395,-2058,790 2 51796
+ah 13227,19905,0,1539,-3567,790 2 51935
+ao 13227,19905,0,0,-5466 2 51930
+f/ 13227,15675,777,0,-339 0 51759
+em 13227,7710,0,1317,1317,790 0 51789
+en 13227,7710,0,0,-1215 0 51790
+dd 13227,18990,0,0,-1713 2 51773
+.i 13227,14025,0,0,-2319 0 51957
+aq 13227,18990,0,0,-6060 2 3623
+bu 13227,12714,0,0,-519 0 51889
+'C 13227,24630,330,1524,-12,790 2 20166
+'c 13227,19725,330,810,261,790 2 20198
+lq 13227,19326,0,1812,-4197,790 2 51838
+rq 13227,19320,0,1512,-3897,790 2 51746
+Bq 13227,2214,2091,0,-897 0 51772
+vz 13227,19905,0,1539,1395,790 2 51834
+fi 13227,19335,0,1065,-339,790 2 51881
+fl 13227,19335,0,1065,-339,790 2 51882
+ff 13227,19335,0,5175,606,790 2 51883
+Fi 13227,19335,0,3579,1149,790 2 51884
+Fl 13227,19335,0,2703,1155,790 2 51885
+ij 13227,18780,4350,2355,645,790 2 51958
+bq 13227,2214,2091,0,-2922 0 51756
+%0 13227,19320,330,1920,4113,790 2 51901
+char175 13227,18051,0,1086,-3930,790 2 3759
+a- "
+ab 13227,19350,0,1683,-3297,790 2 51926
+a. 13227,18195,0,0,-6561 2 51927
+oe 13227,14355,330,1629,1671,790 0 51823
+OE 13227,19320,330,4059,783,790 2 51791
+fo 13227,13710,0,0,-1182 0 51886
+fc 13227,13710,0,0,-663 0 51887
+sq 13227,14106,0,876,876,790 0 51899
+/L 13227,18990,0,0,885 2 51944
+/l 13227,19545,0,0,-2769 2 51960
+a" 13227,19725,0,3210,-3906,790 2 51933
+ho 13227,735,4086,0,-4818 0 51934
+vZ 13227,24810,0,2433,1203,790 2 51802
+IJ 13227,18990,330,2259,3129,790 2 51942
diff --git a/font/devlj4/LGR b/font/devlj4/LGR
new file mode 100644
index 00000000..e4b1fcb8
--- /dev/null
+++ b/font/devlj4/LGR
@@ -0,0 +1,347 @@
+name LGR
+spacewidth 13227
+pcltypeface 4102
+pclproportional 0
+pclweight 0
+pclstyle 0
+charset
+! 13227,18990,330 2 3617
+" 13227,18990 2 3618
+sh 13227,21309,2451 2 3619
+# "
+Do 13227,19320,372 2 3620
+$ "
+% 13227,19320,330 2 3621
+& 13227,19320,330 2 3622
+' 13227,19320 2 51751
+( 13227,19320,1935 2 3624
+) 13227,19320,1935 2 3625
+* 13227,18990 2 3626
++ 13227,15075 0 3627
+, 13227,2055,2235 0 3628
+char173 13227,7815 0 3629
+hy "
+- "
+. 13227,2055,330 0 3630
+sl 13227,19545,330 2 3631
+/ "
+0 13227,19320,330 2 3632
+1 13227,19320 2 3633
+2 13227,19320 2 3634
+3 13227,19320,330 2 3635
+4 13227,19320 2 3636
+5 13227,18990,330 2 3637
+6 13227,19320,330 2 3638
+7 13227,18990 2 3639
+8 13227,19320,330 2 3640
+9 13227,19320,330 2 3641
+: 13227,12414,330 0 3642
+; 13227,12414,2235 0 3643
+< 13227,15063 0 3644
+= 13227,11721 0 3645
+> 13227,15063 0 3646
+? 13227,19320,330 2 3647
+at 13227,19320,330 2 3648
+@ "
+A 13227,18990 2 3649
+B 13227,18990 2 3650
+C 13227,19320,330 2 3651
+D 13227,18990 2 3652
+E 13227,18990 2 3653
+F 13227,18990 2 3654
+G 13227,19320,330 2 3655
+H 13227,18990 2 3656
+I 13227,18990 2 3657
+J 13227,18990,330 2 3658
+K 13227,18990 2 3659
+L 13227,18990 2 3660
+M 13227,18990 2 3661
+N 13227,18990 2 3662
+O 13227,19320,330 2 3663
+P 13227,18990 2 3664
+Q 13227,19320,2712 2 3665
+R 13227,18990 2 3666
+S 13227,19320,330 2 3667
+T 13227,18990 2 3668
+U 13227,18990,330 2 3669
+V 13227,18990 2 3670
+W 13227,18990 2 3671
+X 13227,18990 2 3672
+Y 13227,18990 2 3673
+Z 13227,18990 2 3674
+lB 13227,18990,2940 2 3675
+[ "
+rs 13227,19545,330 2 3676
+\ "
+rB 13227,18990,2940 2 3677
+] "
+ha 13227,19758 2 51875
+_ 13227,191367,6588 3 3679
+oq 13227,19320 2 51808
+` "
+a 13227,14355,330 0 3681
+b 13227,19545,330 2 3682
+c 13227,14355,330 0 3683
+d 13227,19545,330 2 3684
+e 13227,14355,330 0 3685
+f 13227,19335 2 3686
+g 13227,14355,4350 0 3687
+h 13227,19545 2 3688
+i 13227,18780 2 3689
+j 13227,18780,4350 2 3690
+k 13227,19545 2 3691
+l 13227,19545 2 3692
+m 13227,14355 0 3693
+n 13227,14355 0 3694
+o 13227,14355,330 0 3695
+p 13227,14355,5475 1 3696
+q 13227,14355,5475 1 3697
+r 13227,14355 0 3698
+s 13227,14355,330 0 3699
+t 13227,18495,330 2 3700
+u 13227,14025,330 0 3701
+v 13227,14025 0 3702
+w 13227,14025 0 3703
+x 13227,14025 0 3704
+y 13227,14025,4350 0 3705
+z 13227,14025 0 3706
+lC 13227,20130,6075 3 3707
+{ "
+ba 13227,19758,6588 3 3708
+| "
+rC 13227,20130,6075 3 3709
+} "
+ti 13227,10485 0 51876
+char192 13227,24630 2 3776
+`A "
+char194 13227,24810 2 3778
+^A "
+char200 13227,24630 2 3784
+`E "
+char202 13227,24810 2 3786
+^E "
+char203 13227,23115 2 3787
+:E "
+char206 13227,24810 2 3790
+^I "
+char207 13227,23115 2 3791
+:I "
+char180 13227,19725 2 3764
+aa "
+ga 13227,19725 2 3680
+a^ 13227,19905 2 3678
+^ "
+char168 13227,18195 2 3752
+ad "
+a~ 13227,18867 2 3710
+~ "
+char217 13227,24630,330 2 3801
+`U "
+char219 13227,24810,330 2 3803
+^U "
+char221 13227,24630 2 3805
+'Y "
+char253 13227,19725,4350 2 3837
+'y "
+char176 13227,19320 2 3760
+de "
+char199 13227,19320,5430 3 3783
+,C "
+char231 13227,14355,5430 1 3815
+,c "
+char209 13227,23787 2 3793
+~N "
+char241 13227,18867 2 3825
+~n "
+char161 13227,14259,5061 1 3745
+r! "
+char191 13227,14265,5385 1 3775
+r? "
+char164 13227,15684 0 3748
+Cs "
+char163 13227,19320,330 2 3747
+Po "
+char165 13227,18990 2 3749
+Ye "
+char167 13227,19320,1344 2 3751
+sc "
+Fn 13227,19335,3540 2 51871
+char162 13227,19320,330 2 3746
+ct "
+char226 13227,19905,330 2 3810
+^a "
+char234 13227,19905,330 2 3818
+^e "
+char244 13227,19905,330 2 3828
+^o "
+char251 13227,19905,330 2 3835
+^u "
+char225 13227,19725,330 2 3809
+'a "
+char233 13227,19725,330 2 3817
+'e "
+char243 13227,19725,330 2 3827
+'o "
+char250 13227,19725,330 2 3834
+'u "
+char224 13227,19725,330 2 3808
+`a "
+char232 13227,19725,330 2 3816
+`e "
+char242 13227,19725,330 2 3826
+`o "
+char249 13227,19725,330 2 3833
+`u "
+char228 13227,18195,330 2 3812
+:a "
+char235 13227,18195,330 2 3819
+:e "
+char246 13227,18195,330 2 3830
+:o "
+char252 13227,18195,330 2 3836
+:u "
+char197 13227,24735 2 3781
+oA "
+char238 13227,19905 2 3822
+^i "
+char216 13227,19320,444 2 3800
+/O "
+char198 13227,18990 2 3782
+AE "
+char229 13227,19830,330 2 3813
+oa "
+char237 13227,19725 2 3821
+'i "
+char248 13227,14805,747 0 3832
+/o "
+char230 13227,14355,330 0 3814
+ae "
+char196 13227,23115 2 3780
+:A "
+char236 13227,19725 2 3820
+`i "
+char214 13227,23115,330 2 3798
+:O "
+char220 13227,23115,330 2 3804
+:U "
+char201 13227,24630 2 3785
+'E "
+char239 13227,18195 2 3823
+:i "
+char223 13227,19335,330 2 3807
+ss "
+char212 13227,24810,330 2 3796
+^O "
+char193 13227,24630 2 3777
+'A "
+char195 13227,23787 2 3779
+~A "
+char227 13227,18867,330 2 3811
+~a "
+char208 13227,18990 2 3792
+-D "
+char240 13227,19545,330 2 3824
+Sd "
+char205 13227,24630 2 3789
+'I "
+char204 13227,24630 2 3788
+`I "
+char211 13227,24630,330 2 3795
+'O "
+char210 13227,24630,330 2 3794
+`O "
+char213 13227,23787,330 2 3797
+~O "
+char245 13227,18867,330 2 3829
+~o "
+vS 13227,24810,330 2 51795
+vs 13227,19905,330 2 51827
+char218 13227,24630,330 2 3802
+'U "
+:Y 13227,23115 2 51801
+char255 13227,18195,4350 2 3839
+:y "
+char222 13227,18990 2 3806
+TP "
+char254 13227,19545,5475 3 3838
+Tp "
+char181 13227,14025,4350 0 3765
+char182 13227,19635,4200 2 3766
+ps "
+char190 13227,19119,3825 2 3774
+34 "
+\- 13227,9945 0 51757
+char188 13227,19110,3825 2 3772
+14 "
+char189 13227,19110,3825 2 3773
+12 "
+char170 13227,19320 2 3754
+Of "
+char186 13227,19320 2 3770
+Om "
+char171 13227,13710 0 3755
+Fo "
+char187 13227,13710 0 3771
+Fc "
+char177 13227,15075 0 3761
+char166 13227,19083,5916 3 3750
+bb "
+char169 13227,19635 2 3753
+co "
+char172 13227,12501 0 3756
+no "
+char174 13227,19635 2 3758
+rg "
+char178 13227,19110 2 3762
+S2 "
+char179 13227,19119 2 3763
+S3 "
+char184 13227,0,5430 1 3768
+ac "
+char185 13227,19110 2 3769
+S1 "
+char215 13227,14814 0 3799
+char247 13227,14655 0 3831
+char183 13227,11025 0 3767
+fm 13227,18990 2 51873
+sd 13227,18990 2 51874
+dg 13227,18990 2 51755
+tm 13227,17850 2 51796
+ah 13227,19905 2 51935
+ao 13227,19830 2 51930
+f/ 13227,15675,858 0 51759
+em 13227,7710 0 51789
+en 13227,7710 0 51790
+dd 13227,18990 2 51773
+.i 13227,14025 0 51957
+aq 13227,18990 2 3623
+bu 13227,12714 0 51889
+'C 13227,24630,330 2 20166
+'c 13227,19725,330 2 20198
+lq 13227,19320 2 51838
+rq 13227,19320 2 51746
+Bq 13227,2136,2154 0 51772
+vz 13227,19905 2 51834
+fi 13227,19335 2 51881
+fl 13227,19335 2 51882
+ff 13227,19335 2 51883
+Fi 13227,19335 2 51884
+Fl 13227,19335 2 51885
+ij 13227,18780,4350 2 51958
+bq 13227,2136,2154 0 51756
+%0 13227,19320,330 2 51901
+char175 13227,18078 2 3759
+a- "
+ab 13227,19350 2 51926
+a. 13227,18195 2 51927
+oe 13227,14355,330 0 51823
+OE 13227,19320,330 2 51791
+fo 13227,13710 0 51886
+fc 13227,13710 0 51887
+sq 13227,14106 0 51899
+/L 13227,18990 2 51944
+/l 13227,19545 2 51960
+a" 13227,19725 2 51933
+ho 13227,750,4137 0 51934
+vZ 13227,24810 2 51802
+IJ 13227,18990,330 2 51942
diff --git a/font/devlj4/MARIGOLD b/font/devlj4/MARIGOLD
new file mode 100644
index 00000000..60976ca2
--- /dev/null
+++ b/font/devlj4/MARIGOLD
@@ -0,0 +1,348 @@
+name MARIGOLD
+spacewidth 5856
+pcltypeface 4297
+pclproportional 1
+pclweight 0
+pclstyle 0
+ligatures fi fl ff ffi ffl 0
+charset
+! 7806,12570,330 0 3617
+" 6342,11790 0 3618
+sh 9759,11610 0 3619
+# "
+Do 9759,14325,3315 0 3620
+$ "
+% 17076,11940,330 0 3621
+& 12684,12120,330 0 3622
+' 3903,11790 0 51751
+( 6831,16770,2235 2 3624
+) 6831,16770,2235 2 3625
+* 9759,11940 0 3626
++ 11709,8445,360 0 3627
+, 5856,1650,4590 0 3628
+char173 6831,6345 0 3629
+hy "
+- "
+. 5856,2535,330 0 3630
+sl 8781,16770,3240 2 3631
+/ "
+0 9759,11940,330 0 3632
+1 9759,11940,60 0 3633
+2 9759,11940,450 0 3634
+3 9759,11940,330 0 3635
+4 9759,11940,1080 0 3636
+5 9759,12060,330 0 3637
+6 9759,12660,330 0 3638
+7 9759,12480,30 0 3639
+8 9759,11940,330 0 3640
+9 9759,11940,1050 0 3641
+: 5856,8475,330 0 3642
+; 5856,8475,4590 0 3643
+< 26346,16068 2 3644
+= 11709,6510 0 3645
+> 26346,16068 2 3646
+? 8295,12120,330 0 3647
+at 18051,12354,3126 0 3648
+@ "
+A 12198,12120,225 0 3649
+B 10734,12120,60 0 3650
+C 10734,12120,330 0 3651
+D 12684,12015,225 0 3652
+E 10245,11910,225 0 3653
+F 9759,12120,60 0 3654
+G 12198,12120,330 0 3655
+H 12198,12015,60 0 3656
+I 6342,11850,60 0 3657
+J 6342,11850,4128 0 3658
+K 12198,11850,60 0 3659
+L 8781,11850,225 0 3660
+M 16101,12120,225 0 3661
+N 13173,12120,330 0 3662
+O 11709,12120,330 0 3663
+P 9759,12120,60 0 3664
+Q 11709,12120,3744 0 3665
+R 11709,12120,330 0 3666
+S 9759,12120,330 0 3667
+T 10245,12120,60 0 3668
+U 12684,11910,330 0 3669
+V 12198,12120,330 0 3670
+W 16101,12120,330 0 3671
+X 12198,11910,120 0 3672
+Y 10734,12120,60 0 3673
+Z 10734,12345,330 0 3674
+lB 6342,16860,1260 2 3675
+[ "
+rs 8781,16770,3240 2 3676
+\ "
+rB 6342,16860,1260 2 3677
+] "
+ha 13173,19758 2 51875
+_ 13173,191367,6588 2 3679
+oq 3903,11790 0 51808
+` "
+a 8295,10350,330 0 3681
+b 6831,17430,330 2 3682
+c 6342,10350,330 0 3683
+d 7806,17430,330 2 3684
+e 6342,10350,330 0 3685
+f 3903,17430,7950 3 3686
+g 7806,10350,7950 1 3687
+h 8295,17433,330 2 3688
+i 4878,13635,330 0 3689
+j 3903,13635,7950 1 3690
+k 6831,17430,330 2 3691
+l 3903,17430,330 2 3692
+m 11220,10350,330 0 3693
+n 7806,10350,330 0 3694
+o 6831,10350,330 0 3695
+p 7806,10350,7950 1 3696
+q 7317,10575,7950 1 3697
+r 6342,10350 0 3698
+s 5367,10350,330 0 3699
+t 5367,14325,330 0 3700
+u 7806,10350,330 0 3701
+v 7317,10350,330 0 3702
+w 9759,10350,330 0 3703
+x 7317,13590,330 0 3704
+y 7317,10350,7950 1 3705
+z 7317,10350,330 0 3706
+lC 8295,16380,2670 2 3707
+{ "
+ba 13173,19758,6588 2 3708
+| "
+rC 8295,16380,2670 2 3709
+} "
+ti 26346,8952 0 51876
+char192 12198,17040,225 2 3776
+`A "
+char194 12198,17520,225 2 3778
+^A "
+char200 10245,17040,225 2 3784
+`E "
+char202 10245,17520,225 2 3786
+^E "
+char203 10245,16320,225 2 3787
+:E "
+char206 6342,17520,60 2 3790
+^I "
+char207 6342,16320,60 2 3791
+:I "
+char180 11709,15030 0 3764
+aa "
+ga 11709,15030 0 3680
+a^ 11709,15300 0 3678
+^ "
+char168 11709,14580 0 3752
+ad "
+a~ 11709,13782 0 3710
+~ "
+char217 12684,17040,330 2 3801
+`U "
+char219 12684,17520,330 2 3803
+^U "
+char221 10734,17040,60 2 3805
+'Y "
+char253 7317,15030,7950 1 3837
+'y "
+char176 7806,11940 0 3760
+de "
+char199 10734,12120,4140 0 3783
+,C "
+char231 6342,10350,4320 0 3815
+,c "
+char209 13173,15828,330 2 3793
+~N "
+char241 7806,13782,330 0 3825
+~n "
+char161 7806,8313,4587 0 3745
+r! "
+char191 8295,8202,4248 0 3775
+r? "
+char164 9759,10668 0 3748
+Cs "
+char163 9759,11940,225 0 3747
+Po "
+char165 9759,12165,60 0 3749
+Ye "
+char167 9759,12120,4596 0 3751
+sc "
+Fn 9759,17430,7950 3 51871
+char162 9759,12516,2580 0 3746
+ct "
+char226 8295,15300,330 0 3810
+^a "
+char234 6342,15300,330 0 3818
+^e "
+char244 6831,15300,330 0 3828
+^o "
+char251 7806,15300,330 0 3835
+^u "
+char225 8295,15030,330 0 3809
+'a "
+char233 6342,15030,330 0 3817
+'e "
+char243 6831,15030,330 0 3827
+'o "
+char250 7806,15030,330 0 3834
+'u "
+char224 8295,15030,330 0 3808
+`a "
+char232 6342,15030,330 0 3816
+`e "
+char242 6831,15030,330 0 3826
+`o "
+char249 7806,15030,330 0 3833
+`u "
+char228 8295,14580,330 0 3812
+:a "
+char235 6342,14580,330 0 3819
+:e "
+char246 6831,14580,330 0 3830
+:o "
+char252 7806,14580,330 0 3836
+:u "
+char197 12198,16815,225 2 3781
+oA "
+char238 4878,15300,330 0 3822
+^i "
+char216 11709,12849,984 0 3800
+/O "
+char198 17565,11910,225 0 3782
+AE "
+char229 8295,14685,330 0 3813
+oa "
+char237 4878,15030,330 0 3821
+'i "
+char248 6831,11724,1635 0 3832
+/o "
+char230 10734,10350,330 0 3814
+ae "
+char196 12198,16320,225 2 3780
+:A "
+char236 4878,15030,330 0 3820
+`i "
+char214 11709,16320,330 2 3798
+:O "
+char220 12684,16320,330 2 3804
+:U "
+char201 10245,17040,225 2 3785
+'E "
+char239 4878,14580,330 0 3823
+:i "
+char223 9270,18135,7350 3 3807
+ss "
+char212 11709,17520,330 2 3796
+^O "
+char193 12198,17040,225 2 3777
+'A "
+char195 12198,15828,225 2 3779
+~A "
+char227 8295,13782,330 0 3811
+~a "
+char208 12684,12015,225 0 3792
+-D "
+char240 7317,17430,330 2 3824
+Sd "
+char205 6342,17040,60 2 3789
+'I "
+char204 6342,17040,60 2 3788
+`I "
+char211 11709,17040,330 2 3795
+'O "
+char210 11709,17040,330 2 3794
+`O "
+char213 11709,15828,330 2 3797
+~O "
+char245 6831,13782,330 0 3829
+~o "
+vS 9759,17520,330 2 51795
+vs 5367,15330,330 0 51827
+char218 12684,17040,330 2 3802
+'U "
+:Y 10734,16320,60 2 51801
+char255 7317,14580,7950 1 3839
+:y "
+char222 9759,11850,60 0 3806
+TP "
+char254 7806,17430,7950 3 3838
+Tp "
+char181 14637,10800,5595 0 3765
+char182 11709,12450,4455 0 3766
+ps "
+char190 17076,11940,840 0 3774
+34 "
+\- 11709,4770 0 51757
+char188 17076,11940,840 0 3772
+14 "
+char189 17076,11940,330 0 3773
+12 "
+char170 6342,11940 0 3754
+Of "
+char186 6342,11940 0 3770
+Om "
+char171 9270,8535 0 3755
+Fo "
+char187 9270,8535 0 3771
+Fc "
+char177 11709,8445,2595 0 3761
+char166 13173,19083,5916 2 3750
+bb "
+char169 7806,15960 2 3753
+co "
+char172 11709,6780 0 3756
+no "
+char174 7806,15960 2 3758
+rg "
+char178 7317,11850 0 3762
+S2 "
+char179 7317,11850 0 3763
+S3 "
+char184 11709,0,4320 0 3768
+ac "
+char185 7317,11850 0 3769
+S1 "
+char215 11709,7815 0 3799
+char247 11709,8700,360 0 3831
+char183 5856,7662 0 3767
+fm 4878,11610 0 51873
+sd 7806,11610 0 51874
+dg 9759,12315,3795 0 51755
+tm 9759,14445 0 51796
+ah 11709,15330 0 51935
+ao 11709,14685 0 51930
+f/ 1953,11940,330 0 51759
+em 18051,6345 0 51789
+en 11709,6345 0 51790
+dd 9759,12315,3795 0 51773
+.i 4878,10350,330 0 51957
+aq 3903,11790 0 3623
+bu 13173,14226 0 51889
+'C 10734,17040,330 2 20166
+'c 6342,15030,330 0 20198
+lq 6342,11790 0 51838
+rq 6342,11790 0 51746
+Bq 6342,1650,2550 0 51772
+vz 7317,15330,330 0 51834
+fi 7806,17430,7950 3 51881
+fl 7806,17430,7950 3 51882
+ff 7806,17430,7950 3 51883
+Fi 11709,17430,7950 3 51884
+Fl 11709,17430,7950 3 51885
+ij 8781,13635,7950 1 51958
+bq 3903,1650,2550 0 51756
+%0 22932,11940,330 0 51901
+char175 11709,13674 0 3759
+a- "
+ab 11709,14700 0 51926
+a. 11709,14580 0 51927
+oe 10734,10350,330 0 51823
+OE 16587,12120,330 0 51791
+fo 5856,8535 0 51886
+fc 5856,8535 0 51887
+sq 19029,15624 0 51899
+/L 8781,11850,225 0 51944
+/l 4878,17430,330 2 51960
+a" 11709,15030 0 51933
+ho 11709,1341,4410 0 51934
+vZ 10734,17520,330 2 51802
+IJ 12684,11850,4128 0 51942
diff --git a/font/devlj4/Makefile.sub b/font/devlj4/Makefile.sub
new file mode 100644
index 00000000..dd49b637
--- /dev/null
+++ b/font/devlj4/Makefile.sub
@@ -0,0 +1,33 @@
+DEV=lj4
+LJ4RES=600
+LJ4PRINT=$(PSPRINT)
+DEVFILES=DESC \
+ ALBB ALBR \
+ AOB AOI AOR \
+ CB CBI CI CR \
+ GB GBI GI GR \
+ LGB LGI LGR \
+ OB OBI OI OR \
+ TB TBI TI TR \
+ UB UBI UI UR \
+ UCB UCBI UCI UCR \
+ CLARENDON CORONET MARIGOLD S \
+ generate/Makefile generate/text.map generate/special.map
+
+CLEANADD=DESC
+
+DESC: DESC.in
+ -rm -f DESC
+ echo "res $(LJ4RES)" >DESC
+ echo "unitwidth `expr 7620000 / $(LJ4RES)`" >>DESC
+ cat $(srcdir)/DESC.in >>DESC
+ if test "$(PAGE)" = A4; then \
+ echo "papersize a4" >>DESC; \
+ else \
+ echo "papersize letter" >>DESC; \
+ fi
+ test -z '$(LJ4PRINT)' || echo print '$(LJ4PRINT)' >>DESC
+
+fonts:
+ $(MAKE) -f $(srcdir)/generate/Makefile srcdir=$(srcdir)/generate \
+ HPFTODIT=$(top_builddir)/src/utils/hpftodit/hpftodit
diff --git a/font/devlj4/OB b/font/devlj4/OB
new file mode 100644
index 00000000..093e0bb2
--- /dev/null
+++ b/font/devlj4/OB
@@ -0,0 +1,797 @@
+name OB
+spacewidth 7317
+pcltypeface 4113
+pclproportional 1
+pclweight 3
+pclstyle 0
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -2925
+P . -3903
+P , -3903
+V A -3903
+A V -3903
+T o -2925
+T r -1950
+T c -2925
+T e -2925
+T d -2925
+T s -2439
+T y -2925
+T a -2925
+T w -2925
+T u -2925
+L T -1950
+L Y -2925
+Y o -3903
+Y e -3903
+Y a -3903
+A W -3414
+W A -3414
+T A -1950
+V o -2925
+V e -2925
+V a -2925
+Y A -3903
+F A -2925
+F . -3903
+F , -3903
+A T -1950
+A Y -3903
+v . -2439
+v , -2439
+y . -2439
+y , -2439
+T . -1950
+T , -1950
+L W -2925
+P A -2925
+V . -3903
+V , -3903
+Y . -3903
+Y , -3903
+W o -2439
+W e -2439
+W a -2439
+W . -3414
+W , -3414
+r . -2439
+r , -2439
+w . -2439
+w , -2439
+Y u -2439
+A v -2439
+A y -2439
+A w -1461
+o . -1461
+o , -1461
+p . -1461
+p , -1461
+e . -975
+e , -975
+b . -1461
+b , -1461
+O T -1461
+O V -1461
+O Y -1461
+O . -1461
+O , -1461
+L y -2439
+L O -1461
+L G -1950
+L C -1950
+L Q -1950
+V y -1461
+V u -1461
+V O -1461
+V G -1461
+V C -1461
+V Q -1461
+D T -1950
+D V -1461
+D Y -1950
+D . -1950
+D , -1950
+Y O -1461
+Y G -1950
+Y C -1950
+Y Q -1950
+F o -1461
+F e -1461
+F a -1461
+c . -486
+c , -486
+O A -1461
+O W -975
+L U -1950
+R T -975
+R V -975
+R Y -975
+R W -975
+G T -975
+P o -1461
+P g -975
+P e -1461
+P a -1461
+C A -486
+C . -486
+C , -486
+D A -1461
+D W -975
+B T -975
+B Y -975
+B . -975
+B , -975
+A O -1461
+A G -1461
+A C -1461
+A U -1461
+A Q -1461
+W r -975
+W y -975
+W u -975
+W O -975
+W G -975
+W C -975
+W Q -975
+J A -975
+J . -975
+J , -975
+U A -1461
+U . -1950
+U , -1950
+Q A -1461
+Q W -975
+f . -486
+f , -486
+T O -1461
+T G -1950
+T C -1950
+T Q -1950
+O X -1461
+L o -1461
+L e -1461
+L q -1461
+G V -975
+G Y -975
+G W -975
+G . -486
+G , -486
+C T -486
+C V -486
+C Y -486
+D X -1461
+B V -975
+B X -975
+B A -975
+B W -975
+S . -975
+S , -975
+X o -1461
+X e -1461
+X y -1461
+X O -1461
+X G -1461
+X C -1461
+X Q -1461
+A o -1461
+A e -1461
+Q X -1461
+K o -1461
+K e -1461
+K y -1461
+K w -1461
+K O -1461
+K G -1461
+K C -1461
+K Q -1461
+o v -975
+o y -975
+o x -975
+h v -975
+h y -975
+n v -975
+n y -975
+m v -975
+m y -975
+r g -486
+g . -486
+g , -486
+p v -975
+p y -975
+p x -975
+c v -486
+c y -486
+v o -975
+v g -975
+v c -975
+v d -975
+v a -975
+v q -975
+e v -975
+e y -975
+b v -975
+b y -975
+s . -975
+s , -975
+y o -975
+y g -975
+y c -975
+y d -975
+y a -975
+y q -975
+f g -486
+x o -975
+x g -975
+x c -975
+x e -975
+x d -975
+x a -975
+x q -975
+a v -975
+a y -975
+T i -975
+T S -975
+L a -975
+L S -486
+G X -486
+G A -486
+P s -975
+C X -486
+C W -486
+V i -975
+V S -975
+S T -486
+S V -486
+S Y -486
+S X -486
+S A -975
+S W -486
+Y i -975
+Y S -975
+X a -975
+X u -975
+X S -486
+A t -975
+A g -975
+A c -1461
+A d -1461
+A a -975
+A u -975
+A q -1461
+A S -486
+W i -975
+W S -975
+K c -1461
+K u -975
+K S -486
+t g -486
+o f -486
+r o -486
+r c -486
+r e -486
+r d -486
+r a -486
+r q -486
+p f -486
+c f -486
+c x -486
+v e -975
+v s -975
+e f -486
+e x -975
+b f -486
+s v -486
+s y -486
+s f -486
+s x -486
+y e -975
+y s -975
+f o -486
+f c -486
+f e -486
+f d -486
+f s -486
+f a -486
+f q -486
+x s -486
+k o -486
+k g -486
+k c -486
+k v -486
+k e -486
+k d -486
+k y -486
+k a -486
+k w -486
+k q -486
+O Z -486
+L J -1461
+G Z -486
+P M -486
+C Z -486
+Z o -486
+Z e -486
+Z d -486
+Z s -486
+Z y -486
+Z a -486
+Z w -486
+Z u -486
+Z O -486
+Z G -486
+Z C -486
+Z S -486
+Z Q -486
+D Z -486
+B Z -486
+S Z -486
+A s -486
+A J -1461
+J o -486
+J e -486
+J a -486
+J M -486
+K a -975
+K J -486
+t o -486
+t c -486
+t e -486
+t d -486
+t s -486
+t a -486
+t q -486
+o z -486
+h f -486
+n f -486
+m f -486
+r s -486
+p z -486
+c z -486
+e z -486
+z o -486
+z g -486
+z c -486
+z e -486
+z d -486
+z s -486
+z a -486
+z q -486
+b z -486
+s z -486
+a f -486
+k t -486
+k s -486
+k f -486
+k u -486
+F M -486
+A f -486
+K T -486
+K V -486
+K Y -486
+K W -486
+K U -486
+L ' -2925
+T char173 -2925
+T hy -2925
+T - -2925
+T en -2925
+T em -2925
+A ' -3414
+char173 T -2925
+hy T -2925
+- T -2925
+en T -2925
+em T -2925
+Y char173 -2439
+Y hy -2439
+Y - -2439
+Y en -2439
+Y em -2439
+p ' -1461
+c ' -486
+e ' -975
+b ' -1461
+a ' -975
+V char173 -1461
+V hy -1461
+V - -1461
+V en -1461
+V em -1461
+h ' -975
+n ' -975
+m ' -975
+W char173 -975
+W hy -975
+W - -975
+W en -975
+W em -975
+' d -1461
+s ' -486
+L char173 -1950
+L hy -1950
+L - -1950
+L en -1950
+L em -1950
+X char173 -1461
+X hy -1461
+X - -1461
+X en -1461
+X em -1461
+A char173 -1461
+A hy -1461
+A - -1461
+A en -1461
+A em -1461
+K char173 -1461
+K hy -1461
+K - -1461
+K en -1461
+K em -1461
+' s -975
+char173 X -1461
+hy X -1461
+- X -1461
+char173 A -1461
+hy A -1461
+- A -1461
+en X -1461
+en A -1461
+em X -1461
+K ' -486
+t g -486
+b f -486
+k ' -486
+M ' -486
+Z char173 -486
+Z hy -486
+Z - -486
+Z en -486
+Z em -486
+' M -486
+k char173 -486
+k hy -486
+k - -486
+k en -486
+k em -486
+charset
+! 7317,18000,375 2 3617
+" 12198,18375 2 3618
+sh 14637,18069,444 2 3619
+# "
+Do 14637,19755,2988 2 3620
+$ "
+% 23418,17769,444 2 3621
+& 19029,17997,375 2 3622
+' 7317,18375 2 51751
+( 7317,18375,3165 2 3624
+) 7317,18375,3165 2 3625
+* 14637,18150 2 3626
++ 23418,13164,534 0 3627
+, 7317,4068,4902 0 3628
+char173 7317,8307 0 3629
+hy "
+- "
+. 7317,3975,375 0 3630
+sl 7317,19650,525 2 3631
+/ "
+0 14637,17700,375 0 3632
+1 14637,17700,69 0 3633
+2 14637,17700,201 0 3634
+3 14637,17700,375 0 3635
+4 14637,17394,69 0 3636
+5 14637,17526,375 0 3637
+6 14637,17700,375 0 3638
+7 14637,17526,69 0 3639
+8 14637,17700,375 0 3640
+9 14637,17700,375 0 3641
+: 7317,12057,375 0 3642
+; 7317,12057,4902 0 3643
+< 26346,16068 0 3644
+= 23418,9639 0 3645
+> 26346,16068 0 3646
+? 11709,18000,375 2 3647
+at 23418,16950,4131 0 3648
+@ "
+A 17565,18069,69 2 3649
+B 16101,18069,69 2 3650
+C 17565,18375,375 2 3651
+D 20490,18201,201 2 3652
+E 13173,18201,201 2 3653
+F 13173,18201,69 2 3654
+G 20490,18375,375 2 3655
+H 20490,18069,69 2 3656
+I 8781,18069,69 2 3657
+J 8781,18069,4218 2 3658
+K 16587,18069,69 2 3659
+L 13173,18069,201 2 3660
+M 23418,18069,69 2 3661
+N 20490,18069,69 2 3662
+O 21954,18375,375 2 3663
+P 15126,18069,69 2 3664
+Q 21954,18375,5223 3 3665
+R 16101,18069,69 2 3666
+S 13173,18375,375 2 3667
+T 14637,18201,69 2 3668
+U 20490,18069,375 2 3669
+V 17565,18069,69 2 3670
+W 26346,18069,69 2 3671
+X 16101,18069,69 2 3672
+Y 16101,18069,69 2 3673
+Z 16101,18201,201 2 3674
+lB 7317,18201,4701 2 3675
+[ "
+rs 7317,19650,525 2 3676
+\ "
+rB 7317,18201,4701 2 3677
+] "
+ha 13173,19758 2 51875
+_ 13173,191367,6588 3 3679
+oq 7317,18375 2 51808
+` "
+a 13173,12840,375 0 3681
+b 14637,19569,375 2 3682
+c 13173,12840,375 0 3683
+d 14637,19569,375 2 3684
+e 13173,12840,375 0 3685
+f 8781,19710,69 2 3686
+g 13173,12840,5400 1 3687
+h 14637,19569,69 2 3688
+i 7317,19332,69 2 3689
+j 7317,19332,5400 3 3690
+k 13173,19569,69 2 3691
+l 7317,19569,69 2 3692
+m 21954,12900,69 0 3693
+n 14637,12840,69 0 3694
+o 14637,12840,375 0 3695
+p 14637,12840,5469 1 3696
+q 14637,12840,5469 1 3697
+r 10245,12780,69 0 3698
+s 10245,12840,375 0 3699
+t 8781,17100,375 0 3700
+u 14637,12534,375 0 3701
+v 13173,12534,69 0 3702
+w 20490,12534,69 0 3703
+x 13173,12534,69 0 3704
+y 13173,12534,5439 1 3705
+z 13173,12666,201 0 3706
+lC 13173,19935,6210 3 3707
+{ "
+ba 13173,19758,6588 3 3708
+| "
+rC 13173,19935,6210 3 3709
+} "
+ti 26346,9435 0 51876
+char192 17565,24537,69 2 3776
+`A "
+char194 17565,24273,69 2 3778
+^A "
+char200 13173,24537,201 2 3784
+`E "
+char202 13173,24273,201 2 3786
+^E "
+char203 13173,23301,201 2 3787
+:E "
+char206 8781,24273,69 2 3790
+^I "
+char207 8781,23301,69 2 3791
+:I "
+char180 14637,18843 2 3764
+aa "
+ga 14637,18843 2 3680
+a^ 14637,18738 2 3678
+^ "
+char168 14637,17694 0 3752
+ad "
+a~ 14637,17694 0 3710
+~ "
+char217 20490,24537,375 2 3801
+`U "
+char219 20490,24273,375 2 3803
+^U "
+char221 16101,24537,69 2 3805
+'Y "
+char253 13173,18843,5439 3 3837
+'y "
+char176 14637,17700 0 3760
+de "
+char199 17565,18375,6663 3 3783
+,C "
+char231 13173,12840,5469 1 3815
+,c "
+char209 20490,23031,69 2 3793
+~N "
+char241 14637,17694,69 0 3825
+~n "
+char161 7317,12906,5469 1 3745
+r! "
+char191 11709,12906,5469 1 3775
+r? "
+char164 14637,15834 0 3748
+Cs "
+char163 14637,17700,201 0 3747
+Po "
+char165 14637,17769,69 2 3749
+Ye "
+char167 14637,18000,1383 2 3751
+sc "
+Fn 14637,19710,69 2 51871
+char162 14637,19788,135 2 3746
+ct "
+char226 13173,18738,375 2 3810
+^a "
+char234 13173,18738,375 2 3818
+^e "
+char244 14637,18738,375 2 3828
+^o "
+char251 14637,18738,375 2 3835
+^u "
+char225 13173,18843,375 2 3809
+'a "
+char233 13173,18843,375 2 3817
+'e "
+char243 14637,18843,375 2 3827
+'o "
+char250 14637,18843,375 2 3834
+'u "
+char224 13173,18843,375 2 3808
+`a "
+char232 13173,18843,375 2 3816
+`e "
+char242 14637,18843,375 2 3826
+`o "
+char249 14637,18843,375 2 3833
+`u "
+char228 13173,17694,375 0 3812
+:a "
+char235 13173,17694,375 0 3819
+:e "
+char246 14637,17694,375 0 3830
+:o "
+char252 14637,17694,375 0 3836
+:u "
+char197 17565,25002,69 2 3781
+oA "
+char238 7317,18738,69 2 3822
+^i "
+char216 21954,18375,375 2 3800
+/O "
+char198 22932,18201,201 2 3782
+AE "
+char229 13173,18684,375 2 3813
+oa "
+char237 7317,18843,69 2 3821
+'i "
+char248 14637,12849,402 0 3832
+/o "
+char230 20004,12840,375 0 3814
+ae "
+char196 17565,23301,69 2 3780
+:A "
+char236 7317,18843,69 2 3820
+`i "
+char214 21954,23301,375 2 3798
+:O "
+char220 20490,23301,375 2 3804
+:U "
+char201 13173,24537,201 2 3785
+'E "
+char239 7317,17694,69 0 3823
+:i "
+char223 14637,19710,375 2 3807
+ss "
+char212 21954,24273,375 2 3796
+^O "
+char193 17565,24537,69 2 3777
+'A "
+char195 17565,23031,69 2 3779
+~A "
+char227 13173,17694,375 0 3811
+~a "
+char208 20490,18201,201 2 3792
+-D "
+char240 14637,19503,375 2 3824
+Sd "
+char205 8781,24537,69 2 3789
+'I "
+char204 8781,24537,69 2 3788
+`I "
+char211 21954,24537,375 2 3795
+'O "
+char210 21954,24537,375 2 3794
+`O "
+char213 21954,23031,375 2 3797
+~O "
+char245 14637,17694,375 0 3829
+~o "
+vS 13173,24273,375 2 51795
+vs 10245,18738,375 2 51827
+char218 20490,24537,375 2 3802
+'U "
+:Y 16101,23301,69 2 51801
+char255 13173,17694,5439 1 3839
+:y "
+char222 15126,18069,69 2 3806
+TP "
+char254 14637,19569,5469 3 3838
+Tp "
+char181 15612,12630,4680 0 3765
+char182 14637,19635,4200 2 3766
+ps "
+char190 23418,17700,444 0 3774
+34 "
+\- 23418,7455 0 51757
+char188 23418,18099,444 2 3772
+14 "
+char189 23418,18099,444 2 3773
+12 "
+char170 9759,17700 0 3754
+Of "
+char186 9759,17700 0 3770
+Om "
+char171 11709,11028 0 3755
+Fo "
+char187 11709,11028 0 3771
+Fc "
+char177 23418,13164,4314 0 3761
+char166 13173,19083,5916 3 3750
+bb "
+char169 13173,19635 2 3753
+co "
+char172 23418,10770 0 3756
+no "
+char174 13173,19635 2 3758
+rg "
+char178 9759,17700 0 3762
+S2 "
+char179 9759,17700 0 3763
+S3 "
+char184 14637,196476,5469 3 3768
+ac "
+char185 9759,18099 2 3769
+S1 "
+char215 23418,13107,567 0 3799
+char247 23418,13017,387 0 3831
+char183 7317,11274 0 3767
+fm 7317,18096 2 51873
+sd 14637,18096 2 51874
+dg 14637,18201,426 2 51755
+tm 16101,17850 2 51796
+ah 14637,18738 2 51935
+ao 14637,18684 2 51930
+f/ 2928,17544,444 0 51759
+em 23418,8085 0 51789
+en 14637,8085 0 51790
+dd 14637,18201,426 2 51773
+.i 7317,12534,69 0 51957
+aq 7317,18375 2 3623
+bu 13173,14226 0 51889
+'C 17565,24537,375 2 20166
+'c 13173,18843,375 2 20198
+lq 12198,18330 2 51838
+rq 12198,18375 2 51746
+Bq 12198,4095,4371 0 51772
+vz 13173,18738,201 2 51834
+fi 15126,19710,69 2 51881
+fl 15126,19710,69 2 51882
+ff 16587,19710,69 2 51883
+Fi 22932,19710,69 2 51884
+Fl 22932,19710,69 2 51885
+ij 14637,19332,5400 3 51958
+bq 7317,4095,4371 0 51756
+%0 33177,17769,444 2 51901
+char175 14637,16722 0 3759
+a- "
+ab 14637,18525 2 51926
+a. 14637,18792 2 51927
+oe 22443,12840,375 0 51823
+OE 24882,18375,375 2 51791
+fo 7317,11028 0 51886
+fc 7317,11028 0 51887
+sq 19029,15624 0 51899
+/L 13173,18069,201 2 51944
+/l 7317,19569,69 2 51960
+a" 14637,18843 2 51933
+ho 14637,654,3774 0 51934
+vZ 16101,24273,201 2 51802
+IJ 17565,18069,4218 2 51942
diff --git a/font/devlj4/OBI b/font/devlj4/OBI
new file mode 100644
index 00000000..918e0f45
--- /dev/null
+++ b/font/devlj4/OBI
@@ -0,0 +1,793 @@
+name OBI
+spacewidth 7317
+slant 12.350000
+pcltypeface 4113
+pclproportional 1
+pclweight 3
+pclstyle 1
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -2439
+P . -3903
+P , -3903
+V A -3903
+A V -4389
+T o -2439
+T r -2439
+T c -2439
+T e -2439
+T d -2439
+T s -2439
+T y -2439
+T a -2439
+T w -2439
+T u -2439
+L T -2439
+L Y -2439
+Y o -3903
+Y e -3414
+Y a -3903
+A W -3903
+W A -3414
+T A -2439
+V o -2925
+V e -2439
+V a -2925
+Y A -3903
+F A -1461
+F . -3903
+F , -3903
+A T -2925
+A Y -4389
+v . -2925
+v , -2925
+y . -2925
+y , -2925
+T . -2439
+T , -2439
+L W -2439
+P A -1950
+V . -3903
+V , -3903
+Y . -3903
+Y , -3903
+W o -2439
+W e -1950
+W a -2439
+W . -3414
+W , -3414
+r . -2439
+r , -2439
+w . -2925
+w , -2925
+Y u -2439
+A v -2925
+A y -2925
+A w -2925
+o . -975
+o , -975
+p . -975
+p , -975
+e . -486
+e , -486
+b . -975
+b , -975
+O T -2439
+O V -1950
+O Y -2439
+O . -1950
+O , -1950
+L y -2439
+L O -2439
+L G -2439
+L C -2439
+L Q -2439
+V y -1461
+V u -1461
+V O -1461
+V G -1461
+V C -1461
+V Q -1461
+D T -2439
+D V -1950
+D Y -2439
+D . -1950
+D , -1950
+Y O -1950
+Y G -1950
+Y C -1950
+Y Q -1950
+F o -486
+F e -486
+F a -486
+c . -486
+c , -486
+O A -975
+O W -1461
+L U -2439
+R T -486
+R V -486
+R Y -486
+R W -486
+G T -975
+P o -975
+P g -975
+P e -975
+P a -975
+C A -486
+C . -486
+C , -486
+D A -975
+D W -1461
+B T -1950
+B Y -1950
+B . -1461
+B , -1461
+A O -1950
+A G -1950
+A C -1950
+A U -1950
+A Q -1950
+W r -975
+W y -975
+W u -975
+W O -975
+W G -975
+W C -975
+W Q -975
+J A -975
+J . -975
+J , -975
+U A -975
+U . -1950
+U , -1950
+Q W -1461
+f . -486
+f , -486
+T O -1950
+T G -1950
+T C -1950
+T Q -1950
+O X -1461
+L o -1950
+L e -1461
+L q -1950
+G V -975
+G Y -975
+G W -975
+G . -486
+G , -486
+P T -975
+P V -975
+P Y -975
+C T -486
+C V -486
+C Y -486
+D X -1461
+B V -1950
+B X -1461
+B A -975
+B W -1461
+S . -486
+S , -486
+X o -1461
+X e -1461
+X y -1461
+X O -1461
+X G -1461
+X C -1461
+X Q -1461
+A o -1950
+A e -1461
+K o -1461
+K e -1461
+K y -1461
+K w -1461
+K O -1461
+K G -1461
+K C -1461
+K Q -1461
+o v -975
+o y -975
+o x -486
+o w -975
+h v -975
+h y -975
+n v -975
+n y -975
+p v -486
+p y -486
+p x -486
+c v -486
+c y -486
+c w -486
+v o -486
+v g -486
+v c -486
+v d -486
+v a -486
+v q -486
+e v -975
+e y -975
+b v -975
+b y -975
+b w -975
+s . -486
+s , -486
+y o -486
+y g -486
+y c -486
+y d -486
+y a -486
+y q -486
+f g -486
+x o -486
+x g -486
+x c -486
+x e -486
+x d -486
+x a -486
+x q -486
+a v -975
+a y -975
+a w -975
+w o -486
+w g -486
+w c -486
+w d -486
+w a -486
+w q -486
+T i -486
+T S -486
+L a -975
+L S -975
+R o -975
+R y -486
+R O -486
+R G -486
+R C -486
+R U -486
+R Q -486
+G X -486
+G A -486
+P s -975
+P Z -975
+P X -975
+P W -975
+C X -486
+C W -486
+V i -486
+V S -486
+S T -975
+S V -975
+S Y -975
+S X -486
+S A -486
+S W -975
+Y i -486
+Y S -486
+X a -975
+X u -975
+X S -486
+A t -975
+A g -975
+A c -1461
+A d -1950
+A a -975
+A u -975
+A q -1950
+A S -975
+W i -486
+W S -486
+K c -1461
+K u -975
+K S -975
+o f -486
+h w -975
+n w -975
+p f -486
+p w -486
+c f -486
+c x -486
+v e -486
+v s -486
+e f -486
+e x -486
+e w -975
+b f -486
+y e -486
+y s -486
+f o -486
+f c -486
+f e -486
+f d -486
+f s -486
+f a -486
+f q -486
+w e -486
+w s -486
+k o -486
+k g -486
+k c -486
+k v -486
+k e -486
+k d -486
+k y -486
+k a -486
+k w -486
+k q -486
+O Z -486
+R e -975
+R a -975
+R u -486
+R S -486
+G Z -486
+C Z -486
+Z o -975
+Z e -975
+Z d -975
+Z y -486
+Z a -975
+Z w -486
+Z u -486
+Z O -486
+Z G -486
+Z C -486
+Z S -486
+Z Q -486
+D Z -486
+B Z -486
+S Z -486
+J o -486
+J e -486
+J a -486
+K a -975
+o z -486
+h f -486
+n f -486
+p z -486
+c z -486
+e z -486
+z o -486
+z g -486
+z c -486
+z e -486
+z d -486
+z a -486
+z q -486
+b z -486
+a f -486
+k t -486
+k f -486
+k u -486
+A f -486
+K T -486
+K V -486
+K Y -486
+K W -486
+K U -486
+L ' -2439
+T char173 -2439
+T hy -2439
+T - -2439
+T en -2439
+T em -2439
+A ' -3414
+char173 T -2925
+hy T -2925
+- T -2925
+en T -2925
+em T -2925
+Y char173 -2439
+Y hy -2439
+Y - -2439
+Y en -2439
+Y em -2439
+p ' -486
+c ' -486
+e ' -1461
+b ' -1950
+a ' -975
+V char173 -1461
+V hy -1461
+V - -1461
+V en -1461
+V em -1461
+h ' -1461
+n ' -1461
+R ' -486
+W char173 -975
+W hy -975
+W - -975
+W en -975
+W em -975
+' d -1461
+L char173 -1950
+L hy -1950
+L - -1950
+L en -1950
+L em -1950
+X char173 -1461
+X hy -1461
+X - -1461
+X en -1461
+X em -1461
+A char173 -1950
+A hy -1950
+A - -1950
+A en -1950
+A em -1950
+K char173 -1461
+K hy -1461
+K - -1461
+K en -1461
+K em -1461
+' s -975
+char173 X -1461
+hy X -1461
+- X -1461
+char173 A -975
+hy A -975
+- A -975
+en X -1461
+en A -975
+em X -1461
+R char173 -486
+R hy -486
+R - -486
+R en -486
+R em -486
+K ' -486
+b f -486
+k ' -486
+Z char173 -486
+Z hy -486
+Z - -486
+Z en -486
+Z em -486
+k char173 -486
+k hy -486
+k - -486
+k en -486
+k em -486
+charset
+! 7317,18000,375,1944,753,737 2 3617
+" 12198,18375,0,1623,-2622,737 2 3618
+sh 14637,18069,444,1440,228,737 2 3619
+# "
+Do 14637,19839,3099,1341,702,737 2 3620
+$ "
+% 23418,17769,264,0,-2067 0 3621
+& 19029,18000,375,237,198,237 2 3622
+' 7317,18375,0,2511,-531,737 2 51751
+( 7317,18375,3165,3450,135,737 2 3624
+) 7317,18375,3165,1164,2421,737 2 3625
+* 14637,18150,0,63,-2364,63 2 3626
++ 23418,13164,534,0,-3528 0 3627
+, 7317,3966,5040,0,3423 1 3628
+char173 7317,8715,0,1497,1071,737 0 3629
+hy "
+- "
+. 7317,3849,375,0,627 0 3630
+sl 7317,19575,450,4377,2736,737 2 3631
+/ "
+0 14637,17700,375,933,-159,737 0 3632
+1 14637,17700,69,0,-2430 0 3633
+2 14637,17700,201,921,858,737 0 3634
+3 14637,17700,375,372,819,372 0 3635
+4 14637,17394,69,1008,684,737 0 3636
+5 14637,17526,375,1362,669,737 0 3637
+6 14637,17700,375,399,-582,399 0 3638
+7 14637,17526,69,2931,-123,737 0 3639
+8 14637,17700,375,1155,174,737 0 3640
+9 14637,17700,375,843,-405,737 0 3641
+: 7317,11754,375,759,627,737 0 3642
+; 7317,11754,5040,759,3423,737 1 3643
+< 26346,16068,0,0,-3981 0 3644
+= 23418,9624,0,0,-4068 0 3645
+> 26346,16068,0,0,-3981 0 3646
+? 11709,18000,375,900,-1323,737 2 3647
+at 23418,16950,4131,966,348,737 0 3648
+@ "
+A 17565,18069,69,0,2586 2 3649
+B 16101,18069,69,864,306,737 2 3650
+C 17565,18375,375,2640,-600,737 2 3651
+D 20490,18069,69,720,279,720 2 3652
+E 13173,18201,201,2835,738,737 2 3653
+F 13173,18201,69,3051,612,737 2 3654
+G 20490,18375,375,1230,-798,737 2 3655
+H 20490,18069,69,1671,417,737 2 3656
+I 8781,18069,69,1779,441,737 2 3657
+J 8781,18069,4242,1551,2634,737 2 3658
+K 16101,18069,69,3528,366,737 2 3659
+L 13173,18069,201,201,168,201 2 3660
+M 23418,18069,414,1542,768,737 2 3661
+N 20490,18069,69,1383,192,737 2 3662
+O 21954,18375,375,942,-447,737 2 3663
+P 14637,18069,69,2064,519,737 2 3664
+Q 21954,18375,4200,1008,-396,737 2 3665
+R 16101,18069,69,900,387,737 2 3666
+S 13173,18375,375,1626,879,737 2 3667
+T 14637,18201,69,3006,-1071,737 2 3668
+U 20490,18069,375,1671,-1071,737 2 3669
+V 17565,18069,69,3372,-1446,737 2 3670
+W 24882,18069,69,3120,-1605,737 2 3671
+X 16101,18069,69,2451,1470,737 2 3672
+Y 16101,18069,69,3747,-1419,737 2 3673
+Z 16101,18201,201,2589,2115,737 2 3674
+lB 7317,18249,4749,3699,2235,737 2 3675
+[ "
+rs 7317,19575,450,0,-1611 2 3676
+\ "
+rB 7317,18249,4749,3696,2238,737 2 3677
+] "
+ha 13173,19758,0,36,36,36 2 51875
+_ 13173,191367,6588,1317,1317,737 3 3679
+oq 7317,18375,0,2508,-528,737 2 51808
+` "
+a 13173,12840,375,189,954,189 0 3681
+b 14637,19779,375,666,1191,666 2 3682
+c 12684,12840,375,2118,171,737 0 3683
+d 14637,19569,375,2727,594,737 2 3684
+e 13173,12840,375,750,480,737 0 3685
+f 8781,19710,69,3357,996,737 2 3686
+g 13173,12840,5400,1836,1659,737 1 3687
+h 14637,19569,69,423,1242,423 2 3688
+i 7317,19308,69,1794,1131,737 2 3689
+j 7317,19308,5400,1797,3720,737 3 3690
+k 13173,19569,69,2670,1353,737 2 3691
+l 7317,19569,69,2586,1086,737 2 3692
+m 21954,12840,69,375,1272,375 0 3693
+n 14637,12840,69,438,1206,438 0 3694
+o 14637,12840,375,708,618,708 0 3695
+p 14637,12840,5469,663,2349,663 1 3696
+q 14637,12840,5469,1281,558,737 1 3697
+r 10245,12840,69,1326,1107,737 0 3698
+s 10245,12840,375,1188,1230,737 0 3699
+t 8781,17055,375,2148,-189,737 0 3700
+u 14637,12534,375,1230,417,737 0 3701
+v 13173,12534,69,2223,-768,737 0 3702
+w 20490,12534,69,2229,-954,737 0 3703
+x 13173,12534,69,1647,2190,737 0 3704
+y 13173,12534,5469,2040,1176,737 1 3705
+z 13173,12666,201,1464,1689,737 0 3706
+lC 13173,19935,6210,3339,-972,737 3 3707
+{ "
+ba 13173,19758,6588,0,-4596 3 3708
+| "
+rC 13173,19935,6210,63,2304,63 3 3709
+} "
+ti 26346,9435,0,0,-4029 0 51876
+char192 17565,24342,69,0,2586 2 3776
+`A "
+char194 17565,24321,69,0,2586 2 3778
+^A "
+char200 13173,24342,201,2835,738,737 2 3784
+`E "
+char202 13173,24321,201,2835,738,737 2 3786
+^E "
+char203 13173,23610,201,3084,738,737 2 3787
+:E "
+char206 8781,24321,69,4296,441,737 2 3790
+^I "
+char207 8781,23610,69,5280,441,737 2 3791
+:I "
+char180 14637,18801,0,297,-5763,297 2 3764
+aa "
+ga 14637,18801,0,0,-4419 2 3680
+a^ 14637,18780,0,0,-3456 2 3678
+^ "
+char168 14637,18090,0,429,-4023,429 2 3752
+ad "
+a~ 14637,17847,0,1308,-3438,737 2 3710
+~ "
+char217 20490,24342,375,1671,-1071,737 2 3801
+`U "
+char219 20490,24321,375,1671,-1071,737 2 3803
+^U "
+char221 16101,24342,69,3747,-1419,737 2 3805
+'Y "
+char253 13173,18801,5469,2040,1176,737 3 3837
+'y "
+char176 14637,17700,0,0,-2586 0 3760
+de "
+char199 17565,18375,5988,2640,-600,737 3 3783
+,C "
+char231 12684,12840,5733,2118,171,737 1 3815
+,c "
+char209 20490,23382,69,1383,192,737 2 3793
+~N "
+char241 14637,17847,69,1308,1206,737 2 3825
+~n "
+char161 7317,12906,5469,861,1836,737 1 3745
+r! "
+char191 11709,12906,5469,0,90 1 3775
+r? "
+char164 14637,15834,0,1452,477,737 0 3748
+Cs "
+char163 14637,17700,201,1260,1419,737 0 3747
+Po "
+char165 14637,18069,69,4212,-132,737 2 3749
+Ye "
+char167 14637,18375,1383,0,-933 2 3751
+sc "
+Fn 14637,19710,69,366,-1863,366 2 51871
+char162 14637,19812,342,2082,-1152,737 2 3746
+ct "
+char226 13173,18780,375,711,954,711 2 3810
+^a "
+char234 13173,18780,375,750,480,737 2 3818
+^e "
+char244 14637,18780,375,708,618,708 2 3828
+^o "
+char251 14637,18780,375,1230,417,737 2 3835
+^u "
+char225 13173,18801,375,1029,954,737 2 3809
+'a "
+char233 13173,18801,375,1029,480,737 2 3817
+'e "
+char243 14637,18801,375,708,618,708 2 3827
+'o "
+char250 14637,18801,375,1230,417,737 2 3834
+'u "
+char224 13173,18801,375,189,954,189 2 3808
+`a "
+char232 13173,18801,375,750,480,737 2 3816
+`e "
+char242 14637,18801,375,708,618,708 2 3826
+`o "
+char249 14637,18801,375,1230,417,737 2 3833
+`u "
+char228 13173,18090,375,1161,954,737 2 3812
+:a "
+char235 13173,18090,375,1161,480,737 2 3819
+:e "
+char246 14637,18090,375,708,618,708 2 3830
+:o "
+char252 14637,18090,375,1230,417,737 2 3836
+:u "
+char197 17565,25035,69,0,2586 2 3781
+oA "
+char238 7317,18780,69,3639,1134,737 2 3822
+^i "
+char216 21954,18375,1017,1311,-312,737 2 3800
+/O "
+char198 22932,18201,201,2844,2589,737 2 3782
+AE "
+char229 13173,18678,375,189,954,189 2 3813
+oa "
+char237 7317,18801,69,3957,1134,737 2 3821
+'i "
+char248 14637,13446,843,1227,1224,737 0 3832
+/o "
+char230 20004,12840,375,744,945,737 0 3814
+ae "
+char196 17565,23610,69,888,2586,737 2 3780
+:A "
+char236 7317,18801,69,1116,1134,737 2 3820
+`i "
+char214 21954,23610,375,942,-447,737 2 3798
+:O "
+char220 20490,23610,375,1671,-1071,737 2 3804
+:U "
+char201 13173,24342,201,3348,738,737 2 3785
+'E "
+char239 7317,18090,69,4089,1134,737 2 3823
+:i "
+char223 14637,19500,375,396,1206,396 2 3807
+ss "
+char212 21954,24321,375,942,-447,737 2 3796
+^O "
+char193 17565,24342,69,1152,2586,737 2 3777
+'A "
+char195 17565,23382,69,1752,2586,737 2 3779
+~A "
+char227 13173,17847,375,2040,954,737 2 3811
+~a "
+char208 20490,18069,69,720,318,720 2 3792
+-D "
+char240 14637,19674,375,831,618,737 2 3824
+Sd "
+char205 8781,24342,69,5544,441,737 2 3789
+'I "
+char204 8781,24342,69,1779,441,737 2 3788
+`I "
+char211 21954,24342,375,942,-447,737 2 3795
+'O "
+char210 21954,24342,375,942,-447,737 2 3794
+`O "
+char213 21954,23382,375,942,-447,737 2 3797
+~O "
+char245 14637,17847,375,1308,618,737 2 3829
+~o "
+vS 13173,24321,375,3120,879,737 2 51795
+vs 10245,18780,375,3117,1230,737 2 51827
+char218 20490,24342,375,1671,-1071,737 2 3802
+'U "
+:Y 16101,23610,69,3747,-1419,737 2 51801
+char255 13173,18090,5469,2040,1176,737 3 3839
+:y "
+char222 14637,18069,69,1347,384,737 2 3806
+TP "
+char254 14637,19779,5469,672,2361,672 3 3838
+Tp "
+char181 15612,12630,4680,1422,2907,737 0 3765
+char182 14637,19635,4200,18,-1140,18 2 3766
+ps "
+char190 23418,17769,444,0,-870 0 3774
+34 "
+\- 23418,7455,0,0,-3528 0 51757
+char188 23418,17865,444,0,-2133 2 3772
+14 "
+char189 23418,17865,444,0,-1794 2 3773
+12 "
+char170 9759,17700,0,765,-258,737 0 3754
+Of "
+char186 9759,17700,0,1815,-81,737 0 3770
+Om "
+char171 11220,10851,0,1272,132,737 0 3755
+Fo "
+char187 11220,10851,0,588,816,588 0 3771
+Fc "
+char177 23418,13080,4230,0,-3522 0 3761
+char166 13173,19083,5916,0,-4596 3 3750
+bb "
+char169 13173,19635,0,3885,-2094,737 2 3753
+co "
+char172 23418,10770,0,0,-3105 0 3756
+no "
+char174 13173,19635,0,3885,-2094,737 2 3758
+rg "
+char178 9270,17700,0,2130,-162,737 0 3762
+S2 "
+char179 9270,17700,0,1656,-123,737 0 3763
+S3 "
+char184 14637,393,5733,0,-1119 1 3768
+ac "
+char185 9270,17865,0,708,-1470,708 2 3769
+S1 "
+char215 23418,13107,567,0,-4626 0 3799
+char247 23418,12999,369,0,-3531 0 3831
+char183 7317,10899,0,282,-741,282 0 3767
+fm 7317,18096,0,1629,-2067,737 2 51873
+sd 14637,18096,0,0,-2067 2 51874
+dg 14637,18201,426,666,-762,666 2 51755
+tm 16101,17850,0,1425,-1962,737 2 51796
+ah 14637,18780,0,921,-4398,737 2 51935
+ao 14637,18678,0,0,-5652 2 51930
+f/ 2439,17769,444,7344,7137,737 0 51759
+em 23418,8070,0,759,219,737 0 51789
+en 14637,8070,0,681,459,681 0 51790
+dd 14637,18201,426,630,-726,630 2 51773
+.i 7317,12534,69,1116,1134,737 0 51957
+aq 7317,18375,0,1659,-2622,737 2 3623
+bu 13173,14226,0,0,-498 0 51889
+'C 17565,24342,375,2640,-600,737 2 20166
+'c 12684,18801,375,2415,171,737 2 20198
+lq 11709,18375,0,2910,-387,737 2 51838
+rq 11709,18375,0,2895,-372,737 2 51746
+Bq 12198,3972,4527,0,2505 0 51772
+vz 13173,18780,201,1653,1689,737 2 51834
+fi 15612,19710,69,1506,900,737 2 51881
+fl 15612,19710,69,2385,816,737 2 51882
+ff 16587,19710,69,3507,816,737 2 51883
+Fi 23418,19710,69,1683,684,737 2 51884
+Fl 23418,19710,69,2499,666,737 2 51885
+ij 14637,19308,5400,1794,1131,737 3 51958
+bq 7317,3972,4527,0,2502 0 51756
+%0 33663,17769,264,0,-2289 0 51901
+char175 14637,17490,0,843,-3735,737 0 3759
+a- "
+ab 14637,18528,0,396,-3984,396 2 51926
+a. 14637,18786,0,0,-6408 2 51927
+oe 22443,12840,375,720,618,720 0 51823
+OE 24882,18375,375,2916,-513,737 2 51791
+fo 6831,10851,0,1296,132,737 0 51886
+fc 6831,10851,0,609,819,609 0 51887
+sq 19029,15624,0,0,-2022 0 51899
+/L 13173,18069,201,198,1188,198 2 51944
+/l 7317,19569,69,3264,1563,737 2 51960
+a" 14637,18801,0,3432,-3054,737 2 51933
+ho 14637,636,4140,0,-4476 0 51934
+vZ 16101,24321,201,2589,2115,737 2 51802
+IJ 17565,18069,4242,1548,441,737 2 51942
diff --git a/font/devlj4/OI b/font/devlj4/OI
new file mode 100644
index 00000000..6e17dff1
--- /dev/null
+++ b/font/devlj4/OI
@@ -0,0 +1,905 @@
+name OI
+spacewidth 7317
+slant 9.860000
+pcltypeface 4113
+pclproportional 1
+pclweight 0
+pclstyle 1
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -2439
+P . -3903
+P , -3903
+V A -3903
+A V -4389
+T o -3414
+T r -3414
+T c -3414
+T e -3414
+T d -3414
+T s -3414
+T y -3414
+T a -3903
+T w -3414
+T u -3414
+L T -2439
+L Y -2439
+Y o -2925
+Y e -2925
+Y a -3414
+A W -3903
+W A -2925
+T A -3414
+V o -2925
+V e -2925
+V a -3414
+Y A -2925
+F A -3903
+F . -3903
+F , -3903
+A T -4389
+A Y -4389
+v . -2925
+v , -2925
+y . -2925
+y , -2925
+T . -3414
+T , -3414
+L W -2439
+P A -3414
+V . -3903
+V , -3903
+Y . -2925
+Y , -2925
+W o -1950
+W e -1950
+W a -2439
+W . -2925
+W , -2925
+r . -2925
+r , -2925
+w . -2925
+w , -2925
+Y u -1461
+A v -2439
+A y -2925
+A w -2439
+o . -1461
+o , -1461
+p . -1461
+p , -1461
+e . -486
+e , -486
+b . -1950
+b , -1950
+O T -2925
+O V -1461
+O Y -1461
+O . -2439
+O , -2439
+L y -2439
+L O -2439
+L G -2439
+L C -2439
+L Q -2439
+V y -1461
+V u -1461
+V O -1461
+V G -1461
+V C -1461
+V Q -1461
+D T -2925
+D V -1461
+D Y -1461
+D . -2439
+D , -2439
+Y O -1461
+Y G -1461
+Y C -1461
+Y Q -1461
+F o -1950
+F e -1950
+F a -2439
+c . -486
+c , -486
+O A -1950
+O W -975
+L U -1950
+R T -1461
+R V -1461
+R Y -1461
+R W -1461
+G T -975
+P o -1461
+P g -975
+P e -1461
+P a -1950
+C A -975
+C . -975
+C , -975
+D A -1950
+D W -975
+B T -1950
+B Y -1461
+B . -1461
+B , -1461
+A O -1950
+A G -1950
+A C -1950
+A U -2439
+A Q -1950
+W r -975
+W y -975
+W u -975
+W O -975
+W G -975
+W C -975
+W Q -975
+J A -975
+J . -975
+J , -975
+U A -2439
+U . -2439
+U , -2439
+Q W -975
+f . -486
+f , -486
+T O -2439
+T G -2439
+T C -2439
+T Q -2439
+O X -1461
+L o -1950
+L e -1950
+L q -1950
+G V -975
+G Y -975
+G W -975
+G . -486
+G , -486
+P T -975
+P V -975
+P Y -975
+C T -975
+C V -975
+C Y -975
+D X -1461
+B V -1461
+B X -1461
+B A -1461
+B W -975
+S . -1461
+S , -1461
+F r -486
+F y -486
+F u -486
+F O -486
+F G -486
+F C -486
+F Q -486
+X o -1461
+X e -1461
+X y -1461
+X O -1461
+X G -1461
+X C -1461
+X Q -1461
+A o -1950
+A e -1950
+K o -1461
+K e -1461
+K y -1461
+K w -1461
+K O -1461
+K G -1461
+K C -1461
+K Q -1461
+o v -486
+o y -1461
+o x -975
+o w -486
+h v -486
+h y -1461
+n v -486
+n y -1461
+r g -486
+g . -486
+g , -486
+p v -486
+p y -1461
+p x -975
+c v -486
+c y -486
+c w -486
+v o -486
+v g -486
+v c -486
+v d -486
+v a -975
+v q -486
+e v -486
+e y -975
+b v -486
+b y -1461
+b w -486
+s . -975
+s , -975
+y o -486
+y g -486
+y c -486
+y d -486
+y a -975
+y q -486
+f g -486
+x o -975
+x g -975
+x c -975
+x e -975
+x d -975
+x a -975
+x q -975
+a v -486
+a y -1461
+a w -486
+w o -486
+w g -486
+w c -486
+w d -486
+w a -975
+w q -486
+T i -486
+T S -1461
+L a -975
+L S -486
+R o -975
+R y -975
+R O -975
+R G -975
+R C -975
+R U -1461
+R Q -975
+G X -486
+G A -486
+P s -975
+P Z -975
+P X -975
+P W -975
+C X -975
+C W -975
+V i -486
+V S -1461
+S T -486
+S V -486
+S Y -486
+S X -486
+S A -1461
+S W -486
+Y i -486
+Y S -1461
+X a -975
+X u -1461
+X S -486
+A t -1461
+A g -1461
+A c -1950
+A d -1950
+A a -1461
+A u -1950
+A q -1950
+A S -975
+W i -486
+W S -975
+K c -1461
+K u -1461
+K S -486
+t g -486
+o f -486
+h w -486
+n w -486
+r o -486
+r c -486
+r e -486
+r d -486
+r a -975
+r q -486
+p f -486
+p w -486
+c f -486
+c x -486
+v e -486
+v s -486
+e f -486
+e x -486
+e w -486
+b f -486
+y e -486
+y s -486
+f o -486
+f c -486
+f e -486
+f d -486
+f s -486
+f a -975
+f q -486
+w e -486
+w s -486
+k o -486
+k g -486
+k c -486
+k v -486
+k e -486
+k d -486
+k y -486
+k a -975
+k w -486
+k q -486
+O Z -975
+L J -1461
+R e -975
+R a -975
+R u -975
+R S -486
+G Z -486
+P U -486
+C Z -975
+E a -486
+Z o -975
+Z e -975
+Z d -975
+Z y -975
+Z a -975
+Z w -975
+Z u -975
+Z O -975
+Z G -975
+Z C -975
+Z S -486
+Z Q -975
+D Z -975
+B Z -975
+S Z -486
+F i -486
+F j -486
+F S -486
+A s -486
+A J -1950
+A . -486
+A , -486
+J o -486
+J e -486
+J a -975
+J U -486
+U g -486
+U J -486
+K a -975
+K J -486
+t o -486
+t c -486
+t e -486
+t d -486
+t a -975
+t q -486
+o z -486
+h f -486
+n f -486
+r s -486
+g a -486
+p z -486
+c z -486
+e z -486
+z o -486
+z g -486
+z c -486
+z e -486
+z d -486
+z a -975
+z q -486
+b z -486
+a f -486
+k t -486
+k f -486
+k u -486
+T U -486
+R J -975
+C a -486
+C U -486
+V U -486
+E U -486
+B a -486
+B U -486
+Y U -486
+F U -486
+X U -486
+A b -486
+A f -975
+W U -486
+U t -486
+U o -486
+U h -486
+U n -486
+U m -486
+U l -486
+U r -486
+U i -486
+U p -486
+U c -486
+U v -486
+U e -486
+U z -486
+U d -486
+U b -486
+U s -486
+U y -486
+U f -486
+U x -486
+U a -975
+U w -486
+U j -486
+U q -486
+U k -486
+U T -486
+U O -486
+U H -486
+U N -486
+U M -486
+U L -486
+U R -486
+U G -486
+U I -486
+U P -486
+U C -486
+U V -486
+U E -486
+U Z -486
+U D -486
+U B -486
+U S -486
+U Y -486
+U F -486
+U X -486
+U W -486
+U U -975
+U Q -486
+U K -486
+K T -486
+K V -486
+K Y -486
+K W -486
+K U -975
+L ' -2439
+T char173 -3414
+T hy -3414
+T - -3414
+T en -3414
+T em -3414
+A ' -3903
+char173 T -3903
+hy T -3903
+- T -3903
+en T -3903
+em T -3903
+Y char173 -1461
+Y hy -1461
+Y - -1461
+Y en -1461
+Y em -1461
+p ' -1950
+c ' -486
+e ' -975
+b ' -1461
+a ' -1950
+V char173 -1461
+V hy -1461
+V - -1461
+V en -1461
+V em -1461
+h ' -1461
+n ' -1461
+R ' -975
+W char173 -975
+W hy -975
+W - -975
+W en -975
+W em -975
+' d -1461
+L char173 -1950
+L hy -1950
+L - -1950
+L en -1950
+L em -1950
+F char173 -486
+F hy -486
+F - -486
+F en -486
+F em -486
+X char173 -1461
+X hy -1461
+X - -1461
+X en -1461
+X em -1461
+A char173 -1950
+A hy -1950
+A - -1950
+A en -1950
+A em -1950
+K char173 -1461
+K hy -1461
+K - -1461
+K en -1461
+K em -1461
+' s -975
+char173 X -1461
+hy X -1461
+- X -1461
+char173 A -1950
+hy A -1950
+- A -1950
+en X -1461
+en A -1950
+em X -1461
+R char173 -975
+R hy -975
+R - -975
+R en -975
+R em -975
+K ' -486
+t g -486
+b f -486
+k ' -486
+Z char173 -975
+Z hy -975
+Z - -975
+Z en -975
+Z em -975
+U ' -486
+k char173 -486
+k hy -486
+k - -486
+k en -486
+k em -486
+U char173 -486
+U hy -486
+U - -486
+U en -486
+U em -486
+charset
+! 7317,18000,330,723,-177,586 2 3617
+" 10734,18375,0,678,-2778,586 2 3618
+sh 14637,17769,444,1371,570,586 0 3619
+# "
+Do 14637,19515,3105,0,6 2 3620
+$ "
+% 23418,17769,444,0,-2766 0 3621
+& 17565,18000,375,264,174,264 2 3622
+' 7317,18375,0,1704,-1407,586 2 51751
+( 7317,18375,3165,2625,-300,586 2 3624
+) 7317,18375,3165,54,2271,54 2 3625
+* 14637,18150,0,0,-2148 2 3626
++ 23418,13260,393,0,-3789 0 3627
+, 7317,2700,4611,0,1776 0 3628
+char173 7317,7170,0,1245,1176,586 0 3629
+hy "
+- "
+. 7317,2622,330,0,-237 0 3630
+sl 7317,19650,480,2448,1203,586 2 3631
+/ "
+0 14637,17700,375,723,-180,586 0 3632
+1 14637,17700,69,0,-3339 0 3633
+2 14637,17700,201,0,-123 0 3634
+3 14637,17700,375,0,60 0 3635
+4 14637,17769,69,396,285,396 0 3636
+5 14637,17526,375,297,-102,297 0 3637
+6 14637,17700,375,0,-459 0 3638
+7 14637,17526,69,1713,-885,586 0 3639
+8 14637,17700,375,12,-147,12 0 3640
+9 14637,17700,375,267,-963,267 0 3641
+: 7317,11652,330,0,-237 0 3642
+; 7317,11652,4611,0,1776 0 3643
+< 26346,16068,0,0,-3981 0 3644
+= 23418,8622,0,0,-3732 0 3645
+> 26346,16068,0,0,-3981 0 3646
+? 10245,18000,330,1083,-1299,586 2 3647
+at 23418,16980,3654,435,87,435 0 3648
+@ "
+A 17565,18000,69,0,1896 2 3649
+B 16101,18069,69,0,-342 2 3650
+C 17565,18375,375,1455,-411,586 2 3651
+D 20490,18069,69,288,-363,288 2 3652
+E 13173,18201,201,1095,-102,586 2 3653
+F 13173,18201,69,1098,-126,586 2 3654
+G 19515,18375,375,1158,-669,586 2 3655
+H 20490,18069,69,627,-234,586 2 3656
+I 7806,18069,69,609,-249,586 2 3657
+J 7317,18069,3657,1026,2235,586 2 3658
+K 16101,18069,69,2220,-321,586 2 3659
+L 12198,18069,201,414,-222,414 2 3660
+M 23418,18069,69,543,-111,543 2 3661
+N 20490,18069,375,525,-246,525 2 3662
+O 21954,18375,375,555,-372,555 2 3663
+P 14637,18069,69,1464,-360,586 2 3664
+Q 21954,18375,4200,507,-348,507 2 3665
+R 16587,18069,69,498,-159,498 2 3666
+S 13173,18375,375,882,855,586 2 3667
+T 14637,18201,69,2493,-1080,586 2 3668
+U 20490,18069,375,669,-1455,586 2 3669
+V 16101,18069,69,2763,-747,586 2 3670
+W 24882,18069,69,2835,-918,586 2 3671
+X 14637,18069,69,2148,1377,586 2 3672
+Y 14637,18069,69,3225,-543,586 2 3673
+Z 16101,18201,201,1014,921,586 2 3674
+lB 7317,18201,4956,3090,1014,586 3 3675
+[ "
+rs 7317,19650,480,294,-1518,294 2 3676
+\ "
+rB 7317,18201,4956,1338,2766,586 3 3677
+] "
+ha 13173,19758,0,36,36,36 2 51875
+_ 13173,191367,6588,1317,1317,586 3 3679
+oq 7317,18375,0,1704,-1407,586 2 51808
+` "
+a 13173,12795,330,168,582,168 0 3681
+b 14637,19779,330,279,651,279 2 3682
+c 12684,12795,330,1245,282,586 0 3683
+d 14637,19779,330,2097,-27,586 2 3684
+e 13173,12795,330,588,327,586 0 3685
+f 7317,19710,69,3714,57,586 2 3686
+g 13173,12996,5400,1656,876,586 1 3687
+h 14637,19779,69,0,348 2 3688
+i 7317,18336,69,885,-288,586 2 3689
+j 7317,18336,5400,876,1554,586 3 3690
+k 13173,19779,69,1581,249,586 2 3691
+l 7317,19779,69,1068,-111,586 2 3692
+m 21954,12534,69,0,414 0 3693
+n 14637,12795,69,0,282 0 3694
+o 14637,12795,330,453,351,453 0 3695
+p 14637,12795,5469,216,1740,216 1 3696
+q 14637,12795,5469,828,-51,586 1 3697
+r 8781,12795,69,1512,279,586 0 3698
+s 10245,12795,330,411,960,411 0 3699
+t 7806,15654,330,1212,258,586 0 3700
+u 14637,12534,330,372,-348,372 0 3701
+v 13173,12534,69,1632,-207,586 0 3702
+w 20490,12534,69,1974,-183,586 0 3703
+x 11709,12534,69,1191,1662,586 0 3704
+y 13173,12534,5469,1659,-57,586 1 3705
+z 13173,12666,201,795,714,586 0 3706
+lC 11709,19935,6210,2910,-1242,586 3 3707
+{ "
+ba 13173,19758,6588,0,-4596 3 3708
+| "
+rC 11709,19935,6210,0,2682 3 3709
+} "
+ti 26346,8952,0,0,-4029 0 51876
+char192 17565,24042,69,0,1896 2 3776
+`A "
+char194 17565,23745,69,0,1896 2 3778
+^A "
+char200 13173,24042,201,1095,-102,586 2 3784
+`E "
+char202 13173,23745,201,1095,-102,586 2 3786
+^E "
+char203 13173,22896,201,1455,-102,586 2 3787
+:E "
+char206 7806,23745,69,3768,-249,586 2 3790
+^I "
+char207 7806,22896,69,4140,-249,586 2 3791
+:I "
+char180 14637,18375,0,0,-6180 2 3764
+aa "
+ga 14637,18378,0,0,-4620 2 3680
+a^ 14637,18225,0,0,-3891 2 3678
+^ "
+char168 14637,17223,0,0,-3717 0 3752
+ad "
+a~ 14637,17166,0,0,-3717 0 3710
+~ "
+char217 20490,24042,375,669,-1455,586 2 3801
+`U "
+char219 20490,23745,375,669,-1455,586 2 3803
+^U "
+char221 14637,24048,69,3225,-543,586 2 3805
+'Y "
+char253 13173,18375,5469,1659,-57,586 3 3837
+'y "
+char176 14637,17700,0,0,-2664 0 3760
+de "
+char199 17565,18375,5736,1455,-411,586 3 3783
+,C "
+char231 12684,12795,5193,1245,282,586 1 3815
+,c "
+char209 20490,22812,375,525,-246,525 2 3793
+~N "
+char241 14637,17166,69,0,282 0 3825
+~n "
+char161 7317,12696,5634,0,639 1 3745
+r! "
+char191 10245,12696,5634,0,795 1 3775
+r? "
+char164 14637,15684,0,660,-117,586 0 3748
+Cs "
+char163 14637,17700,201,1269,1179,586 0 3747
+Po "
+char165 14637,18069,69,2862,-180,586 2 3749
+Ye "
+char167 14637,17865,3633,0,-960 2 3751
+sc "
+Fn 14637,19710,69,0,-3318 2 51871
+char162 14637,19782,0,393,-999,393 2 3746
+ct "
+char226 13173,18225,330,168,582,168 2 3810
+^a "
+char234 13173,18225,330,588,327,586 2 3818
+^e "
+char244 14637,18225,330,453,351,453 2 3828
+^o "
+char251 14637,18225,330,372,-348,372 2 3835
+^u "
+char225 13173,18375,330,168,582,168 2 3809
+'a "
+char233 13173,18375,330,588,327,586 2 3817
+'e "
+char243 14637,18375,330,453,351,453 2 3827
+'o "
+char250 14637,18375,330,372,-348,372 2 3834
+'u "
+char224 13173,18378,330,168,582,168 2 3808
+`a "
+char232 13173,18378,330,588,327,586 2 3816
+`e "
+char242 14637,18378,330,453,351,453 2 3826
+`o "
+char249 14637,18378,330,372,-348,372 2 3833
+`u "
+char228 13173,17223,330,285,582,285 0 3812
+:a "
+char235 13173,17223,330,588,327,586 0 3819
+:e "
+char246 14637,17223,330,453,351,453 0 3830
+:o "
+char252 14637,17223,330,372,-348,372 0 3836
+:u "
+char197 17565,23979,69,0,1896 2 3781
+oA "
+char238 7317,18225,69,2628,-231,586 2 3822
+^i "
+char216 21954,18375,375,1341,588,586 2 3800
+/O "
+char198 20979,18201,201,1296,3312,586 2 3782
+AE "
+char229 13173,17973,330,168,582,168 2 3813
+oa "
+char237 7317,18375,69,2973,-279,586 2 3821
+'i "
+char248 14637,12795,399,1320,1203,586 0 3832
+/o "
+char230 20490,12795,330,906,678,586 0 3814
+ae "
+char196 17565,22896,69,0,1896 2 3780
+:A "
+char236 7317,18378,69,174,-279,174 2 3820
+`i "
+char214 21954,22896,375,555,-372,555 2 3798
+:O "
+char220 20490,22896,375,669,-1455,586 2 3804
+:U "
+char201 13173,24048,201,1239,-102,586 2 3785
+'E "
+char239 7317,17223,69,3213,-57,586 0 3823
+:i "
+char223 14148,19710,330,147,516,147 2 3807
+ss "
+char212 21954,23745,375,555,-372,555 2 3796
+^O "
+char193 17565,24048,69,0,1896 2 3777
+'A "
+char195 17565,22812,69,0,1896 2 3779
+~A "
+char227 13173,17166,330,168,582,168 0 3811
+~a "
+char208 20490,18069,69,288,936,288 2 3792
+-D "
+char240 14637,19590,330,453,351,453 2 3824
+Sd "
+char205 7806,24048,69,3924,-249,586 2 3789
+'I "
+char204 7806,24042,69,909,-249,586 2 3788
+`I "
+char211 21954,24048,375,555,-372,555 2 3795
+'O "
+char210 21954,24042,375,555,-372,555 2 3794
+`O "
+char213 21954,22812,375,555,-372,555 2 3797
+~O "
+char245 14637,17166,330,453,351,453 0 3829
+~o "
+vS 13173,23745,375,1725,855,586 2 51795
+vs 10245,18225,330,1680,960,586 2 51827
+char218 20490,24048,375,669,-1455,586 2 3802
+'U "
+:Y 14637,22896,69,3225,-543,586 2 51801
+char255 13173,17223,5469,1659,-57,586 1 3839
+:y "
+char222 14637,18069,69,834,-351,586 2 3806
+TP "
+char254 14637,19779,5469,225,1752,225 3 3838
+Tp "
+char181 14637,12630,4350,1122,2931,586 0 3765
+char182 14637,19635,4200,135,-1257,135 2 3766
+ps "
+char190 23418,17850,525,0,-1326 2 3774
+34 "
+\- 23418,7122,0,0,-3801 0 51757
+char188 23418,17850,525,0,-2268 2 3772
+14 "
+char189 23418,17850,525,0,-2139 2 3773
+12 "
+char170 12198,17700,0,18,-1692,18 0 3754
+Of "
+char186 12198,17700,0,1029,-1608,586 0 3770
+Om "
+char171 9759,10920,0,849,306,586 0 3755
+Fo "
+char187 9759,10920,0,120,1035,120 0 3771
+Fc "
+char177 23418,13260,3132,0,-3333 0 3761
+char166 13173,19083,5916,0,-4596 3 3750
+bb "
+char169 13173,19635,0,3384,-1593,586 2 3753
+co "
+char172 23418,10671,0,0,-3015 0 3756
+no "
+char174 13173,19635,0,3384,-1593,586 2 3758
+rg "
+char178 10245,17700,0,705,-774,586 0 3762
+S2 "
+char179 10245,17700,0,525,-807,525 0 3763
+S3 "
+char184 14637,300,5193,0,-1905 1 3768
+ac "
+char185 10245,17700,0,0,-2472 0 3769
+S1 "
+char215 23418,13137,585,0,-3780 0 3799
+char247 23418,11139,0,0,-3900 0 3831
+char183 7317,10905,0,0,-1392 0 3767
+fm 7317,17700,0,1092,-1740,586 0 51873
+sd 14637,17700,0,0,-1740 0 51874
+dg 14637,18213,846,0,-1323 2 51755
+tm 16101,17850,0,924,-1461,586 2 51796
+ah 14637,18225,0,0,-4407 2 51935
+ao 14637,17973,0,0,-5853 2 51930
+f/ 3414,17850,525,7596,6609,586 2 51759
+em 23418,6885,0,390,537,390 0 51789
+en 14637,6885,0,507,537,507 0 51790
+dd 14637,18213,846,0,-1335 2 51773
+.i 7317,12534,69,174,-279,174 0 51957
+aq 7317,18375,0,705,-2778,586 2 3623
+bu 13173,14226,0,0,-498 0 51889
+'C 17565,24048,375,1455,-411,586 2 20166
+'c 12684,18375,330,1245,282,586 2 20198
+lq 11220,18375,0,1620,-1311,586 2 51838
+rq 11220,18375,0,1527,-1218,586 2 51746
+Bq 11220,2535,4482,0,1782 0 51772
+vz 13173,18225,201,795,714,586 2 51834
+fi 14637,19710,69,876,45,586 2 51881
+fl 14637,19710,69,1137,117,586 2 51882
+ff 14637,19710,69,3714,57,586 2 51883
+Fi 21954,19710,69,876,48,586 2 51884
+Fl 21954,19710,69,1137,120,586 2 51885
+ij 14148,18336,5400,873,-288,586 3 51958
+bq 7317,2535,4482,0,1593 0 51756
+%0 32202,17769,444,0,-2811 0 51901
+char175 14637,16521,0,0,-3732 0 3759
+a- "
+ab 14637,18165,0,0,-3657 2 51926
+a. 14637,17400,0,0,-6228 0 51927
+oe 23418,12795,330,696,354,586 0 51823
+OE 24396,18375,375,1089,-372,586 2 51791
+fo 6342,10920,0,624,243,586 0 51886
+fc 6342,10920,0,0,972 0 51887
+sq 19029,15624,0,0,-2022 0 51899
+/L 12198,18069,201,405,1215,405 2 51944
+/l 7317,19779,69,2694,1233,586 2 51960
+a" 14637,18375,0,1413,-3645,586 2 51933
+ho 14637,600,3876,0,-6093 0 51934
+vZ 16101,23745,201,1014,921,586 2 51802
+IJ 15126,18069,3657,1026,-249,586 2 51942
diff --git a/font/devlj4/OR b/font/devlj4/OR
new file mode 100644
index 00000000..140d9840
--- /dev/null
+++ b/font/devlj4/OR
@@ -0,0 +1,876 @@
+name OR
+spacewidth 7317
+pcltypeface 4113
+pclproportional 1
+pclweight 0
+pclstyle 0
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -3414
+P . -3903
+P , -3903
+V A -4389
+A V -4389
+T o -3903
+T r -3414
+T c -3903
+T e -3903
+T d -3903
+T s -3903
+T y -3903
+T a -3903
+T w -3903
+T u -3903
+L T -3414
+L Y -3414
+Y o -3903
+Y e -3903
+Y a -3903
+A W -3903
+W A -3903
+T A -3414
+V o -3414
+V e -3414
+V a -3414
+Y A -4389
+F A -3414
+F . -3414
+F , -3414
+A T -3414
+A Y -4389
+v . -2925
+v , -2925
+y . -2925
+y , -2925
+T . -3414
+T , -3414
+L W -3414
+P A -2925
+V . -3903
+V , -3903
+Y . -3903
+Y , -3903
+W o -2925
+W e -2925
+W a -2925
+W . -3903
+W , -3903
+r . -2925
+r , -2925
+w . -1950
+w , -1950
+Y u -2439
+A v -1950
+A y -1950
+A w -1461
+o . -1461
+o , -1461
+p . -1461
+p , -1461
+e . -975
+e , -975
+b . -1461
+b , -1461
+O T -2439
+O V -2439
+O Y -2439
+O . -2439
+O , -2439
+L y -2925
+L O -2439
+L G -2439
+L C -975
+L Q -2439
+V y -2439
+V u -2439
+V O -2439
+V G -2439
+V C -1461
+V Q -2439
+D T -1950
+D V -1950
+D Y -1950
+D . -1950
+D , -1950
+Y O -2439
+Y G -2439
+Y C -1461
+Y Q -2439
+F o -1461
+F e -1461
+F a -1461
+c . -486
+c , -486
+O A -1461
+O W -1461
+L U -1461
+R T -975
+R V -975
+R Y -975
+R W -975
+G T -1461
+P o -1461
+P g -975
+P e -1461
+P a -1461
+C A -486
+C . -486
+C , -486
+D A -1461
+D W -1461
+B T -1461
+B Y -1461
+B . -1461
+B , -1461
+A O -1461
+A G -1461
+A C -975
+A U -1461
+A Q -1461
+W r -1461
+W y -1461
+W u -1461
+W O -1461
+W G -1461
+W C -1461
+W Q -1461
+J A -975
+J . -975
+J , -975
+U A -1461
+U . -1461
+U , -1461
+Q A -1461
+Q W -1461
+f . -486
+f , -486
+T O -2439
+T G -2439
+T C -1461
+T Q -2439
+O X -1461
+L o -1461
+L e -1461
+L q -1461
+G V -1461
+G Y -1461
+G W -1461
+G . -486
+G , -486
+P T -486
+P V -486
+P Y -486
+D X -1461
+B V -1461
+B X -1461
+B A -1461
+B W -1461
+S . -975
+S , -975
+X o -1461
+X e -1461
+X y -1461
+X O -1461
+X G -1461
+X C -975
+X Q -1461
+A o -1461
+A e -1461
+Q X -1461
+K o -1461
+K e -1461
+K y -1461
+K w -1461
+K O -1461
+K G -1461
+K C -975
+K Q -1461
+o v -486
+o y -486
+o x -975
+h v -486
+h y -486
+n v -486
+n y -486
+m v -486
+m y -486
+g . -486
+g , -486
+p v -486
+p y -486
+p x -975
+c v -486
+c y -486
+v o -486
+v g -486
+v c -486
+v d -486
+v a -486
+v q -486
+e v -486
+e y -486
+b v -486
+b y -486
+s . -975
+s , -975
+y o -486
+y g -486
+y c -486
+y d -486
+y a -486
+y q -486
+f g -486
+x o -975
+x g -975
+x c -975
+x e -975
+x d -975
+x a -975
+x q -975
+a v -486
+a y -486
+T i -486
+T S -975
+L a -975
+L S -975
+R o -975
+R y -975
+R O -975
+R G -975
+R C -975
+R U -1461
+R Q -975
+G X -486
+G A -486
+P s -975
+P Z -486
+P X -486
+P W -486
+V i -486
+V S -975
+S T -975
+S V -975
+S Y -975
+S X -975
+S A -975
+S W -975
+Y i -486
+Y S -975
+X a -975
+X u -1461
+X S -975
+A t -1461
+A g -975
+A c -1461
+A d -1461
+A a -975
+A u -1461
+A q -1461
+A S -975
+W i -486
+W S -975
+K c -1461
+K u -1461
+K S -975
+c x -486
+v e -486
+v s -486
+e x -975
+s v -486
+s y -486
+s x -486
+y e -486
+y s -486
+f o -486
+f c -486
+f e -486
+f d -486
+f s -486
+f a -486
+f q -486
+x s -486
+k o -486
+k g -486
+k c -486
+k v -486
+k e -486
+k d -486
+k y -486
+k a -486
+k w -486
+k q -486
+O Z -975
+R e -975
+R a -975
+R u -975
+R S -975
+G Z -486
+P M -486
+P U -486
+Z o -975
+Z e -975
+Z d -975
+Z s -486
+Z y -975
+Z a -975
+Z w -975
+Z u -975
+Z O -975
+Z G -975
+Z C -975
+Z S -975
+Z Q -975
+D Z -975
+B Z -1461
+B J -486
+S Z -975
+A s -486
+J U -486
+U g -486
+U J -486
+K a -975
+o z -486
+p z -486
+c z -486
+e z -486
+z o -486
+z g -486
+z c -486
+z e -486
+z d -486
+z s -486
+z a -486
+z q -486
+b z -486
+s z -486
+k t -486
+k s -486
+k f -486
+k u -486
+T U -486
+G J -486
+C U -486
+V U -486
+E U -486
+B o -486
+B h -486
+B l -486
+B r -486
+B i -486
+B e -486
+B y -486
+B a -486
+B u -486
+B O -486
+B H -486
+B N -486
+B M -486
+B L -486
+B R -486
+B G -486
+B I -486
+B P -486
+B C -486
+B E -486
+B D -486
+B B -486
+B S -486
+B F -486
+B U -975
+B Q -486
+B K -486
+Y U -486
+F M -486
+F U -486
+X U -486
+A f -486
+W U -486
+U t -486
+U o -486
+U h -486
+U n -486
+U m -486
+U l -486
+U r -486
+U i -486
+U p -486
+U c -486
+U v -486
+U e -486
+U z -486
+U d -486
+U b -486
+U s -486
+U y -486
+U f -486
+U x -486
+U a -486
+U w -486
+U j -486
+U q -486
+U k -486
+U T -486
+U O -486
+U H -486
+U N -486
+U M -486
+U L -486
+U R -486
+U G -486
+U I -486
+U P -486
+U C -486
+U V -486
+U E -486
+U Z -486
+U D -486
+U B -486
+U S -486
+U Y -486
+U F -486
+U X -486
+U W -486
+U U -975
+U Q -486
+U K -486
+K U -486
+L ' -3414
+T char173 -3903
+T hy -3903
+T - -3903
+T en -3903
+T em -3903
+A ' -3903
+char173 T -3903
+hy T -3903
+- T -3903
+en T -3903
+em T -3903
+Y char173 -2439
+Y hy -2439
+Y - -2439
+Y en -2439
+Y em -2439
+p ' -1461
+c ' -486
+e ' -975
+b ' -1461
+a ' -1461
+V char173 -2439
+V hy -2439
+V - -2439
+V en -2439
+V em -2439
+h ' -1461
+n ' -1461
+m ' -1461
+R ' -975
+W char173 -1461
+W hy -1461
+W - -1461
+W en -1461
+W em -1461
+' d -1461
+s ' -486
+L char173 -1950
+L hy -1950
+L - -1950
+L en -1950
+L em -1950
+X char173 -1461
+X hy -1461
+X - -1461
+X en -1461
+X em -1461
+A char173 -1461
+A hy -1461
+A - -1461
+A en -1461
+A em -1461
+K char173 -1461
+K hy -1461
+K - -1461
+K en -1461
+K em -1461
+' s -975
+char173 X -1461
+hy X -1461
+- X -1461
+char173 A -1461
+hy A -1461
+- A -1461
+en X -1461
+en A -1461
+em X -1461
+R char173 -975
+R hy -975
+R - -975
+R en -975
+R em -975
+k ' -486
+M ' -486
+G ' -486
+Z char173 -975
+Z hy -975
+Z - -975
+Z en -975
+Z em -975
+B ' -486
+U ' -486
+' M -486
+k char173 -486
+k hy -486
+k - -486
+k en -486
+k em -486
+B char173 -486
+B hy -486
+B - -486
+B en -486
+B em -486
+U char173 -486
+U hy -486
+U - -486
+U en -486
+U em -486
+charset
+! 7317,18000,330 2 3617
+" 10734,18375 2 3618
+sh 14637,17994,405 2 3619
+# "
+Do 14637,19554,2919 2 3620
+$ "
+% 23418,17961,510 2 3621
+& 19029,17667,375 0 3622
+' 7317,18375 2 51751
+( 7317,18375,3165 2 3624
+) 7317,18375,3165 2 3625
+* 14637,18066 2 3626
++ 23418,13260,393 0 3627
+, 7317,2718,4923 1 3628
+char173 7317,7275 0 3629
+hy "
+- "
+. 7317,2715,330 0 3630
+sl 7317,19566,396 2 3631
+/ "
+0 14637,17700,375 0 3632
+1 14637,17700,69 0 3633
+2 14637,17700,201 0 3634
+3 14637,17700,375 0 3635
+4 14637,17394,69 0 3636
+5 14637,17526,375 0 3637
+6 14637,17700,375 0 3638
+7 14637,17526,69 0 3639
+8 14637,17700,375 0 3640
+9 14637,17700,375 0 3641
+: 7317,11805,330 0 3642
+; 7317,11805,4923 1 3643
+< 26346,16068 0 3644
+= 23418,8634 0 3645
+> 26346,16068 0 3646
+? 10245,18000,330 2 3647
+at 23418,16980,3654 0 3648
+@ "
+A 17565,18000,69 2 3649
+B 16101,18069,69 2 3650
+C 17565,18375,375 2 3651
+D 20490,18069,69 2 3652
+E 13173,18201,201 2 3653
+F 13173,18201,69 2 3654
+G 20490,18375,375 2 3655
+H 20490,18069,69 2 3656
+I 7317,18069,69 2 3657
+J 7317,18069,3855 2 3658
+K 16101,18069,69 2 3659
+L 13173,18069,201 2 3660
+M 23418,18000,69 2 3661
+N 20490,18069,375 2 3662
+O 21954,18375,375 2 3663
+P 14637,18069,69 2 3664
+Q 21954,18375,5400 3 3665
+R 16101,18069,69 2 3666
+S 13173,18375,375 2 3667
+T 14637,18201,69 2 3668
+U 20490,18069,375 2 3669
+V 17565,18069,69 2 3670
+W 26346,18069,69 2 3671
+X 16101,18069,69 2 3672
+Y 16101,18069,69 2 3673
+Z 16101,18201,201 2 3674
+lB 7317,18204,4179 2 3675
+[ "
+rs 7317,19566,396 2 3676
+\ "
+rB 7317,18204,4179 2 3677
+] "
+ha 13173,19758 2 51875
+_ 13173,191367,6588 3 3679
+oq 7317,18375 2 51808
+` "
+a 12684,12795,330 0 3681
+b 14637,19569,330 2 3682
+c 12684,12795,330 0 3683
+d 14637,19569,330 2 3684
+e 13173,12795,330 0 3685
+f 7317,19710,69 2 3686
+g 13173,12882,5400 1 3687
+h 14637,19569,69 2 3688
+i 7317,18399,69 2 3689
+j 7317,18399,5400 3 3690
+k 13173,19569,69 2 3691
+l 7317,19569,69 2 3692
+m 21954,12795,69 0 3693
+n 14637,12795,69 0 3694
+o 14637,12795,330 0 3695
+p 14637,12795,5469 1 3696
+q 14637,12795,5469 1 3697
+r 8781,12795,69 0 3698
+s 10245,12795,330 0 3699
+t 7317,16185,330 0 3700
+u 14637,12534,330 0 3701
+v 13173,12534,69 0 3702
+w 20490,12534,69 0 3703
+x 13173,12534,69 0 3704
+y 13173,12534,5469 1 3705
+z 13173,12666,201 0 3706
+lC 11709,19935,6210 3 3707
+{ "
+ba 13173,19758,6588 3 3708
+| "
+rC 11709,19935,6210 3 3709
+} "
+ti 26346,8952 0 51876
+char192 17565,23730,69 2 3776
+`A "
+char194 17565,23760,69 2 3778
+^A "
+char200 13173,23730,201 2 3784
+`E "
+char202 13173,23760,201 2 3786
+^E "
+char203 13173,22902,201 2 3787
+:E "
+char206 7317,23760,69 2 3790
+^I "
+char207 7317,22902,69 2 3791
+:I "
+char180 14637,18189 2 3764
+aa "
+ga 14637,18189 2 3680
+a^ 14637,18000 2 3678
+^ "
+char168 14637,17223 0 3752
+ad "
+a~ 14637,16980 0 3710
+~ "
+char217 20490,23730,375 2 3801
+`U "
+char219 20490,23760,375 2 3803
+^U "
+char221 16101,23730,69 2 3805
+'Y "
+char253 13173,18189,5469 3 3837
+'y "
+char176 14637,17700 0 3760
+de "
+char199 17565,18375,5988 3 3783
+,C "
+char231 12684,12795,5673 1 3815
+,c "
+char209 20490,22707,375 2 3793
+~N "
+char241 14637,16980,69 0 3825
+~n "
+char161 7317,12696,5634 1 3745
+r! "
+char191 10245,12696,5634 1 3775
+r? "
+char164 14637,15684 0 3748
+Cs "
+char163 14637,17700,201 0 3747
+Po "
+char165 14637,17769,69 2 3749
+Ye "
+char167 14637,18000,3633 2 3751
+sc "
+Fn 14637,19710,69 2 51871
+char162 14637,19155,93 2 3746
+ct "
+char226 12684,18000,330 2 3810
+^a "
+char234 13173,18000,330 2 3818
+^e "
+char244 14637,18000,330 2 3828
+^o "
+char251 14637,18000,330 2 3835
+^u "
+char225 12684,18189,330 2 3809
+'a "
+char233 13173,18189,330 2 3817
+'e "
+char243 14637,18189,330 2 3827
+'o "
+char250 14637,18189,330 2 3834
+'u "
+char224 12684,18189,330 2 3808
+`a "
+char232 13173,18189,330 2 3816
+`e "
+char242 14637,18189,330 2 3826
+`o "
+char249 14637,18189,330 2 3833
+`u "
+char228 12684,17223,330 0 3812
+:a "
+char235 13173,17223,330 0 3819
+:e "
+char246 14637,17223,330 0 3830
+:o "
+char252 14637,17223,330 0 3836
+:u "
+char197 17565,23964,69 2 3781
+oA "
+char238 7317,18000,69 2 3822
+^i "
+char216 21954,18375,375 2 3800
+/O "
+char198 21468,18201,201 2 3782
+AE "
+char229 12684,18045,330 2 3813
+oa "
+char237 7317,18189,69 2 3821
+'i "
+char248 14637,12876,330 0 3832
+/o "
+char230 20490,12795,330 0 3814
+ae "
+char196 17565,22902,69 2 3780
+:A "
+char236 7317,18189,69 2 3820
+`i "
+char214 21954,22902,375 2 3798
+:O "
+char220 20490,22902,375 2 3804
+:U "
+char201 13173,23730,201 2 3785
+'E "
+char239 7317,17223,69 0 3823
+:i "
+char223 14637,19710,330 2 3807
+ss "
+char212 21954,23760,375 2 3796
+^O "
+char193 17565,23730,69 2 3777
+'A "
+char195 17565,22707,69 2 3779
+~A "
+char227 12684,16980,330 0 3811
+~a "
+char208 20490,18069,69 2 3792
+-D "
+char240 14637,19500,330 2 3824
+Sd "
+char205 7317,23730,69 2 3789
+'I "
+char204 7317,23730,69 2 3788
+`I "
+char211 21954,23730,375 2 3795
+'O "
+char210 21954,23730,375 2 3794
+`O "
+char213 21954,22707,375 2 3797
+~O "
+char245 14637,16980,330 0 3829
+~o "
+vS 13173,23760,375 2 51795
+vs 10245,18183,330 2 51827
+char218 20490,23730,375 2 3802
+'U "
+:Y 16101,22902,69 2 51801
+char255 13173,17223,5469 1 3839
+:y "
+char222 14637,18069,69 2 3806
+TP "
+char254 14637,19569,5469 3 3838
+Tp "
+char181 14637,12630,4350 0 3765
+char182 14637,19635,4200 2 3766
+ps "
+char190 23418,17700,519 0 3774
+34 "
+\- 23418,7122 0 51757
+char188 23418,17700,519 0 3772
+14 "
+char189 23418,17700,519 0 3773
+12 "
+char170 10734,17700 0 3754
+Of "
+char186 10734,17700 0 3770
+Om "
+char171 9759,10809 0 3755
+Fo "
+char187 9759,10809 0 3771
+Fc "
+char177 23418,13260,3132 0 3761
+char166 13173,19083,5916 3 3750
+bb "
+char169 13173,19635 2 3753
+co "
+char172 23418,10671 0 3756
+no "
+char174 13173,19635 2 3758
+rg "
+char178 9759,17700 0 3762
+S2 "
+char179 9759,17700 0 3763
+S3 "
+char184 14637,0,5673 1 3768
+ac "
+char185 9759,17700 0 3769
+S1 "
+char215 23418,13137,585 0 3799
+char247 23418,11139 0 3831
+char183 7317,10407 0 3767
+fm 7317,17700 0 51873
+sd 14637,17700 0 51874
+dg 14637,18213,846 2 51755
+tm 16101,17850 2 51796
+ah 14637,18183 2 51935
+ao 14637,18045 2 51930
+f/ 2439,17637,519 0 51759
+em 23418,6867 0 51789
+en 14637,6867 0 51790
+dd 14637,18213,846 2 51773
+.i 7317,12534,69 0 51957
+aq 7317,18375 2 3623
+bu 13173,14226 0 51889
+'C 17565,23730,375 2 20166
+'c 12684,18189,330 2 20198
+lq 11220,18375 2 51838
+rq 11220,18375 2 51746
+Bq 11220,2718,4509 0 51772
+vz 13173,18183,201 2 51834
+fi 14148,19710,69 2 51881
+fl 14148,19779,69 2 51882
+ff 14637,19710,69 2 51883
+Fi 21468,19710,69 2 51884
+Fl 21468,19779,69 2 51885
+ij 14148,18399,5400 3 51958
+bq 7317,2718,4509 0 51756
+%0 32202,17769,444 2 51901
+char175 14637,16662 0 3759
+a- "
+ab 14637,18111 2 51926
+a. 14637,17223 0 51927
+oe 23418,12795,330 0 51823
+OE 24396,18375,375 2 51791
+fo 5856,10809 0 51886
+fc 5856,10809 0 51887
+sq 19029,15624 0 51899
+/L 13173,18069,201 2 51944
+/l 7317,19569,69 2 51960
+a" 14637,18189 2 51933
+ho 14637,1059,3885 0 51934
+vZ 16101,23760,201 2 51802
+IJ 14637,18069,3855 2 51942
diff --git a/font/devlj4/S b/font/devlj4/S
new file mode 100644
index 00000000..599867f6
--- /dev/null
+++ b/font/devlj4/S
@@ -0,0 +1,195 @@
+name S
+special
+spacewidth 7806
+pcltypeface 4101
+pclproportional 1
+pclweight 0
+pclstyle 0
+kernpairs
+*T *A -2925
+*A *T -2925
+*R *A -3903
+*O *T -1950
+*O *A -2439
+*B *T -1950
+*A *O -2439
+*T *O -1950
+*O *X -1461
+*B *X -1461
+*B *A -1950
+*X *O -1461
+*K *O -1461
+*O *Z -486
+*Z *O -486
+*B *Z -486
+*N *A -486
+*K *T -486
+charset
+pl 23418,15750 0 68907
+eq 23418,10875 0 68925
+*A 19029,18225 2 68929
+*B 16587,17895 2 68930
+*E 16587,17895 2 68933
+*Y 19515,17895 2 68935
+*I 8781,17895 2 68937
+*K 18540,17895 2 68938
+*M 23907,17895 2 68940
+*N 19515,17895,330 2 68941
+*O 19029,18225,330 2 68943
+*R 15126,17895 2 68945
+*T 16587,17895 2 68947
+*X 19029,17895 2 68950
+*Z 17076,17895 2 68934
+or 13173,19758,6588 3 44412
+ap 26346,8952 0 44414
+mi 23418,8610 0 68909
++- 23418,15750,2625 0 69118
+no 23418,12165 0 69064
+mu 23418,15117 0 68906
+di 23418,14010 0 68901
+HE 26346,19500 2 44457
+DI 26346,19500,840 2 44456
+CL 26346,18951 2 44455
+SP 26346,19851 2 44458
+va 19029,17670 2 69033
+ua 19029,17670 2 69025
+da 19029,17670 2 69027
+-> 19029,12231 0 69026
+<- 19029,12231 0 69028
+<> 19029,12453 0 69034
+if 26346,12846 0 68900
+ca 26346,16650 0 69046
+== 26346,11634 0 68989
+>= 26346,15960 0 68958
+<= 26346,15960 0 68956
+~~ 26346,11172 0 68927
+md 8781,10407 0 69066
+sr 19029,23322 2 68897
+pt 26346,12723 0 68902
++e 11709,12705,555 0 68923
+tf 26346,16545 0 68928
+3d "
+*G 16101,18045 2 68931
+*D 17565,18045 2 68932
+*H 19029,18450,405 2 68936
+*L 17565,18045 2 68939
+*C 17565,19335,1752 2 68942
+*P 19029,18045 2 68944
+*S 16101,18045 2 68946
+*U 16101,18450 2 68948
+*F 17565,18045 2 68949
+*Q 20490,18045 2 68951
+*W 16101,18450 2 68952
+gr 17565,18045 2 68953
+pd 13173,18450,405 2 68954
+ts 13173,12600,4734 0 68955
+!= 26346,15396,1197 0 68957
+*a 16101,11205,405 0 68961
+*b 14637,18450,4260 2 68962
+*g 14637,11205,5595 1 68963
+*d 11709,18450,405 2 68964
+*e 10245,11205,405 0 68965
+*z 11709,17508,4920 2 68966
+*y 13173,11205,5283 1 68967
+*h 11709,18450,405 2 68968
+*i 7317,10800,405 0 68969
+*k 11709,11205,405 0 68970
+*l 14637,18450,405 2 68971
+*m 14637,10800,5595 1 68972
+*n 11709,11205,405 0 68973
+*c 13173,18450,4647 2 68974
+*o 11709,11205,405 0 68975
+*p 16101,11295,405 0 68976
+*r 13173,11205,4527 0 68977
+*s 13173,11544,405 0 68978
+*t 11709,11295,405 0 68979
+*u 11709,11205,405 0 68980
+*f 16101,17304,4314 2 68981
+*x 14637,11205,4734 0 68982
+*q 16101,18450,4734 2 68983
+*w 16101,11205,405 0 68984
++h 16101,18450,405 2 68985
++f 16101,11205,4608 0 68986
++p 16101,11442,405 0 68987
+~= 26346,11436 0 68988
+ne 26346,15300,966 0 68990
+uA 19029,17553,1536 2 69029
+arrowverttp "
+rh 19029,13407 0 69030
+rA "
+dA 19029,17553,1536 2 69031
+arrowvertbt "
+lh 19029,13407 0 69032
+lA "
+vA 19029,17553,1812 2 69035
+hA 19029,14346 0 69036
+radicalex 19029,23322 2 69040
+fa 15612,15153 0 69041
+te 11220,15165 0 69042
+pp 26346,16560 0 69044
+cu 26346,16650 0 69045
+mo 26346,17925 2 69047
+nm 26346,20625,2700 2 69049
+sb 26346,16290 0 69050
+sp 26346,16290 0 69051
+nb 26346,18165,1875 2 69052
+nc 26346,18165,1875 2 69053
+ib 26346,16641 0 69054
+ip 26346,16641 0 69055
+c+ 26346,18900 2 69056
+c* 26346,18900 2 69058
+AN 26346,15240 0 69061
+OR 26346,15240 0 69062
+ci 26346,18900 2 69069
+is 26346,20268,5997 3 69077
+/_ 26346,19365 2 69079
+es 26346,18465,435 2 69080
+Ah 13173,13980 0 69081
+Im 19029,18255,1890 2 69085
+Re 20490,18255,1890 2 69086
+lc 19029,23322,5124 3 69088
+bracketlefttp "
+lf 19029,23322,5124 3 69089
+bracketleftbt "
+lt 19029,19758,6588 3 69090
+parenlefttp "
+bracelefttp "
+lk 19029,19758,6588 3 69091
+braceleftmid "
+lb 19029,19758,6588 3 69092
+parenleftbt "
+braceleftbt "
+arrowvertex 19029,23322,6588 3 69097
+rc 19029,23322,5124 3 69104
+bracketrighttp "
+rf 19029,23322,5124 3 69105
+bracketrightbt "
+rt 19029,19758,6588 3 69106
+parenrighttp "
+bracerighttp "
+rk 19029,19758,6588 3 69107
+bracerightmid "
+rb 19029,19758,6588 3 69108
+parenrightbt "
+bracerightbt "
+bv 19029,23322,6588 3 69109
+bracerightex "
+braceleftex "
+parenrightex 19029,23322,6588 3 69110
+parenleftex "
+bracketrightex "
+bracketleftex "
+barex "
+-+ 26346,18366 2 69117
+la 8781,21000,4950 2 44513
+ra 8781,21000,4950 2 44529
+=~ 26346,14187 0 69103
+<< 26346,15294,1086 0 128316
+>> 26346,15294,1086 0 128318
+-h 15126,18564,486 2 128328
+wp 17076,13026,4218 0 44483
+lz 26346,17844,294 2 44512
+st 12198,12846,396 0 69076
+** 26346,13275 0 69102
+an 19029,8676 0 69100
+CR 26346,12165 0 44479
diff --git a/font/devlj4/TB b/font/devlj4/TB
new file mode 100644
index 00000000..c352b153
--- /dev/null
+++ b/font/devlj4/TB
@@ -0,0 +1,971 @@
+name TB
+spacewidth 7806
+pcltypeface 4101
+pclproportional 1
+pclweight 3
+pclstyle 0
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -3414
+P . -4389
+P , -4389
+V A -4878
+A V -4878
+T o -2925
+T r -1461
+T c -2439
+T e -2925
+T d -2925
+T s -2439
+T y -1461
+T a -2925
+T w -1461
+T u -1461
+T J -1461
+L T -2439
+L Y -3414
+Y o -4878
+Y e -4878
+Y a -4878
+Y J -1461
+A W -4389
+W A -4389
+T A -2439
+V o -3903
+V e -3903
+V a -3903
+Y A -3903
+F A -3903
+F . -3903
+F , -3903
+A T -2439
+A Y -3903
+v . -3414
+v , -3414
+y . -3414
+y , -3414
+T . -2439
+T , -2439
+L W -3414
+P A -3414
+V J -1461
+V . -3903
+V , -3903
+Y . -3903
+Y , -3903
+W o -3414
+W e -3414
+W a -3414
+W . -3903
+W , -3903
+r . -3414
+r , -3414
+w . -3414
+w , -3414
+Y u -3414
+A v -3414
+A y -3414
+A w -3414
+o . -1461
+o , -1461
+p . -1461
+p , -1461
+e . -975
+e , -975
+b . -486
+b , -486
+O T -1461
+O V -2439
+O Y -2925
+O . -2925
+O , -2925
+L y -1950
+L O -975
+L G -975
+L C -975
+L Q -975
+P J -975
+V y -2439
+V u -2439
+V O -2439
+V G -2439
+V C -2439
+V Q -2439
+D T -1461
+D V -2439
+D Y -2925
+D . -2925
+D , -2925
+Y O -2925
+Y G -2925
+Y C -2925
+Y Q -2925
+F o -1950
+F e -1950
+F a -1950
+c . -975
+c , -975
+O A -2439
+O W -1950
+L U -1461
+R T -1950
+R V -1950
+R Y -1950
+R W -1950
+G T -1461
+P o -975
+P g -975
+P e -975
+P a -975
+C A -2439
+C . -2439
+C , -2439
+D A -2439
+D W -1950
+B T -1461
+B Y -1461
+B . -1461
+B , -1461
+F J -1461
+A O -2439
+A G -2439
+A C -2439
+A U -2439
+A Q -2439
+W r -1950
+W y -1950
+W u -1950
+W O -1950
+W G -1950
+W C -1950
+W J -1461
+W Q -1950
+J A -1461
+J . -1461
+J , -1461
+U A -2439
+U . -2439
+U , -2439
+Q A -2439
+Q W -1950
+T O -1461
+T G -1461
+T C -1461
+T Q -1461
+O X -1950
+L o -975
+L e -975
+L q -975
+G V -1461
+G Y -1461
+G W -1461
+G . -1461
+G , -1461
+P T -486
+P V -486
+P Y -486
+C T -975
+C V -975
+C Y -975
+D X -1950
+B V -1461
+B X -1461
+B A -1461
+B W -1461
+S . -1461
+S , -1461
+F r -486
+F y -486
+F u -486
+F O -486
+F G -486
+F C -486
+F Q -486
+X o -1461
+X e -1461
+X y -1950
+X O -1950
+X G -1950
+X C -1950
+X Q -1950
+A o -1461
+A e -1461
+Q X -1950
+K o -1461
+K e -1461
+K y -1461
+K w -1461
+K O -1461
+K G -1461
+K C -1461
+K Q -1461
+o v -975
+o y -975
+o x -975
+o w -975
+h v -975
+h y -975
+n v -975
+n y -975
+m v -975
+m y -975
+r g -486
+g . -1461
+g , -1461
+c v -975
+c y -975
+c w -975
+v o -975
+v g -975
+v c -975
+v d -975
+v a -975
+v q -975
+e v -975
+e y -975
+b v -486
+b y -486
+b w -486
+s . -975
+s , -975
+y o -975
+y g -975
+y c -975
+y d -975
+y a -975
+y q -975
+f g -486
+x o -975
+x g -486
+x c -975
+x e -975
+x d -975
+x a -975
+x q -975
+a v -975
+a y -975
+a w -975
+w o -975
+w g -975
+w c -975
+w d -975
+w a -975
+w q -975
+T i -975
+T S -1461
+L a -975
+L S -486
+R o -975
+R y -975
+R O -975
+R G -975
+R C -975
+R U -1461
+R Q -975
+G X -1461
+G A -1461
+P s -975
+P Z -486
+P X -486
+P W -486
+C X -975
+C W -975
+C J -486
+V i -975
+V S -1461
+S T -486
+S V -486
+S Y -486
+S X -486
+S A -1461
+S W -486
+Y i -975
+Y S -1461
+X a -975
+X u -975
+X S -486
+A t -975
+A g -486
+A c -975
+A d -1461
+A a -975
+A u -975
+A q -1461
+A S -486
+W i -975
+W S -1461
+K c -975
+K u -975
+K S -486
+t g -486
+t . -486
+t , -486
+o f -486
+h w -975
+n w -975
+m w -975
+r o -486
+r c -486
+r e -486
+r d -486
+r a -486
+r q -486
+c f -486
+c x -975
+v e -975
+v s -975
+e f -486
+e x -975
+e w -975
+b f -486
+s v -486
+s y -486
+s f -486
+s x -486
+s w -486
+y e -975
+y s -975
+f o -486
+f c -486
+f e -486
+f d -486
+f s -486
+f a -486
+f q -486
+x s -486
+w e -975
+w s -975
+k o -486
+k g -486
+k c -486
+k v -486
+k e -486
+k d -486
+k y -486
+k a -486
+k w -486
+k q -486
+O Z -486
+N . -486
+N , -486
+R e -975
+R a -975
+R u -975
+R S -486
+G Z -486
+P U -486
+C Z -975
+E t -486
+E o -486
+E g -486
+E c -486
+E v -486
+E e -486
+E d -486
+E y -486
+E f -486
+E a -486
+E w -486
+E u -486
+E q -486
+E O -486
+E G -486
+E C -486
+E S -486
+E J -486
+E Q -486
+E . -486
+E , -486
+Z o -486
+Z e -486
+Z d -486
+Z s -486
+Z y -975
+Z a -486
+Z w -975
+Z u -486
+Z O -486
+Z G -486
+Z C -486
+Z S -486
+Z Q -486
+D Z -486
+B Z -486
+S Z -486
+F i -486
+F j -975
+F S -486
+A s -486
+U g -486
+U J -486
+K a -975
+t o -486
+t c -486
+t e -486
+t d -486
+t s -486
+t a -486
+t j -486
+t q -486
+o z -486
+r s -486
+r j -486
+c z -486
+v j -486
+e z -486
+z o -486
+z g -486
+z c -486
+z e -486
+z d -486
+z s -486
+z a -486
+z q -486
+b z -486
+s z -486
+y j -486
+w j -486
+k t -486
+k s -486
+k u -486
+N A -486
+C t -486
+C o -486
+C h -486
+C l -486
+C r -486
+C i -486
+C e -486
+C y -486
+C a -486
+C u -486
+C O -486
+C H -486
+C N -486
+C M -486
+C L -486
+C R -486
+C G -486
+C I -486
+C P -486
+C C -486
+C E -486
+C D -486
+C B -486
+C S -486
+C F -486
+C U -975
+C Q -486
+C K -486
+E n -486
+E m -486
+E l -486
+E r -486
+E i -486
+E p -486
+E z -486
+E b -486
+E s -486
+E x -486
+E j -486
+E k -486
+E T -486
+E H -486
+E N -486
+E M -486
+E L -486
+E R -486
+E I -486
+E P -486
+E V -486
+E E -486
+E Z -486
+E D -486
+E B -486
+E Y -486
+E F -486
+E X -486
+E A -486
+E W -486
+E U -486
+E K -486
+B U -486
+U t -486
+U o -486
+U n -486
+U m -486
+U r -486
+U i -486
+U p -486
+U c -486
+U v -486
+U e -486
+U z -486
+U d -486
+U s -486
+U y -486
+U f -486
+U x -486
+U a -486
+U w -486
+U j -486
+U q -486
+U O -486
+U G -486
+U C -486
+U S -486
+U Q -486
+K T -486
+K V -486
+K Y -486
+K W -486
+K U -486
+L ' -3414
+T char173 -1461
+T hy -1461
+T - -1461
+T en -1461
+T em -1461
+A ' -3414
+char173 T -1461
+hy T -1461
+- T -1461
+en T -1461
+em T -1461
+Y char173 -3414
+Y hy -3414
+Y - -3414
+Y en -3414
+Y em -3414
+c ' -975
+e ' -975
+b ' -486
+a ' -1461
+V char173 -2439
+V hy -2439
+V - -2439
+V en -2439
+V em -2439
+h ' -975
+n ' -975
+m ' -975
+R ' -975
+W char173 -1950
+W hy -1950
+W - -1950
+W en -1950
+W em -1950
+' d -1461
+s ' -486
+L char173 -975
+L hy -975
+L - -975
+L en -975
+L em -975
+F char173 -486
+F hy -486
+F - -486
+F en -486
+F em -486
+X char173 -1950
+X hy -1950
+X - -1950
+X en -1950
+X em -1950
+A char173 -1950
+A hy -1950
+A - -1950
+A en -1950
+A em -1950
+K char173 -1461
+K hy -1461
+K - -1461
+K en -1461
+K em -1461
+' s -975
+char173 X -1950
+hy X -1950
+- X -1950
+char173 A -1950
+hy A -1950
+- A -1950
+en X -1950
+en A -1950
+em X -1950
+R char173 -975
+R hy -975
+R - -975
+R en -975
+R em -975
+K ' -486
+t g -486
+b f -486
+k ' -486
+C ' -486
+E ' -486
+E char173 -486
+E hy -486
+E - -486
+E en -486
+E em -486
+Z char173 -486
+Z hy -486
+Z - -486
+Z en -486
+Z em -486
+k char173 -486
+k hy -486
+k - -486
+k en -486
+k em -486
+C char173 -486
+C hy -486
+C - -486
+C en -486
+C em -486
+U char173 -486
+U hy -486
+U - -486
+U en -486
+U em -486
+charset
+! 8781,18045,405 2 3617
+" 12198,18450 2 3618
+sh 13173,18450,405 2 3619
+# "
+Do 13173,19755,2610 2 3620
+$ "
+% 23418,18237,405 2 3621
+& 21954,18045,405 2 3622
+' 8781,18450 2 51751
+( 8781,18450,4305 2 3624
+) 8781,18450,4305 2 3625
+* 13173,18450 2 3626
++ 23418,15975 0 3627
+, 8781,4380,4560 0 3628
+char173 8781,7740 0 3629
+hy "
+- "
+. 8781,4125,405 0 3630
+sl 8781,18450,405 2 3631
+/ "
+0 13173,18450,405 2 3632
+1 13173,18450 2 3633
+2 13173,18450 2 3634
+3 13173,18450,405 2 3635
+4 13173,18450 2 3636
+5 13173,18045,405 2 3637
+6 13173,18450,405 2 3638
+7 13173,18045 2 3639
+8 13173,18450,405 2 3640
+9 13173,18450,405 2 3641
+: 8781,12549,405 0 3642
+; 8781,12549,4560 0 3643
+< 26346,16068 0 3644
+= 23418,11370 0 3645
+> 26346,16068 0 3646
+? 13173,18045,405 2 3647
+at 23418,16950,4131 2 3648
+@ "
+A 19029,18450 2 3649
+B 17565,18045 2 3650
+C 19029,18450,405 2 3651
+D 19029,18045 2 3652
+E 17565,18045 2 3653
+F 16101,18045 2 3654
+G 20490,18519,405 2 3655
+H 20490,18045 2 3656
+I 10245,18045 2 3657
+J 12684,18045,405 2 3658
+K 20490,18045 2 3659
+L 17565,18045 2 3660
+M 24882,18045 2 3661
+N 19029,18045,405 2 3662
+O 20490,18450,405 2 3663
+P 16101,18045 2 3664
+Q 20490,18450,4515 2 3665
+R 19029,18045 2 3666
+S 14637,18450,462 2 3667
+T 17565,18045 2 3668
+U 19029,18045,405 2 3669
+V 19029,18045,405 2 3670
+W 26346,18045,405 2 3671
+X 19029,18045 2 3672
+Y 19029,18045 2 3673
+Z 17565,18045 2 3674
+lB 8781,18045,4305 2 3675
+[ "
+rs 8781,18450,405 2 3676
+\ "
+rB 8781,18045,4305 2 3677
+] "
+ha 13173,19758 2 51875
+_ 13173,191367,6588 3 3679
+oq 8781,18450 2 51808
+` "
+a 13173,12735,405 0 3681
+b 14637,18090,405 2 3682
+c 11709,12735,405 0 3683
+d 14637,18090,405 2 3684
+e 11709,12735,405 0 3685
+f 9270,18540 2 3686
+g 13173,12735,5484 1 3687
+h 14637,18090 2 3688
+i 7317,18450 2 3689
+j 8781,18450,5490 3 3690
+k 14637,18090 2 3691
+l 7317,18090 2 3692
+m 21954,12735 0 3693
+n 14637,12735 0 3694
+o 13173,12735,405 0 3695
+p 14637,12735,5490 1 3696
+q 14637,12828,5490 1 3697
+r 11709,12735 0 3698
+s 10245,12735,411 0 3699
+t 8781,16773,405 2 3700
+u 14637,12330,405 0 3701
+v 13173,12330,405 0 3702
+w 19029,12330,405 0 3703
+x 13173,12330 0 3704
+y 13173,12330,5490 1 3705
+z 11709,12330 0 3706
+lC 13173,19935,6210 3 3707
+{ "
+ba 13173,19758,6588 3 3708
+| "
+rC 13173,19935,6210 3 3709
+} "
+ti 26346,9435 0 51876
+char192 19029,24795 2 3776
+`A "
+char194 19029,24795 2 3778
+^A "
+char200 17565,24795 2 3784
+`E "
+char202 17565,24795 2 3786
+^E "
+char203 17565,23955 2 3787
+:E "
+char206 10245,24795 2 3790
+^I "
+char207 10245,23955 2 3791
+:I "
+char180 13173,19065 2 3764
+aa "
+ga 13173,19065 2 3680
+a^ 13173,19065 2 3678
+^ "
+char168 13173,17820 2 3752
+ad "
+a~ 13173,17772 2 3710
+~ "
+char217 19029,24795,405 2 3801
+`U "
+char219 19029,24795,405 2 3803
+^U "
+char221 19029,24795 2 3805
+'Y "
+char253 13173,19065,5490 3 3837
+'y "
+char176 13173,18450 2 3760
+de "
+char199 19029,18450,5532 3 3783
+,C "
+char231 11709,12735,5661 1 3815
+,c "
+char209 19029,23892,405 2 3793
+~N "
+char241 14637,17772 2 3825
+~n "
+char161 8781,12672,5778 1 3745
+r! "
+char191 13173,12846,5604 1 3775
+r? "
+char164 13173,16089 0 3748
+Cs "
+char163 13173,18450,429 2 3747
+Po "
+char165 13173,18045 2 3749
+Ye "
+char167 13173,18450,3225 2 3751
+sc "
+Fn 13173,18540,5490 3 51871
+char162 13173,17682 2 3746
+ct "
+char226 13173,19065,405 2 3810
+^a "
+char234 11709,19065,405 2 3818
+^e "
+char244 13173,19065,405 2 3828
+^o "
+char251 14637,19065,405 2 3835
+^u "
+char225 13173,19065,405 2 3809
+'a "
+char233 11709,19065,405 2 3817
+'e "
+char243 13173,19065,405 2 3827
+'o "
+char250 14637,19065,405 2 3834
+'u "
+char224 13173,19065,405 2 3808
+`a "
+char232 11709,19065,405 2 3816
+`e "
+char242 13173,19065,405 2 3826
+`o "
+char249 14637,19065,405 2 3833
+`u "
+char228 13173,17820,405 2 3812
+:a "
+char235 11709,17820,405 2 3819
+:e "
+char246 13173,17820,405 2 3830
+:o "
+char252 14637,17820,405 2 3836
+:u "
+char197 19029,24750 2 3781
+oA "
+char238 7317,19065 2 3822
+^i "
+char216 20490,18450,405 2 3800
+/O "
+char198 27321,18045 2 3782
+AE "
+char229 13173,19020,405 2 3813
+oa "
+char237 7317,19065 2 3821
+'i "
+char248 13173,12750,405 0 3832
+/o "
+char230 19029,12735,405 0 3814
+ae "
+char196 19029,23955 2 3780
+:A "
+char236 7317,19065 2 3820
+`i "
+char214 20490,23955,405 2 3798
+:O "
+char220 19029,23955,405 2 3804
+:U "
+char201 17565,24795 2 3785
+'E "
+char239 7317,17820 2 3823
+:i "
+char223 14637,18492,405 2 3807
+ss "
+char212 20490,24795,405 2 3796
+^O "
+char193 19029,24795 2 3777
+'A "
+char195 19029,23892 2 3779
+~A "
+char227 13173,17772,405 2 3811
+~a "
+char208 19029,18045 2 3792
+-D "
+char240 13173,18090,405 2 3824
+Sd "
+char205 10245,24795 2 3789
+'I "
+char204 10245,24795 2 3788
+`I "
+char211 20490,24795,405 2 3795
+'O "
+char210 20490,24795,405 2 3794
+`O "
+char213 20490,23892,405 2 3797
+~O "
+char245 13173,17772,405 2 3829
+~o "
+vS 14637,24795,462 2 51795
+vs 10245,19065,411 2 51827
+char218 19029,24795,405 2 3802
+'U "
+:Y 19029,23955 2 51801
+char255 13173,17820,5490 3 3839
+:y "
+char222 16101,18045 2 3806
+TP "
+char254 14637,18090,5490 3 3838
+Tp "
+char181 14637,10800,5193 1 3765
+char182 13173,19635,4200 2 3766
+ps "
+char190 23418,18450,405 2 3774
+34 "
+\- 23418,9000 0 51757
+char188 23418,18450,405 2 3772
+14 "
+char189 23418,18450,405 2 3773
+12 "
+char170 13173,18450 2 3754
+Of "
+char186 13173,18450 2 3770
+Om "
+char171 11220,9861 0 3755
+Fo "
+char187 11220,9861 0 3771
+Fc "
+char177 23418,15975,2880 0 3761
+char166 13173,19083,5916 3 3750
+bb "
+char169 13173,19725 2 3753
+co "
+char172 23418,12210 0 3756
+no "
+char174 13173,19725 2 3758
+rg "
+char178 9270,18285 2 3762
+S2 "
+char179 9270,18285 2 3763
+S3 "
+char184 13173,0,5661 1 3768
+ac "
+char185 9270,18285 2 3769
+S1 "
+char215 23418,15033 0 3799
+char247 23418,14505 0 3831
+char183 8781,11274 0 3767
+fm 8781,18450 2 51873
+sd 13173,18450 2 51874
+dg 13173,18450,3075 2 51755
+tm 16101,17550 2 51796
+ah 13173,19065 2 51935
+ao 13173,19020 2 51930
+f/ 3417,18450,405 2 51759
+em 23418,7200 0 51789
+en 13173,7200 0 51790
+dd 13173,18450,3075 2 51773
+.i 7317,12330 0 51957
+aq 8781,18450 2 3623
+bu 13173,14226 0 51889
+'C 19029,24795,405 2 20166
+'c 11709,19065,405 2 20198
+lq 15126,18450 2 51838
+rq 15126,18450 2 51746
+Bq 15126,4134,4806 0 51772
+vz 11709,19065 2 51834
+fi 14637,18540 2 51881
+fl 14637,19116 2 51882
+ff 16587,18540 2 51883
+Fi 21954,18540 2 51884
+Fl 21954,19116 2 51885
+ij 15075,18450,5490 3 51958
+bq 8781,4134,4806 0 51756
+%0 30738,18237,405 2 51901
+char175 13173,17259 2 3759
+a- "
+ab 13173,18285 2 51926
+a. 13173,17820 2 51927
+oe 19515,12735,405 0 51823
+OE 29760,18450,405 2 51791
+fo 6831,9861 0 51886
+fc 6831,9861 0 51887
+sq 19029,15624 0 51899
+/L 17565,18045 2 51944
+/l 7317,18090 2 51960
+a" 13173,19065 2 51933
+ho 13173,513,4413 0 51934
+vZ 17565,24795 2 51802
+IJ 23904,18045,405 2 51942
diff --git a/font/devlj4/TBI b/font/devlj4/TBI
new file mode 100644
index 00000000..59300fe8
--- /dev/null
+++ b/font/devlj4/TBI
@@ -0,0 +1,1023 @@
+name TBI
+spacewidth 7806
+slant 15.300000
+pcltypeface 4101
+pclproportional 1
+pclweight 3
+pclstyle 1
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -2925
+P . -4389
+P , -4389
+V A -3903
+A V -4389
+T o -2439
+T r -975
+T c -2439
+T e -2439
+T d -1950
+T s -1461
+T y -975
+T a -2439
+T w -975
+T u -975
+T J -1950
+L T -2439
+L Y -2925
+Y o -3903
+Y e -3903
+Y a -3414
+Y J -1950
+A W -3903
+W A -3414
+T A -2439
+V o -3414
+V e -3414
+V a -3414
+Y A -2925
+F A -2439
+F . -3903
+F , -3903
+A T -2439
+A Y -3414
+v . -2439
+v , -2439
+y . -2439
+y , -2439
+T . -2439
+T , -2439
+L W -2925
+P A -2925
+V J -1950
+V . -3903
+V , -3903
+Y . -2925
+Y , -2925
+W o -2925
+W e -2925
+W a -2925
+W . -3414
+W , -3414
+r . -3414
+r , -3414
+w . -2439
+w , -2439
+Y u -2439
+A v -2439
+A y -2925
+A w -2439
+o . -1461
+o , -1461
+p . -1461
+p , -1461
+e . -975
+e , -975
+b . -1461
+b , -1461
+O T -1461
+O V -1950
+O Y -1950
+O . -2439
+O , -2439
+L y -975
+P J -2925
+V y -1950
+V u -1950
+V O -1950
+V G -1950
+V C -1950
+V Q -1950
+D T -1461
+D V -1950
+D Y -1950
+D . -2439
+D , -2439
+Y O -2439
+Y G -2439
+Y C -2439
+Y Q -2439
+F o -1461
+F e -1461
+F a -1461
+c . -975
+c , -975
+O A -975
+O W -1950
+R T -1461
+R V -1461
+R Y -1461
+R W -1461
+G T -1461
+P o -1461
+P g -1461
+P e -1461
+P a -1461
+C A -1461
+C . -2439
+C , -2439
+D A -975
+D W -1950
+B T -1461
+B Y -1950
+B . -1461
+B , -1461
+F J -1950
+A O -1950
+A G -1950
+A C -1950
+A U -1950
+A Q -1950
+W r -1950
+W y -1950
+W u -1950
+W O -1950
+W G -1950
+W C -1950
+W J -1950
+W Q -1950
+J A -975
+J . -975
+J , -975
+U A -975
+U . -1950
+U , -1950
+Q A -975
+Q W -1950
+f . -975
+f , -975
+T O -975
+T G -975
+T C -975
+T Q -975
+O X -1461
+G V -1461
+G Y -1461
+G W -1461
+G . -486
+G , -486
+P T -1461
+P V -1461
+P Y -1461
+C T -975
+C V -975
+C Y -975
+D X -1461
+B V -1950
+B X -1461
+B A -975
+B W -1950
+S . -975
+S , -975
+X o -1461
+X e -1461
+X y -1461
+X O -1461
+X G -1461
+X C -1461
+X Q -1461
+A o -1950
+A e -1950
+Q X -1461
+K o -1461
+K e -1461
+K y -1461
+K w -1461
+K O -1461
+K G -1461
+K C -1461
+K Q -1461
+o v -975
+o y -975
+o x -486
+o w -975
+h v -975
+h y -975
+n v -975
+n y -975
+m v -975
+m y -975
+r g -975
+g . -975
+g , -975
+p v -975
+p y -975
+p x -486
+c v -975
+c y -975
+c w -975
+v o -486
+v g -975
+v c -486
+v d -486
+v a -486
+v q -486
+e v -975
+e y -975
+b v -975
+b y -975
+b w -975
+s . -486
+s , -486
+y o -486
+y g -975
+y c -486
+y d -486
+y a -486
+y q -486
+f g -1461
+x o -486
+x g -486
+x c -486
+x e -486
+x d -486
+x a -486
+x q -486
+w o -486
+w g -975
+w c -486
+w d -486
+w a -486
+w q -486
+T i -975
+T S -975
+R o -486
+R y -486
+R O -486
+R G -486
+R C -486
+R U -486
+R Q -486
+G X -486
+G A -486
+P s -486
+P Z -486
+P X -1461
+P W -1461
+C X -975
+C W -975
+C J -1461
+V i -975
+V S -975
+S T -1461
+S V -1461
+S Y -1461
+S X -975
+S A -975
+S W -1461
+Y i -975
+Y S -975
+X a -486
+X u -975
+X S -486
+A t -486
+A g -486
+A c -1950
+A d -1461
+A a -486
+A u -975
+A q -975
+A S -486
+W i -975
+W S -975
+J y -1461
+K c -1461
+K u -975
+K S -486
+t g -486
+o f -975
+h w -975
+n w -975
+m w -975
+r o -486
+r c -486
+r e -486
+r d -486
+r a -486
+r q -486
+g g -975
+p f -975
+p w -975
+c f -975
+c x -486
+v e -486
+v s -486
+e f -975
+e x -486
+e w -975
+b f -975
+y e -486
+y s -486
+f o -975
+f c -975
+f e -975
+f d -975
+f s -486
+f a -975
+f q -975
+w e -486
+w s -486
+k o -486
+k g -486
+k c -486
+k e -486
+k d -486
+k a -486
+k q -486
+O Z -486
+O J -975
+R e -486
+R a -486
+R u -486
+R S -486
+G Z -486
+C Z -975
+E t -486
+E o -486
+E g -975
+E c -486
+E v -486
+E e -486
+E d -486
+E y -486
+E f -486
+E a -486
+E w -486
+E u -486
+E q -486
+E O -486
+E G -486
+E C -486
+E S -486
+E J -486
+E Q -486
+E . -486
+E , -486
+Z o -486
+Z e -486
+Z d -486
+Z y -975
+Z a -486
+Z w -975
+Z u -486
+Z O -486
+Z G -486
+Z C -486
+Z S -486
+Z Q -486
+D Z -486
+D J -975
+B Z -486
+B J -975
+S Z -486
+S J -975
+J o -975
+J i -975
+J e -975
+J a -975
+J u -975
+J T -975
+J O -975
+J H -975
+J N -975
+J M -975
+J L -975
+J R -975
+J G -975
+J I -975
+J P -975
+J C -975
+J V -975
+J E -975
+J Z -975
+J D -975
+J B -975
+J S -975
+J Y -975
+J F -975
+J X -975
+J W -975
+J J -975
+J U -975
+J Q -975
+J K -975
+U g -486
+U J -975
+K a -486
+o g -486
+o z -486
+h g -486
+h f -486
+n g -486
+n f -486
+m g -486
+m f -486
+l g -486
+r s -486
+g o -486
+g c -486
+g e -486
+g d -486
+g s -486
+g a -486
+g q -486
+i g -486
+p g -486
+p z -486
+c g -486
+c z -486
+v t -486
+v h -486
+v n -486
+v m -486
+v r -486
+v i -486
+v p -486
+v z -486
+v b -486
+v y -486
+v f -486
+v x -486
+v w -486
+v j -486
+v u -486
+v k -486
+e g -486
+e z -486
+z o -486
+z g -486
+z c -486
+z e -486
+z d -486
+z a -486
+z q -486
+d g -486
+b g -486
+b z -486
+s g -486
+y t -486
+y h -486
+y n -486
+y m -486
+y l -486
+y r -486
+y i -486
+y p -486
+y v -486
+y z -486
+y b -486
+y y -486
+y f -486
+y x -486
+y w -486
+y j -486
+y u -486
+y k -486
+a g -486
+w t -486
+w h -486
+w n -486
+w m -486
+w l -486
+w r -486
+w i -486
+w p -486
+w v -486
+w z -486
+w b -486
+w y -486
+w f -486
+w x -486
+w w -486
+w j -486
+w u -486
+w k -486
+j g -486
+u g -486
+q g -486
+O g -486
+M g -486
+G J -486
+I g -486
+C t -486
+C o -486
+C h -486
+C l -486
+C r -486
+C i -486
+C e -486
+C y -486
+C a -486
+C u -486
+C O -486
+C H -486
+C N -486
+C M -486
+C L -486
+C R -486
+C G -486
+C I -486
+C P -486
+C C -486
+C E -486
+C D -486
+C B -486
+C S -486
+C F -486
+C U -486
+C Q -486
+C K -486
+E n -486
+E m -486
+E l -486
+E r -486
+E i -486
+E p -486
+E z -486
+E b -486
+E s -486
+E x -486
+E j -486
+E k -486
+E T -486
+E H -486
+E N -486
+E M -486
+E L -486
+E R -486
+E I -486
+E P -486
+E V -486
+E E -486
+E Z -486
+E D -486
+E B -486
+E Y -486
+E F -486
+E X -486
+E A -486
+E W -486
+E U -486
+E K -486
+A f -486
+K T -486
+K V -486
+K Y -486
+K W -486
+K U -486
+L ' -2925
+T char173 -975
+T hy -975
+T - -975
+T en -975
+T em -975
+A ' -3414
+char173 T -1461
+hy T -1461
+- T -1461
+en T -1461
+em T -1461
+Y char173 -2439
+Y hy -2439
+Y - -2439
+Y en -2439
+Y em -2439
+p ' -1950
+c ' -1461
+e ' -1950
+b ' -1950
+V char173 -1950
+V hy -1950
+V - -1950
+V en -1950
+V em -1950
+h ' -975
+n ' -975
+m ' -975
+R ' -486
+W char173 -1950
+W hy -1950
+W - -1950
+W en -1950
+W em -1950
+' d -975
+X char173 -1461
+X hy -1461
+X - -1461
+X en -1461
+X em -1461
+A char173 -1950
+A hy -1950
+A - -1950
+A en -1950
+A em -1950
+K char173 -1461
+K hy -1461
+K - -1461
+K en -1461
+K em -1461
+' s -486
+char173 X -1461
+hy X -1461
+- X -1461
+char173 A -975
+hy A -975
+- A -975
+en X -1461
+en A -975
+em X -1461
+R char173 -486
+R hy -486
+R - -486
+R en -486
+R em -486
+K ' -486
+t g -486
+v ' -486
+b f -975
+y ' -486
+w ' -486
+C ' -486
+E ' -486
+E char173 -486
+E hy -486
+E - -486
+E en -486
+E em -486
+Z char173 -486
+Z hy -486
+Z - -486
+Z en -486
+Z em -486
+J ' -975
+J char173 -975
+J hy -975
+J - -975
+J en -975
+J em -975
+v char173 -486
+v hy -486
+v - -486
+v en -486
+v em -486
+y char173 -486
+y hy -486
+y - -486
+y en -486
+y em -486
+w char173 -486
+w hy -486
+w - -486
+w en -486
+w em -486
+C char173 -486
+C hy -486
+C - -486
+C en -486
+C em -486
+char173 g -486
+hy g -486
+- g -486
+en g -486
+em g -486
+charset
+! 10245,18450,405,963,-453,913 2 3617
+" 13662,18450,0,1380,-3414,913 2 3618
+sh 13173,18450,405,1902,270,913 2 3619
+# "
+Do 13173,19770,2295,1998,1053,913 2 3620
+$ "
+% 23418,18237,405,288,-1509,288 2 3621
+& 20490,18045,405,234,87,234 2 3622
+' 8781,18450,0,2001,-2790,913 2 51751
+( 8781,18450,4761,3096,-318,913 2 3624
+) 8781,18450,4761,846,1932,846 2 3625
+* 13173,18450,0,1518,-1812,913 2 3626
++ 23418,15975,0,0,-3105 0 3627
+, 8781,3612,4728,0,1515 0 3628
+char173 8781,7740,0,660,426,660 0 3629
+hy "
+- "
+. 8781,3645,405,0,129 0 3630
+sl 8781,18450,405,3012,1209,913 2 3631
+/ "
+0 13173,18450,405,1722,72,913 2 3632
+1 13173,18450,0,0,765 2 3633
+2 13173,18450,0,657,1419,657 2 3634
+3 13173,18450,405,702,1116,702 2 3635
+4 13173,18450,0,1953,1386,913 2 3636
+5 13173,18045,405,1845,855,913 2 3637
+6 13173,18450,405,2286,-9,913 2 3638
+7 13173,18045,0,2997,-969,913 2 3639
+8 13173,18450,405,1548,240,913 2 3640
+9 13173,18450,405,1572,705,913 2 3641
+: 8781,12360,405,0,408 0 3642
+; 8781,12360,4728,0,1515 0 3643
+< 26346,16068,0,0,-3981 0 3644
+= 23418,11370,0,0,-3300 0 3645
+> 26346,16068,0,0,-3981 0 3646
+? 13173,18450,405,1725,-1932,913 2 3647
+at 23418,16950,4131,1095,219,913 2 3648
+@ "
+A 17565,18450,0,546,2412,546 2 3649
+B 17565,18045,0,1257,1167,913 2 3650
+C 17565,18594,405,2331,-393,913 2 3651
+D 19029,18045,0,1707,1611,913 2 3652
+E 17565,18045,0,1974,1428,913 2 3653
+F 16101,18045,0,3384,1536,913 2 3654
+G 19029,18450,405,1863,-12,913 2 3655
+H 20490,18045,0,3006,1266,913 2 3656
+I 10245,18045,0,2997,1338,913 2 3657
+J 13173,18045,405,2652,1491,913 2 3658
+K 17565,18045,0,3312,1326,913 2 3659
+L 16101,18045,0,1188,1815,913 2 3660
+M 23418,18045,0,3132,1362,913 2 3661
+N 19029,18045,405,3270,1227,913 2 3662
+O 19029,18450,405,1503,-183,913 2 3663
+P 16101,18045,0,2490,1233,913 2 3664
+Q 18540,18450,5550,1902,-177,913 3 3665
+R 17565,18045,0,1260,1188,913 2 3666
+S 14637,18525,510,1452,543,913 2 3667
+T 16101,18045,0,3513,-963,913 2 3668
+U 19029,18045,405,3249,-1455,913 2 3669
+V 17565,18045,405,3771,-1356,913 2 3670
+W 23418,18045,405,3891,-1311,913 2 3671
+X 17565,18045,0,2883,1578,913 2 3672
+Y 16101,18045,0,3630,-1254,913 2 3673
+Z 16101,18045,0,1923,876,913 2 3674
+lB 8781,18045,4095,4575,2064,913 2 3675
+[ "
+rs 8781,18450,405,0,-2226 2 3676
+\ "
+rB 8781,18045,4095,2826,3813,913 2 3677
+] "
+ha 13173,19758,0,36,36,36 2 51875
+_ 13173,191367,6588,1317,1317,913 3 3679
+oq 8781,18450,0,2001,-2790,913 2 51808
+` "
+a 13173,12735,405,1059,1059,913 0 3681
+b 13173,18540,405,876,948,876 2 3682
+c 11709,12735,405,900,435,900 0 3683
+d 13173,18540,405,2541,1068,913 2 3684
+e 11709,12735,405,687,390,687 0 3685
+f 9270,18540,5490,4809,4866,913 3 3686
+g 13173,12735,5490,1500,1977,913 1 3687
+h 14637,18540,405,345,1146,345 2 3688
+i 7317,18585,405,1734,783,913 2 3689
+j 7317,18585,5490,2319,5745,913 3 3690
+k 13173,18540,405,1923,1194,913 2 3691
+l 7317,18540,405,2166,843,913 2 3692
+m 20490,12735,405,630,1101,630 0 3693
+n 14637,12735,405,321,954,321 0 3694
+o 13173,12735,405,675,714,675 0 3695
+p 13173,12735,5490,843,3888,843 1 3696
+q 13173,12735,5490,1317,672,913 1 3697
+r 10245,12783,0,2421,1005,913 0 3698
+s 10245,12735,405,885,891,885 0 3699
+t 7317,15870,405,2289,1056,913 0 3700
+u 14637,12735,405,426,279,426 0 3701
+v 11709,12735,405,1068,153,913 0 3702
+w 17565,12735,405,822,75,822 0 3703
+x 13173,12735,405,1137,1836,913 0 3704
+y 11709,12735,5490,543,3189,543 1 3705
+z 10245,12330,1935,1404,1839,913 0 3706
+lC 13173,19935,6210,3339,-972,913 3 3707
+{ "
+ba 13173,19758,6588,0,-4596 3 3708
+| "
+rC 13173,19935,6210,63,2304,63 3 3709
+} "
+ti 26346,9435,0,0,-4029 0 51876
+char192 17565,24795,0,546,2412,546 2 3776
+`A "
+char194 17565,24795,0,546,2412,546 2 3778
+^A "
+char200 17565,24795,0,1974,1428,913 2 3784
+`E "
+char202 17565,24795,0,1974,1428,913 2 3786
+^E "
+char203 17565,23955,0,1974,1428,913 2 3787
+:E "
+char206 10245,24795,0,3930,1338,913 2 3790
+^I "
+char207 10245,23955,0,4875,1338,913 2 3791
+:I "
+char180 13173,19065,0,786,-5055,786 2 3764
+aa "
+ga 13173,19065,0,0,-3540 2 3680
+a^ 13173,19065,0,417,-2931,417 2 3678
+^ "
+char168 13173,17820,0,1179,-2964,913 2 3752
+ad "
+a~ 13173,17703,0,1884,-3213,913 2 3710
+~ "
+char217 19029,24795,405,3249,-1455,913 2 3801
+`U "
+char219 19029,24795,405,3249,-1455,913 2 3803
+^U "
+char221 16101,24795,0,3630,-1254,913 2 3805
+'Y "
+char253 11709,19065,5490,1518,3189,913 3 3837
+'y "
+char176 13173,18450,0,111,-2970,111 2 3760
+de "
+char199 17565,18594,5718,2331,-393,913 3 3783
+,C "
+char231 11709,12735,5655,900,1278,900 1 3815
+,c "
+char209 19029,23733,405,3270,1227,913 2 3793
+~N "
+char241 14637,17703,405,1152,954,913 2 3825
+~n "
+char161 10245,13050,5805,0,855 1 3745
+r! "
+char191 13173,13050,5805,0,1680 1 3775
+r? "
+char164 13173,15834,0,2598,795,913 0 3748
+Cs "
+char163 13173,18450,429,2508,1473,913 2 3747
+Po "
+char165 13173,18045,0,5067,834,913 2 3749
+Ye "
+char167 13173,18450,3225,0,-597 2 3751
+sc "
+Fn 13173,18540,5490,2607,3165,913 3 51871
+char162 13173,16914,0,1431,-684,913 2 3746
+ct "
+char226 13173,19065,405,1059,1059,913 2 3810
+^a "
+char234 11709,19065,405,1149,390,913 2 3818
+^e "
+char244 13173,19065,405,675,714,675 2 3828
+^o "
+char251 14637,19065,405,426,279,426 2 3835
+^u "
+char225 13173,19065,405,1059,1059,913 2 3809
+'a "
+char233 11709,19065,405,1518,390,913 2 3817
+'e "
+char243 13173,19065,405,786,714,786 2 3827
+'o "
+char250 14637,19065,405,426,279,426 2 3834
+'u "
+char224 13173,19065,405,1059,1059,913 2 3808
+`a "
+char232 11709,19065,405,687,390,687 2 3816
+`e "
+char242 13173,19065,405,675,714,675 2 3826
+`o "
+char249 14637,19065,405,426,279,426 2 3833
+`u "
+char228 13173,17820,405,1179,1059,913 2 3812
+:a "
+char235 11709,17820,405,1911,390,913 2 3819
+:e "
+char246 13173,17820,405,1179,714,913 2 3830
+:o "
+char252 14637,17820,405,447,279,447 2 3836
+:u "
+char197 17565,24750,0,546,2412,546 2 3781
+oA "
+char238 7317,19065,405,3345,723,913 2 3822
+^i "
+char216 19029,18450,405,3702,2070,913 2 3800
+/O "
+char198 24396,18045,0,2730,2331,913 2 3782
+AE "
+char229 13173,19020,405,1059,1059,913 2 3813
+oa "
+char237 7317,19065,405,3714,723,913 2 3821
+'i "
+char248 13173,12735,405,2199,2256,913 0 3832
+/o "
+char230 18540,12735,405,876,1074,876 0 3814
+ae "
+char196 17565,23955,0,765,2412,765 2 3780
+:A "
+char236 7317,19065,405,1749,723,913 2 3820
+`i "
+char214 19029,23955,405,1503,-183,913 2 3798
+:O "
+char220 19029,23955,405,3249,-1455,913 2 3804
+:U "
+char201 17565,24795,0,1974,1428,913 2 3785
+'E "
+char239 7317,17820,405,4107,723,913 2 3823
+:i "
+char223 13173,18540,5490,1572,5862,913 3 3807
+ss "
+char212 19029,24795,405,1503,-183,913 2 3796
+^O "
+char193 17565,24795,0,567,2412,567 2 3777
+'A "
+char195 17565,23733,0,966,2412,913 2 3779
+~A "
+char227 13173,17703,405,1884,1059,913 2 3811
+~a "
+char208 19029,18045,0,1707,1611,913 2 3792
+-D "
+char240 13173,18540,405,2235,708,913 2 3824
+Sd "
+char205 10245,24795,0,4227,1338,913 2 3789
+'I "
+char204 10245,24795,0,2997,1338,913 2 3788
+`I "
+char211 19029,24795,405,1503,-183,913 2 3795
+'O "
+char210 19029,24795,405,1503,-183,913 2 3794
+`O "
+char213 19029,23733,405,1503,-183,913 2 3797
+~O "
+char245 13173,17703,405,1884,714,913 2 3829
+~o "
+vS 14637,24798,510,2061,543,913 2 51795
+vs 10245,19065,405,2856,891,913 2 51827
+char218 19029,24795,405,3249,-1455,913 2 3802
+'U "
+:Y 16101,23955,0,3630,-1254,913 2 51801
+char255 11709,17820,5490,1311,3189,913 3 3839
+:y "
+char222 16101,18045,0,1203,1227,913 2 3806
+TP "
+char254 13173,18540,5490,843,3888,843 3 3838
+Tp "
+char181 14637,10800,5193,582,756,582 1 3765
+char182 13173,19635,4200,1350,-1008,913 2 3766
+ps "
+char190 23418,18450,405,0,-1899 2 3774
+34 "
+\- 23418,9000,0,0,-3315 0 51757
+char188 23418,18450,405,0,-1572 2 3772
+14 "
+char189 23418,18450,405,0,-1311 2 3773
+12 "
+char170 13173,18450,0,1368,-2397,913 2 3754
+Of "
+char186 13173,18450,0,744,-2295,744 2 3770
+Om "
+char171 11709,10200,0,1158,567,913 0 3755
+Fo "
+char187 11709,10200,0,615,1110,615 0 3771
+Fc "
+char177 23418,15975,2880,0,-2883 0 3761
+char166 13173,19083,5916,0,-4596 3 3750
+bb "
+char169 13173,19725,0,4398,-2574,913 2 3753
+co "
+char172 23418,12225,0,0,-4023 0 3756
+no "
+char174 13173,19725,0,4398,-2574,913 2 3758
+rg "
+char178 8781,18285,0,1911,-213,913 2 3762
+S2 "
+char179 8781,18285,0,1980,-552,913 2 3763
+S3 "
+char184 13173,0,5655,0,546 1 3768
+ac "
+char185 8781,18285,0,1173,-471,913 2 3769
+S1 "
+char215 23418,15033,0,0,-3690 0 3799
+char247 23418,14505,0,0,-3327 0 3831
+char183 8781,11121,0,0,-1899 0 3767
+fm 8781,18450,0,930,-3342,913 2 51873
+sd 13173,18450,0,873,-3342,873 2 51874
+dg 13173,18450,3075,1344,-1188,913 2 51755
+tm 16101,17550,0,4884,-2535,913 2 51796
+ah 13173,19065,0,1392,-3906,913 2 51935
+ao 13173,19020,0,0,-4269 2 51930
+f/ 3402,18450,405,8832,6945,913 2 51759
+em 23418,7200,0,609,459,609 0 51789
+en 13173,7200,0,624,459,624 0 51790
+dd 13173,18450,3075,939,-783,913 2 51773
+.i 7317,12735,405,825,723,825 0 51957
+aq 8781,18450,0,1065,-3147,913 2 3623
+bu 13173,14226,0,0,-498 0 51889
+'C 17565,24795,405,2331,-393,913 2 20166
+'c 11709,19065,405,1518,435,913 2 20198
+lq 14148,18450,0,1974,-2790,913 2 51838
+rq 14148,18450,0,1974,-2790,913 2 51746
+Bq 14148,3651,4689,0,1425 0 51772
+vz 10245,19065,1935,2856,1839,913 2 51834
+fi 15126,18540,5490,726,5055,726 3 51881
+fl 15126,18540,5490,2328,5034,913 3 51882
+ff 15126,18540,5490,5574,5268,913 3 51883
+Fi 21954,18540,5490,738,5223,738 3 51884
+Fl 21954,18540,5490,1959,5583,913 3 51885
+ij 14148,18585,5490,2271,783,913 3 51958
+bq 8781,3651,4689,0,510 0 51756
+%0 32202,18237,405,612,-1122,612 2 51901
+char175 13173,16860,0,1341,-2904,913 2 3759
+a- "
+ab 13173,18570,0,1281,-3690,913 2 51926
+a. 13173,17820,0,0,-5589 2 51927
+oe 19515,12735,405,462,462,462 0 51823
+OE 28299,18450,405,1695,-156,913 2 51791
+fo 7317,10200,0,1035,567,913 0 51886
+fc 7317,10200,0,618,984,618 0 51887
+sq 19029,15624,0,0,-2022 0 51899
+/L 16101,18045,0,1188,1815,913 2 51944
+/l 7317,18540,405,2622,1539,913 2 51960
+a" 13173,19065,0,4053,-3627,913 2 51933
+ho 13173,681,3249,420,-4389,420 0 51934
+vZ 16101,24798,0,1923,876,913 2 51802
+IJ 23418,18045,405,2652,1338,913 2 51942
diff --git a/font/devlj4/TI b/font/devlj4/TI
new file mode 100644
index 00000000..ee43c0bc
--- /dev/null
+++ b/font/devlj4/TI
@@ -0,0 +1,1106 @@
+name TI
+spacewidth 7806
+slant 15.600000
+pcltypeface 4101
+pclproportional 1
+pclweight 0
+pclstyle 1
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -1950
+P . -4389
+P , -4389
+V A -2925
+A V -2925
+T o -1950
+T r -486
+T c -1461
+T e -1950
+T d -1950
+T s -975
+T y -486
+T a -1950
+T w -486
+T u -486
+T J -1461
+L T -1950
+L Y -1950
+Y o -3414
+Y e -3414
+Y a -3414
+Y J -1461
+A W -2925
+W A -3414
+T A -2439
+V o -1950
+V e -1950
+V a -1950
+Y A -2439
+F A -3903
+F . -3903
+F , -3903
+A T -2439
+A Y -2439
+v . -2439
+v , -2439
+y . -2439
+y , -2439
+T . -2439
+T , -2439
+L W -1950
+P A -3414
+V J -1461
+V . -3903
+V , -3903
+Y . -2439
+Y , -2439
+W o -2439
+W e -2439
+W a -2439
+W . -3903
+W , -3903
+r . -2439
+r , -2439
+w . -2439
+w , -2439
+Y u -1950
+A v -2439
+A y -2439
+A w -2439
+o . -1461
+o , -1461
+p . -1461
+p , -1461
+e . -975
+e , -975
+b . -1461
+b , -1461
+O T -486
+O V -1461
+O Y -1950
+O . -2439
+O , -2439
+L y -975
+P J -1950
+V y -1950
+V u -1950
+V O -1950
+V G -1950
+V C -1950
+V Q -1950
+D T -486
+D V -1461
+D Y -1950
+D . -2439
+D , -2439
+Y O -1950
+Y G -1950
+Y C -1950
+Y Q -1950
+F o -2925
+F e -2925
+F a -2925
+c . -975
+c , -975
+O A -975
+O W -1461
+L U -486
+R T -1461
+R V -1461
+R Y -1461
+R W -1461
+G T -486
+P o -2439
+P g -2439
+P e -2439
+P a -2439
+C A -975
+C . -975
+C , -975
+D A -975
+D W -1461
+B T -975
+B Y -2439
+B . -1950
+B , -1950
+F J -1461
+A O -1461
+A G -1461
+A C -1461
+A U -1950
+A Q -1461
+W r -2439
+W y -2439
+W u -2439
+W O -2439
+W G -2439
+W C -2439
+W J -1461
+W Q -2439
+J A -1461
+J . -1461
+J , -1461
+U A -1461
+U . -2439
+U , -2439
+Q A -975
+Q W -1461
+f . -486
+f , -486
+T O -486
+T G -486
+T C -486
+T Q -486
+O X -1461
+G V -1461
+G Y -1950
+G W -1461
+G . -975
+G , -975
+P T -486
+P V -486
+P Y -486
+C T -486
+C V -486
+C Y -486
+D X -1461
+B V -1950
+B X -1950
+B A -1461
+B W -1950
+S . -486
+S , -486
+F r -1950
+F y -1950
+F u -1950
+F O -1950
+F G -1950
+F C -1950
+F Q -1950
+X o -1950
+X e -1950
+X y -1950
+X O -1950
+X G -1950
+X C -1950
+X Q -1950
+A o -1461
+A e -1461
+Q X -1461
+K o -1950
+K e -1950
+K y -1950
+K w -1950
+K O -1950
+K G -1950
+K C -1950
+K Q -1950
+o v -975
+o y -975
+o x -486
+o w -975
+h v -975
+h y -975
+n v -975
+n y -975
+m v -975
+m y -975
+r g -1461
+g . -486
+g , -486
+p v -975
+p y -975
+p x -486
+c v -975
+c y -975
+c w -975
+v o -486
+v g -975
+v c -486
+v d -486
+v a -486
+v q -486
+e v -975
+e y -975
+b v -975
+b y -975
+b w -975
+s . -486
+s , -486
+y o -486
+y g -975
+y c -486
+y d -486
+y a -486
+y q -486
+f g -486
+x o -486
+x g -486
+x c -486
+x e -486
+x d -486
+x a -486
+x q -486
+w o -486
+w g -975
+w c -486
+w d -486
+w a -486
+w q -486
+T i -486
+T S -486
+R o -975
+R y -1461
+R O -975
+R G -975
+R C -975
+R U -1461
+R Q -975
+G X -975
+G A -975
+P s -1461
+P Z -486
+P X -486
+P W -486
+C X -486
+C W -486
+V i -486
+V S -486
+S T -486
+S V -1461
+S Y -1461
+S X -486
+S A -486
+S W -1461
+Y i -486
+Y S -486
+X a -975
+X u -975
+X S -486
+A t -975
+A g -486
+A c -1461
+A d -1461
+A a -975
+A u -975
+A q -1461
+A S -1461
+W i -486
+W S -486
+J y -486
+K c -1461
+K u -975
+K S -975
+t g -975
+t . -486
+t , -486
+o f -486
+h w -975
+n w -975
+m w -975
+r o -975
+r c -975
+r e -975
+r d -975
+r a -975
+r q -975
+g g -975
+p f -486
+p w -975
+c f -486
+c x -486
+v e -486
+v s -486
+e f -486
+e x -486
+e w -975
+b f -486
+y e -486
+y s -486
+w e -486
+w s -486
+k g -486
+k v -975
+k y -975
+k w -975
+R e -975
+R a -975
+R u -975
+R S -975
+P t -975
+P h -486
+P n -975
+P l -486
+P r -975
+P i -975
+P y -975
+P u -975
+P O -975
+P H -486
+P N -486
+P M -486
+P L -486
+P R -486
+P G -975
+P I -486
+P P -486
+P C -975
+P E -486
+P D -486
+P B -486
+P S -975
+P F -486
+P U -975
+P Q -975
+P K -486
+E t -975
+E o -975
+E g -975
+E c -975
+E v -975
+E e -975
+E d -975
+E y -975
+E f -975
+E a -975
+E w -975
+E u -975
+E q -975
+E O -975
+E G -975
+E C -975
+E S -975
+E J -486
+E Q -975
+E . -486
+E , -486
+B Z -486
+B J -486
+F i -486
+F j -486
+F S -486
+J o -486
+J i -486
+J e -486
+J a -486
+J u -486
+J T -486
+J O -486
+J H -486
+J N -486
+J M -486
+J L -486
+J R -486
+J G -486
+J I -486
+J P -486
+J C -486
+J V -486
+J E -486
+J Z -486
+J D -486
+J B -486
+J S -486
+J Y -486
+J F -486
+J X -486
+J W -486
+J J -486
+J U -975
+J Q -486
+J K -486
+U g -975
+U J -486
+K a -975
+t o -486
+t c -486
+t e -486
+t d -486
+t s -486
+t a -486
+t q -486
+o g -486
+o z -486
+h g -486
+h f -486
+n g -486
+n f -486
+m g -486
+m f -486
+l g -486
+r s -486
+g o -486
+g c -486
+g e -486
+g d -486
+g s -486
+g a -486
+g q -486
+i g -486
+p g -486
+p z -486
+c g -486
+c z -486
+v t -486
+v h -486
+v n -486
+v m -486
+v r -486
+v i -486
+v p -486
+v z -486
+v b -486
+v y -486
+v f -486
+v x -486
+v w -486
+v j -486
+v u -486
+v k -486
+e g -486
+e z -486
+z o -486
+z g -486
+z c -486
+z e -486
+z d -486
+z a -486
+z q -486
+d g -486
+b g -486
+b z -486
+s g -486
+y t -486
+y h -486
+y n -486
+y m -486
+y l -486
+y r -486
+y i -486
+y p -486
+y v -486
+y z -486
+y b -486
+y y -486
+y f -486
+y x -486
+y w -486
+y j -486
+y u -486
+y k -486
+a g -486
+w t -486
+w h -486
+w n -486
+w m -486
+w l -486
+w r -486
+w i -486
+w p -486
+w v -486
+w z -486
+w b -486
+w y -486
+w f -486
+w x -486
+w w -486
+w j -486
+w u -486
+w k -486
+j g -486
+u g -486
+q g -486
+k f -486
+T U -486
+O g -486
+M g -486
+I g -486
+C U -486
+V U -486
+E n -486
+E m -486
+E l -486
+E r -486
+E i -486
+E p -486
+E z -486
+E b -486
+E s -486
+E x -486
+E j -486
+E k -486
+E T -486
+E H -486
+E N -486
+E M -486
+E L -486
+E R -486
+E I -486
+E P -486
+E V -486
+E E -486
+E Z -486
+E D -486
+E B -486
+E Y -486
+E F -486
+E X -486
+E A -486
+E W -486
+E U -975
+E K -486
+B o -486
+B h -486
+B l -486
+B r -486
+B i -486
+B e -486
+B y -486
+B a -486
+B u -486
+B O -486
+B H -486
+B N -486
+B M -486
+B L -486
+B R -486
+B G -486
+B I -486
+B P -486
+B C -486
+B E -486
+B D -486
+B B -486
+B S -486
+B F -486
+B U -975
+B Q -486
+B K -486
+Y U -486
+F U -486
+X U -486
+A b -486
+A f -486
+W U -486
+U t -486
+U o -486
+U h -486
+U n -486
+U m -486
+U l -486
+U r -486
+U i -486
+U p -486
+U c -486
+U v -486
+U e -486
+U z -486
+U d -486
+U b -486
+U s -486
+U y -486
+U f -486
+U x -486
+U a -486
+U w -486
+U j -486
+U q -486
+U k -486
+U T -486
+U O -486
+U H -486
+U N -486
+U M -486
+U L -486
+U R -486
+U G -486
+U I -486
+U P -486
+U C -486
+U V -486
+U E -486
+U Z -486
+U D -486
+U B -486
+U S -486
+U Y -486
+U F -486
+U X -486
+U W -486
+U U -975
+U Q -486
+U K -486
+K T -486
+K V -486
+K Y -486
+K W -486
+K U -975
+L ' -1950
+T char173 -486
+T hy -486
+T - -486
+T en -486
+T em -486
+A ' -2439
+char173 T -486
+hy T -486
+- T -486
+en T -486
+em T -486
+Y char173 -1950
+Y hy -1950
+Y - -1950
+Y en -1950
+Y em -1950
+p ' -1950
+c ' -1461
+e ' -1950
+b ' -1950
+V char173 -1950
+V hy -1950
+V - -1950
+V en -1950
+V em -1950
+h ' -975
+n ' -975
+m ' -975
+R ' -1461
+W char173 -2439
+W hy -2439
+W - -2439
+W en -2439
+W em -2439
+' d -1461
+F char173 -1950
+F hy -1950
+F - -1950
+F en -1950
+F em -1950
+X char173 -1950
+X hy -1950
+X - -1950
+X en -1950
+X em -1950
+A char173 -1461
+A hy -1461
+A - -1461
+A en -1461
+A em -1461
+K char173 -1950
+K hy -1950
+K - -1950
+K en -1950
+K em -1950
+' s -486
+char173 X -1461
+hy X -1461
+- X -1461
+char173 A -975
+hy A -975
+- A -975
+en X -1461
+en A -975
+em X -1461
+R char173 -975
+R hy -975
+R - -975
+R en -975
+R em -975
+K ' -486
+t g -975
+v ' -486
+b f -486
+y ' -486
+w ' -486
+k ' -975
+P ' -486
+P char173 -975
+P hy -975
+P - -975
+P en -975
+P em -975
+E ' -486
+E char173 -975
+E hy -975
+E - -975
+E en -975
+E em -975
+B ' -486
+J ' -486
+J char173 -486
+J hy -486
+J - -486
+J en -486
+J em -486
+U ' -486
+v char173 -486
+v hy -486
+v - -486
+v en -486
+v em -486
+y char173 -486
+y hy -486
+y - -486
+y en -486
+y em -486
+w char173 -486
+w hy -486
+w - -486
+w en -486
+w em -486
+B char173 -486
+B hy -486
+B - -486
+B en -486
+B em -486
+U char173 -486
+U hy -486
+U - -486
+U en -486
+U em -486
+char173 g -486
+hy g -486
+- g -486
+en g -486
+em g -486
+charset
+! 8781,18225,330,1170,-693,899 2 3617
+" 12684,18225,0,945,-4194,899 2 3618
+sh 13173,18225,687,2103,-75,899 2 3619
+# "
+Do 13173,19686,2730,1710,507,899 2 3620
+$ "
+% 23418,18894,1026,0,-3054 2 3621
+& 20490,18225,330,0,-321 2 3622
+' 8781,18225,0,1434,-3582,899 2 51751
+( 8781,18225,4845,3531,-2058,899 2 3624
+) 8781,18225,4845,0,2067 2 3625
+* 13173,18225,0,927,-1581,899 2 3626
++ 23418,15750,0,0,-2994 0 3627
+, 8781,2835,3360,0,648 0 3628
+char173 8781,7155,0,468,153,468 0 3629
+hy "
+- "
+. 8781,2685,330,0,-633 0 3630
+sl 8781,18225,330,3183,801,899 2 3631
+/ "
+0 13173,18225,330,1938,237,899 2 3632
+1 13173,18225,0,0,165 2 3633
+2 13173,18225,0,876,567,876 2 3634
+3 13173,18225,330,1020,645,899 2 3635
+4 13173,18225,0,1773,618,899 2 3636
+5 13173,17895,330,1362,1008,899 2 3637
+6 13173,18480,330,2085,147,899 2 3638
+7 13173,17895,330,4029,-1494,899 2 3639
+8 13173,18225,330,1827,306,899 2 3640
+9 13173,18225,570,1785,447,899 2 3641
+: 8781,11988,330,501,-633,501 0 3642
+; 8781,11988,3360,0,1074 0 3643
+< 26346,16068,0,0,-3981 0 3644
+= 23418,10875,0,0,-3183 0 3645
+> 26346,16068,0,0,-3981 0 3646
+? 13173,18225,330,1362,-2850,899 2 3647
+at 23418,16980,3654,750,-228,750 2 3648
+@ "
+A 16101,18225,0,33,2700,33 2 3649
+B 16101,17895,0,1116,1701,899 2 3650
+C 17565,18225,330,2700,-873,899 2 3651
+D 19029,17895,0,594,2298,594 2 3652
+E 16101,17895,0,2091,1800,899 2 3653
+F 15126,17895,0,3180,1725,899 2 3654
+G 19029,18225,330,2301,-606,899 2 3655
+H 19029,17895,0,3057,1614,899 2 3656
+I 8781,17895,0,3165,1716,899 2 3657
+J 11709,17895,330,2847,1797,899 2 3658
+K 17565,17895,0,3273,1425,899 2 3659
+L 14637,17895,0,1023,2487,899 2 3660
+M 21954,17895,0,2712,1983,899 2 3661
+N 17565,17895,330,3843,1578,899 2 3662
+O 19029,18225,330,1356,-492,899 2 3663
+P 16101,17895,0,1950,1116,899 2 3664
+Q 19029,18225,4761,1215,-351,899 2 3665
+R 16101,17895,0,1041,1926,899 2 3666
+S 13173,18225,330,2190,609,899 2 3667
+T 14637,17895,0,3939,-90,899 2 3668
+U 19029,17895,330,3246,-1635,899 2 3669
+V 16101,17895,330,4185,-1170,899 2 3670
+W 21954,17895,330,4353,-822,899 2 3671
+X 16101,17895,0,3276,2067,899 2 3672
+Y 14637,17895,0,4533,-1086,899 2 3673
+Z 14637,17895,0,2856,1710,899 2 3674
+lB 8781,17895,4380,4026,1575,899 2 3675
+[ "
+rs 8781,18225,330,0,-2229 2 3676
+\ "
+rB 8781,17895,4380,1938,3663,899 2 3677
+] "
+ha 13173,19758,0,36,36,36 2 51875
+_ 13173,191367,6588,1317,1317,899 3 3679
+oq 8781,18225,0,1422,-3570,899 2 51808
+` "
+a 13173,12669,330,759,1044,759 0 3681
+b 13173,18300,330,732,1038,732 2 3682
+c 11709,12669,330,1275,318,899 0 3683
+d 13173,18300,330,2283,1065,899 2 3684
+e 11709,12669,330,1011,444,899 0 3685
+f 7317,18300,5655,5346,5535,899 3 3686
+g 13173,12669,5655,813,1281,813 1 3687
+h 13173,18300,330,750,1188,750 2 3688
+i 7317,18369,330,1002,435,899 2 3689
+j 7317,18369,5655,1212,5187,899 3 3690
+k 11709,18300,330,1941,1422,899 2 3691
+l 7317,18300,330,1731,276,899 2 3692
+m 19029,12669,330,1080,1098,899 0 3693
+n 13173,12669,330,786,1053,786 0 3694
+o 13173,12669,330,771,732,771 0 3695
+p 13173,12669,5655,471,3981,471 1 3696
+q 13173,12669,5655,1377,651,899 1 3697
+r 10245,12669,0,2094,429,899 0 3698
+s 10245,12669,330,786,1116,786 0 3699
+t 7317,15339,330,1908,672,899 0 3700
+u 13173,12669,330,747,468,747 0 3701
+v 11709,12684,330,1404,399,899 0 3702
+w 17565,12669,330,1461,720,899 0 3703
+x 11709,12669,330,1134,2592,899 0 3704
+y 11709,12669,5655,561,2538,561 1 3705
+z 10245,12339,2163,1122,1815,899 0 3706
+lC 11709,19935,6210,3360,-1692,899 3 3707
+{ "
+ba 13173,19758,6588,0,-4596 3 3708
+| "
+rC 11709,19935,6210,0,2232 3 3709
+} "
+ti 26346,8952,0,0,-4029 0 51876
+char192 16101,23955,0,33,2700,33 2 3776
+`A "
+char194 16101,23955,0,1314,2700,899 2 3778
+^A "
+char200 16101,23955,0,2091,1800,899 2 3784
+`E "
+char202 16101,23955,0,2091,1800,899 2 3786
+^E "
+char203 16101,23085,0,2091,1800,899 2 3787
+:E "
+char206 8781,23955,0,3984,1716,899 2 3790
+^I "
+char207 8781,23085,0,4665,1716,899 2 3791
+:I "
+char180 13173,18399,0,141,-5400,141 2 3764
+aa "
+ga 13173,18399,0,0,-4314 2 3680
+a^ 13173,18399,0,0,-3453 2 3678
+^ "
+char168 13173,17124,0,624,-4002,624 2 3752
+ad "
+a~ 13173,17145,0,990,-3309,899 2 3710
+~ "
+char217 19029,23955,330,3246,-1635,899 2 3801
+`U "
+char219 19029,23955,330,3246,-1635,899 2 3803
+^U "
+char221 14637,23955,0,4533,-1086,899 2 3805
+'Y "
+char253 11709,18399,5655,561,2538,561 3 3837
+'y "
+char176 13173,18225,0,543,-3522,543 2 3760
+de "
+char199 17565,18225,5019,2700,-873,899 2 3783
+,C "
+char231 11709,12669,4785,1275,636,899 0 3815
+,c "
+char209 17565,23079,330,3843,1578,899 2 3793
+~N "
+char241 13173,17145,330,990,1053,899 2 3825
+~n "
+char161 8781,12231,6324,33,444,33 1 3745
+r! "
+char191 13173,12312,6243,0,663 1 3775
+r? "
+char164 13173,15684,0,1779,228,899 0 3748
+Cs "
+char163 13173,17895,330,3153,1971,899 2 3747
+Po "
+char165 13173,17895,0,4170,-15,899 2 3749
+Ye "
+char167 13173,18225,4200,447,-1359,447 2 3751
+sc "
+Fn 13173,18300,5655,2388,2691,899 3 51871
+char162 13173,17034,0,996,-777,899 2 3746
+ct "
+char226 13173,18399,330,759,1044,759 2 3810
+^a "
+char234 11709,18399,330,1761,444,899 2 3818
+^e "
+char244 13173,18399,330,771,732,771 2 3828
+^o "
+char251 13173,18399,330,747,468,747 2 3835
+^u "
+char225 13173,18399,330,759,1044,759 2 3809
+'a "
+char233 11709,18399,330,1011,444,899 2 3817
+'e "
+char243 13173,18399,330,771,732,771 2 3827
+'o "
+char250 13173,18399,330,747,468,747 2 3834
+'u "
+char224 13173,18399,330,759,1044,759 2 3808
+`a "
+char232 11709,18399,330,1011,444,899 2 3816
+`e "
+char242 13173,18399,330,771,732,771 2 3826
+`o "
+char249 13173,18399,330,747,468,747 2 3833
+`u "
+char228 13173,17124,330,759,1044,759 2 3812
+:a "
+char235 11709,17124,330,1356,444,899 2 3819
+:e "
+char246 13173,17124,330,1074,732,899 2 3830
+:o "
+char252 13173,17124,330,747,468,747 2 3836
+:u "
+char197 16101,23865,0,525,2700,525 2 3781
+oA "
+char238 7317,18399,330,2907,420,899 2 3822
+^i "
+char216 19029,18255,330,2082,234,899 2 3800
+/O "
+char198 23418,17895,0,2961,1959,899 2 3782
+AE "
+char229 13173,18309,330,759,1044,759 2 3813
+oa "
+char237 7317,18399,330,3069,420,899 2 3821
+'i "
+char248 13173,12738,336,1491,1443,899 0 3832
+/o "
+char230 17565,12669,330,933,771,899 0 3814
+ae "
+char196 16101,23085,0,2055,2700,899 2 3780
+:A "
+char236 7317,18399,330,1383,420,899 2 3820
+`i "
+char214 19029,23085,330,1356,-492,899 2 3798
+:O "
+char220 19029,23085,330,3246,-1635,899 2 3804
+:U "
+char201 16101,23955,0,2091,1800,899 2 3785
+'E "
+char239 7317,17124,330,3552,420,899 2 3823
+:i "
+char223 13173,18300,5655,1131,5829,899 3 3807
+ss "
+char212 19029,23955,330,1356,-492,899 2 3796
+^O "
+char193 16101,23955,0,1914,2700,899 2 3777
+'A "
+char195 16101,23079,0,2580,2700,899 2 3779
+~A "
+char227 13173,17145,330,990,1044,899 2 3811
+~a "
+char208 19029,17895,0,594,2298,594 2 3792
+-D "
+char240 13173,18300,330,2040,732,899 2 3824
+Sd "
+char205 8781,23955,0,5124,1716,899 2 3789
+'I "
+char204 8781,23955,0,3165,1716,899 2 3788
+`I "
+char211 19029,23955,330,1356,-492,899 2 3795
+'O "
+char210 19029,23955,330,1356,-492,899 2 3794
+`O "
+char213 19029,23079,330,1356,-492,899 2 3797
+~O "
+char245 13173,17145,330,1665,732,899 2 3829
+~o "
+vS 13173,23955,330,2268,609,899 2 51795
+vs 10245,18399,330,2472,1116,899 2 51827
+char218 19029,23955,330,3246,-1635,899 2 3802
+'U "
+:Y 14637,23085,0,4533,-1086,899 2 51801
+char255 11709,17124,5655,561,2538,561 3 3839
+:y "
+char222 16101,17895,0,813,1107,813 2 3806
+TP "
+char254 13173,18300,5655,471,3981,471 3 3838
+Tp "
+char181 14637,10800,5595,612,585,612 1 3765
+char182 13173,19635,4200,1650,-1308,899 2 3766
+ps "
+char190 23418,18225,330,0,-2985 2 3774
+34 "
+\- 23418,8610,0,0,-3027 0 51757
+char188 23418,18225,330,0,-2472 2 3772
+14 "
+char189 23418,18225,330,0,-1632 2 3773
+12 "
+char170 13173,18225,0,1119,-1827,899 2 3754
+Of "
+char186 13173,18225,0,1503,-2640,899 2 3770
+Om "
+char171 12198,10095,0,501,330,501 0 3755
+Fo "
+char187 12198,10095,0,336,495,336 0 3771
+Fc "
+char177 23418,15750,2625,0,-2949 0 3761
+char166 13173,19083,5916,0,-4596 3 3750
+bb "
+char169 13173,19725,0,5355,-3531,899 2 3753
+co "
+char172 23418,12165,0,0,-3045 0 3756
+no "
+char174 13173,19725,0,5355,-3531,899 2 3758
+rg "
+char178 9270,18060,0,1602,-555,899 2 3762
+S2 "
+char179 9270,18060,0,1980,-771,899 2 3763
+S3 "
+char184 13173,0,4785,0,-96 0 3768
+ac "
+char185 9270,18060,0,1146,-1233,899 2 3769
+S1 "
+char215 23418,14658,0,0,-3630 0 3799
+char247 23418,14010,0,0,-2958 0 3831
+char183 8781,9945,0,0,-2400 0 3767
+fm 8781,18225,0,852,-3669,852 2 51873
+sd 13173,18225,0,612,-3669,612 2 51874
+dg 13173,18225,4200,1470,-1434,899 2 51755
+tm 16101,17550,0,5841,-3492,899 2 51796
+ah 13173,18399,0,1908,-5382,899 2 51935
+ao 13173,18309,0,0,-5421 2 51930
+f/ 3402,18225,330,8451,6846,899 2 51759
+em 23418,6900,0,345,153,345 0 51789
+en 13173,6900,0,393,153,393 0 51790
+dd 13173,18225,4200,1056,-1020,899 2 51773
+.i 7317,12669,330,120,420,120 0 51957
+aq 8781,18225,0,585,-3807,585 2 3623
+bu 13173,14226,0,0,-498 0 51889
+'C 17565,23955,330,2700,-873,899 2 20166
+'c 11709,18399,330,2199,318,899 2 20198
+lq 13173,18225,0,1320,-3570,899 2 51838
+rq 13173,18225,0,1332,-3582,899 2 51746
+Bq 13173,3039,3156,0,453 0 51772
+vz 10245,18399,2163,1872,1815,899 2 51834
+fi 13173,18300,5655,534,5772,534 3 51881
+fl 13173,18300,5655,1773,5736,899 3 51882
+ff 14148,18300,5655,5796,5352,899 3 51883
+Fi 20004,18300,5655,672,5466,672 3 51884
+Fl 20004,18300,5655,1851,5418,899 3 51885
+ij 13173,18369,5655,1212,435,899 3 51958
+bq 8781,3039,3156,0,-582 0 51756
+%0 32202,18894,1026,0,-3135 2 51901
+char175 13173,15819,0,867,-4257,867 0 3759
+a- "
+ab 13173,18339,0,1122,-4281,899 2 51926
+a. 13173,17124,0,0,-6222 2 51927
+oe 17565,12669,330,1107,711,899 0 51823
+OE 24882,18225,330,2016,978,899 2 51791
+fo 7317,10095,0,939,333,899 0 51886
+fc 7317,10095,0,774,498,774 0 51887
+sq 19029,15624,0,0,-2022 0 51899
+/L 14637,17895,0,1023,2487,899 2 51944
+/l 7317,18300,330,1749,654,899 2 51960
+a" 13173,18399,0,3321,-4644,899 2 51933
+ho 13173,564,3186,0,-3846 0 51934
+vZ 14637,23955,0,2856,1710,899 2 51802
+IJ 21465,17895,330,1872,1716,899 2 51942
diff --git a/font/devlj4/TR b/font/devlj4/TR
new file mode 100644
index 00000000..03d63fb7
--- /dev/null
+++ b/font/devlj4/TR
@@ -0,0 +1,860 @@
+name TR
+spacewidth 7806
+pcltypeface 4101
+pclproportional 1
+pclweight 0
+pclstyle 0
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -3903
+P . -3903
+P , -3903
+V A -5364
+A V -5364
+T o -3414
+T r -1950
+T c -3414
+T e -2925
+T d -2925
+T s -2925
+T y -1950
+T a -3414
+T w -1950
+T u -1950
+T J -1461
+L T -2925
+L Y -3903
+Y o -4878
+Y e -4389
+Y a -4878
+Y J -1461
+A W -4878
+W A -4878
+T A -2925
+V o -3903
+V e -3903
+V a -3903
+Y A -4389
+F A -3903
+F . -3903
+F , -3903
+A T -2925
+A Y -4389
+v . -3414
+v , -3414
+y . -3414
+y , -3414
+T . -2925
+T , -2925
+L W -3414
+P A -3903
+V J -1461
+V . -3903
+V , -3903
+Y . -3903
+Y , -3903
+W o -3414
+W e -3414
+W a -3414
+W . -3903
+W , -3903
+r . -2439
+r , -2439
+w . -3414
+w , -3414
+Y u -3414
+A v -3414
+A y -3414
+A w -3414
+o . -1461
+o , -1461
+p . -1461
+p , -1461
+e . -975
+e , -975
+b . -1461
+b , -1461
+O T -1950
+O V -2925
+O Y -2925
+O . -2925
+O , -2925
+L y -1461
+P J -1461
+V y -2925
+V u -2925
+V O -2925
+V G -2925
+V C -2925
+V Q -2925
+D T -1950
+D V -2925
+D Y -2925
+D . -2925
+D , -2925
+Y O -2925
+Y G -2925
+Y C -2925
+Y Q -2925
+F o -1461
+F e -1461
+F a -1461
+c . -1461
+c , -1461
+O A -2439
+O W -2439
+R T -2439
+R V -2439
+R Y -2439
+R W -2439
+G T -1950
+P o -1461
+P g -1461
+P e -975
+P a -1461
+C A -1950
+C . -1950
+C , -1950
+D A -2439
+D W -2439
+B T -1950
+B Y -1950
+B . -1950
+B , -1950
+F J -1461
+A O -2439
+A G -2439
+A C -2439
+A U -2439
+A Q -2439
+W r -2439
+W y -2439
+W u -2439
+W O -2439
+W G -2439
+W C -2439
+W J -1461
+W Q -2439
+J A -2439
+J . -2439
+J , -2439
+U A -2439
+U . -2439
+U , -2439
+Q A -2439
+Q W -2439
+T O -1950
+T G -1950
+T C -1950
+T Q -1950
+O X -1461
+G V -1950
+G Y -1950
+G W -1950
+G . -1461
+G , -1461
+C T -975
+C V -975
+C Y -975
+D X -1461
+B V -1950
+B X -1461
+B A -1950
+B W -1950
+S . -1461
+S , -1461
+F r -486
+F y -486
+F u -486
+F O -486
+F G -486
+F C -486
+F Q -486
+X o -1461
+X e -975
+X y -1461
+X O -1461
+X G -1461
+X C -1461
+X Q -1461
+A o -1461
+A e -975
+Q X -1461
+K o -1461
+K e -975
+K y -1461
+K w -1461
+K O -1461
+K G -1461
+K C -1461
+K Q -1461
+o v -1461
+o y -1461
+o x -975
+o w -1461
+h v -975
+h y -975
+n v -975
+n y -975
+m v -975
+m y -975
+r g -975
+g . -975
+g , -975
+p v -975
+p y -975
+p x -975
+c v -1461
+c y -1461
+c w -1461
+v o -1461
+v g -1461
+v c -1461
+v d -1461
+v a -1461
+v q -1461
+e v -975
+e y -975
+b v -1461
+b y -1461
+b w -1461
+s . -975
+s , -975
+y o -1461
+y g -1461
+y c -1461
+y d -1461
+y a -1461
+y q -1461
+f g -486
+x o -975
+x g -486
+x c -975
+x e -975
+x d -975
+x a -975
+x q -975
+a v -1461
+a y -1461
+a w -1461
+w o -1461
+w g -1461
+w c -1461
+w d -1461
+w a -1461
+w q -1461
+T i -1461
+T S -1461
+R o -1461
+R y -1461
+R O -1461
+R G -1461
+R C -1461
+R U -1461
+R Q -1461
+G X -1461
+G A -1461
+P s -975
+C X -975
+C W -975
+V i -1461
+V S -1461
+S T -486
+S V -486
+S Y -486
+S X -486
+S A -1461
+S W -486
+Y i -1461
+Y S -1461
+X a -975
+X u -975
+X S -486
+A t -975
+A g -486
+A c -1461
+A d -1461
+A a -975
+A u -975
+A q -1461
+A S -486
+W i -1461
+W S -1461
+J y -486
+K c -1461
+K u -975
+K S -486
+t g -486
+o f -975
+h w -975
+n w -975
+m w -975
+r o -486
+r c -486
+r e -486
+r d -486
+r a -486
+r q -486
+g g -975
+p f -975
+p w -975
+c f -975
+c x -975
+v e -975
+v s -975
+e f -975
+e x -975
+e w -975
+b f -975
+s v -975
+s y -975
+s f -975
+s x -975
+s w -975
+y e -975
+y s -975
+f o -975
+f c -975
+f e -975
+f d -975
+f s -975
+f a -975
+f q -975
+x s -975
+w e -975
+w s -975
+k o -486
+k g -486
+k c -486
+k e -486
+k d -486
+k a -486
+k q -486
+O Z -486
+N . -486
+N , -486
+R e -975
+R a -975
+R u -975
+R S -486
+G Z -486
+C Z -486
+E g -486
+Z o -486
+Z e -486
+Z d -486
+Z s -486
+Z y -486
+Z a -486
+Z w -486
+Z u -486
+Z O -486
+Z G -486
+Z C -486
+Z S -486
+Z J -486
+Z Q -486
+D Z -486
+B Z -486
+S Z -486
+F i -486
+F j -486
+F S -486
+X J -486
+A s -975
+A J -486
+J o -486
+J i -486
+J e -486
+J a -486
+J u -486
+J O -486
+J G -486
+J C -486
+J S -486
+J J -486
+J Q -486
+U g -486
+K a -975
+K J -486
+o g -486
+o z -486
+h g -486
+n g -486
+m g -486
+l g -486
+r s -486
+g o -486
+g c -486
+g e -486
+g d -486
+g s -486
+g a -486
+g q -486
+i g -486
+p g -486
+p z -486
+c g -486
+c z -486
+e g -486
+e z -486
+z o -486
+z g -486
+z c -486
+z e -486
+z d -486
+z s -486
+z a -486
+z q -486
+d g -486
+b g -486
+b z -486
+s g -486
+s z -486
+a g -486
+j g -486
+u g -486
+q g -486
+k s -486
+O g -486
+N A -486
+M g -486
+R J -486
+I g -486
+K T -486
+K V -486
+K Y -486
+K W -486
+K U -486
+L ' -3903
+T char173 -1950
+T hy -1950
+T - -1950
+T en -1950
+T em -1950
+A ' -3903
+char173 T -1950
+hy T -1950
+- T -1950
+en T -1950
+em T -1950
+Y char173 -3414
+Y hy -3414
+Y - -3414
+Y en -3414
+Y em -3414
+p ' -975
+c ' -1461
+e ' -975
+b ' -1461
+a ' -1461
+V char173 -2925
+V hy -2925
+V - -2925
+V en -2925
+V em -2925
+h ' -975
+n ' -975
+m ' -975
+R ' -1461
+W char173 -2439
+W hy -2439
+W - -2439
+W en -2439
+W em -2439
+' d -1461
+s ' -975
+F char173 -486
+F hy -486
+F - -486
+F en -486
+F em -486
+X char173 -1461
+X hy -1461
+X - -1461
+X en -1461
+X em -1461
+A char173 -1950
+A hy -1950
+A - -1950
+A en -1950
+A em -1950
+K char173 -1461
+K hy -1461
+K - -1461
+K en -1461
+K em -1461
+' s -975
+char173 X -1461
+hy X -1461
+- X -1461
+char173 A -1950
+hy A -1950
+- A -1950
+en X -1461
+en A -1950
+em X -1461
+R char173 -1461
+R hy -1461
+R - -1461
+R en -1461
+R em -1461
+K ' -486
+t g -486
+b f -975
+Z char173 -486
+Z hy -486
+Z - -486
+Z en -486
+Z em -486
+J char173 -486
+J hy -486
+J - -486
+J en -486
+J em -486
+char173 g -486
+hy g -486
+- g -486
+en g -486
+em g -486
+charset
+! 8781,18225,330 2 3617
+" 12198,18225 2 3618
+sh 13173,18225,837 2 3619
+# "
+Do 13173,19845,2370 2 3620
+$ "
+% 23418,18894,1026 2 3621
+& 20490,18225,330 2 3622
+' 8781,18225 2 51751
+( 8781,18225,4845 2 3624
+) 8781,18225,4845 2 3625
+* 13173,18225 2 3626
++ 23418,15750 0 3627
+, 8781,2565,4005 0 3628
+char173 8781,7155 0 3629
+hy "
+- "
+. 8781,2685,330 0 3630
+sl 8781,18225,330 2 3631
+/ "
+0 13173,18225,330 2 3632
+1 13173,18225 2 3633
+2 13173,18225 2 3634
+3 13173,18225,330 2 3635
+4 13173,18225 2 3636
+5 13173,17895,330 2 3637
+6 13173,18225,330 2 3638
+7 13173,17895 2 3639
+8 13173,18225,330 2 3640
+9 13173,18225,330 2 3641
+: 8781,12252,330 0 3642
+; 8781,12252,4005 0 3643
+< 26346,16068 0 3644
+= 23418,10875 0 3645
+> 26346,16068 0 3646
+? 11709,18225,330 2 3647
+at 23418,16980,3654 2 3648
+@ "
+A 19029,18225 2 3649
+B 16587,17895 2 3650
+C 18051,18225,330 2 3651
+D 19515,17895 2 3652
+E 16587,17895 2 3653
+F 15612,17895 2 3654
+G 19029,18225,330 2 3655
+H 19515,17895 2 3656
+I 8781,17895 2 3657
+J 10245,17895,330 2 3658
+K 18540,17895 2 3659
+L 16587,17895 2 3660
+M 23907,17895 2 3661
+N 19515,17895,330 2 3662
+O 19029,18225,330 2 3663
+P 15126,17895 2 3664
+Q 19029,18225,4605 2 3665
+R 17565,17895 2 3666
+S 14148,18225,330 2 3667
+T 16587,17895 2 3668
+U 19515,17895,330 2 3669
+V 19029,17895,330 2 3670
+W 24882,17895,330 2 3671
+X 19029,17895 2 3672
+Y 19029,17895 2 3673
+Z 17076,17895 2 3674
+lB 8781,17895,4380 2 3675
+[ "
+rs 8781,18225,330 2 3676
+\ "
+rB 8781,17895,4380 2 3677
+] "
+ha 13173,19758 2 51875
+_ 13173,191367,6588 3 3679
+oq 8781,18225 2 51808
+` "
+a 11709,12669,330 0 3681
+b 13173,18300,330 2 3682
+c 11709,12669,330 0 3683
+d 13173,18300,330 2 3684
+e 11709,12669,330 0 3685
+f 8781,18300 2 3686
+g 13173,12669,5655 1 3687
+h 13173,18300 2 3688
+i 7317,18534 2 3689
+j 7317,18534,5655 3 3690
+k 13173,18300 2 3691
+l 7317,18300 2 3692
+m 20490,12669 0 3693
+n 13173,12669 0 3694
+o 13173,12669,330 0 3695
+p 13173,12669,5655 1 3696
+q 13173,12669,5655 1 3697
+r 9759,12669 0 3698
+s 10245,12669,330 0 3699
+t 7317,15465,330 0 3700
+u 13173,12339,330 0 3701
+v 13173,12339,330 0 3702
+w 19029,12339,330 0 3703
+x 13173,12339 0 3704
+y 13173,12339,5655 1 3705
+z 11709,12339 0 3706
+lC 11709,19935,6210 3 3707
+{ "
+ba 13173,19758,6588 3 3708
+| "
+rC 11709,19935,6210 3 3709
+} "
+ti 26346,8952 0 51876
+char192 19029,23955 2 3776
+`A "
+char194 19029,23955 2 3778
+^A "
+char200 16587,23955 2 3784
+`E "
+char202 16587,23955 2 3786
+^E "
+char203 16587,23085 2 3787
+:E "
+char206 8781,23955 2 3790
+^I "
+char207 8781,23085 2 3791
+:I "
+char180 13173,18399 2 3764
+aa "
+ga 13173,18399 2 3680
+a^ 13173,18399 2 3678
+^ "
+char168 13173,17124 2 3752
+ad "
+a~ 13173,17064 2 3710
+~ "
+char217 19515,23955,330 2 3801
+`U "
+char219 19515,23955,330 2 3803
+^U "
+char221 19029,23955 2 3805
+'Y "
+char253 13173,18399,5655 3 3837
+'y "
+char176 13173,18225 2 3760
+de "
+char199 18051,18225,4908 2 3783
+,C "
+char231 11709,12669,4572 0 3815
+,c "
+char209 19515,23034,330 2 3793
+~N "
+char241 13173,17064 2 3825
+~n "
+char161 8781,12783,5772 1 3745
+r! "
+char191 11709,12783,5772 1 3775
+r? "
+char164 13173,15684 0 3748
+Cs "
+char163 13173,18225,330 2 3747
+Po "
+char165 13173,17895 2 3749
+Ye "
+char167 13173,18225,4230 2 3751
+sc "
+Fn 13173,18300,5655 3 51871
+char162 13173,16866 2 3746
+ct "
+char226 11709,18399,330 2 3810
+^a "
+char234 11709,18399,330 2 3818
+^e "
+char244 13173,18399,330 2 3828
+^o "
+char251 13173,18399,330 2 3835
+^u "
+char225 11709,18399,330 2 3809
+'a "
+char233 11709,18399,330 2 3817
+'e "
+char243 13173,18399,330 2 3827
+'o "
+char250 13173,18399,330 2 3834
+'u "
+char224 11709,18399,330 2 3808
+`a "
+char232 11709,18399,330 2 3816
+`e "
+char242 13173,18399,330 2 3826
+`o "
+char249 13173,18399,330 2 3833
+`u "
+char228 11709,17124,330 2 3812
+:a "
+char235 11709,17124,330 2 3819
+:e "
+char246 13173,17124,330 2 3830
+:o "
+char252 13173,17124,330 2 3836
+:u "
+char197 19029,23865 2 3781
+oA "
+char238 7317,18399 2 3822
+^i "
+char216 19029,18225,339 2 3800
+/O "
+char198 23418,17895 2 3782
+AE "
+char229 11709,18309,330 2 3813
+oa "
+char237 7317,18399 2 3821
+'i "
+char248 13173,12765,330 0 3832
+/o "
+char230 17565,12669,330 0 3814
+ae "
+char196 19029,23085 2 3780
+:A "
+char236 7317,18399 2 3820
+`i "
+char214 19029,23085,330 2 3798
+:O "
+char220 19515,23085,330 2 3804
+:U "
+char201 16587,23955 2 3785
+'E "
+char239 7317,17124 2 3823
+:i "
+char223 13173,18300,330 2 3807
+ss "
+char212 19029,23955,330 2 3796
+^O "
+char193 19029,23955 2 3777
+'A "
+char195 19029,23034 2 3779
+~A "
+char227 11709,17064,330 2 3811
+~a "
+char208 19515,17895 2 3792
+-D "
+char240 13173,18456,330 2 3824
+Sd "
+char205 8781,23955 2 3789
+'I "
+char204 8781,23955 2 3788
+`I "
+char211 19029,23955,330 2 3795
+'O "
+char210 19029,23955,330 2 3794
+`O "
+char213 19029,23034,330 2 3797
+~O "
+char245 13173,17064,330 2 3829
+~o "
+vS 14148,23955,330 2 51795
+vs 10245,18399,330 2 51827
+char218 19515,23955,330 2 3802
+'U "
+:Y 19029,23085 2 51801
+char255 13173,17124,5655 3 3839
+:y "
+char222 15126,17895 2 3806
+TP "
+char254 13173,18300,5655 3 3838
+Tp "
+char181 14637,10800,5595 1 3765
+char182 13173,19635,4200 2 3766
+ps "
+char190 23418,18225,330 2 3774
+34 "
+\- 23418,8610 0 51757
+char188 23418,18225,330 2 3772
+14 "
+char189 23418,18225,330 2 3773
+12 "
+char170 13173,18225 2 3754
+Of "
+char186 13173,18225 2 3770
+Om "
+char171 10734,10095 0 3755
+Fo "
+char187 10734,10095 0 3771
+Fc "
+char177 23418,15750,2625 0 3761
+char166 13173,19083,5916 3 3750
+bb "
+char169 13173,19725 2 3753
+co "
+char172 23418,12165 0 3756
+no "
+char174 13173,19725 2 3758
+rg "
+char178 9270,18060 2 3762
+S2 "
+char179 9270,18060 2 3763
+S3 "
+char184 13173,258,4572 0 3768
+ac "
+char185 9270,18060 2 3769
+S1 "
+char215 23418,15117 0 3799
+char247 23418,14010 0 3831
+char183 8781,10407 0 3767
+fm 8781,18225 2 51873
+sd 13173,18225 2 51874
+dg 13173,18225,4200 2 51755
+tm 16101,17550 2 51796
+ah 13173,18399 2 51935
+ao 13173,18309 2 51930
+f/ 3423,18225,330 2 51759
+em 23418,6900 0 51789
+en 13173,6900 0 51790
+dd 13173,18225,4200 2 51773
+.i 7317,12669 0 51957
+aq 8781,18225 2 3623
+bu 13173,14226 0 51889
+'C 18051,23955,330 2 20166
+'c 11709,18399,330 2 20198
+lq 13662,18231 2 51838
+rq 13662,18225 2 51746
+Bq 13662,3009,3576 0 51772
+vz 11709,18399 2 51834
+fi 14637,18300 2 51881
+fl 14637,18300 2 51882
+ff 15612,18300 2 51883
+Fi 21954,18300 2 51884
+Fl 21954,18300 2 51885
+ij 14637,18534,5655 3 51958
+bq 8781,3009,3561 0 51756
+%0 31713,18894,1026 2 51901
+char175 13173,16539 0 3759
+a- "
+ab 13173,17769 2 51926
+a. 13173,17124 2 51927
+oe 19029,12669,330 0 51823
+OE 23418,18225,330 2 51791
+fo 6831,10095 0 51886
+fc 6831,10095 0 51887
+sq 19029,15624 0 51899
+/L 16587,17895 2 51944
+/l 7317,18300 2 51960
+a" 13173,18399 2 51933
+ho 13173,750,3165 0 51934
+vZ 17076,23955 2 51802
+IJ 19245,17895,330 2 51942
diff --git a/font/devlj4/UB b/font/devlj4/UB
new file mode 100644
index 00000000..554e71be
--- /dev/null
+++ b/font/devlj4/UB
@@ -0,0 +1,809 @@
+name UB
+spacewidth 8781
+pcltypeface 4148
+pclproportional 1
+pclweight 3
+pclstyle 0
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -3414
+P . -4878
+P , -4878
+V A -3414
+A V -3414
+T o -4389
+T r -4389
+T c -4389
+T e -4389
+T d -4389
+T s -4389
+T y -4389
+T a -4389
+T w -4389
+T u -4389
+T J -4389
+L T -4389
+L Y -3903
+Y o -3903
+Y e -3903
+Y a -3414
+Y J -3903
+A W -2439
+W A -2439
+T A -3414
+V o -2925
+V e -2925
+V a -2439
+Y A -3414
+F A -1950
+F . -3903
+F , -3903
+A T -3414
+A Y -3414
+v . -2439
+v , -2439
+y . -2439
+y , -2439
+T . -3903
+T , -3903
+L W -2439
+P A -2439
+V J -3414
+V . -3903
+V , -3903
+Y . -3903
+Y , -3903
+W o -1950
+W e -1950
+W a -1950
+W . -2925
+W , -2925
+r . -2439
+r , -2439
+w . -2439
+w , -2439
+Y u -2439
+A v -1950
+A y -1950
+A w -1950
+o . -1950
+o , -1950
+p . -1461
+p , -1461
+e . -1461
+e , -1461
+b . -1461
+b , -1461
+O T -1950
+O V -1461
+O Y -1950
+O . -2439
+O , -2439
+L y -1950
+L O -975
+L G -975
+L C -975
+L Q -975
+P J -1950
+V y -1461
+V u -1461
+V O -1461
+V G -1461
+V C -1461
+V Q -1461
+D T -2439
+D V -1461
+D Y -2439
+D . -2925
+D , -2925
+Y O -1950
+Y G -1950
+Y C -1950
+Y Q -1950
+F o -486
+F e -486
+F a -486
+c . -1461
+c , -1461
+O A -1461
+O W -975
+L U -975
+R T -1461
+R V -1461
+R Y -1461
+R W -975
+G T -1461
+P o -1461
+P g -1461
+P e -1461
+P a -975
+C A -1461
+C . -1950
+C , -1950
+D A -1461
+D W -975
+B T -1461
+B Y -1461
+B . -1461
+B , -1461
+F J -975
+A O -1461
+A G -1461
+A C -1461
+A U -1461
+A Q -1461
+W r -975
+W y -975
+W u -975
+W O -975
+W G -975
+W C -975
+W J -2439
+W Q -975
+J A -1461
+J . -1950
+J , -1950
+U A -1461
+U . -2439
+U , -2439
+Q W -975
+f . -486
+f , -486
+T O -1950
+T G -1950
+T C -1950
+T Q -1950
+O X -1461
+L o -975
+L e -975
+L q -975
+G V -1461
+G Y -1461
+G W -975
+G . -1461
+G , -1461
+P T -975
+P V -975
+P Y -975
+C T -1461
+C V -1461
+C Y -1461
+D X -1461
+B V -1461
+B X -975
+B A -975
+B W -975
+S . -1950
+S , -1950
+X o -1461
+X e -1461
+X y -1461
+X O -1461
+X G -1461
+X C -1461
+X Q -1461
+A o -1461
+A e -1461
+K o -1461
+K e -1461
+K y -1461
+K w -1461
+K O -1461
+K G -1461
+K C -1461
+K Q -1461
+o v -975
+o y -975
+o x -975
+o w -975
+h v -975
+h y -975
+n v -975
+n y -975
+m v -975
+m y -975
+g . -486
+g , -486
+p v -975
+p y -975
+p x -975
+c v -975
+c y -975
+c w -975
+v o -975
+v g -975
+v c -975
+v d -975
+v a -975
+v q -975
+e v -975
+e y -975
+b v -975
+b y -975
+b w -975
+s . -975
+s , -975
+y o -975
+y g -975
+y c -975
+y d -975
+y a -975
+y q -975
+x o -975
+x c -975
+x e -975
+x d -975
+x a -486
+x q -975
+a v -975
+a y -975
+a w -975
+w o -975
+w g -975
+w c -975
+w d -975
+w a -975
+w q -975
+T S -1461
+L a -486
+L S -975
+G X -975
+G A -975
+P s -486
+P Z -975
+P X -975
+P W -975
+C X -1461
+C W -975
+C J -486
+V S -1461
+S T -1461
+S V -1461
+S Y -1461
+S X -1461
+S A -1461
+S W -975
+Y S -1461
+X a -486
+X u -975
+X S -975
+A t -486
+A c -1461
+A d -975
+A a -486
+A u -975
+A q -975
+A S -975
+W S -975
+K c -1461
+K u -975
+K S -975
+t . -486
+t , -486
+o f -486
+h w -975
+h . -486
+h , -486
+n w -975
+n . -486
+n , -486
+m w -975
+m . -486
+m , -486
+l . -486
+l , -486
+i . -486
+i , -486
+p f -486
+p w -975
+c f -486
+c x -975
+v e -975
+v s -486
+e f -486
+e x -975
+e w -975
+z . -486
+z , -486
+d . -486
+d , -486
+b f -486
+s v -486
+s y -486
+s f -486
+s x -486
+s w -486
+y e -975
+y s -486
+x s -486
+x . -486
+x , -486
+a . -486
+a , -486
+w e -975
+w s -486
+j . -486
+j , -486
+u . -486
+k o -975
+k c -975
+k e -975
+k d -975
+k a -486
+k q -975
+k . -486
+k , -486
+O Z -975
+O J -486
+H . -486
+H , -486
+N . -486
+N , -486
+M . -486
+M , -486
+L . -486
+L , -486
+R . -486
+R , -486
+G Z -975
+I . -486
+I , -486
+C Z -975
+E . -486
+E , -486
+Z o -975
+Z e -975
+Z d -975
+Z s -486
+Z y -975
+Z a -486
+Z w -975
+Z u -975
+Z O -975
+Z G -975
+Z C -975
+Z S -975
+Z Q -975
+Z . -486
+Z , -486
+D Z -975
+D J -486
+B Z -975
+B J -486
+S Z -975
+S J -486
+X . -486
+X , -486
+A s -486
+A . -486
+A , -486
+J J -486
+U J -486
+K a -486
+K . -486
+K , -486
+h f -486
+n f -486
+m f -486
+a f -486
+k s -486
+G J -486
+A f -486
+L ' -6342
+T char173 -4389
+T hy -4389
+T - -4389
+T en -4389
+T em -4389
+A ' -2439
+char173 T -4389
+hy T -4389
+- T -4389
+en T -4389
+em T -4389
+Y char173 -2439
+Y hy -2439
+Y - -2439
+Y en -2439
+Y em -2439
+p ' -1461
+c ' -975
+e ' -1461
+b ' -1461
+a ' -975
+V char173 -1461
+V hy -1461
+V - -1461
+V en -1461
+V em -1461
+h ' -975
+n ' -975
+m ' -975
+W char173 -975
+W hy -975
+W - -975
+W en -975
+W em -975
+' d -2439
+s ' -486
+L char173 -975
+L hy -975
+L - -975
+L en -975
+L em -975
+X char173 -1461
+X hy -1461
+X - -1461
+X en -1461
+X em -1461
+A char173 -1461
+A hy -1461
+A - -1461
+A en -1461
+A em -1461
+K char173 -1461
+K hy -1461
+K - -1461
+K en -1461
+K em -1461
+' s -1950
+char173 X -1461
+hy X -1461
+- X -1461
+char173 A -1461
+hy A -1461
+- A -1461
+en X -1461
+en A -1461
+em X -1461
+b f -486
+Z char173 -975
+Z hy -975
+Z - -975
+Z en -975
+Z em -975
+' n -1461
+' m -1461
+' r -1461
+' v -1461
+charset
+! 8781,18165 2 3617
+" 13662,18135 2 3618
+sh 16587,18105 2 3619
+# "
+Do 16587,18750,645 2 3620
+$ "
+% 26346,18720,840 2 3621
+& 20004,18495 2 3622
+' 8781,18135 2 51751
+( 8781,18135,2355 2 3624
+) 8781,18135,2355 2 3625
+* 16587,18495 2 3626
++ 26346,14940 0 3627
+, 8781,3390,2355 0 3628
+char173 8781,7875 0 3629
+hy "
+- "
+. 8781,3390 0 3630
+sl 8781,18495,885 2 3631
+/ "
+0 16587,18465,360 2 3632
+1 16587,18105 2 3633
+2 16587,18465 2 3634
+3 16587,18465,360 2 3635
+4 16587,18105 2 3636
+5 16587,18105,360 2 3637
+6 16587,18465,360 2 3638
+7 16587,18105 2 3639
+8 16587,18465,360 2 3640
+9 16587,18465,360 2 3641
+: 8781,12627 0 3642
+; 8781,12627,2355 0 3643
+< 26346,16068 0 3644
+= 26346,10563 0 3645
+> 26346,16068 0 3646
+? 13662,18315 2 3647
+at 26346,21057,2679 2 3648
+@ "
+A 19515,18135 2 3649
+B 16587,18135 2 3650
+C 18540,18495,360 2 3651
+D 19029,18135 2 3652
+E 15126,18135 2 3653
+F 14637,18135 2 3654
+G 19515,18495,360 2 3655
+H 19029,18135 2 3656
+I 7317,18135 2 3657
+J 14637,18135,360 2 3658
+K 17565,18135 2 3659
+L 14148,18135 2 3660
+M 23907,18135 2 3661
+N 19029,18135 2 3662
+O 20004,18495,360 2 3663
+P 15612,18135 2 3664
+Q 20490,18495,360 2 3665
+R 17076,18135 2 3666
+S 17076,18495,360 2 3667
+T 16587,18135 2 3668
+U 19029,18135,360 2 3669
+V 19029,18135 2 3670
+W 26346,18135 2 3671
+X 19029,18135 2 3672
+Y 18051,18135 2 3673
+Z 16101,18135 2 3674
+lB 8781,18135,2355 2 3675
+[ "
+rs 8781,18495,885 2 3676
+\ "
+rB 8781,18135,2355 2 3677
+] "
+ha 13173,19758 2 51875
+_ 13173,191367,6588 3 3679
+oq 8781,18135 2 51808
+` "
+a 14148,12990,360 0 3681
+b 15126,18165,360 2 3682
+c 14148,12990,360 0 3683
+d 15126,18165,360 2 3684
+e 14148,12990,360 0 3685
+f 9759,18315 2 3686
+g 15126,12990,5313 1 3687
+h 15126,18165 2 3688
+i 6342,18165 2 3689
+j 6342,18165,4995 3 3690
+k 14148,18165 2 3691
+l 6342,18165 2 3692
+m 22932,12990 0 3693
+n 15126,12990 0 3694
+o 15126,12990,360 0 3695
+p 15126,12990,4680 0 3696
+q 15126,12990,4680 0 3697
+r 9270,13005 0 3698
+s 13173,12990,360 0 3699
+t 9759,16110,360 0 3700
+u 15126,12630,360 0 3701
+v 14637,12630 0 3702
+w 22932,12630 0 3703
+x 14637,12630 0 3704
+y 14637,12630,4680 0 3705
+z 12684,12630 0 3706
+lC 13173,20130,6075 3 3707
+{ "
+ba 13173,19758,6588 3 3708
+| "
+rC 13173,20130,6075 3 3709
+} "
+ti 26346,9435 0 51876
+char192 19515,23130 2 3776
+`A "
+char194 19515,23130 2 3778
+^A "
+char200 15126,23130 2 3784
+`E "
+char202 15126,23130 2 3786
+^E "
+char203 15126,23040 2 3787
+:E "
+char206 7317,23130 2 3790
+^I "
+char207 7317,23040 2 3791
+:I "
+char180 16587,18090 2 3764
+aa "
+ga 16587,18090 2 3680
+a^ 16587,18090 2 3678
+^ "
+char168 16587,17910 2 3752
+ad "
+a~ 16587,17946 2 3710
+~ "
+char217 19029,23130,360 2 3801
+`U "
+char219 19029,23130,360 2 3803
+^U "
+char221 18051,23130 2 3805
+'Y "
+char253 14637,18090,4680 2 3837
+'y "
+char176 16587,18465 2 3760
+de "
+char199 18540,18495,5175 3 3783
+,C "
+char231 14148,12990,5160 1 3815
+,c "
+char209 19029,23130 2 3793
+~N "
+char241 15126,17946 2 3825
+~n "
+char161 8781,12645,5520 1 3745
+r! "
+char191 13662,12480,5835 1 3775
+r? "
+char164 16587,15834 0 3748
+Cs "
+char163 16587,18465 2 3747
+Po "
+char165 16587,18105 2 3749
+Ye "
+char167 16587,18495,360 2 3751
+sc "
+Fn 16587,18315 2 51871
+char162 16587,18750,645 2 3746
+ct "
+char226 14148,18090,360 2 3810
+^a "
+char234 14148,18090,360 2 3818
+^e "
+char244 15126,18090,360 2 3828
+^o "
+char251 15126,18090,360 2 3835
+^u "
+char225 14148,18090,360 2 3809
+'a "
+char233 14148,18090,360 2 3817
+'e "
+char243 15126,18090,360 2 3827
+'o "
+char250 15126,18090,360 2 3834
+'u "
+char224 14148,18090,360 2 3808
+`a "
+char232 14148,18090,360 2 3816
+`e "
+char242 15126,18090,360 2 3826
+`o "
+char249 15126,18090,360 2 3833
+`u "
+char228 14148,17910,360 2 3812
+:a "
+char235 14148,17910,360 2 3819
+:e "
+char246 15126,17910,360 2 3830
+:o "
+char252 15126,17910,360 2 3836
+:u "
+char197 19515,25830 2 3781
+oA "
+char238 6342,18090 2 3822
+^i "
+char216 20004,18495,366 2 3800
+/O "
+char198 25857,18135 2 3782
+AE "
+char229 14148,20100,360 2 3813
+oa "
+char237 6342,18090 2 3821
+'i "
+char248 15126,13047,360 0 3832
+/o "
+char230 22443,12990,360 0 3814
+ae "
+char196 19515,23040 2 3780
+:A "
+char236 6342,18090 2 3820
+`i "
+char214 20004,23040,360 2 3798
+:O "
+char220 19029,23040,360 2 3804
+:U "
+char201 15126,23130 2 3785
+'E "
+char239 6342,17910 2 3823
+:i "
+char223 16101,17790,360 2 3807
+ss "
+char212 20004,23130,360 2 3796
+^O "
+char193 19515,23130 2 3777
+'A "
+char195 19515,23130 2 3779
+~A "
+char227 14148,17946,360 2 3811
+~a "
+char208 19029,18135 2 3792
+-D "
+char240 15126,18747,360 2 3824
+Sd "
+char205 7317,23130 2 3789
+'I "
+char204 7317,23130 2 3788
+`I "
+char211 20004,23130,360 2 3795
+'O "
+char210 20004,23130,360 2 3794
+`O "
+char213 20004,23130,360 2 3797
+~O "
+char245 15126,17946,360 2 3829
+~o "
+vS 17076,23130,360 2 51795
+vs 13173,18090,360 2 51827
+char218 19029,23130,360 2 3802
+'U "
+:Y 18051,23040 2 51801
+char255 14637,17910,4680 2 3839
+:y "
+char222 15612,18135 2 3806
+TP "
+char254 15126,18165,4680 2 3838
+Tp "
+char181 15612,12630,4680 0 3765
+char182 16590,19635,4200 2 3766
+ps "
+char190 26346,18465,900 2 3774
+34 "
+\- 26346,8445 0 51757
+char188 26346,18465,900 2 3772
+14 "
+char189 26346,18465,900 2 3773
+12 "
+char170 10734,18465 2 3754
+Of "
+char186 10734,18465 2 3770
+Om "
+char171 14637,11250 0 3755
+Fo "
+char187 14637,11250 0 3771
+Fc "
+char177 26346,14670 0 3761
+char166 13173,19083,5916 3 3750
+bb "
+char169 13173,19635 2 3753
+co "
+char172 26346,11787 0 3756
+no "
+char174 13173,19635 2 3758
+rg "
+char178 10245,18465 2 3762
+S2 "
+char179 10245,18465 2 3763
+S3 "
+char184 16587,195033,5160 3 3768
+ac "
+char185 10245,18345 2 3769
+S1 "
+char215 26346,14154 0 3799
+char247 26346,12870 0 3831
+char183 8781,10740 0 3767
+fm 8781,18054 2 51873
+sd 16587,18054 2 51874
+dg 16587,18135 2 51755
+tm 16128,17850 2 51796
+ah 16587,18090 2 51935
+ao 16587,20100 2 51930
+f/ 1464,18465,900 2 51759
+em 26346,7650 0 51789
+en 16587,7650 0 51790
+dd 16587,18135 2 51773
+.i 6342,12630 0 51957
+aq 8781,18135 2 3623
+bu 13173,14226 0 51889
+'C 18540,23130,360 2 20166
+'c 14148,18090,360 2 20198
+lq 13173,18135 2 51838
+rq 13173,18135 2 51746
+Bq 13173,3348,2292 0 51772
+vz 12684,18090 2 51834
+fi 16101,18315 2 51881
+fl 16101,18315 2 51882
+ff 18051,18315 2 51883
+Fi 24396,18315 2 51884
+Fl 24396,18315 2 51885
+ij 12684,18165,4995 3 51958
+bq 8781,3348,2307 0 51756
+%0 26346,18720,840 2 51901
+char175 16587,16950 2 3759
+a- "
+ab 16587,18147 2 51926
+a. 16587,18405 2 51927
+oe 23907,12990,360 0 51823
+OE 26346,18270,135 2 51791
+fo 9759,11277 0 51886
+fc 9759,11277 0 51887
+sq 19029,15624 0 51899
+/L 14148,18135 2 51944
+/l 7320,18165 2 51960
+a" 16587,18090 2 51933
+ho 16587,1197,4299 0 51934
+vZ 16101,23130 2 51802
+IJ 21954,18135,360 2 51942
diff --git a/font/devlj4/UBI b/font/devlj4/UBI
new file mode 100644
index 00000000..3c3b77e4
--- /dev/null
+++ b/font/devlj4/UBI
@@ -0,0 +1,759 @@
+name UBI
+spacewidth 8781
+slant 16.750000
+pcltypeface 4148
+pclproportional 1
+pclweight 3
+pclstyle 1
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -2925
+P . -4389
+P , -4389
+V A -2439
+A V -2925
+T o -3903
+T r -2925
+T c -3414
+T e -3414
+T d -3414
+T s -2925
+T y -3414
+T a -3414
+T w -3414
+T u -2925
+T J -2925
+L T -3414
+L Y -3903
+Y o -3414
+Y e -3414
+Y a -3414
+Y J -2925
+A W -2925
+W A -975
+T A -2925
+V o -1950
+V e -1950
+V a -1950
+Y A -2925
+F A -1950
+F . -1950
+F , -1950
+A T -3414
+A Y -3414
+v . -1950
+v , -1950
+y . -1461
+y , -1461
+T . -2925
+T , -2925
+L W -2925
+P A -1950
+V J -1950
+V . -2439
+V , -2439
+Y . -2925
+Y , -2925
+W o -1461
+W e -975
+W a -975
+W . -975
+W , -975
+r . -1461
+r , -1461
+w . -1461
+w , -1461
+Y u -2439
+A v -1461
+A y -1461
+A w -1461
+o . -975
+o , -975
+p . -975
+p , -975
+e . -975
+e , -975
+b . -975
+b , -975
+O T -2925
+O V -1950
+O Y -1950
+O . -1950
+O , -1950
+L y -1461
+L O -2925
+L G -2925
+L C -2925
+L Q -2925
+P J -1461
+V y -1461
+V u -975
+V O -975
+V G -975
+V C -975
+V Q -975
+D T -2925
+D V -1950
+D Y -1950
+D . -2439
+D , -2439
+Y O -1950
+Y G -1950
+Y C -1950
+Y Q -1950
+F o -975
+F e -975
+F a -975
+c . -975
+c , -975
+O A -975
+O W -1461
+L U -2439
+R T -975
+R V -975
+R Y -975
+R W -975
+G T -2439
+P o -975
+P g -486
+P e -975
+P a -975
+C A -975
+C . -1461
+C , -1461
+D A -1461
+D W -1461
+B T -2439
+B Y -1950
+B . -486
+B , -486
+F J -975
+A O -1950
+A G -1950
+A C -1950
+A U -1950
+A Q -1950
+W r -486
+W y -975
+W u -486
+W O -486
+W G -486
+W C -486
+W J -975
+W Q -486
+U A -975
+U . -1950
+U , -1950
+Q W -1461
+T O -1950
+T G -1950
+T C -1950
+T Q -1950
+O X -1461
+L o -1461
+L e -1461
+L q -1461
+G V -1950
+G Y -1950
+G W -1461
+P T -1950
+P V -1950
+P Y -1950
+C T -1950
+C V -1950
+C Y -1950
+D X -1461
+B V -1950
+B X -486
+B A -486
+B W -1461
+S . -975
+S , -975
+F y -486
+X o -1461
+X e -1461
+X y -1461
+X O -1461
+X G -1461
+X C -1461
+X Q -1461
+A o -1461
+A e -1461
+K o -1461
+K e -1461
+K y -1461
+K w -1461
+K O -1461
+K G -1461
+K C -1461
+K Q -1461
+o v -975
+o y -1461
+o x -975
+o w -1461
+h v -486
+h y -975
+n v -486
+n y -975
+m v -486
+m y -975
+p v -486
+p y -975
+p x -975
+c v -486
+c y -975
+c w -975
+v o -975
+v g -486
+v c -486
+v d -486
+v a -486
+v q -486
+e v -486
+e y -975
+b v -975
+b y -1461
+b w -1461
+y o -975
+y g -486
+y c -975
+y d -975
+y a -975
+y q -975
+x o -975
+x c -975
+x e -975
+x d -975
+x a -975
+x q -975
+a v -486
+a y -975
+a w -975
+w o -975
+w g -486
+w c -486
+w d -486
+w a -486
+w q -486
+T S -975
+L a -975
+L S -1461
+R o -486
+R y -486
+P Z -1461
+P X -1461
+P W -1461
+C X -1461
+C W -1461
+V S -975
+S T -1461
+S V -1461
+S Y -1461
+S X -975
+S A -975
+S W -1461
+Y S -975
+X a -975
+X u -975
+X S -975
+A t -1461
+A c -1461
+A d -975
+A a -975
+A u -975
+A q -1461
+A S -1461
+W S -486
+J y -486
+K c -1461
+K u -975
+K S -975
+o f -486
+h w -975
+n w -975
+m w -975
+r o -486
+p w -975
+c x -975
+v e -486
+e x -975
+e w -975
+b f -486
+s v -486
+s y -975
+s w -975
+y e -975
+f o -486
+w e -486
+k o -975
+k c -486
+k v -486
+k e -486
+k d -486
+k y -486
+k a -486
+k w -486
+k q -486
+O Z -486
+P y -486
+C Z -486
+E o -486
+E v -486
+E y -486
+E w -486
+Z o -975
+Z e -975
+Z d -975
+Z y -486
+Z a -975
+Z w -486
+D Z -975
+D J -486
+B Z -486
+S Z -486
+A s -486
+J o -486
+K a -975
+t o -486
+o t -486
+o g -486
+o z -486
+o j -486
+g o -486
+v y -486
+v w -486
+z o -486
+b t -486
+b g -486
+b z -486
+b j -486
+y v -486
+y y -486
+y w -486
+x v -486
+x y -486
+x w -486
+w v -486
+w y -486
+w w -486
+C o -486
+C y -486
+B o -486
+B y -486
+U o -486
+U v -486
+U y -486
+U w -486
+L ' -6342
+T char173 -2925
+T hy -2925
+T - -2925
+T en -2925
+T em -2925
+A ' -2439
+char173 T -3414
+hy T -3414
+- T -3414
+en T -3414
+em T -3414
+Y char173 -2439
+Y hy -2439
+Y - -2439
+Y en -2439
+Y em -2439
+p ' -975
+c ' -1461
+e ' -1461
+b ' -1461
+a ' -1461
+V char173 -975
+V hy -975
+V - -975
+V en -975
+V em -975
+h ' -1461
+n ' -975
+m ' -975
+W char173 -486
+W hy -486
+W - -486
+W en -486
+W em -486
+' d -2439
+s ' -486
+L char173 -1950
+L hy -1950
+L - -1950
+L en -1950
+L em -1950
+X char173 -1461
+X hy -1461
+X - -1461
+X en -1461
+X em -1461
+A char173 -1950
+A hy -1950
+A - -1950
+A en -1950
+A em -1950
+K char173 -1461
+K hy -1461
+K - -1461
+K en -1461
+K em -1461
+' s -1461
+char173 X -1461
+hy X -1461
+- X -1461
+char173 A -975
+hy A -975
+- A -975
+en X -1461
+en A -975
+em X -1461
+b f -486
+' n -1461
+' m -1461
+' r -1461
+' v -1950
+charset
+! 8781,18165,0,2643,33,1012 2 3617
+" 14148,18135,0,1890,-3297,1012 2 3618
+sh 16587,18105,0,1677,-99,1012 2 3619
+# "
+Do 16587,18738,630,495,-1428,495 2 3620
+$ "
+% 26346,18720,840,0,-2070 2 3621
+& 20004,18495,360,54,-231,54 2 3622
+' 8781,18135,0,3414,-2601,1012 2 51751
+( 8781,18135,2445,3198,-834,1012 2 3624
+) 8781,18135,2445,180,2184,180 2 3625
+* 16587,18582,0,0,-3291 2 3626
++ 26346,14940,0,0,-4728 0 3627
+, 8781,3255,2580,0,1794 0 3628
+char173 8781,7737,0,624,270,624 0 3629
+hy "
+- "
+. 8781,3255,0,0,453 0 3630
+sl 8781,18135,1470,4308,2982,1012 2 3631
+/ "
+0 16587,18465,360,1398,-357,1012 2 3632
+1 16587,18105,0,0,-3771 2 3633
+2 16587,18465,0,984,414,984 2 3634
+3 16587,18465,360,1794,363,1012 2 3635
+4 16587,18105,0,1389,1245,1012 2 3636
+5 16587,18105,360,2424,-39,1012 2 3637
+6 16587,18465,360,2316,-345,1012 2 3638
+7 16587,18105,0,1770,-1455,1012 2 3639
+8 16587,18465,360,1776,435,1012 2 3640
+9 16587,18465,360,1464,369,1012 2 3641
+: 8781,12612,0,540,453,540 0 3642
+; 8781,12612,2580,732,1794,732 0 3643
+< 26346,16068,0,0,-3981 0 3644
+= 26346,10563,0,0,-5079 0 3645
+> 26346,16068,0,0,-3981 0 3646
+? 13662,18315,0,1908,-951,1012 2 3647
+at 26346,21057,2679,1164,-888,1012 2 3648
+@ "
+A 19515,18135,0,0,2535 2 3649
+B 16587,18135,0,1848,1233,1012 2 3650
+C 18540,18495,360,1737,-633,1012 2 3651
+D 19029,18135,0,924,1227,924 2 3652
+E 15126,18135,0,3285,1188,1012 2 3653
+F 14637,18135,0,3723,1200,1012 2 3654
+G 19515,18495,360,1380,-786,1012 2 3655
+H 19029,18135,0,2856,1161,1012 2 3656
+I 7317,18135,0,3219,1521,1012 2 3657
+J 14637,18135,360,3054,1341,1012 2 3658
+K 17565,18135,0,3273,534,1012 2 3659
+L 14148,18135,0,0,1185 2 3660
+M 23907,18135,0,2730,1281,1012 2 3661
+N 19029,18135,0,2883,1248,1012 2 3662
+O 20004,18495,360,969,-705,969 2 3663
+P 15612,18135,0,2871,1203,1012 2 3664
+Q 20490,18495,360,531,-714,531 2 3665
+R 17076,18135,0,2247,1200,1012 2 3666
+S 17076,18495,360,1797,117,1012 2 3667
+T 16587,18135,0,3990,-2166,1012 2 3668
+U 19029,18135,360,2898,-384,1012 2 3669
+V 19029,18135,0,4005,-2604,1012 2 3670
+W 26346,18135,0,3900,-2478,1012 2 3671
+X 19029,18135,0,3222,1893,1012 2 3672
+Y 18051,18135,0,3942,-2616,1012 2 3673
+Z 16101,18135,0,3348,1491,1012 2 3674
+lB 8781,18135,2445,4068,1977,1012 2 3675
+[ "
+rs 8781,18135,1470,540,-1632,540 2 3676
+\ "
+rB 8781,18135,2445,2919,3126,1012 2 3677
+] "
+ha 13173,19758,0,36,36,36 2 51875
+_ 13173,191367,6588,1317,1317,1012 3 3679
+oq 8781,18135,0,2880,-2067,1012 2 51808
+` "
+a 14148,12990,360,651,978,651 0 3681
+b 15126,18165,360,498,1566,498 2 3682
+c 14148,12990,360,903,411,903 0 3683
+d 15126,18165,360,3291,477,1012 2 3684
+e 14148,12990,360,924,600,924 0 3685
+f 9759,18315,0,4158,297,1012 2 3686
+g 15126,12990,5187,1683,2037,1012 1 3687
+h 15126,18165,0,684,1527,684 2 3688
+i 6342,18165,0,3591,1872,1012 2 3689
+j 6342,18165,4995,3681,5787,1012 3 3690
+k 14148,18165,0,2109,1359,1012 2 3691
+l 6342,18165,0,3579,1839,1012 2 3692
+m 22932,12990,0,609,1551,609 0 3693
+n 15126,12990,0,729,1482,729 0 3694
+o 15126,12990,360,492,465,492 0 3695
+p 15126,12990,4680,531,2868,531 1 3696
+q 15126,12990,4680,1671,471,1012 1 3697
+r 9270,12990,0,2751,1533,1012 0 3698
+s 13173,12990,360,984,1026,984 0 3699
+t 9759,16146,360,2166,-522,1012 0 3700
+u 15126,12630,360,1557,666,1012 0 3701
+v 14637,12630,0,2502,-837,1012 0 3702
+w 22932,12630,0,2004,-1311,1012 0 3703
+x 14637,12630,0,2088,2364,1012 0 3704
+y 14637,12630,4680,2472,-528,1012 1 3705
+z 12684,12630,0,1701,1482,1012 0 3706
+lC 13173,20130,6075,3600,-1356,1012 3 3707
+{ "
+ba 13173,19758,6588,0,-4596 3 3708
+| "
+rC 13173,20130,6075,0,3360 3 3709
+} "
+ti 26346,9435,0,0,-4029 0 51876
+char192 19515,23220,0,0,2535 2 3776
+`A "
+char194 19515,23220,0,0,2535 2 3778
+^A "
+char200 15126,23220,0,3285,1188,1012 2 3784
+`E "
+char202 15126,23220,0,3285,1188,1012 2 3786
+^E "
+char203 15126,22830,0,3285,1188,1012 2 3787
+:E "
+char206 7317,23220,0,5631,1521,1012 2 3790
+^I "
+char207 7317,22830,0,6792,1521,1012 2 3791
+:I "
+char180 16587,18105,0,360,-7359,360 2 3764
+aa "
+ga 16587,18105,0,0,-6009 2 3680
+a^ 16587,18105,0,0,-4518 2 3678
+^ "
+char168 16587,18180,0,693,-5457,693 2 3752
+ad "
+a~ 16587,17994,0,771,-5169,771 2 3710
+~ "
+char217 19029,23220,360,2898,-384,1012 2 3801
+`U "
+char219 19029,23220,360,2898,-384,1012 2 3803
+^U "
+char221 18051,23220,0,3942,-2616,1012 2 3805
+'Y "
+char253 14637,18105,4680,2472,-528,1012 3 3837
+'y "
+char176 16587,18465,0,0,-3642 2 3760
+de "
+char199 18540,18495,5409,1737,-633,1012 3 3783
+,C "
+char231 14148,12990,5046,903,411,903 1 3815
+,c "
+char209 19029,23124,0,2883,1248,1012 2 3793
+~N "
+char241 15126,17994,0,1503,1482,1012 2 3825
+~n "
+char161 8781,12651,5514,432,2244,432 1 3745
+r! "
+char191 13662,12486,5829,0,1398 1 3775
+r? "
+char164 16587,15834,0,753,-774,753 0 3748
+Cs "
+char163 16587,18465,0,2046,663,1012 2 3747
+Po "
+char165 16587,18105,0,4872,-30,1012 2 3749
+Ye "
+char167 16587,18495,360,0,-2661 2 3751
+sc "
+Fn 16587,18315,0,1008,-3099,1008 2 51871
+char162 16587,18750,630,678,-1458,678 2 3746
+ct "
+char226 14148,18105,360,651,978,651 2 3810
+^a "
+char234 14148,18105,360,924,600,924 2 3818
+^e "
+char244 15126,18105,360,492,465,492 2 3828
+^o "
+char251 15126,18105,360,1557,666,1012 2 3835
+^u "
+char225 14148,18105,360,1581,978,1012 2 3809
+'a "
+char233 14148,18105,360,1581,600,1012 2 3817
+'e "
+char243 15126,18105,360,1092,465,1012 2 3827
+'o "
+char250 15126,18105,360,1557,666,1012 2 3834
+'u "
+char224 14148,18105,360,651,978,651 2 3808
+`a "
+char232 14148,18105,360,924,600,924 2 3816
+`e "
+char242 15126,18105,360,492,465,492 2 3826
+`o "
+char249 15126,18105,360,1557,666,1012 2 3833
+`u "
+char228 14148,18180,360,1914,978,1012 2 3812
+:a "
+char235 14148,18180,360,1914,600,1012 2 3819
+:e "
+char246 15126,18180,360,1425,465,1012 2 3830
+:o "
+char252 15126,18180,360,1557,666,1012 2 3836
+:u "
+char197 19515,25830,0,0,2535 2 3781
+oA "
+char238 6342,18105,0,4479,1860,1012 2 3822
+^i "
+char216 20004,18495,360,2802,1200,1012 2 3800
+/O "
+char198 25857,18135,0,3294,2781,1012 2 3782
+AE "
+char229 14148,20100,360,651,978,651 2 3813
+oa "
+char237 6342,18105,0,5484,1860,1012 2 3821
+'i "
+char248 15126,12990,360,1764,1686,1012 0 3832
+/o "
+char230 22443,12990,360,840,906,840 0 3814
+ae "
+char196 19515,22830,0,693,2535,693 2 3780
+:A "
+char236 6342,18105,0,2136,1860,1012 2 3820
+`i "
+char214 20004,22830,360,969,-705,969 2 3798
+:O "
+char220 19029,22830,360,2898,-384,1012 2 3804
+:U "
+char201 15126,23220,0,3285,1188,1012 2 3785
+'E "
+char239 6342,18180,0,5817,1860,1012 2 3823
+:i "
+char223 16101,18315,360,795,1515,795 2 3807
+ss "
+char212 20004,23220,360,969,-705,969 2 3796
+^O "
+char193 19515,23220,0,0,2535 2 3777
+'A "
+char195 19515,23124,0,1020,2535,1012 2 3779
+~A "
+char227 14148,17994,360,1992,978,1012 2 3811
+~a "
+char208 19029,18135,0,924,1227,924 2 3792
+-D "
+char240 15126,18693,360,492,465,492 2 3824
+Sd "
+char205 7317,23220,0,5907,1521,1012 2 3789
+'I "
+char204 7317,23220,0,3219,1521,1012 2 3788
+`I "
+char211 20004,23220,360,969,-705,969 2 3795
+'O "
+char210 20004,23220,360,969,-705,969 2 3794
+`O "
+char213 20004,23124,360,969,-705,969 2 3797
+~O "
+char245 15126,17994,360,1503,465,1012 2 3829
+~o "
+vS 17076,23220,360,2220,117,1012 2 51795
+vs 13173,18105,360,2985,1026,1012 2 51827
+char218 19029,23220,360,2898,-384,1012 2 3802
+'U "
+:Y 18051,22830,0,3942,-2616,1012 2 51801
+char255 14637,18180,4680,2472,-528,1012 3 3839
+:y "
+char222 15612,18135,0,1857,1209,1012 2 3806
+TP "
+char254 15126,18165,4680,516,2856,516 3 3838
+Tp "
+char181 15612,12630,4680,1422,2907,1012 1 3765
+char182 16590,19635,4200,0,-2529 2 3766
+ps "
+char190 26346,18465,990,0,-2625 2 3774
+34 "
+\- 26346,8445,0,0,-4746 0 51757
+char188 26346,18465,990,0,-2682 2 3772
+14 "
+char189 26346,18465,990,0,-3168 2 3773
+12 "
+char170 10734,18465,0,2211,-1464,1012 2 3754
+Of "
+char186 10734,18465,0,2520,-1473,1012 2 3770
+Om "
+char171 14637,11115,0,1530,180,1012 0 3755
+Fo "
+char187 14637,11115,0,243,1467,243 0 3771
+Fc "
+char177 26346,14670,0,0,-4695 0 3761
+char166 13173,19083,5916,0,-4596 3 3750
+bb "
+char169 13173,19635,0,4881,-3090,1012 2 3753
+co "
+char172 26346,11787,0,0,-4329 0 3756
+no "
+char174 13173,19635,0,4881,-3090,1012 2 3758
+rg "
+char178 10245,18465,0,2217,-933,1012 2 3762
+S2 "
+char179 10245,18465,0,2439,-957,1012 2 3763
+S3 "
+char184 16587,195102,5046,0,-1809 3 3768
+ac "
+char185 10245,18345,0,1083,-2880,1012 2 3769
+S1 "
+char215 26346,14154,0,0,-5958 0 3799
+char247 26346,12870,0,0,-4767 0 3831
+char183 8781,10692,0,276,-2055,276 0 3767
+fm 8781,18105,0,2145,-2916,1012 2 51873
+sd 16587,18105,0,0,-2916 2 51874
+dg 16587,18135,0,0,-2718 2 51755
+tm 16101,17850,0,2421,-2958,1012 2 51796
+ah 16587,18105,0,1278,-6441,1012 2 51935
+ao 16587,20100,0,0,-7413 2 51930
+f/ 2439,18465,990,9276,7884,1012 2 51759
+em 26346,7620,0,0,-2226 0 51789
+en 16587,7620,0,72,-372,72 0 51790
+dd 16587,18135,0,0,-2718 2 51773
+.i 6342,12630,0,1857,1860,1012 0 51957
+aq 8781,18135,0,2100,-3297,1012 2 3623
+bu 13173,14226,0,0,-498 0 51889
+'C 18540,23220,360,1737,-633,1012 2 20166
+'c 14148,18105,360,1581,411,1012 2 20198
+lq 13173,18135,0,3480,-1524,1012 2 51838
+rq 13173,18135,0,4002,-2046,1012 2 51746
+Bq 13173,3234,2241,0,2283 0 51772
+vz 12684,18105,0,3231,1482,1012 2 51834
+fi 16101,18315,0,3693,-33,1012 2 51881
+fl 16101,18315,0,3678,-132,1012 2 51882
+ff 18051,18315,0,4557,-114,1012 2 51883
+Fi 24396,18315,0,3795,-126,1012 2 51884
+Fl 24396,18315,0,3666,-42,1012 2 51885
+ij 12684,18165,4995,3681,1872,1012 3 51958
+bq 8781,3234,2241,0,1878 0 51756
+%0 26346,18720,840,696,51,696 2 51901
+char175 16587,17778,0,102,-5931,102 2 3759
+a- "
+ab 16587,18147,0,771,-5874,771 2 51926
+a. 16587,18222,0,0,-7887 2 51927
+oe 23907,12990,360,525,258,525 0 51823
+OE 26346,18270,135,3186,-819,1012 2 51791
+fo 9759,11142,0,1299,-1029,1012 0 51886
+fc 9759,11142,0,27,243,27 0 51887
+sq 19029,15624,0,0,-2022 0 51899
+/L 14148,18135,0,0,1692 2 51944
+/l 7320,18165,0,3519,1320,1012 2 51960
+a" 16587,18105,0,3672,-5376,1012 2 51933
+ho 16587,279,4248,0,-6180 0 51934
+vZ 16101,23220,0,3348,1491,1012 2 51802
+IJ 21954,18135,360,3054,1521,1012 2 51942
diff --git a/font/devlj4/UCB b/font/devlj4/UCB
new file mode 100644
index 00000000..c67dc51b
--- /dev/null
+++ b/font/devlj4/UCB
@@ -0,0 +1,774 @@
+name UCB
+spacewidth 5856
+pcltypeface 4148
+pclproportional 1
+pclweight 3
+pclstyle 4
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -2925
+P . -4389
+P , -4389
+V A -1950
+A V -1950
+T o -2925
+T r -2925
+T c -2925
+T e -2925
+T d -2925
+T s -2925
+T y -2925
+T a -2925
+T w -2925
+T u -2925
+T J -3414
+L T -2925
+L Y -2925
+Y o -2925
+Y e -2925
+Y a -2439
+Y J -3414
+A W -1461
+W A -1461
+T A -2439
+V o -1461
+V e -1461
+V a -1461
+Y A -2439
+F A -1461
+F . -2925
+F , -2925
+A T -2439
+A Y -2439
+v . -1461
+v , -1461
+y . -1461
+y , -1461
+T . -2925
+T , -2925
+L W -1461
+P A -1461
+V J -1950
+V . -2925
+V , -2925
+Y . -2925
+Y , -2925
+W o -975
+W e -975
+W a -975
+W . -1461
+W , -1461
+r . -1461
+r , -1461
+w . -975
+w , -975
+Y u -1461
+A v -1461
+A y -975
+A w -975
+o . -1461
+o , -1461
+p . -975
+p , -975
+e . -975
+e , -975
+b . -975
+b , -975
+O T -1461
+O V -486
+O Y -1461
+O . -1461
+O , -1461
+L y -975
+L O -1461
+L G -1950
+L C -1461
+L Q -1461
+P J -1950
+V y -486
+V u -486
+V O -486
+V G -486
+V C -486
+V Q -486
+D T -1950
+D V -486
+D Y -1461
+D . -1950
+D , -1950
+Y O -1461
+Y G -1461
+Y C -1461
+Y Q -1461
+F o -975
+F e -975
+F a -975
+c . -975
+c , -975
+O A -975
+O W -486
+L U -1461
+R T -975
+R V -486
+R Y -975
+R W -486
+G T -1461
+P o -1461
+P g -1461
+P e -1461
+P a -975
+C A -975
+C . -1461
+C , -1461
+D A -975
+D W -486
+B T -1461
+B Y -1461
+B . -1461
+B , -1461
+F J -1461
+A O -975
+A G -975
+A C -975
+A U -975
+A Q -975
+W r -486
+W y -486
+W u -486
+W O -486
+W G -486
+W C -486
+W J -1461
+W Q -486
+J A -975
+J . -1461
+J , -1461
+U A -975
+U . -1461
+U , -1461
+Q W -486
+f . -486
+f , -486
+T O -1461
+T G -1950
+T C -1461
+T Q -1461
+O X -1461
+L o -1461
+L e -1461
+L q -975
+G V -486
+G Y -1461
+G W -486
+P T -975
+P V -486
+P Y -975
+C T -1461
+C V -486
+C Y -1461
+D X -1461
+B V -486
+B X -1461
+B A -975
+B W -486
+S . -975
+S , -975
+X o -1461
+X e -1461
+X y -975
+X O -1461
+X G -1461
+X C -1461
+X Q -1461
+A o -975
+A e -975
+K o -1461
+K e -1461
+K y -975
+K w -975
+K O -1461
+K G -1461
+K C -1461
+K Q -1461
+o v -486
+o y -486
+o x -486
+o w -486
+h v -486
+h y -486
+n v -486
+n y -486
+m v -486
+m y -486
+r g -486
+p v -486
+p y -486
+p x -486
+c v -486
+c y -486
+c w -486
+v o -486
+v g -486
+v c -486
+v d -486
+v a -486
+v q -486
+e v -486
+e y -486
+b v -486
+b y -486
+b w -486
+s . -486
+s , -486
+y o -486
+y g -486
+y c -486
+y d -486
+y a -486
+y q -486
+f g -486
+x o -486
+x c -486
+x e -486
+x d -486
+x a -486
+x q -486
+a v -486
+a y -486
+a w -486
+w o -486
+w g -486
+w c -486
+w d -486
+w a -486
+w q -486
+T S -975
+L a -486
+L S -975
+P s -975
+P Z -975
+P X -975
+P W -486
+C X -1461
+C W -486
+C J -486
+V S -486
+S T -975
+S V -486
+S Y -975
+S X -975
+S A -975
+S W -486
+Y S -975
+X a -486
+X u -975
+X S -975
+A t -975
+A c -975
+A d -975
+A a -486
+A u -975
+A q -975
+A S -975
+W S -486
+K c -1461
+K u -975
+K S -975
+o f -486
+h w -486
+n w -486
+m w -486
+r o -486
+r c -486
+r e -486
+r d -486
+r a -486
+r q -486
+p f -486
+p w -486
+c f -486
+c x -486
+v e -486
+v s -486
+e f -486
+e x -486
+e w -486
+b f -486
+s v -486
+s y -486
+s f -486
+s x -486
+s w -486
+y e -486
+y s -486
+f o -486
+f c -486
+f e -486
+f d -486
+f s -486
+f a -486
+f q -486
+x s -486
+w e -486
+w s -486
+k o -975
+k c -975
+k e -975
+k d -975
+k a -486
+k q -975
+O Z -486
+O J -486
+L J -486
+C Z -486
+E J -486
+Z o -1461
+Z e -1461
+Z d -975
+Z s -975
+Z y -486
+Z a -486
+Z w -486
+Z u -486
+Z O -486
+Z G -486
+Z C -486
+Z S -486
+Z J -486
+Z Q -486
+D Z -486
+D J -486
+B Z -486
+B J -486
+S Z -486
+S J -486
+X J -486
+A s -975
+A J -486
+J J -486
+U J -486
+K a -486
+K J -486
+h f -486
+n f -486
+m f -486
+r s -486
+a f -486
+k s -975
+R J -486
+G J -486
+A f -486
+L ' -4389
+T char173 -2925
+T hy -2925
+T - -2925
+T en -2925
+T em -2925
+A ' -1461
+char173 T -2925
+hy T -2925
+- T -2925
+en T -2925
+em T -2925
+Y char173 -1461
+Y hy -1461
+Y - -1461
+Y en -1461
+Y em -1461
+p ' -1461
+c ' -975
+e ' -1461
+b ' -1461
+a ' -975
+V char173 -486
+V hy -486
+V - -486
+V en -486
+V em -486
+h ' -975
+n ' -975
+m ' -975
+W char173 -486
+W hy -486
+W - -486
+W en -486
+W em -486
+' d -975
+s ' -975
+L char173 -1950
+L hy -1950
+L - -1950
+L en -1950
+L em -1950
+X char173 -1461
+X hy -1461
+X - -1461
+X en -1461
+X em -1461
+A char173 -975
+A hy -975
+A - -975
+A en -975
+A em -975
+K char173 -1461
+K hy -1461
+K - -1461
+K en -1461
+K em -1461
+' s -975
+char173 X -1461
+hy X -1461
+- X -1461
+char173 A -975
+hy A -975
+- A -975
+en X -1461
+en A -975
+em X -1461
+b f -486
+Z char173 -486
+Z hy -486
+Z - -486
+Z en -486
+Z em -486
+charset
+! 7806,18135 2 3617
+" 10734,18135 2 3618
+sh 12684,18360,825 2 3619
+# "
+Do 12684,18705,765 2 3620
+$ "
+% 17565,18765,900 2 3621
+& 16587,18390,255 2 3622
+' 5856,18135 2 51751
+( 5856,18135,2430 2 3624
+) 5856,18135,2430 2 3625
+* 12684,18495 2 3626
++ 17565,12810 0 3627
+, 5856,3465,2430 0 3628
+char173 5856,7710 0 3629
+hy "
+- "
+. 5856,3330 0 3630
+sl 5856,18165,2430 2 3631
+/ "
+0 12684,18360,255 2 3632
+1 12684,18105 2 3633
+2 12684,18360 2 3634
+3 12684,18360,255 2 3635
+4 12684,18105 2 3636
+5 12684,18105,255 2 3637
+6 12684,18360,255 2 3638
+7 12684,18105 2 3639
+8 12684,18360,255 2 3640
+9 12684,18360,255 2 3641
+: 5856,12378 0 3642
+; 5856,12378,2430 0 3643
+< 26346,16068 0 3644
+= 17565,9792 0 3645
+> 26346,16068 0 3646
+? 11709,18390 2 3647
+at 17565,18357,3219 2 3648
+@ "
+A 14637,18135 2 3649
+B 14148,18135 2 3650
+C 13662,18390,255 2 3651
+D 14637,18135 2 3652
+E 12198,18135 2 3653
+F 11709,18135 2 3654
+G 14637,18390,255 2 3655
+H 14637,18135 2 3656
+I 6831,18135 2 3657
+J 12684,18135,255 2 3658
+K 14148,18135 2 3659
+L 11220,18135 2 3660
+M 19515,18135 2 3661
+N 15126,18135 2 3662
+O 14637,18390,255 2 3663
+P 13662,18135 2 3664
+Q 15126,18390,255 2 3665
+R 13662,18135 2 3666
+S 14148,18390,255 2 3667
+T 13173,18135 2 3668
+U 14637,18135,255 2 3669
+V 13662,18135 2 3670
+W 20490,18135 2 3671
+X 14637,18135 2 3672
+Y 13662,18135 2 3673
+Z 12198,18135 2 3674
+lB 5856,18135,2430 2 3675
+[ "
+rs 5856,18165,2430 2 3676
+\ "
+rB 5856,18135,2430 2 3677
+] "
+ha 13173,19758 2 51875
+_ 13173,191367,6588 3 3679
+oq 5856,18135 2 51808
+` "
+a 11709,12885,255 0 3681
+b 11709,18165,255 2 3682
+c 10734,12885,255 0 3683
+d 11709,18165,255 2 3684
+e 11220,12885,255 0 3685
+f 8295,18315 2 3686
+g 11709,12885,4995 1 3687
+h 12198,18165 2 3688
+i 6342,18165 2 3689
+j 6342,18165,4995 3 3690
+k 11709,18165 2 3691
+l 6342,18165 2 3692
+m 17565,12885 0 3693
+n 12198,12885 0 3694
+o 11709,12885,255 0 3695
+p 11709,12885,4995 1 3696
+q 11709,12885,4995 1 3697
+r 8781,12885 0 3698
+s 10734,12885,255 0 3699
+t 8295,16086,255 0 3700
+u 12198,12630,255 0 3701
+v 11709,12630 0 3702
+w 18540,12630 0 3703
+x 11709,12630 0 3704
+y 11709,12630,4680 1 3705
+z 9759,12630 0 3706
+lC 13173,20130,6075 3 3707
+{ "
+ba 13173,19758,6588 3 3708
+| "
+rC 13173,20130,6075 3 3709
+} "
+ti 26346,9435 0 51876
+char192 14637,23130 2 3776
+`A "
+char194 14637,23130 2 3778
+^A "
+char200 12198,23130 2 3784
+`E "
+char202 12198,23130 2 3786
+^E "
+char203 12198,22815 2 3787
+:E "
+char206 6831,23130 2 3790
+^I "
+char207 6831,22815 2 3791
+:I "
+char180 12684,18285 2 3764
+aa "
+ga 12684,18285 2 3680
+a^ 12684,18285 2 3678
+^ "
+char168 12684,18225 2 3752
+ad "
+a~ 12684,17874 2 3710
+~ "
+char217 14637,23130,255 2 3801
+`U "
+char219 14637,23130,255 2 3803
+^U "
+char221 13662,23130 2 3805
+'Y "
+char253 11709,18285,4680 3 3837
+'y "
+char176 12684,18360 2 3760
+de "
+char199 13662,18390,5580 3 3783
+,C "
+char231 10734,12885,5190 1 3815
+,c "
+char209 15126,23031 2 3793
+~N "
+char241 12198,17874 2 3825
+~n "
+char161 7806,12630,5505 1 3745
+r! "
+char191 11709,12576,5814 1 3775
+r? "
+char164 12684,15834 0 3748
+Cs "
+char163 12684,18360 2 3747
+Po "
+char165 12684,18105 2 3749
+Ye "
+char167 12684,18495,600 2 3751
+sc "
+Fn 12684,18315 2 51871
+char162 12684,18705,765 2 3746
+ct "
+char226 11709,18285,255 2 3810
+^a "
+char234 11220,18285,255 2 3818
+^e "
+char244 11709,18285,255 2 3828
+^o "
+char251 12198,18285,255 2 3835
+^u "
+char225 11709,18285,255 2 3809
+'a "
+char233 11220,18285,255 2 3817
+'e "
+char243 11709,18285,255 2 3827
+'o "
+char250 12198,18285,255 2 3834
+'u "
+char224 11709,18285,255 2 3808
+`a "
+char232 11220,18285,255 2 3816
+`e "
+char242 11709,18285,255 2 3826
+`o "
+char249 12198,18285,255 2 3833
+`u "
+char228 11709,18225,255 2 3812
+:a "
+char235 11220,18225,255 2 3819
+:e "
+char246 11709,18225,255 2 3830
+:o "
+char252 12198,18225,255 2 3836
+:u "
+char197 14637,25080 2 3781
+oA "
+char238 6342,18285 2 3822
+^i "
+char216 14637,19890,2019 2 3800
+/O "
+char198 20490,18135 2 3782
+AE "
+char229 11709,19455,255 2 3813
+oa "
+char237 6342,18285 2 3821
+'i "
+char248 11709,14256,2172 0 3832
+/o "
+char230 17565,12885,255 0 3814
+ae "
+char196 14637,22815 2 3780
+:A "
+char236 6342,18285 2 3820
+`i "
+char214 14637,22815,255 2 3798
+:O "
+char220 14637,22815,255 2 3804
+:U "
+char201 12198,23130 2 3785
+'E "
+char239 6342,18225 2 3823
+:i "
+char223 13173,18315,255 2 3807
+ss "
+char212 14637,23130,255 2 3796
+^O "
+char193 14637,23130 2 3777
+'A "
+char195 14637,23031 2 3779
+~A "
+char227 11709,17874,255 2 3811
+~a "
+char208 14637,18135 2 3792
+-D "
+char240 11709,18573,255 2 3824
+Sd "
+char205 6831,23130 2 3789
+'I "
+char204 6831,23130 2 3788
+`I "
+char211 14637,23130,255 2 3795
+'O "
+char210 14637,23130,255 2 3794
+`O "
+char213 14637,23031,255 2 3797
+~O "
+char245 11709,17874,255 2 3829
+~o "
+vS 14148,23130,255 2 51795
+vs 10734,18285,255 2 51827
+char218 14637,23130,255 2 3802
+'U "
+:Y 13662,22815 2 51801
+char255 11709,18225,4680 3 3839
+:y "
+char222 13662,18135 2 3806
+TP "
+char254 11709,18165,4995 3 3838
+Tp "
+char181 15612,12630,4680 1 3765
+char182 12684,19635,4200 2 3766
+ps "
+char190 17565,18765,900 2 3774
+34 "
+\- 17565,7740 0 51757
+char188 17565,18765,900 2 3772
+14 "
+char189 17565,18765,900 2 3773
+12 "
+char170 10734,18360 2 3754
+Of "
+char186 10734,18360 2 3770
+Om "
+char171 11709,11070 0 3755
+Fo "
+char187 11709,11070 0 3771
+Fc "
+char177 17565,12810,2520 0 3761
+char166 13173,19083,5916 3 3750
+bb "
+char169 13173,19635 2 3753
+co "
+char172 17565,10320 0 3756
+no "
+char174 13173,19635 2 3758
+rg "
+char178 8295,18465 2 3762
+S2 "
+char179 8295,18465 2 3763
+S3 "
+char184 12684,195258,5190 3 3768
+ac "
+char185 8295,18345 2 3769
+S1 "
+char215 17565,12345 0 3799
+char247 17565,12015 0 3831
+char183 5856,10251 0 3767
+fm 5856,18105 2 51873
+sd 12684,18105 2 51874
+dg 12684,18135 2 51755
+tm 16101,17850 2 51796
+ah 12684,18285 2 51935
+ao 12684,19455 2 51930
+f/ 2928,18765,900 2 51759
+em 17565,7530 0 51789
+en 12684,7530 0 51790
+dd 12684,18135 2 51773
+.i 6342,12630 0 51957
+aq 5856,18135 2 3623
+bu 13173,14226 0 51889
+'C 13662,23130,255 2 20166
+'c 10734,18285,255 2 20198
+lq 10245,18135 2 51838
+rq 10245,18135 2 51746
+Bq 10245,3513,2382 0 51772
+vz 9759,18285 2 51834
+fi 14148,18315 2 51881
+fl 14148,18315 2 51882
+ff 15126,18315 2 51883
+Fi 20979,18315 2 51884
+Fl 20979,18315 2 51885
+ij 12684,18165,4995 3 51958
+bq 5856,3513,2382 0 51756
+%0 26346,18765,900 2 51901
+char175 12684,17595 2 3759
+a- "
+ab 12684,18285 2 51926
+a. 12684,18345 2 51927
+oe 17565,12885,255 0 51823
+OE 20490,18270,135 2 51791
+fo 6342,11070 0 51886
+fc 6342,11070 0 51887
+sq 19029,15624 0 51899
+/L 11709,18135 2 51944
+/l 6831,18165 2 51960
+a" 12684,18285 2 51933
+ho 12684,300,4335 0 51934
+vZ 12198,23130 2 51802
+IJ 18540,18135,255 2 51942
diff --git a/font/devlj4/UCBI b/font/devlj4/UCBI
new file mode 100644
index 00000000..ceef7343
--- /dev/null
+++ b/font/devlj4/UCBI
@@ -0,0 +1,683 @@
+name UCBI
+spacewidth 5856
+slant 16.500000
+pcltypeface 4148
+pclproportional 1
+pclweight 3
+pclstyle 5
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -2439
+P . -4389
+P , -4389
+V A -1461
+A V -1950
+T o -2439
+T r -1950
+T c -2439
+T e -2439
+T d -2439
+T s -1950
+T y -1950
+T a -2439
+T w -1950
+T u -1950
+T J -1950
+L T -2439
+L Y -2925
+Y o -1950
+Y e -1461
+Y a -1461
+Y J -1950
+A W -1461
+W A -975
+T A -1950
+V o -975
+V e -975
+V a -975
+Y A -1950
+F A -975
+F . -3414
+F , -3414
+A T -2439
+A Y -2439
+v . -975
+v , -975
+y . -975
+y , -975
+T . -1950
+T , -1950
+L W -1461
+P A -1461
+V J -975
+V . -1950
+V , -1950
+Y . -1950
+Y , -1950
+W o -975
+W e -975
+W a -975
+W . -975
+W , -975
+r . -1461
+r , -1461
+w . -975
+w , -975
+Y u -975
+A v -486
+A y -975
+A w -486
+o . -975
+o , -975
+p . -975
+p , -975
+e . -486
+e , -486
+b . -975
+b , -975
+O T -1950
+O V -486
+O Y -975
+O . -1461
+O , -1461
+L y -1461
+L O -1950
+L G -1950
+L C -1950
+L Q -1950
+P J -1461
+V y -486
+V u -486
+V O -486
+V G -486
+V C -486
+V Q -486
+D T -1461
+D V -486
+D Y -975
+D . -1950
+D , -1950
+Y O -975
+Y G -975
+Y C -975
+Y Q -975
+F o -486
+F e -486
+F a -486
+c . -486
+c , -486
+O A -486
+O W -486
+L U -1461
+R T -1461
+R V -486
+R Y -975
+R W -486
+G T -1461
+P o -975
+P g -486
+P e -486
+P a -486
+C A -486
+C . -1461
+C , -1461
+D A -486
+D W -486
+B T -1950
+B Y -975
+B . -486
+B , -486
+F J -486
+A O -486
+A G -486
+A C -486
+A U -486
+A Q -486
+W r -486
+W y -486
+W u -486
+W O -486
+W G -486
+W C -486
+W J -975
+W Q -486
+U A -486
+U . -975
+U , -975
+Q W -486
+T O -1461
+T G -1461
+T C -1461
+T Q -1461
+O X -975
+L o -1461
+L e -1461
+L q -1461
+G V -486
+G Y -975
+G W -486
+P T -1461
+P V -486
+P Y -975
+C T -1950
+C V -486
+C Y -975
+D X -975
+B V -486
+B X -486
+B A -486
+B W -486
+S . -486
+S , -486
+X o -975
+X e -975
+X y -975
+X O -975
+X G -975
+X C -975
+X Q -975
+A o -486
+A e -486
+K o -975
+K e -975
+K y -975
+K w -975
+K O -975
+K G -975
+K C -975
+K Q -975
+o y -486
+o x -975
+h y -486
+n y -486
+m y -486
+r g -486
+p y -486
+p x -975
+c y -486
+e y -486
+b y -486
+x o -975
+x c -975
+x e -486
+x d -975
+x a -486
+x q -975
+a y -486
+T S -486
+L a -486
+L S -975
+P Z -486
+P X -975
+P W -486
+C X -975
+C W -486
+V S -486
+S T -975
+S V -486
+S Y -975
+S X -486
+S A -486
+S W -486
+Y S -486
+X a -486
+X u -975
+X S -486
+A t -486
+A c -486
+A d -486
+A a -486
+A u -486
+A q -486
+A S -486
+W S -486
+K c -975
+K u -975
+K S -486
+r o -486
+r c -486
+r e -486
+r d -486
+r a -486
+r q -486
+c x -486
+e x -486
+s y -486
+k o -486
+k c -486
+k e -486
+k d -486
+k a -486
+k q -486
+O Z -486
+C Z -486
+Z o -486
+Z e -486
+Z d -486
+Z s -486
+Z y -486
+Z a -486
+Z w -486
+Z u -486
+Z O -486
+Z G -486
+Z C -486
+Z S -486
+Z Q -486
+D Z -486
+B Z -486
+S Z -486
+A s -486
+K a -486
+L ' -3903
+T char173 -1950
+T hy -1950
+T - -1950
+T en -1950
+T em -1950
+A ' -1461
+char173 T -2439
+hy T -2439
+- T -2439
+en T -2439
+em T -2439
+Y char173 -975
+Y hy -975
+Y - -975
+Y en -975
+Y em -975
+p ' -975
+c ' -975
+e ' -1461
+b ' -1461
+a ' -975
+V char173 -486
+V hy -486
+V - -486
+V en -486
+V em -486
+h ' -1461
+n ' -975
+m ' -975
+W char173 -486
+W hy -486
+W - -486
+W en -486
+W em -486
+' d -975
+s ' -486
+L char173 -1950
+L hy -1950
+L - -1950
+L en -1950
+L em -1950
+X char173 -975
+X hy -975
+X - -975
+X en -975
+X em -975
+A char173 -486
+A hy -486
+A - -486
+A en -486
+A em -486
+K char173 -975
+K hy -975
+K - -975
+K en -975
+K em -975
+char173 X -975
+hy X -975
+- X -975
+char173 A -486
+hy A -486
+- A -486
+en X -975
+en A -486
+em X -975
+Z char173 -486
+Z hy -486
+Z - -486
+Z en -486
+Z em -486
+charset
+! 7806,18135,0,2628,993,994 2 3617
+" 10734,18135,0,3669,-2133,994 2 3618
+sh 12684,18360,825,2676,684,994 2 3619
+# "
+Do 12684,18840,570,1326,-291,994 2 3620
+$ "
+% 17565,18465,1050,1386,228,994 2 3621
+& 16587,18390,255,609,471,609 2 3622
+' 5856,18135,0,4215,-1392,994 2 51751
+( 5856,18135,2430,4416,744,994 2 3624
+) 5856,18135,2430,1812,3348,994 2 3625
+* 12684,18390,0,1635,-3465,994 2 3626
++ 17565,12810,0,0,-1431 0 3627
+, 5856,3465,2370,0,3042 0 3628
+char173 5856,7785,0,726,585,726 0 3629
+hy "
+- "
+. 5856,3465,0,0,1917 0 3630
+sl 5856,18165,2430,4518,3396,994 2 3631
+/ "
+0 12684,18360,255,2343,627,994 2 3632
+1 12684,18105,0,1020,-2307,994 2 3633
+2 12684,18360,0,2235,1779,994 2 3634
+3 12684,18360,255,2184,687,994 2 3635
+4 12684,18105,0,2082,1284,994 2 3636
+5 12684,18105,255,2490,525,994 2 3637
+6 12684,18360,255,2397,546,994 2 3638
+7 12684,18105,0,3309,315,994 2 3639
+8 12684,18360,255,2274,600,994 2 3640
+9 12684,18360,255,2289,819,994 2 3641
+: 5856,12570,0,1947,1917,994 0 3642
+; 5856,12570,2370,1836,3042,994 0 3643
+< 26346,16068,0,0,-3981 0 3644
+= 17565,9792,0,0,-1455 0 3645
+> 26346,16068,0,0,-3981 0 3646
+? 11709,18390,0,2205,-738,994 2 3647
+at 17565,18372,3231,2163,1152,994 2 3648
+@ "
+A 14637,18135,0,0,2460 2 3649
+B 14148,18135,0,1668,1362,994 2 3650
+C 13662,18390,255,2247,375,994 2 3651
+D 14637,18135,0,1851,1398,994 2 3652
+E 12198,18135,0,3423,1440,994 2 3653
+F 11709,18135,0,3855,1584,994 2 3654
+G 14637,18390,255,1926,117,994 2 3655
+H 14637,18135,0,3243,1542,994 2 3656
+I 6831,18135,0,3342,1641,994 2 3657
+J 12684,18135,255,3231,1059,994 2 3658
+K 14148,18135,0,3366,1374,994 2 3659
+L 11220,18135,0,0,1488 2 3660
+M 19515,18135,0,2958,1551,994 2 3661
+N 15126,18135,0,3003,1431,994 2 3662
+O 14637,18390,255,1872,204,994 2 3663
+P 13662,18135,0,2412,1506,994 2 3664
+Q 15126,18390,255,1449,189,994 2 3665
+R 13662,18135,0,1968,1545,994 2 3666
+S 14148,18390,255,2079,495,994 2 3667
+T 13173,18135,0,3891,-1554,994 2 3668
+U 14637,18135,255,3147,72,994 2 3669
+V 13662,18135,0,4206,-1620,994 2 3670
+W 20490,18135,0,3927,-699,994 2 3671
+X 14637,18135,0,3828,2505,994 2 3672
+Y 13662,18135,0,4230,-1767,994 2 3673
+Z 12198,18135,0,3639,2217,994 2 3674
+lB 5856,18135,2430,4086,2592,994 2 3675
+[ "
+rs 8295,18165,2430,534,-1680,534 2 3676
+\ "
+rB 5856,18135,2430,3555,3123,994 2 3677
+] "
+ha 13173,19758,0,36,36,36 2 51875
+_ 13173,191367,6588,1317,1317,994 3 3679
+oq 5856,18135,0,3957,-1134,994 2 51808
+` "
+a 11709,12885,255,999,1161,994 0 3681
+b 11709,18165,255,1164,1920,994 2 3682
+c 10734,12885,255,1290,990,994 0 3683
+d 11709,18165,255,3657,1038,994 2 3684
+e 11220,12885,255,1140,1023,994 0 3685
+f 8295,18315,0,4233,960,994 2 3686
+g 11709,12885,4995,2007,2487,994 1 3687
+h 12198,18165,0,987,1677,987 2 3688
+i 6342,18165,0,3393,1722,994 2 3689
+j 6342,18165,4995,3432,4620,994 3 3690
+k 11709,18165,0,2241,1605,994 2 3691
+l 6342,18165,0,3426,1746,994 2 3692
+m 17565,12885,0,1053,1842,994 0 3693
+n 12198,12885,0,915,1734,915 0 3694
+o 11709,12885,255,990,927,990 0 3695
+p 11709,12885,4680,1098,3417,994 1 3696
+q 11709,12885,4680,1926,1122,994 1 3697
+r 8781,12885,0,2637,1686,994 0 3698
+s 10734,12885,255,1116,1380,994 0 3699
+t 8295,15693,255,2280,354,994 0 3700
+u 12198,12630,255,1764,849,994 0 3701
+v 11709,12630,0,2337,-546,994 0 3702
+w 18540,12630,0,2337,-171,994 0 3703
+x 11709,12630,0,2193,2526,994 0 3704
+y 11709,12630,4680,2457,1983,994 1 3705
+z 9759,12630,0,1977,2220,994 0 3706
+lC 13173,20130,6075,3150,-906,994 3 3707
+{ "
+ba 13173,19758,6588,0,-4596 3 3708
+| "
+rC 13173,20130,6075,0,3510 3 3709
+} "
+ti 26346,9435,0,0,-4029 0 51876
+char192 14637,23100,0,0,2460 2 3776
+`A "
+char194 14637,23100,0,1626,2460,994 2 3778
+^A "
+char200 12198,23100,0,3423,1440,994 2 3784
+`E "
+char202 12198,23100,0,3423,1440,994 2 3786
+^E "
+char203 12198,23265,0,3948,1440,994 2 3787
+:E "
+char206 6831,23100,0,5529,1641,994 2 3790
+^I "
+char207 6831,23265,0,6630,1641,994 2 3791
+:I "
+char180 12684,18225,0,1785,-5265,994 2 3764
+aa "
+ga 12684,18225,0,0,-5271 2 3680
+a^ 12684,18225,0,702,-3897,702 2 3678
+^ "
+char168 12684,18120,0,2067,-3990,994 2 3752
+ad "
+a~ 12684,17811,0,1560,-3786,994 2 3710
+~ "
+char217 14637,23100,255,3147,72,994 2 3801
+`U "
+char219 14637,23100,255,3147,72,994 2 3803
+^U "
+char221 13662,23100,0,4230,-1767,994 2 3805
+'Y "
+char253 11709,18225,4680,2457,1983,994 3 3837
+'y "
+char176 12684,18360,0,1377,-3201,994 2 3760
+de "
+char199 13662,18390,5295,2247,375,994 3 3783
+,C "
+char231 10734,12885,5205,1290,1419,994 1 3815
+,c "
+char209 15126,22833,0,3003,1431,994 2 3793
+~N "
+char241 12198,17811,0,1803,1734,994 2 3825
+~n "
+char161 7806,12615,5520,936,2685,936 1 3745
+r! "
+char191 11709,12600,5790,0,2256 1 3775
+r? "
+char164 12684,15834,0,2757,1125,994 0 3748
+Cs "
+char163 12684,18360,0,2571,1257,994 2 3747
+Po "
+char165 12684,18105,0,4791,834,994 2 3749
+Ye "
+char167 12684,18390,255,174,-1545,174 2 3751
+sc "
+Fn 12684,18315,0,2196,-1392,994 2 51871
+char162 12684,18840,570,1299,-636,994 2 3746
+ct "
+char226 11709,18225,255,1188,1161,994 2 3810
+^a "
+char234 11220,18225,255,1434,1023,994 2 3818
+^e "
+char244 11709,18225,255,1188,927,994 2 3828
+^o "
+char251 12198,18225,255,1764,849,994 2 3835
+^u "
+char225 11709,18225,255,2271,1161,994 2 3809
+'a "
+char233 11220,18225,255,2517,1023,994 2 3817
+'e "
+char243 11709,18225,255,2271,927,994 2 3827
+'o "
+char250 12198,18225,255,2028,849,994 2 3834
+'u "
+char224 11709,18225,255,999,1161,994 2 3808
+`a "
+char232 11220,18225,255,1140,1023,994 2 3816
+`e "
+char242 11709,18225,255,990,927,990 2 3826
+`o "
+char249 12198,18225,255,1764,849,994 2 3833
+`u "
+char228 11709,18120,255,2553,1161,994 2 3812
+:a "
+char235 11220,18120,255,2799,1023,994 2 3819
+:e "
+char246 11709,18120,255,2553,927,994 2 3830
+:o "
+char252 12198,18120,255,2310,849,994 2 3836
+:u "
+char197 14637,25164,0,1713,2460,994 2 3781
+oA "
+char238 6342,18225,0,3873,1713,994 2 3822
+^i "
+char216 14637,19854,1755,1872,204,994 2 3800
+/O "
+char198 20490,18135,0,2688,3147,994 2 3782
+AE "
+char229 11709,19089,255,1488,1161,994 2 3813
+oa "
+char237 6342,18225,0,5760,1713,994 2 3821
+'i "
+char248 11709,14208,1830,993,927,993 0 3832
+/o "
+char230 17565,12885,255,924,966,924 0 3814
+ae "
+char196 14637,23265,0,2727,2460,994 2 3780
+:A "
+char236 6342,18225,0,2367,1713,994 2 3820
+`i "
+char214 14637,23265,255,2727,204,994 2 3798
+:O "
+char220 14637,23265,255,3147,72,994 2 3804
+:U "
+char201 12198,23100,0,3660,1440,994 2 3785
+'E "
+char239 6342,18120,0,5238,1713,994 2 3823
+:i "
+char223 13173,18165,0,1956,1704,994 2 3807
+ss "
+char212 14637,23100,255,1872,204,994 2 3796
+^O "
+char193 14637,23100,0,2439,2460,994 2 3777
+'A "
+char195 14637,22833,0,2379,2460,994 2 3779
+~A "
+char227 11709,17811,255,2046,1161,994 2 3811
+~a "
+char208 14637,18135,0,1851,1398,994 2 3792
+-D "
+char240 11709,18756,255,1419,936,994 2 3824
+Sd "
+char205 6831,23100,0,6342,1641,994 2 3789
+'I "
+char204 6831,23100,0,3732,1641,994 2 3788
+`I "
+char211 14637,23100,255,2439,204,994 2 3795
+'O "
+char210 14637,23100,255,1872,204,994 2 3794
+`O "
+char213 14637,22833,255,2379,204,994 2 3797
+~O "
+char245 11709,17811,255,2046,927,994 2 3829
+~o "
+vS 14148,23100,255,2754,495,994 2 51795
+vs 10734,18225,255,2754,1380,994 2 51827
+char218 14637,23100,255,3147,72,994 2 3802
+'U "
+:Y 13662,23265,0,4230,-1767,994 2 51801
+char255 11709,18120,4680,2553,1983,994 3 3839
+:y "
+char222 13662,18135,0,1518,1470,994 2 3806
+TP "
+char254 11709,18165,4680,1098,3417,994 3 3838
+Tp "
+char181 15612,12630,4680,1422,2907,994 1 3765
+char182 12684,19635,4200,2046,-1215,994 2 3766
+ps "
+char190 17565,18465,1050,1788,-174,994 2 3774
+34 "
+\- 17565,7740,0,0,-1455 0 51757
+char188 17565,18345,1050,639,975,639 2 3772
+14 "
+char189 17565,18345,1050,165,1449,165 2 3773
+12 "
+char170 10734,18360,0,1965,-2322,994 2 3754
+Of "
+char186 10734,18360,0,1956,-2496,994 2 3770
+Om "
+char171 11709,10965,0,1749,306,994 0 3755
+Fo "
+char187 11709,10965,0,219,1836,219 0 3771
+Fc "
+char177 17565,12810,2520,0,-1431 0 3761
+char166 13173,19083,5916,0,-4596 3 3750
+bb "
+char169 13173,19635,0,4629,-2838,994 2 3753
+co "
+char172 17565,10320,0,0,-1455 0 3756
+no "
+char174 13173,19635,0,4629,-2838,994 2 3758
+rg "
+char178 8295,18465,0,2814,-432,994 2 3762
+S2 "
+char179 8295,18465,0,2817,-1047,994 2 3763
+S3 "
+char184 12684,195183,5205,0,444 3 3768
+ac "
+char185 8295,18345,0,1920,-2586,994 2 3769
+S1 "
+char215 17565,12345,0,0,-2448 0 3799
+char247 17565,12015,0,0,-1446 0 3831
+char183 5856,10671,0,1371,-189,994 0 3767
+fm 5856,18105,0,3432,-2124,994 2 51873
+sd 12684,18105,0,1554,-2124,994 2 51874
+dg 12684,18135,0,318,-1353,318 2 51755
+tm 16101,17850,0,2169,-2706,994 2 51796
+ah 12684,18225,0,1779,-4974,994 2 51935
+ao 12684,19089,0,1002,-4803,994 2 51930
+f/ 2928,18345,1050,8775,7476,994 2 51759
+em 17565,7605,0,426,354,426 0 51789
+en 12684,7605,0,753,546,753 0 51790
+dd 12684,18135,0,399,-1434,399 2 51773
+.i 6342,12630,0,1770,1713,994 0 51957
+aq 5856,18135,0,3546,-2133,994 2 3623
+bu 13173,14226,0,0,-498 0 51889
+'C 13662,23100,255,3378,375,994 2 20166
+'c 10734,18225,255,2910,990,994 2 20198
+lq 10245,18135,0,3945,-1131,994 2 51838
+rq 10245,18135,0,4314,-1500,994 2 51746
+Bq 10245,3459,2376,0,3000 0 51772
+vz 9759,18225,0,3240,2220,994 2 51834
+fi 14148,18315,0,3318,981,994 2 51881
+fl 14148,18315,0,3378,978,994 2 51882
+ff 15126,18315,0,4389,963,994 2 51883
+Fi 20979,18315,0,3477,981,994 2 51884
+Fl 20979,18315,0,3537,978,994 2 51885
+ij 12684,18165,4995,3432,1722,994 3 51958
+bq 5856,3459,2376,57,2766,57 0 51756
+%0 26346,18465,1050,450,-201,450 2 51901
+char175 12684,16386,0,927,-4566,927 0 3759
+a- "
+ab 12684,18195,0,1674,-4344,994 2 51926
+a. 12684,18120,0,0,-5505 2 51927
+oe 17565,12885,255,903,948,903 0 51823
+OE 20490,18270,135,2994,153,994 2 51791
+fo 6342,10965,0,1878,399,994 0 51886
+fc 6342,10965,0,453,1824,453 0 51887
+sq 19029,15624,0,0,-2022 0 51899
+/L 13173,18135,0,951,96,951 2 51944
+/l 8781,18165,0,2745,807,994 2 51960
+a" 12684,18225,0,4065,-4167,994 2 51933
+ho 12684,918,4755,0,-2397 1 51934
+vZ 12198,23100,0,3729,2217,994 2 51802
+IJ 19515,18135,255,3231,1641,994 2 51942
diff --git a/font/devlj4/UCI b/font/devlj4/UCI
new file mode 100644
index 00000000..9e26536f
--- /dev/null
+++ b/font/devlj4/UCI
@@ -0,0 +1,822 @@
+name UCI
+spacewidth 5856
+slant 16.500000
+pcltypeface 4148
+pclproportional 1
+pclweight 0
+pclstyle 5
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -2925
+P . -5364
+P , -5364
+V A -1950
+A V -1950
+T o -3414
+T r -3414
+T c -3414
+T e -3414
+T d -3414
+T s -3903
+T y -3414
+T a -3414
+T w -3414
+T u -3414
+T J -3414
+L T -3414
+L Y -2925
+Y o -2925
+Y e -2925
+Y a -2439
+Y J -2925
+A W -1950
+W A -1950
+T A -2925
+V o -1950
+V e -1950
+V a -1461
+Y A -2925
+F A -1461
+F . -3903
+F , -3903
+A T -2925
+A Y -2925
+v . -1950
+v , -1950
+y . -2439
+y , -2439
+T . -3414
+T , -3414
+L W -1950
+P A -1461
+V J -1950
+V . -2925
+V , -2925
+Y . -2925
+Y , -2925
+W o -1461
+W e -1461
+W a -1461
+W . -1950
+W , -1950
+r . -1461
+r , -1461
+w . -1950
+w , -1950
+Y u -1461
+A v -975
+A y -975
+A w -975
+o . -486
+o , -486
+p . -486
+p , -486
+e . -486
+e , -486
+b . -486
+b , -486
+O T -1461
+O V -486
+O Y -1461
+O . -975
+O , -975
+L y -2439
+L O -1461
+L G -1461
+L C -1461
+L Q -1461
+P J -1950
+V y -486
+V u -486
+V O -486
+V G -486
+V C -486
+V Q -486
+D T -1461
+D V -486
+D Y -1461
+D . -975
+D , -975
+Y O -975
+Y G -975
+Y C -975
+Y Q -975
+F o -975
+F e -975
+F a -975
+c . -486
+c , -486
+O A -486
+O W -486
+L U -1461
+R T -1461
+R V -486
+R Y -1461
+R W -486
+G T -1461
+P o -1461
+P g -1461
+P e -1461
+P a -975
+C A -975
+C . -975
+C , -975
+D A -486
+D W -486
+B T -1461
+B Y -1461
+B . -975
+B , -975
+F J -975
+A O -486
+A G -486
+A C -486
+A U -486
+A Q -486
+W r -486
+W y -486
+W u -486
+W O -486
+W G -486
+W C -486
+W J -1461
+W Q -486
+J A -486
+J . -1461
+J , -1461
+U A -486
+U . -975
+U , -975
+Q W -486
+f . -975
+f , -975
+T O -975
+T G -975
+T C -975
+T Q -975
+O X -486
+L o -1950
+L e -1950
+L q -1950
+G V -486
+G Y -1461
+G W -486
+P T -1461
+P V -486
+P Y -1461
+C T -1461
+C V -975
+C Y -1461
+D X -486
+B V -486
+B X -486
+B A -486
+B W -486
+S . -486
+S , -486
+X o -486
+X e -486
+X y -486
+X O -486
+X G -486
+X C -486
+X Q -486
+A o -486
+A e -486
+K o -975
+K e -975
+K y -975
+K w -975
+K O -975
+K G -975
+K C -975
+K Q -975
+o v -486
+o y -486
+o x -486
+o w -486
+h v -486
+h y -486
+n v -486
+n y -486
+m v -486
+m y -486
+r g -486
+p v -486
+p y -486
+p x -486
+c v -486
+c y -486
+c w -486
+v o -486
+v g -486
+v c -486
+v d -486
+v a -486
+v q -486
+e v -486
+e y -486
+b v -486
+b y -486
+b w -486
+s . -486
+s , -486
+y o -486
+y g -486
+y c -486
+y d -486
+y a -486
+y q -486
+f g -486
+x o -486
+x g -486
+x c -486
+x e -486
+x d -486
+x a -486
+x q -486
+a v -486
+a y -486
+a w -486
+w o -486
+w g -486
+w c -486
+w d -486
+w a -486
+w q -486
+T i -486
+T S -486
+L a -1461
+L S -975
+P s -486
+P Z -486
+P X -486
+P W -486
+C X -975
+C W -975
+C J -486
+V i -486
+V S -486
+S T -975
+S V -486
+S Y -975
+S X -486
+S A -486
+S W -486
+Y i -486
+Y S -486
+X a -486
+X u -486
+X S -486
+A t -486
+A g -486
+A c -486
+A d -486
+A a -486
+A u -486
+A q -486
+A S -486
+W i -486
+W S -486
+K c -975
+K u -975
+K S -486
+h w -486
+n w -486
+m w -486
+r o -486
+r c -486
+r e -486
+r d -486
+r a -486
+r q -486
+p w -486
+c x -486
+v e -486
+v s -975
+e x -486
+e w -486
+s v -486
+s y -486
+s x -486
+s w -486
+y e -486
+y s -486
+f o -486
+f c -486
+f e -486
+f d -486
+f s -486
+f a -486
+f q -486
+x s -486
+w e -486
+w s -486
+k o -486
+k g -486
+k c -486
+k e -486
+k d -486
+k a -486
+k q -486
+O Z -486
+L J -975
+C Z -975
+Z o -486
+Z e -486
+Z d -486
+Z s -975
+Z y -486
+Z a -486
+Z w -486
+Z u -486
+Z O -486
+Z G -486
+Z C -486
+Z S -486
+Z J -486
+Z Q -486
+D Z -486
+B Z -486
+S Z -486
+X J -486
+A s -975
+A J -486
+K a -975
+K J -975
+t s -486
+r s -486
+g s -486
+v t -486
+v h -486
+v n -486
+v m -486
+v r -486
+v i -486
+v p -486
+v z -486
+v b -486
+v y -486
+v f -486
+v x -486
+v w -486
+v j -486
+v u -486
+v k -486
+z s -486
+k s -486
+C t -486
+C o -486
+C h -486
+C l -486
+C r -486
+C i -486
+C e -486
+C y -486
+C a -486
+C u -486
+C O -486
+C H -486
+C N -486
+C M -486
+C L -486
+C R -486
+C G -486
+C I -486
+C P -486
+C C -486
+C E -486
+C D -486
+C B -486
+C S -486
+C F -486
+C U -486
+C Q -486
+C K -486
+E s -486
+U s -486
+L ' -3414
+T char173 -3414
+T hy -3414
+T - -3414
+T en -3414
+T em -3414
+A ' -1461
+char173 T -3414
+hy T -3414
+- T -3414
+en T -3414
+em T -3414
+Y char173 -1461
+Y hy -1461
+Y - -1461
+Y en -1461
+Y em -1461
+p ' -1950
+c ' -1950
+e ' -1950
+b ' -1950
+a ' -1950
+V char173 -486
+V hy -486
+V - -486
+V en -486
+V em -486
+h ' -1461
+n ' -1461
+m ' -1461
+W char173 -486
+W hy -486
+W - -486
+W en -486
+W em -486
+' d -486
+s ' -975
+L char173 -1950
+L hy -1950
+L - -1950
+L en -1950
+L em -1950
+X char173 -486
+X hy -486
+X - -486
+X en -486
+X em -486
+A char173 -486
+A hy -486
+A - -486
+A en -486
+A em -486
+K char173 -975
+K hy -975
+K - -975
+K en -975
+K em -975
+' s -486
+char173 X -486
+hy X -486
+- X -486
+char173 A -486
+hy A -486
+- A -486
+en X -486
+en A -486
+em X -486
+v ' -486
+C ' -486
+Z char173 -486
+Z hy -486
+Z - -486
+Z en -486
+Z em -486
+v char173 -486
+v hy -486
+v - -486
+v en -486
+v em -486
+C char173 -486
+C hy -486
+C - -486
+C en -486
+C em -486
+charset
+! 7806,18135,0,2241,591,996 2 3617
+" 9759,18135,0,3060,-2391,996 2 3618
+sh 12198,18360,975,1389,3,996 2 3619
+# "
+Do 12198,18465,630,843,-735,843 2 3620
+$ "
+% 17565,18675,975,576,-672,576 2 3621
+& 16101,18390,255,210,177,210 2 3622
+' 5856,18135,0,3690,-1482,996 2 51751
+( 5856,18135,2325,3999,699,996 2 3624
+) 5856,18135,2325,1524,3174,996 2 3625
+* 12198,18390,0,1251,-3045,996 2 3626
++ 17565,12495,0,0,-2097 0 3627
+, 5856,2970,2730,0,2856 0 3628
+char173 5856,7560,0,534,348,534 0 3629
+hy "
+- "
+. 5856,2970,0,0,1347 0 3630
+sl 5856,18165,1980,4254,3456,996 2 3631
+/ "
+0 12198,18360,255,2505,636,996 2 3632
+1 12198,18105,0,309,-2085,309 2 3633
+2 12198,18360,0,1968,1710,996 2 3634
+3 12198,18360,255,2127,735,996 2 3635
+4 12198,18105,0,3057,699,996 2 3636
+5 12198,18105,255,3717,123,996 2 3637
+6 12198,18360,255,3078,21,996 2 3638
+7 12198,18105,0,3684,138,996 2 3639
+8 12198,18360,255,3024,132,996 2 3640
+9 12198,18360,255,2850,480,996 2 3641
+: 5856,12621,0,1656,1347,996 0 3642
+; 5856,12621,2730,1737,2856,996 0 3643
+< 26346,16068,0,0,-3981 0 3644
+= 17565,9375,0,0,-2115 0 3645
+> 26346,16068,0,0,-3981 0 3646
+? 11220,18390,0,2100,-609,996 2 3647
+at 17565,18357,3849,1746,1029,996 2 3648
+@ "
+A 13662,18135,0,0,2325 2 3649
+B 13173,18135,0,1743,1536,996 2 3650
+C 13173,18390,255,1860,513,996 2 3651
+D 13662,18135,0,1749,1557,996 2 3652
+E 11220,18135,0,3267,1563,996 2 3653
+F 10734,18135,0,3414,1449,996 2 3654
+G 13662,18390,255,1893,333,996 2 3655
+H 13662,18135,0,2958,1509,996 2 3656
+I 5856,18135,0,3066,1566,996 2 3657
+J 11220,18135,255,2781,1866,996 2 3658
+K 13173,18135,0,2982,1341,996 2 3659
+L 10245,18135,0,0,1506 2 3660
+M 18051,18135,0,2886,1590,996 2 3661
+N 14148,18135,0,3030,1638,996 2 3662
+O 13662,18390,255,1875,447,996 2 3663
+P 12198,18135,0,2514,1401,996 2 3664
+Q 13662,18390,255,1773,495,996 2 3665
+R 13173,18135,0,2247,1515,996 2 3666
+S 12684,18390,255,2274,978,996 2 3667
+T 12684,18135,0,3735,-1890,996 2 3668
+U 13662,18135,255,2892,363,996 2 3669
+V 12198,18135,0,4140,-1263,996 2 3670
+W 18051,18135,0,3870,-1209,996 2 3671
+X 13662,18135,0,3108,2223,996 2 3672
+Y 12198,18135,0,4026,-1473,996 2 3673
+Z 12198,18135,0,3390,2130,996 2 3674
+lB 5856,18135,2325,4227,2679,996 2 3675
+[ "
+rs 7806,18165,1980,420,-1230,420 2 3676
+\ "
+rB 5856,18135,2325,3114,3792,996 2 3677
+] "
+ha 13173,19758,0,36,36,36 2 51875
+_ 13173,191367,6588,1317,1317,996 3 3679
+oq 5856,18135,0,3690,-1482,996 2 51808
+` "
+a 10734,12885,255,918,1242,918 0 3681
+b 10734,18165,255,1200,1791,996 2 3682
+c 10245,12885,255,1047,816,996 0 3683
+d 10734,18165,255,3501,1155,996 2 3684
+e 10245,12885,255,1245,1065,996 0 3685
+f 7806,18315,0,3972,753,996 2 3686
+g 10734,12885,4995,1737,2589,996 1 3687
+h 10734,18165,0,1167,1812,996 2 3688
+i 4878,18165,0,3690,1905,996 2 3689
+j 4878,18165,4995,3777,5010,996 3 3690
+k 10734,18165,0,2250,1443,996 2 3691
+l 4878,18165,0,3627,1932,996 2 3692
+m 16101,12885,0,1227,1803,996 0 3693
+n 10734,12885,0,1218,1824,996 0 3694
+o 10734,12885,255,1047,825,996 0 3695
+p 10734,12885,4680,972,3273,972 1 3696
+q 10734,12885,4680,1965,1020,996 1 3697
+r 7317,12885,0,2601,1803,996 0 3698
+s 9759,12885,255,1320,1314,996 0 3699
+t 7806,15879,255,1989,144,996 0 3700
+u 10734,12630,255,1800,1011,996 0 3701
+v 10245,12630,0,2412,-423,996 0 3702
+w 17076,12630,0,2343,-369,996 0 3703
+x 10245,12630,0,2328,2280,996 0 3704
+y 10734,12630,4680,2364,1923,996 1 3705
+z 8781,12630,0,2136,2154,996 0 3706
+lC 11709,20130,6075,2865,-1290,996 3 3707
+{ "
+ba 13173,19758,6588,0,-4596 3 3708
+| "
+rC 11709,20130,6075,0,2577 3 3709
+} "
+ti 26346,8952,0,0,-4029 0 51876
+char192 13662,23640,0,0,2325 2 3776
+`A "
+char194 13662,23415,0,1611,2325,996 2 3778
+^A "
+char200 11220,23640,0,3267,1563,996 2 3784
+`E "
+char202 11220,23415,0,3267,1563,996 2 3786
+^E "
+char203 11220,22560,0,3693,1563,996 2 3787
+:E "
+char206 5856,23415,0,5514,1566,996 2 3790
+^I "
+char207 5856,22560,0,6375,1566,996 2 3791
+:I "
+char180 12198,18165,0,1326,-5685,996 2 3764
+aa "
+ga 12198,18165,0,0,-4539 2 3680
+a^ 12198,17940,0,795,-3729,795 2 3678
+^ "
+char168 12198,17355,0,1464,-3699,996 2 3752
+ad "
+a~ 12198,17652,0,1776,-3729,996 2 3710
+~ "
+char217 13662,23640,255,2892,363,996 2 3801
+`U "
+char219 13662,23415,255,2892,363,996 2 3803
+^U "
+char221 12198,23640,0,4026,-1473,996 2 3805
+'Y "
+char253 10734,18165,4680,2364,1923,996 3 3837
+'y "
+char176 12198,18360,0,1284,-2982,996 2 3760
+de "
+char199 13173,18390,4995,1860,540,996 3 3783
+,C "
+char231 10245,12885,4995,1047,2838,996 1 3815
+,c "
+char209 14148,22743,0,3030,1638,996 2 3793
+~N "
+char241 10734,17652,0,2508,1824,996 2 3825
+~n "
+char161 7806,13041,5094,861,1971,861 1 3745
+r! "
+char191 11220,12591,5799,0,2016 1 3775
+r? "
+char164 12198,15684,0,2514,468,996 0 3748
+Cs "
+char163 12198,18360,0,2223,522,996 2 3747
+Po "
+char165 12198,18105,0,4137,1266,996 2 3749
+Ye "
+char167 12198,18390,255,96,-1509,96 2 3751
+sc "
+Fn 12198,18315,0,1662,-1329,996 2 51871
+char162 12198,18465,630,873,-1005,873 2 3746
+ct "
+char226 10734,17940,255,1527,1242,996 2 3810
+^a "
+char234 10245,17940,255,1770,1065,996 2 3818
+^e "
+char244 10734,17940,255,1527,825,996 2 3828
+^o "
+char251 10734,17940,255,1800,1011,996 2 3835
+^u "
+char225 10734,18165,255,2058,1242,996 2 3809
+'a "
+char233 10245,18165,255,2301,1065,996 2 3817
+'e "
+char243 10734,18165,255,2058,825,996 2 3827
+'o "
+char250 10734,18165,255,2058,1011,996 2 3834
+'u "
+char224 10734,18165,255,918,1242,918 2 3808
+`a "
+char232 10245,18165,255,1245,1065,996 2 3816
+`e "
+char242 10734,18165,255,1047,825,996 2 3826
+`o "
+char249 10734,18165,255,1800,1011,996 2 3833
+`u "
+char228 10734,17355,255,2478,1242,996 2 3812
+:a "
+char235 10245,17355,255,2721,1065,996 2 3819
+:e "
+char246 10734,17355,255,2478,825,996 2 3830
+:o "
+char252 10734,17355,255,2478,1011,996 2 3836
+:u "
+char197 13662,24480,0,1125,2325,996 2 3781
+oA "
+char238 5856,17940,0,3966,1425,996 2 3822
+^i "
+char216 13662,19944,1833,1989,555,996 2 3800
+/O "
+char198 18540,18135,0,2904,2310,996 2 3782
+AE "
+char229 10734,19005,255,918,1242,918 2 3813
+oa "
+char237 5856,18165,0,4779,1425,996 2 3821
+'i "
+char248 10734,14238,1866,1050,930,996 0 3832
+/o "
+char230 16587,12885,255,681,957,681 0 3814
+ae "
+char196 13662,22560,0,2472,2325,996 2 3780
+:A "
+char236 5856,18165,0,1461,1425,996 2 3820
+`i "
+char214 13662,22560,255,2472,447,996 2 3798
+:O "
+char220 13662,22560,255,2892,363,996 2 3804
+:U "
+char201 11220,23640,0,3267,1563,996 2 3785
+'E "
+char239 5856,17355,0,5118,1425,996 2 3823
+:i "
+char223 11709,18315,255,1839,1917,996 2 3807
+ss "
+char212 13662,23415,255,1875,447,996 2 3796
+^O "
+char193 13662,23640,0,1884,2325,996 2 3777
+'A "
+char195 13662,22743,0,2355,2325,996 2 3779
+~A "
+char227 10734,17652,255,2508,1242,996 2 3811
+~a "
+char208 13662,18135,0,1749,1557,996 2 3792
+-D "
+char240 10734,18579,255,2247,927,996 2 3824
+Sd "
+char205 5856,23640,0,6393,1566,996 2 3789
+'I "
+char204 5856,23640,0,3258,1566,996 2 3788
+`I "
+char211 13662,23640,255,1884,447,996 2 3795
+'O "
+char210 13662,23640,255,1875,447,996 2 3794
+`O "
+char213 13662,22743,255,2355,447,996 2 3797
+~O "
+char245 10734,17652,255,2508,825,996 2 3829
+~o "
+vS 12684,23415,255,3015,978,996 2 51795
+vs 9759,17940,255,2751,1314,996 2 51827
+char218 13662,23640,255,2892,363,996 2 3802
+'U "
+:Y 12198,22560,0,4026,-1473,996 2 51801
+char255 10734,17355,4680,2364,1923,996 3 3839
+:y "
+char222 12198,18135,0,1260,1407,996 2 3806
+TP "
+char254 10734,18165,4680,969,3273,969 3 3838
+Tp "
+char181 14637,12630,4350,1122,2931,996 0 3765
+char182 12198,19635,4200,1923,-606,996 2 3766
+ps "
+char190 17565,18675,918,891,-987,891 2 3774
+34 "
+\- 17565,8175,0,0,-2097 0 51757
+char188 17565,18675,918,183,-279,183 2 3772
+14 "
+char189 17565,18675,918,0,156 2 3773
+12 "
+char170 7806,18360,0,3285,-1188,996 2 3754
+Of "
+char186 7806,18360,0,3303,-1197,996 2 3770
+Om "
+char171 11709,11160,0,741,-426,741 0 3755
+Fo "
+char187 11709,11160,0,0,777 0 3771
+Fc "
+char177 17565,12210,213,0,-2133 0 3761
+char166 13173,19083,5916,0,-4596 3 3750
+bb "
+char169 13173,19635,0,4470,-2679,996 2 3753
+co "
+char172 17565,10185,0,0,-2097 0 3756
+no "
+char174 13173,19635,0,4470,-2679,996 2 3758
+rg "
+char178 7317,18465,0,3258,-300,996 2 3762
+S2 "
+char179 7317,18465,0,3042,-957,996 2 3763
+S3 "
+char184 12198,195108,4995,0,1860 3 3768
+ac "
+char185 7317,18345,0,2562,-2493,996 2 3769
+S1 "
+char215 17565,12216,0,0,-2850 0 3799
+char247 17565,11610,0,0,-2667 0 3831
+char183 5856,10578,0,1095,-723,996 0 3767
+fm 5856,18105,0,3918,-1725,996 2 51873
+sd 12198,18105,0,2577,-2925,996 2 51874
+dg 12198,18135,0,315,-1854,315 2 51755
+tm 16101,17850,0,2010,-2547,996 2 51796
+ah 12198,17940,0,1533,-4467,996 2 51935
+ao 12198,19005,0,114,-4878,114 2 51930
+f/ 2928,18675,918,8010,6531,996 2 51759
+em 17565,7350,0,423,330,423 0 51789
+en 12198,7350,0,936,786,936 0 51790
+dd 12198,18135,0,315,-1854,315 2 51773
+.i 5856,12630,0,1461,1425,996 0 51957
+aq 5856,18135,0,3051,-2388,996 2 3623
+bu 13173,14226,0,0,-498 0 51889
+'C 13173,23640,255,2427,513,996 2 20166
+'c 10245,18165,255,2301,816,996 2 20198
+lq 9270,18135,0,4254,-1485,996 2 51838
+rq 9270,18135,0,4254,-1485,996 2 51746
+Bq 9270,2916,2784,0,3018 0 51772
+vz 8781,17940,0,3240,2154,996 2 51834
+fi 12684,18315,0,2934,795,996 2 51881
+fl 12684,18315,0,2949,744,996 2 51882
+ff 13662,18315,0,3921,888,996 2 51883
+Fi 18540,18315,0,2892,921,996 2 51884
+Fl 18540,18315,0,2928,849,996 2 51885
+ij 9759,18165,4995,3777,1905,996 3 51958
+bq 5856,2916,2784,0,3330 0 51756
+%0 22443,18675,975,1293,267,996 2 51901
+char175 12198,16434,0,1257,-3453,996 0 3759
+a- "
+ab 12198,17940,0,1890,-4329,996 2 51926
+a. 12198,17355,0,0,-6069 2 51927
+oe 16587,12885,255,912,783,912 0 51823
+OE 18051,18270,135,3174,363,996 2 51791
+fo 6342,11160,0,1608,-186,996 0 51886
+fc 6342,11160,0,537,885,537 0 51887
+sq 19029,15624,0,0,-2022 0 51899
+/L 10245,18135,0,0,1620 2 51944
+/l 4878,18165,0,3627,1932,996 2 51960
+a" 12198,18165,0,3174,-3894,996 2 51933
+ho 12198,879,4716,0,-2142 1 51934
+vZ 12198,23415,0,3390,2130,996 2 51802
+IJ 17076,18135,255,2781,1566,996 2 51942
diff --git a/font/devlj4/UCR b/font/devlj4/UCR
new file mode 100644
index 00000000..6684eae2
--- /dev/null
+++ b/font/devlj4/UCR
@@ -0,0 +1,742 @@
+name UCR
+spacewidth 5856
+pcltypeface 4148
+pclproportional 1
+pclweight 0
+pclstyle 4
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -2439
+P . -4878
+P , -4878
+V A -1950
+A V -1950
+T o -3414
+T r -3414
+T c -3414
+T e -3414
+T d -3414
+T s -3414
+T y -3414
+T a -3414
+T w -3414
+T u -3414
+T J -3414
+L T -3414
+L Y -2925
+Y o -1950
+Y e -1950
+Y a -2439
+Y J -2925
+A W -1461
+W A -1461
+T A -2439
+V o -1461
+V e -1461
+V a -1461
+Y A -2439
+F A -975
+F . -2925
+F , -2925
+A T -2439
+A Y -2439
+v . -1950
+v , -1950
+y . -1950
+y , -1950
+T . -3414
+T , -3414
+L W -1461
+P A -1461
+V J -1461
+V . -2439
+V , -2439
+Y . -2925
+Y , -2925
+W o -975
+W e -975
+W a -975
+W . -1461
+W , -1461
+r . -1461
+r , -1461
+w . -1950
+w , -1950
+Y u -975
+A v -975
+A y -975
+A w -975
+o . -975
+o , -975
+p . -975
+p , -975
+e . -975
+e , -975
+b . -975
+b , -975
+O T -1461
+O V -486
+O Y -975
+O . -1461
+O , -1461
+L y -1950
+L O -1461
+L G -1461
+L C -1461
+L Q -1461
+P J -1461
+V y -486
+V u -486
+V O -486
+V G -486
+V C -486
+V Q -486
+D T -1461
+D V -486
+D Y -975
+D . -1461
+D , -1461
+Y O -975
+Y G -975
+Y C -975
+Y Q -975
+F o -486
+F e -486
+F a -486
+c . -975
+c , -975
+O A -486
+O W -486
+L U -1461
+R T -1461
+R V -486
+R Y -975
+R W -486
+G T -1461
+P o -975
+P g -1461
+P e -975
+P a -1461
+C A -486
+C . -1461
+C , -1461
+D A -486
+D W -486
+B T -1461
+B Y -975
+B . -1461
+B , -1461
+F J -486
+A O -486
+A G -486
+A C -486
+A U -486
+A Q -486
+W r -486
+W y -486
+W u -486
+W O -486
+W G -486
+W C -486
+W J -975
+W Q -486
+J A -486
+J . -486
+J , -486
+U A -486
+U . -1461
+U , -1461
+Q W -486
+f . -975
+f , -975
+T O -1461
+T G -1461
+T C -1461
+T Q -1461
+O X -486
+L o -975
+L e -975
+L q -1950
+G V -486
+G Y -975
+G W -486
+P T -975
+P V -486
+P Y -975
+C T -1461
+C V -486
+C Y -975
+D X -486
+B V -486
+B X -486
+B A -486
+B W -486
+S . -486
+S , -486
+X o -486
+X e -486
+X y -486
+X O -486
+X G -486
+X C -486
+X Q -486
+A o -486
+A e -486
+K o -975
+K e -975
+K y -975
+K w -975
+K O -975
+K G -975
+K C -975
+K Q -975
+o v -486
+o y -486
+o w -486
+h v -486
+h y -486
+n v -486
+n y -486
+m v -486
+m y -486
+r g -486
+p v -486
+p y -486
+c v -486
+c y -486
+c w -486
+v o -486
+v g -486
+v c -486
+v d -486
+v a -486
+v q -486
+e v -486
+e y -486
+b v -486
+b y -486
+b w -486
+s . -486
+s , -486
+y o -486
+y g -486
+y c -486
+y d -486
+y a -486
+y q -486
+a v -486
+a y -486
+a w -486
+w o -486
+w g -486
+w c -486
+w d -486
+w a -486
+w q -486
+T S -486
+L a -486
+L S -486
+P s -486
+P Z -486
+P X -486
+P W -486
+C X -486
+C W -486
+V S -486
+S T -486
+S V -486
+S Y -486
+S X -486
+S A -486
+S W -486
+Y S -486
+X a -486
+X u -486
+X S -486
+A t -486
+A g -486
+A c -486
+A d -486
+A a -486
+A u -486
+A q -486
+A S -486
+W S -486
+K c -975
+K u -975
+K S -975
+h w -486
+n w -486
+m w -486
+r o -486
+r c -486
+r e -486
+r d -486
+r a -486
+r q -486
+p w -486
+v e -486
+v s -486
+e w -486
+s v -486
+s y -486
+s w -486
+y e -486
+y s -486
+w e -486
+w s -486
+k o -486
+k g -486
+k c -486
+k e -486
+k d -486
+k a -486
+k q -486
+O Z -486
+L J -486
+C Z -486
+Z o -486
+Z e -486
+Z d -486
+Z s -486
+Z y -486
+Z a -486
+Z w -486
+Z u -486
+Z O -486
+Z G -486
+Z C -486
+Z S -486
+Z J -486
+Z Q -486
+D Z -486
+B Z -486
+S Z -486
+X J -486
+A s -486
+A J -486
+K a -975
+K J -975
+K . -486
+K , -486
+r s -486
+k s -486
+K T -486
+K V -486
+K Y -486
+K W -486
+K U -486
+L ' -5364
+T char173 -3414
+T hy -3414
+T - -3414
+T en -3414
+T em -3414
+A ' -1461
+char173 T -3414
+hy T -3414
+- T -3414
+en T -3414
+em T -3414
+Y char173 -975
+Y hy -975
+Y - -975
+Y en -975
+Y em -975
+p ' -975
+c ' -975
+e ' -975
+b ' -975
+a ' -1461
+V char173 -486
+V hy -486
+V - -486
+V en -486
+V em -486
+h ' -1461
+n ' -1461
+m ' -1461
+W char173 -486
+W hy -486
+W - -486
+W en -486
+W em -486
+' d -1950
+s ' -486
+L char173 -1950
+L hy -1950
+L - -1950
+L en -1950
+L em -1950
+X char173 -486
+X hy -486
+X - -486
+X en -486
+X em -486
+A char173 -486
+A hy -486
+A - -486
+A en -486
+A em -486
+K char173 -975
+K hy -975
+K - -975
+K en -975
+K em -975
+' s -486
+char173 X -486
+hy X -486
+- X -486
+char173 A -486
+hy A -486
+- A -486
+en X -486
+en A -486
+em X -486
+K ' -486
+Z char173 -486
+Z hy -486
+Z - -486
+Z en -486
+Z em -486
+charset
+! 7806,18135 2 3617
+" 9759,18135 2 3618
+sh 12198,18360,975 2 3619
+# "
+Do 12198,18360,630 2 3620
+$ "
+% 17565,18675,975 2 3621
+& 16101,18390,255 2 3622
+' 5856,18135 2 51751
+( 5856,18135,2520 2 3624
+) 5856,18135,2520 2 3625
+* 12198,18390 2 3626
++ 17565,12495 0 3627
+, 5856,2970,2730 0 3628
+char173 5856,7560 0 3629
+hy "
+- "
+. 5856,2760 0 3630
+sl 5856,18165,1980 2 3631
+/ "
+0 12198,18360,255 2 3632
+1 12198,18105 2 3633
+2 12198,18360 2 3634
+3 12198,18360,255 2 3635
+4 12198,18105 2 3636
+5 12198,18105,255 2 3637
+6 12198,18360,255 2 3638
+7 12198,18105 2 3639
+8 12198,18360,255 2 3640
+9 12198,18360,255 2 3641
+: 5856,12333 0 3642
+; 5856,12333,2730 0 3643
+< 26346,16068 0 3644
+= 17565,9570 0 3645
+> 26346,16068 0 3646
+? 11220,18390 2 3647
+at 17565,18438,3246 2 3648
+@ "
+A 13662,18135 2 3649
+B 13173,18135 2 3650
+C 13173,18390,255 2 3651
+D 13662,18135 2 3652
+E 11220,18135 2 3653
+F 10734,18135 2 3654
+G 13662,18390,255 2 3655
+H 13662,18135 2 3656
+I 5856,18135 2 3657
+J 11220,18135,255 2 3658
+K 13173,18135 2 3659
+L 10245,18135 2 3660
+M 18051,18135 2 3661
+N 14148,18135 2 3662
+O 13662,18390,255 2 3663
+P 12198,18135 2 3664
+Q 13662,18390,255 2 3665
+R 13173,18135 2 3666
+S 12684,18390,255 2 3667
+T 12684,18135 2 3668
+U 13662,18135,255 2 3669
+V 12198,18135 2 3670
+W 18051,18135 2 3671
+X 13662,18135 2 3672
+Y 12198,18135 2 3673
+Z 12198,18135 2 3674
+lB 5856,18135,2520 2 3675
+[ "
+rs 5856,18165,1980 2 3676
+\ "
+rB 5856,18135,2520 2 3677
+] "
+ha 13173,19758 2 51875
+_ 13173,191367,6588 3 3679
+oq 5856,18135 2 51808
+` "
+a 10734,12885,255 0 3681
+b 10734,18165,255 2 3682
+c 10245,12885,255 0 3683
+d 10734,18165,255 2 3684
+e 10245,12885,255 0 3685
+f 7806,18315 2 3686
+g 10734,12885,4995 1 3687
+h 10734,18165 2 3688
+i 4878,18165 2 3689
+j 4878,18165,4995 3 3690
+k 10734,18165 2 3691
+l 4878,18165 2 3692
+m 16101,12885 0 3693
+n 10734,12885 0 3694
+o 10734,12885,255 0 3695
+p 10734,12885,4680 1 3696
+q 10734,12885,4680 1 3697
+r 7317,12885 0 3698
+s 9759,12885,255 0 3699
+t 7806,15954,255 0 3700
+u 10734,12630,255 0 3701
+v 10245,12630 0 3702
+w 17076,12630 0 3703
+x 10245,12630 0 3704
+y 10734,12630,4680 1 3705
+z 8781,12630 0 3706
+lC 11709,20130,6075 3 3707
+{ "
+ba 13173,19758,6588 3 3708
+| "
+rC 11709,20130,6075 3 3709
+} "
+ti 26346,8952 0 51876
+char192 13662,23640 2 3776
+`A "
+char194 13662,23415 2 3778
+^A "
+char200 11220,23640 2 3784
+`E "
+char202 11220,23415 2 3786
+^E "
+char203 11220,22710 2 3787
+:E "
+char206 5856,23415 2 3790
+^I "
+char207 5856,22710 2 3791
+:I "
+char180 12198,18165 2 3764
+aa "
+ga 12198,18165 2 3680
+a^ 12198,17940 2 3678
+^ "
+char168 12198,17355 2 3752
+ad "
+a~ 12198,17844 2 3710
+~ "
+char217 13662,23640,255 2 3801
+`U "
+char219 13662,23415,255 2 3803
+^U "
+char221 12198,23640 2 3805
+'Y "
+char253 10734,18165,4680 3 3837
+'y "
+char176 12198,18360 2 3760
+de "
+char199 13173,18390,4755 3 3783
+,C "
+char231 10245,12885,4755 1 3815
+,c "
+char209 14148,23121 2 3793
+~N "
+char241 10734,17844 2 3825
+~n "
+char161 7806,12591,5544 1 3745
+r! "
+char191 11220,12480,5910 1 3775
+r? "
+char164 12198,15684 0 3748
+Cs "
+char163 12198,18360 2 3747
+Po "
+char165 12198,18105 2 3749
+Ye "
+char167 12198,18390,255 2 3751
+sc "
+Fn 12198,18315 2 51871
+char162 12198,18360,630 2 3746
+ct "
+char226 10734,17940,255 2 3810
+^a "
+char234 10245,17940,255 2 3818
+^e "
+char244 10734,17940,255 2 3828
+^o "
+char251 10734,17940,255 2 3835
+^u "
+char225 10734,18165,255 2 3809
+'a "
+char233 10245,18165,255 2 3817
+'e "
+char243 10734,18165,255 2 3827
+'o "
+char250 10734,18165,255 2 3834
+'u "
+char224 10734,18165,255 2 3808
+`a "
+char232 10245,18165,255 2 3816
+`e "
+char242 10734,18165,255 2 3826
+`o "
+char249 10734,18165,255 2 3833
+`u "
+char228 10734,17355,255 2 3812
+:a "
+char235 10245,17355,255 2 3819
+:e "
+char246 10734,17355,255 2 3830
+:o "
+char252 10734,17355,255 2 3836
+:u "
+char197 13662,24480 2 3781
+oA "
+char238 5856,17940 2 3822
+^i "
+char216 13662,19767,1851 2 3800
+/O "
+char198 18540,18135 2 3782
+AE "
+char229 10734,19005,255 2 3813
+oa "
+char237 5856,18165 2 3821
+'i "
+char248 10734,14274,2115 0 3832
+/o "
+char230 16587,12885,255 0 3814
+ae "
+char196 13662,22710 2 3780
+:A "
+char236 5856,18165 2 3820
+`i "
+char214 13662,22710,255 2 3798
+:O "
+char220 13662,22710,255 2 3804
+:U "
+char201 11220,23640 2 3785
+'E "
+char239 5856,17355 2 3823
+:i "
+char223 11709,18315,255 2 3807
+ss "
+char212 13662,23415,255 2 3796
+^O "
+char193 13662,23640 2 3777
+'A "
+char195 13662,23121 2 3779
+~A "
+char227 10734,17844,255 2 3811
+~a "
+char208 13662,18135 2 3792
+-D "
+char240 10734,18531,255 2 3824
+Sd "
+char205 5856,23640 2 3789
+'I "
+char204 5856,23640 2 3788
+`I "
+char211 13662,23640,255 2 3795
+'O "
+char210 13662,23640,255 2 3794
+`O "
+char213 13662,23121,255 2 3797
+~O "
+char245 10734,17844,255 2 3829
+~o "
+vS 12684,23415,255 2 51795
+vs 9759,17940,255 2 51827
+char218 13662,23640,255 2 3802
+'U "
+:Y 12198,22710 2 51801
+char255 10734,17355,4680 3 3839
+:y "
+char222 12198,18135 2 3806
+TP "
+char254 10734,18165,4680 3 3838
+Tp "
+char181 14637,12630,4350 0 3765
+char182 12198,19635,4200 2 3766
+ps "
+char190 17565,18675,975 2 3774
+34 "
+\- 17565,8175 0 51757
+char188 17565,18675,975 2 3772
+14 "
+char189 17565,18675,975 2 3773
+12 "
+char170 7317,18360 2 3754
+Of "
+char186 7317,18360 2 3770
+Om "
+char171 11709,11010 0 3755
+Fo "
+char187 11709,11010 0 3771
+Fc "
+char177 17565,12210,213 0 3761
+char166 13173,19083,5916 3 3750
+bb "
+char169 13173,19635 2 3753
+co "
+char172 17565,10185 0 3756
+no "
+char174 13173,19635 2 3758
+rg "
+char178 7317,18465 2 3762
+S2 "
+char179 7317,18465 2 3763
+S3 "
+char184 12198,195348,4755 3 3768
+ac "
+char185 7317,18345 2 3769
+S1 "
+char215 17565,12216 0 3799
+char247 17565,11610 0 3831
+char183 5856,10755 0 3767
+fm 5856,18105 2 51873
+sd 12198,18105 2 51874
+dg 12198,18135 2 51755
+tm 16101,17850 2 51796
+ah 12198,17940 2 51935
+ao 12198,19005 2 51930
+f/ 2439,18675,975 2 51759
+em 17565,7350 0 51789
+en 12198,7350 0 51790
+dd 12198,18135 2 51773
+.i 5856,12630 0 51957
+aq 5856,18135 2 3623
+bu 13173,14226 0 51889
+'C 13173,23640,255 2 20166
+'c 10245,18165,255 2 20198
+lq 9270,18135 2 51838
+rq 9270,18135 2 51746
+Bq 9270,3006,2694 0 51772
+vz 8781,17940 2 51834
+fi 12198,18315 2 51881
+fl 12684,18315 2 51882
+ff 13662,18315 2 51883
+Fi 17826,18315 2 51884
+Fl 17694,18315 2 51885
+ij 9759,18165,4995 3 51958
+bq 5856,3006,2694 0 51756
+%0 22443,18675,975 2 51901
+char175 12198,16440 0 3759
+a- "
+ab 12198,17940 2 51926
+a. 12198,17700 2 51927
+oe 16587,12885,255 0 51823
+OE 18051,18270,135 2 51791
+fo 6342,11010 0 51886
+fc 6342,11010 0 51887
+sq 19029,15624 0 51899
+/L 10245,18135 2 51944
+/l 4878,18165 2 51960
+a" 12198,18165 2 51933
+ho 12198,363,4077 0 51934
+vZ 12198,23415 2 51802
+IJ 17076,18135,255 2 51942
diff --git a/font/devlj4/UI b/font/devlj4/UI
new file mode 100644
index 00000000..00b953c7
--- /dev/null
+++ b/font/devlj4/UI
@@ -0,0 +1,917 @@
+name UI
+spacewidth 8781
+slant 16.500000
+pcltypeface 4148
+pclproportional 1
+pclweight 0
+pclstyle 1
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -5853
+P . -5364
+P , -5364
+V A -3414
+A V -4389
+T o -4389
+T r -4389
+T c -4389
+T e -4389
+T d -4389
+T s -4389
+T y -4389
+T a -4389
+T w -4389
+T u -4389
+T J -4389
+L T -4389
+L Y -4878
+Y o -3903
+Y e -3903
+Y a -3414
+Y J -3903
+A W -3903
+W A -1950
+T A -3414
+V o -2439
+V e -2439
+V a -2439
+Y A -3414
+F A -2925
+F . -3903
+F , -3903
+A T -4389
+A Y -4389
+v . -3903
+v , -3903
+y . -3903
+y , -3903
+T . -3903
+T , -3903
+L W -3903
+P A -2439
+V J -2439
+V . -3903
+V , -3903
+Y . -3903
+Y , -3903
+W o -975
+W e -975
+W a -975
+W . -2925
+W , -2925
+r . -2439
+r , -2439
+w . -3414
+w , -3414
+Y u -2439
+A v -2925
+A y -2439
+A w -2439
+o . -2439
+o , -2439
+p . -2439
+p , -2439
+e . -1950
+e , -1950
+b . -2439
+b , -2439
+O T -2439
+O V -1950
+O Y -2439
+O . -1950
+O , -1950
+L y -2925
+L O -2439
+L G -1950
+L C -1950
+L Q -1461
+P J -975
+V y -1461
+V u -1461
+V O -975
+V G -975
+V C -975
+V Q -975
+D T -2439
+D V -1950
+D Y -2439
+D . -1950
+D , -1950
+Y O -975
+Y G -975
+Y C -975
+Y Q -975
+F o -1461
+F e -1461
+F a -975
+c . -1950
+c , -1950
+O A -975
+O W -975
+L U -1461
+R T -1461
+R V -1461
+R Y -1461
+R W -975
+G T -1950
+P o -975
+P g -975
+P e -975
+P a -975
+C A -975
+C . -1950
+C , -1950
+D A -975
+D W -975
+B T -1461
+B Y -1461
+B . -1950
+B , -1950
+F J -1461
+A O -1461
+A G -1461
+A C -1461
+A U -1461
+A Q -1461
+W r -486
+W y -486
+W u -486
+W O -486
+W G -486
+W C -486
+W J -975
+W Q -486
+J A -1461
+J . -2439
+J , -2439
+U A -975
+U . -1950
+U , -1950
+Q W -975
+f . -1950
+f , -1950
+T O -975
+T G -975
+T C -975
+T Q -975
+O X -975
+L o -1950
+L e -1950
+L q -1950
+G V -1950
+G Y -1950
+G W -975
+G . -1461
+G , -1461
+P T -1461
+P V -1461
+P Y -1461
+C T -1461
+C V -1461
+C Y -1461
+D X -975
+B V -1461
+B X -975
+B A -975
+B W -975
+S . -1950
+S , -1950
+X o -1461
+X e -1461
+X y -1461
+X O -1461
+X G -1461
+X C -1461
+X Q -1461
+A o -1461
+A e -1461
+K o -975
+K e -975
+K y -975
+K w -975
+K O -975
+K G -975
+K C -975
+K Q -975
+o v -1461
+o y -975
+o x -1461
+o w -975
+h v -1461
+h y -975
+n v -1461
+n y -975
+m v -1461
+m y -975
+r g -486
+g . -975
+g , -975
+p v -1461
+p y -975
+p x -1461
+c v -1461
+c y -975
+c w -975
+v o -975
+v g -975
+v c -975
+v d -975
+v a -975
+v q -975
+e v -1461
+e y -975
+b v -1461
+b y -975
+b w -975
+s . -1461
+s , -1461
+y o -975
+y g -975
+y c -975
+y d -975
+y a -975
+y q -975
+f g -486
+x o -1461
+x g -1461
+x c -1461
+x e -1461
+x d -1461
+x a -1461
+x q -1461
+a v -1461
+a y -975
+a w -975
+w o -975
+w g -975
+w c -975
+w d -975
+w a -975
+w q -975
+T i -975
+T S -975
+L a -1461
+L S -1461
+G X -486
+G A -486
+P s -486
+P Z -975
+P X -1461
+P W -975
+C X -975
+C W -975
+V i -975
+V S -975
+S T -1461
+S V -1461
+S Y -1461
+S X -975
+S A -975
+S W -975
+Y i -975
+Y S -975
+X a -1461
+X u -1461
+X S -1461
+A t -975
+A g -1461
+A c -1461
+A d -1461
+A a -1461
+A u -1461
+A q -1461
+A S -1461
+W i -486
+W S -486
+K c -975
+K u -975
+K S -975
+t g -486
+t . -975
+t , -975
+h w -975
+h . -975
+h , -975
+n w -975
+n . -975
+n , -975
+m w -975
+m . -975
+m , -975
+l . -975
+l , -975
+r o -486
+r c -486
+r e -486
+r d -486
+r a -486
+r q -486
+i . -975
+i , -975
+p w -975
+c x -975
+v e -975
+v s -486
+e x -975
+e w -975
+z . -975
+z , -975
+d . -975
+d , -975
+s v -975
+s y -975
+s x -486
+s w -975
+y e -975
+y s -486
+f o -486
+f c -486
+f e -486
+f d -486
+f s -486
+f a -486
+f q -486
+x s -975
+x . -975
+x , -975
+a . -975
+a , -975
+w e -975
+w s -486
+j . -975
+j , -975
+u . -975
+k o -486
+k g -486
+k c -486
+k e -486
+k d -486
+k a -486
+k q -486
+k . -975
+k , -975
+O Z -975
+H . -975
+H , -975
+N . -975
+N , -975
+M . -975
+M , -975
+L J -975
+L . -975
+L , -975
+R . -975
+R , -975
+G Z -486
+I . -975
+I , -975
+C Z -975
+E . -975
+E , -975
+Z o -975
+Z e -975
+Z d -975
+Z s -975
+Z y -975
+Z a -975
+Z w -975
+Z u -975
+Z O -975
+Z G -975
+Z C -975
+Z S -975
+Z J -975
+Z Q -975
+Z . -975
+Z , -975
+D Z -975
+B Z -975
+S Z -975
+X J -975
+X . -975
+X , -975
+A s -975
+A J -975
+A . -975
+A , -975
+K a -975
+K J -975
+K . -975
+K , -975
+t o -486
+t c -486
+t e -486
+t d -486
+t s -486
+t a -486
+t q -486
+o t -486
+o z -486
+h t -486
+n t -486
+m t -486
+r s -486
+p t -486
+p z -486
+c t -486
+c z -486
+e t -486
+e z -486
+z o -486
+z g -486
+z c -486
+z e -486
+z d -486
+z s -486
+z a -486
+z q -486
+b t -486
+b z -486
+s t -486
+s z -486
+x t -486
+x v -486
+x y -486
+x w -486
+x u -486
+a t -486
+k s -486
+X T -486
+X V -486
+X Y -486
+X W -486
+X U -486
+K T -486
+K V -486
+K Y -486
+K W -486
+K U -486
+L ' -7317
+T char173 -4389
+T hy -4389
+T - -4389
+T en -4389
+T em -4389
+A ' -3903
+char173 T -4389
+hy T -4389
+- T -4389
+en T -4389
+em T -4389
+Y char173 -2439
+Y hy -2439
+Y - -2439
+Y en -2439
+Y em -2439
+p ' -2925
+c ' -2925
+e ' -2925
+b ' -2925
+a ' -2925
+V char173 -1461
+V hy -1461
+V - -1461
+V en -1461
+V em -1461
+h ' -2439
+n ' -2439
+m ' -2439
+R ' -975
+W char173 -486
+W hy -486
+W - -486
+W en -486
+W em -486
+' d -2925
+s ' -1950
+L char173 -1950
+L hy -1950
+L - -1950
+L en -1950
+L em -1950
+X char173 -1461
+X hy -1461
+X - -1461
+X en -1461
+X em -1461
+A char173 -1461
+A hy -1461
+A - -1461
+A en -1461
+A em -1461
+K char173 -975
+K hy -975
+K - -975
+K en -975
+K em -975
+' s -1950
+char173 X -1461
+hy X -1461
+- X -1461
+char173 A -1461
+hy A -1461
+- A -1461
+en X -1461
+en A -1461
+em X -1461
+x ' -1461
+X ' -1461
+K ' -1461
+t g -486
+t ' -975
+l ' -975
+r ' -975
+g ' -975
+i ' -975
+v ' -975
+z ' -975
+d ' -975
+y ' -975
+f ' -975
+w ' -975
+j ' -975
+u ' -975
+k ' -975
+T ' -975
+O ' -975
+H ' -975
+N ' -975
+M ' -975
+G ' -975
+I ' -975
+P ' -975
+C ' -975
+V ' -975
+E ' -975
+Z ' -975
+Z char173 -975
+Z hy -975
+Z - -975
+Z en -975
+Z em -975
+D ' -975
+B ' -975
+S ' -975
+Y ' -975
+F ' -975
+W ' -975
+J ' -975
+U ' -975
+' t -1461
+' n -1461
+' m -1461
+' l -975
+' r -1461
+' v -1461
+' T -975
+' N -975
+' M -975
+' L -975
+' R -975
+' D -975
+x char173 -486
+x hy -486
+x - -486
+x en -486
+x em -486
+charset
+! 8781,18165,0,1956,81,1000 2 3617
+" 13173,18246,0,2049,-4233,1000 2 3618
+sh 16587,18105,0,1020,-1137,1000 2 3619
+# "
+Do 16587,18750,765,0,-2391 2 3620
+$ "
+% 26346,18720,840,0,-3195 2 3621
+& 20004,18495,360,0,-942 2 3622
+' 8781,18135,0,3114,-2751,1000 2 51751
+( 8781,18135,2397,2823,-1443,1000 2 3624
+) 8781,18135,2397,0,1764 2 3625
+* 16587,18495,0,0,-4155 2 3626
++ 26346,14745,105,0,-4860 0 3627
+, 8781,3000,3135,0,1794 0 3628
+char173 8781,7680,0,561,147,561 0 3629
+hy "
+- "
+. 8781,2970,0,0,192 0 3630
+sl 8781,18135,1500,4326,3072,1000 2 3631
+/ "
+0 16587,18465,360,1602,-243,1000 2 3632
+1 16587,18105,0,0,-4467 2 3633
+2 16587,18465,0,540,78,540 2 3634
+3 16587,18465,360,1374,-354,1000 2 3635
+4 16587,18105,0,843,609,843 2 3636
+5 16587,18105,360,1494,-396,1000 2 3637
+6 16587,18465,360,1632,-966,1000 2 3638
+7 16587,18105,0,1188,-2583,1000 2 3639
+8 16587,18465,360,1356,-177,1000 2 3640
+9 16587,18465,360,630,171,630 2 3641
+: 8781,12615,0,330,192,330 0 3642
+; 8781,12615,3135,405,1794,405 0 3643
+< 26346,16068,0,0,-3981 0 3644
+= 26346,10500,0,0,-4950 0 3645
+> 26346,16068,0,0,-3981 0 3646
+? 13662,18315,0,1380,-1017,1000 2 3647
+at 26349,21030,2745,243,-1713,243 2 3648
+@ "
+A 19515,18135,0,0,2400 2 3649
+B 16587,18135,0,1641,684,1000 2 3650
+C 18540,18495,360,1554,-990,1000 2 3651
+D 19029,18135,0,477,804,477 2 3652
+E 15126,18135,0,3099,699,1000 2 3653
+F 14637,18135,0,3549,702,1000 2 3654
+G 19515,18495,360,1095,-1047,1000 2 3655
+H 19029,18135,0,2322,852,1000 2 3656
+I 7317,18135,0,2439,852,1000 2 3657
+J 14637,18135,360,2559,1242,1000 2 3658
+K 17565,18135,0,2910,417,1000 2 3659
+L 14148,18135,0,0,693 2 3660
+M 23907,18135,0,2115,669,1000 2 3661
+N 19029,18135,0,2688,750,1000 2 3662
+O 20004,18495,360,582,-948,582 2 3663
+P 15612,18135,0,2715,708,1000 2 3664
+Q 20490,18495,360,168,-1080,168 2 3665
+R 17076,18135,0,1728,729,1000 2 3666
+S 17076,18495,360,1455,-21,1000 2 3667
+T 16587,18135,0,3801,-2427,1000 2 3668
+U 19029,18135,360,2250,-801,1000 2 3669
+V 19029,18135,0,3789,-2919,1000 2 3670
+W 26346,18135,0,4122,-2541,1000 2 3671
+X 19029,18135,0,3081,1605,1000 2 3672
+Y 18051,18135,0,3720,-2763,1000 2 3673
+Z 16101,18135,0,2598,1719,1000 2 3674
+lB 8781,18135,2397,3690,1038,1000 2 3675
+[ "
+rs 8781,18135,1500,0,-2547 2 3676
+\ "
+rB 8781,18135,2397,2013,2715,1000 2 3677
+] "
+ha 13173,19758,0,36,36,36 2 51875
+_ 13173,191367,6588,1317,1317,1000 3 3679
+oq 8781,18135,0,2658,-2295,1000 2 51808
+` "
+a 14148,12990,360,87,729,87 0 3681
+b 15126,18165,360,129,1092,129 2 3682
+c 14148,12990,360,534,114,534 0 3683
+d 15126,18165,360,2658,144,1000 2 3684
+e 14148,12990,360,567,153,567 0 3685
+f 9759,18315,0,3546,-33,1000 2 3686
+g 15126,12990,5169,1059,1470,1000 1 3687
+h 15126,18165,0,126,1185,126 2 3688
+i 6342,18165,0,3060,1143,1000 2 3689
+j 6342,18165,4995,2970,4578,1000 3 3690
+k 14148,18165,0,1248,1092,1000 2 3691
+l 6342,18165,0,2937,1137,1000 2 3692
+m 22932,12990,0,363,1182,363 0 3693
+n 15126,12990,0,117,1182,117 0 3694
+o 15126,12990,360,12,261,12 0 3695
+p 15126,12990,4680,9,2592,9 1 3696
+q 15126,12990,4680,1146,132,1000 1 3697
+r 9270,12990,0,2499,1026,1000 0 3698
+s 13173,12990,360,579,960,579 0 3699
+t 9759,15843,360,2022,-864,1000 0 3700
+u 15126,12630,360,1023,261,1000 0 3701
+v 14637,12630,0,1902,-1086,1000 0 3702
+w 22932,12630,0,1953,-1578,1000 0 3703
+x 14637,12630,0,1035,1767,1000 0 3704
+y 14637,12630,4680,1992,-963,1000 1 3705
+z 12684,12630,0,1344,1365,1000 0 3706
+lC 11709,20130,6075,3315,-1740,1000 3 3707
+{ "
+ba 13173,19758,6588,0,-4596 3 3708
+| "
+rC 11709,20130,6075,0,3183 3 3709
+} "
+ti 26346,8952,0,0,-4029 0 51876
+char192 19515,23100,0,0,2400 2 3776
+`A "
+char194 19515,23085,0,0,2400 2 3778
+^A "
+char200 15126,23100,0,3099,699,1000 2 3784
+`E "
+char202 15126,23085,0,3099,699,1000 2 3786
+^E "
+char203 15126,22638,0,3099,699,1000 2 3787
+:E "
+char206 7317,23085,0,5385,852,1000 2 3790
+^I "
+char207 7317,22638,0,6231,852,1000 2 3791
+:I "
+char180 16587,17970,0,0,-7479 2 3764
+aa "
+ga 16587,17970,0,0,-6621 2 3680
+a^ 16587,18105,0,0,-5334 2 3678
+^ "
+char168 16587,17943,0,174,-6261,174 2 3752
+ad "
+a~ 16587,17724,0,312,-5604,312 2 3710
+~ "
+char217 19029,23100,360,2250,-801,1000 2 3801
+`U "
+char219 19029,23085,360,2250,-801,1000 2 3803
+^U "
+char221 18051,23100,0,3720,-2763,1000 2 3805
+'Y "
+char253 14637,17970,4680,1992,-963,1000 3 3837
+'y "
+char176 16587,18465,0,0,-4104 2 3760
+de "
+char199 18540,18495,4875,1554,-990,1000 3 3783
+,C "
+char231 14148,12990,4875,534,114,534 1 3815
+,c "
+char209 19029,23019,0,2688,750,1000 2 3793
+~N "
+char241 15126,17724,0,1044,1182,1000 2 3825
+~n "
+char161 8781,12576,5589,54,1983,54 1 3745
+r! "
+char191 13662,12573,5742,0,921 1 3775
+r? "
+char164 16587,15684,0,126,-1533,126 0 3748
+Cs "
+char163 16587,18465,0,2265,291,1000 2 3747
+Po "
+char165 16587,18105,0,4818,-1089,1000 2 3749
+Ye "
+char167 16587,18495,360,0,-3750 2 3751
+sc "
+Fn 16587,18315,0,330,-3528,330 2 51871
+char162 16587,18750,765,0,-2322 2 3746
+ct "
+char226 14148,18105,360,711,729,711 2 3810
+^a "
+char234 14148,18105,360,711,153,711 2 3818
+^e "
+char244 15126,18105,360,222,261,222 2 3828
+^o "
+char251 15126,18105,360,1023,261,1000 2 3835
+^u "
+char225 14148,17970,360,690,729,690 2 3809
+'a "
+char233 14148,17970,360,690,153,690 2 3817
+'e "
+char243 15126,17970,360,201,261,201 2 3827
+'o "
+char250 15126,17970,360,1023,261,1000 2 3834
+'u "
+char224 14148,17970,360,87,729,87 2 3808
+`a "
+char232 14148,17970,360,567,153,567 2 3816
+`e "
+char242 15126,17970,360,12,261,12 2 3826
+`o "
+char249 15126,17970,360,1023,261,1000 2 3833
+`u "
+char228 14148,17943,360,1395,729,1000 2 3812
+:a "
+char235 14148,17943,360,1395,153,1000 2 3819
+:e "
+char246 15126,17943,360,906,261,906 2 3830
+:o "
+char252 15126,17943,360,1023,261,1000 2 3836
+:u "
+char197 19515,25923,0,0,2400 2 3781
+oA "
+char238 6342,18105,0,4614,1155,1000 2 3822
+^i "
+char216 20004,18495,360,2847,1161,1000 2 3800
+/O "
+char198 25857,18135,0,3231,2919,1000 2 3782
+AE "
+char229 14148,20490,360,87,729,87 2 3813
+oa "
+char237 6342,17970,0,4593,1155,1000 2 3821
+'i "
+char248 15126,12990,360,1242,1386,1000 0 3832
+/o "
+char230 22443,12990,360,165,384,165 0 3814
+ae "
+char196 19515,22638,0,132,2400,132 2 3780
+:A "
+char236 6342,17970,0,1737,1155,1000 2 3820
+`i "
+char214 20004,22638,360,582,-948,582 2 3798
+:O "
+char220 19029,22638,360,2250,-801,1000 2 3804
+:U "
+char201 15126,23100,0,3099,699,1000 2 3785
+'E "
+char239 6342,17943,0,5298,1155,1000 2 3823
+:i "
+char223 16101,18315,360,1320,939,1000 2 3807
+ss "
+char212 20004,23085,360,582,-948,582 2 3796
+^O "
+char193 19515,23100,0,0,2400 2 3777
+'A "
+char195 19515,23019,0,936,2400,936 2 3779
+~A "
+char227 14148,17724,360,1533,729,1000 2 3811
+~a "
+char208 19029,18135,0,477,804,477 2 3792
+-D "
+char240 15126,18315,360,357,108,357 2 3824
+Sd "
+char205 7317,23100,0,5619,852,1000 2 3789
+'I "
+char204 7317,23100,0,2787,852,1000 2 3788
+`I "
+char211 20004,23100,360,582,-948,582 2 3795
+'O "
+char210 20004,23100,360,582,-948,582 2 3794
+`O "
+char213 20004,23019,360,693,-948,693 2 3797
+~O "
+char245 15126,17724,360,1044,261,1000 2 3829
+~o "
+vS 17076,23085,360,1629,-21,1000 2 51795
+vs 13173,18234,360,2241,960,1000 2 51827
+char218 19029,23100,360,2250,-801,1000 2 3802
+'U "
+:Y 18051,22638,0,3720,-2763,1000 2 51801
+char255 14637,17943,4680,1992,-963,1000 3 3839
+:y "
+char222 15612,18135,0,1692,717,1000 2 3806
+TP "
+char254 15126,18165,4680,9,2592,9 3 3838
+Tp "
+char181 14637,12630,4350,1122,2931,1000 0 3765
+char182 16590,19635,4200,0,-2379 2 3766
+ps "
+char190 26346,18465,945,0,-3291 2 3774
+34 "
+\- 26346,8070,0,0,-4869 0 51757
+char188 26346,18465,945,0,-3621 2 3772
+14 "
+char189 26346,18465,945,0,-3087 2 3773
+12 "
+char170 10734,18465,0,1791,-1671,1000 2 3754
+Of "
+char186 10734,18465,0,2232,-1599,1000 2 3770
+Om "
+char171 14637,11046,0,468,-876,468 0 3755
+Fo "
+char187 14637,11046,0,0,537 0 3771
+Fc "
+char177 26346,14910,0,0,-4770 0 3761
+char166 13173,19083,5916,0,-4596 3 3750
+bb "
+char169 13173,19635,0,4683,-2892,1000 2 3753
+co "
+char172 26346,11697,0,0,-4425 0 3756
+no "
+char174 13173,19635,0,4683,-2892,1000 2 3758
+rg "
+char178 10245,18465,0,1800,-1065,1000 2 3762
+S2 "
+char179 10245,18465,0,1941,-1134,1000 2 3763
+S3 "
+char184 16587,195048,4875,0,-1797 3 3768
+ac "
+char185 10245,18345,0,693,-3387,693 2 3769
+S1 "
+char215 26346,14010,0,0,-6081 0 3799
+char247 26346,12255,0,0,-4845 0 3831
+char183 8781,10935,0,0,-2136 0 3767
+fm 8781,18105,0,1911,-3000,1000 2 51873
+sd 16587,18105,0,0,-3000 2 51874
+dg 16587,18135,0,0,-2772 2 51755
+tm 16128,17850,0,2196,-2760,1000 2 51796
+ah 16587,18234,0,534,-6378,534 2 51935
+ao 16587,20490,0,0,-6318 2 51930
+f/ 2439,18465,945,8739,7344,1000 2 51759
+em 26346,7380,0,0,-2343 0 51789
+en 16587,7470,0,24,-378,24 0 51790
+dd 16587,18135,0,0,-2799 2 51773
+.i 6342,12630,0,1374,1155,1000 0 51957
+aq 8781,18246,0,2136,-4233,1000 2 3623
+bu 13173,14226,0,0,-498 0 51889
+'C 18540,23100,360,1554,-990,1000 2 20166
+'c 14148,17970,360,690,114,690 2 20198
+lq 13173,18135,0,3186,-2322,1000 2 51838
+rq 13173,18135,0,3246,-2382,1000 2 51746
+Bq 13173,2925,3150,0,1596 0 51772
+vz 12684,18234,0,2487,1365,1000 2 51834
+fi 16101,18315,0,2976,-249,1000 2 51881
+fl 16101,18315,0,2811,-216,1000 2 51882
+ff 18051,18315,0,3666,-165,1000 2 51883
+Fi 24396,18315,0,2886,-174,1000 2 51884
+Fl 24396,18315,0,2748,-168,1000 2 51885
+ij 12684,18165,4995,2970,1143,1000 3 51958
+bq 8781,2925,3150,0,2349 0 51756
+%0 26346,18720,840,426,-315,426 2 51901
+char175 16587,17040,0,327,-5010,327 2 3759
+a- "
+ab 16587,17937,0,0,-5469 2 51926
+a. 16587,17943,0,0,-8355 2 51927
+oe 23907,12990,360,141,-243,141 0 51823
+OE 26346,18270,135,3102,-987,1000 2 51791
+fo 9759,11046,0,438,-1293,438 0 51886
+fc 9759,11046,0,0,-363 0 51887
+sq 19029,15624,0,0,-2022 0 51899
+/L 14148,18135,0,0,693 2 51944
+/l 6342,18165,0,2937,1122,1000 2 51960
+a" 16587,17970,0,2460,-5865,1000 2 51933
+ho 16587,696,4458,0,-6957 0 51934
+vZ 16101,23085,0,2598,1719,1000 2 51802
+IJ 20976,18135,360,2559,852,1000 2 51942
diff --git a/font/devlj4/UR b/font/devlj4/UR
new file mode 100644
index 00000000..a4cf9ff7
--- /dev/null
+++ b/font/devlj4/UR
@@ -0,0 +1,858 @@
+name UR
+spacewidth 8781
+pcltypeface 4148
+pclproportional 1
+pclweight 0
+pclstyle 0
+ligatures fi fl ff ffi ffl 0
+kernpairs
+L V -3903
+P . -4389
+P , -4389
+V A -3903
+A V -3903
+T o -4878
+T r -4878
+T c -4878
+T e -4878
+T d -4878
+T s -4878
+T y -4878
+T a -4878
+T w -4878
+T u -4878
+T J -4878
+L T -4878
+L Y -4389
+Y o -4389
+Y e -4389
+Y a -4389
+Y J -4389
+A W -2439
+W A -2439
+T A -4389
+V o -2925
+V e -2925
+V a -2925
+Y A -4389
+F A -2925
+F . -3903
+F , -3903
+A T -4389
+A Y -4389
+v . -3903
+v , -3903
+y . -3903
+y , -3903
+T . -3903
+T , -3903
+L W -2439
+P A -2925
+V J -3903
+V . -3903
+V , -3903
+Y . -3903
+Y , -3903
+W o -1950
+W e -1950
+W a -1950
+W . -3414
+W , -3414
+r . -2439
+r , -2439
+w . -3414
+w , -3414
+Y u -2925
+A v -2439
+A y -1950
+A w -2439
+o . -2925
+o , -2925
+p . -2925
+p , -2925
+e . -2925
+e , -2925
+b . -2925
+b , -2925
+O T -1950
+O V -1461
+O Y -1950
+O . -2925
+O , -2925
+L y -2439
+L O -1950
+L G -1950
+L C -1950
+L Q -1950
+P J -2439
+V y -1461
+V u -1461
+V O -1461
+V G -1461
+V C -1461
+V Q -1461
+D T -1950
+D V -1461
+D Y -1950
+D . -2925
+D , -2925
+Y O -1950
+Y G -1950
+Y C -1950
+Y Q -1950
+F o -1461
+F e -1461
+F a -1461
+c . -2439
+c , -2439
+O A -1461
+O W -975
+L U -1461
+R T -1461
+R V -1461
+R Y -1461
+R W -975
+G T -1461
+P o -1461
+P g -1461
+P e -1461
+P a -1461
+C A -1461
+C . -2439
+C , -2439
+D A -1461
+D W -975
+B T -1461
+B Y -1461
+B . -1950
+B , -1950
+F J -2439
+A O -1461
+A G -1461
+A C -1461
+A U -1461
+A Q -1461
+W r -975
+W y -975
+W u -975
+W O -975
+W G -975
+W C -975
+W J -2439
+W Q -975
+J A -1461
+J . -2439
+J , -2439
+U A -1461
+U . -2439
+U , -2439
+Q W -975
+f . -1950
+f , -1950
+T O -1950
+T G -1950
+T C -1950
+T Q -1950
+O X -1461
+L o -1950
+L e -1950
+L q -1950
+G V -1461
+G Y -1461
+G W -975
+G . -975
+G , -975
+P T -486
+P V -486
+P Y -486
+C T -1461
+C V -1461
+C Y -1461
+D X -1461
+B V -1461
+B X -975
+B A -975
+B W -975
+S . -1950
+S , -1950
+X o -1461
+X e -1461
+X y -1461
+X O -1461
+X G -1461
+X C -1461
+X Q -1461
+A o -1461
+A e -1461
+K o -1461
+K e -1461
+K y -1461
+K w -1461
+K O -1461
+K G -1461
+K C -1461
+K Q -1461
+o v -975
+o y -486
+o x -975
+o w -975
+h v -975
+h y -486
+n v -975
+n y -486
+m v -975
+m y -486
+r g -486
+g . -975
+g , -975
+p v -975
+p y -486
+p x -975
+c v -975
+c y -486
+c w -975
+v o -975
+v g -975
+v c -975
+v d -975
+v a -975
+v q -975
+e v -975
+e y -486
+b v -975
+b y -486
+b w -975
+s . -1461
+s , -1461
+y o -975
+y g -975
+y c -975
+y d -975
+y a -975
+y q -975
+f g -486
+x o -975
+x g -975
+x c -975
+x e -975
+x d -975
+x a -975
+x q -975
+a v -975
+a y -486
+a w -975
+w o -975
+w g -975
+w c -975
+w d -975
+w a -975
+w q -975
+T i -975
+T S -975
+L a -975
+L S -975
+P s -486
+P Z -486
+P X -486
+P W -486
+C X -1461
+C W -975
+C J -975
+V i -975
+V S -975
+S T -975
+S V -975
+S Y -975
+S X -975
+S A -975
+S W -975
+Y i -975
+Y S -975
+X a -975
+X u -1461
+X S -975
+A t -975
+A g -1461
+A c -1461
+A d -1461
+A a -975
+A u -1461
+A q -1461
+A S -975
+W i -975
+W S -975
+K c -1461
+K u -1461
+K S -975
+t g -486
+t . -975
+t , -975
+o f -486
+h w -975
+h . -975
+h , -975
+n w -975
+n . -975
+n , -975
+m w -975
+m . -975
+m , -975
+l . -975
+l , -975
+r o -486
+r c -486
+r e -486
+r d -486
+r a -486
+r q -486
+i . -975
+i , -975
+p f -486
+p w -975
+c f -486
+c x -975
+v e -975
+v s -486
+e f -486
+e x -975
+e w -975
+z . -975
+z , -975
+d . -975
+d , -975
+b f -486
+s v -486
+s y -486
+s f -486
+s x -486
+s w -486
+y e -975
+y s -486
+f o -486
+f c -486
+f e -486
+f d -486
+f s -486
+f a -486
+f q -486
+x s -486
+x . -975
+x , -975
+a . -975
+a , -975
+w e -975
+w s -486
+j . -975
+j , -975
+u . -975
+k o -975
+k g -975
+k c -975
+k e -975
+k d -975
+k a -975
+k q -975
+k . -975
+k , -975
+O Z -486
+O J -975
+H . -975
+H , -975
+N . -975
+N , -975
+M . -975
+M , -975
+L . -975
+L , -975
+R . -975
+R , -975
+I . -975
+I , -975
+C Z -486
+E . -975
+E , -975
+Z o -486
+Z e -486
+Z d -486
+Z s -486
+Z y -486
+Z a -486
+Z w -486
+Z u -486
+Z O -486
+Z G -486
+Z C -486
+Z S -486
+Z Q -486
+Z . -975
+Z , -975
+D Z -486
+D J -975
+B Z -486
+B J -975
+S Z -486
+S J -975
+X . -975
+X , -975
+A s -486
+A . -975
+A , -975
+J J -975
+U J -975
+K a -975
+K . -975
+K , -975
+t o -486
+t c -486
+t e -486
+t d -486
+t s -486
+t a -486
+t q -486
+o z -486
+h f -486
+n f -486
+m f -486
+r s -486
+p z -486
+c z -486
+e z -486
+z o -486
+z g -486
+z c -486
+z e -486
+z d -486
+z s -486
+z a -486
+z q -486
+b z -486
+s z -486
+a f -486
+k s -486
+A f -486
+K T -486
+K V -486
+K Y -486
+K W -486
+K U -486
+L ' -6342
+T char173 -4878
+T hy -4878
+T - -4878
+T en -4878
+T em -4878
+A ' -2925
+char173 T -4878
+hy T -4878
+- T -4878
+en T -4878
+em T -4878
+Y char173 -2925
+Y hy -2925
+Y - -2925
+Y en -2925
+Y em -2925
+p ' -1950
+c ' -1461
+e ' -1950
+b ' -1950
+a ' -1461
+V char173 -1461
+V hy -1461
+V - -1461
+V en -1461
+V em -1461
+h ' -1461
+n ' -1461
+m ' -1461
+W char173 -975
+W hy -975
+W - -975
+W en -975
+W em -975
+' d -3414
+s ' -486
+L char173 -1950
+L hy -1950
+L - -1950
+L en -1950
+L em -1950
+X char173 -1461
+X hy -1461
+X - -1461
+X en -1461
+X em -1461
+A char173 -1461
+A hy -1461
+A - -1461
+A en -1461
+A em -1461
+K char173 -1461
+K hy -1461
+K - -1461
+K en -1461
+K em -1461
+' s -1950
+char173 X -1461
+hy X -1461
+- X -1461
+char173 A -1461
+hy A -1461
+- A -1461
+en X -1461
+en A -1461
+em X -1461
+K ' -486
+t g -486
+b f -486
+Z char173 -486
+Z hy -486
+Z - -486
+Z en -486
+Z em -486
+' t -975
+' n -1461
+' m -1461
+' r -1461
+' v -1461
+charset
+! 8781,18165 2 3617
+" 13173,18237 2 3618
+sh 16587,18105 2 3619
+# "
+Do 16587,18825,720 2 3620
+$ "
+% 26346,18720,840 2 3621
+& 20004,18495,360 2 3622
+' 8781,18135 2 51751
+( 8781,18135,2550 2 3624
+) 8781,18135,2550 2 3625
+* 16587,18495 2 3626
++ 26346,14775,105 0 3627
+, 8781,3030,3075 0 3628
+char173 8781,7755 0 3629
+hy "
+- "
+. 8781,3030 0 3630
+sl 8781,18135,1380 2 3631
+/ "
+0 16587,18465,360 2 3632
+1 16587,18105 2 3633
+2 16587,18465 2 3634
+3 16587,18465,360 2 3635
+4 16587,18105 2 3636
+5 16587,18105,360 2 3637
+6 16587,18465,360 2 3638
+7 16587,18105 2 3639
+8 16587,18465,360 2 3640
+9 16587,18465,360 2 3641
+: 8781,12630 0 3642
+; 8781,12630,3075 0 3643
+< 26346,16068 0 3644
+= 26346,10566 0 3645
+> 26346,16068 0 3646
+? 13662,18315 2 3647
+at 26352,21030,2745 2 3648
+@ "
+A 19515,18135 2 3649
+B 16587,18135 2 3650
+C 18540,18495,360 2 3651
+D 19029,18135 2 3652
+E 15126,18135 2 3653
+F 14637,18135 2 3654
+G 19515,18495,360 2 3655
+H 19029,18135 2 3656
+I 7317,18135 2 3657
+J 14637,18135,360 2 3658
+K 17565,18135 2 3659
+L 14148,18135 2 3660
+M 23907,18135 2 3661
+N 19029,18135 2 3662
+O 20004,18495,360 2 3663
+P 15612,18135 2 3664
+Q 20490,18495,360 2 3665
+R 17076,18135 2 3666
+S 17076,18495,360 2 3667
+T 16587,18135 2 3668
+U 19029,18135,360 2 3669
+V 19029,18135 2 3670
+W 26346,18135 2 3671
+X 19029,18135 2 3672
+Y 18051,18135 2 3673
+Z 16101,18135 2 3674
+lB 8781,18135,2370 2 3675
+[ "
+rs 8781,18135,1380 2 3676
+\ "
+rB 8781,18135,2370 2 3677
+] "
+ha 13173,19758 2 51875
+_ 13173,191367,6588 3 3679
+oq 8781,18135 2 51808
+` "
+a 14148,12990,360 0 3681
+b 15126,18165,360 2 3682
+c 14148,12990,360 0 3683
+d 15126,18165,360 2 3684
+e 14148,12990,360 0 3685
+f 9759,18315 2 3686
+g 15126,12990,5088 1 3687
+h 15126,18165 2 3688
+i 6342,18165 2 3689
+j 6342,18165,4995 3 3690
+k 14148,18165 2 3691
+l 6342,18165 2 3692
+m 22932,12990 0 3693
+n 15126,12990 0 3694
+o 15126,12990,360 0 3695
+p 15126,12990,4680 1 3696
+q 15126,12990,4680 1 3697
+r 9270,12990 0 3698
+s 13173,12990,360 0 3699
+t 9759,15963,360 0 3700
+u 15126,12630,360 0 3701
+v 14637,12630 0 3702
+w 22932,12630 0 3703
+x 14637,12630 0 3704
+y 14637,12630,4680 1 3705
+z 12684,12630 0 3706
+lC 11712,20130,6075 3 3707
+{ "
+ba 13173,19758,6588 3 3708
+| "
+rC 11712,20130,6075 3 3709
+} "
+ti 26346,8952 0 51876
+char192 19515,23085 2 3776
+`A "
+char194 19515,23085 2 3778
+^A "
+char200 15126,23085 2 3784
+`E "
+char202 15126,23085 2 3786
+^E "
+char203 15126,22755 2 3787
+:E "
+char206 7317,23085 2 3790
+^I "
+char207 7317,22755 2 3791
+:I "
+char180 16587,18075 2 3764
+aa "
+ga 16587,18075 2 3680
+a^ 16587,17985 2 3678
+^ "
+char168 16587,17775 2 3752
+ad "
+a~ 16587,18294 2 3710
+~ "
+char217 19029,23085,360 2 3801
+`U "
+char219 19029,23085,360 2 3803
+^U "
+char221 18051,23085 2 3805
+'Y "
+char253 14637,18075,4680 3 3837
+'y "
+char176 16587,18465 2 3760
+de "
+char199 18540,18495,5025 3 3783
+,C "
+char231 14148,12990,5025 1 3815
+,c "
+char209 19029,22959 2 3793
+~N "
+char241 15126,18294 2 3825
+~n "
+char161 8781,12645,5520 1 3745
+r! "
+char191 13662,12516,5799 1 3775
+r? "
+char164 16587,15684 0 3748
+Cs "
+char163 16587,18465 2 3747
+Po "
+char165 16587,18105 2 3749
+Ye "
+char167 16587,18495,360 2 3751
+sc "
+Fn 16587,18315 2 51871
+char162 16587,18825,720 2 3746
+ct "
+char226 14148,17985,360 2 3810
+^a "
+char234 14148,17985,360 2 3818
+^e "
+char244 15126,17985,360 2 3828
+^o "
+char251 15126,17985,360 2 3835
+^u "
+char225 14148,18075,360 2 3809
+'a "
+char233 14148,18075,360 2 3817
+'e "
+char243 15126,18075,360 2 3827
+'o "
+char250 15126,18075,360 2 3834
+'u "
+char224 14148,18075,360 2 3808
+`a "
+char232 14148,18075,360 2 3816
+`e "
+char242 15126,18075,360 2 3826
+`o "
+char249 15126,18075,360 2 3833
+`u "
+char228 14148,17775,360 2 3812
+:a "
+char235 14148,17775,360 2 3819
+:e "
+char246 15126,17775,360 2 3830
+:o "
+char252 15126,17775,360 2 3836
+:u "
+char197 19515,25923 2 3781
+oA "
+char238 6342,17985 2 3822
+^i "
+char216 20004,18495,375 2 3800
+/O "
+char198 25857,18165 2 3782
+AE "
+char229 14148,20412,360 2 3813
+oa "
+char237 6342,18075 2 3821
+'i "
+char248 15126,13008,408 0 3832
+/o "
+char230 22443,12990,360 0 3814
+ae "
+char196 19515,22755 2 3780
+:A "
+char236 6342,18075 2 3820
+`i "
+char214 20004,22755,360 2 3798
+:O "
+char220 19029,22755,360 2 3804
+:U "
+char201 15126,23085 2 3785
+'E "
+char239 6342,17775 2 3823
+:i "
+char223 16101,18165,360 2 3807
+ss "
+char212 20004,23085,360 2 3796
+^O "
+char193 19515,23085 2 3777
+'A "
+char195 19515,22959 2 3779
+~A "
+char227 14148,18294,360 2 3811
+~a "
+char208 19029,18135 2 3792
+-D "
+char240 15126,18315,360 2 3824
+Sd "
+char205 7317,23085 2 3789
+'I "
+char204 7317,23085 2 3788
+`I "
+char211 20004,23085,360 2 3795
+'O "
+char210 20004,23085,360 2 3794
+`O "
+char213 20004,22959,360 2 3797
+~O "
+char245 15126,18294,360 2 3829
+~o "
+vS 17076,23085,360 2 51795
+vs 13173,17985,360 2 51827
+char218 19029,23085,360 2 3802
+'U "
+:Y 18051,22755 2 51801
+char255 14637,17775,4680 3 3839
+:y "
+char222 15612,18135 2 3806
+TP "
+char254 15126,18165,4680 3 3838
+Tp "
+char181 14637,12630,4350 0 3765
+char182 16587,19635,4200 2 3766
+ps "
+char190 26346,18465,1020 2 3774
+34 "
+\- 26346,8100 0 51757
+char188 26346,18465,1020 2 3772
+14 "
+char189 26346,18465,1020 2 3773
+12 "
+char170 10734,18465 2 3754
+Of "
+char186 10734,18465 2 3770
+Om "
+char171 14637,11085 0 3755
+Fo "
+char187 14637,11085 0 3771
+Fc "
+char177 26346,14985 0 3761
+char166 13173,19083,5916 3 3750
+bb "
+char169 13173,19635 2 3753
+co "
+char172 26346,11607 0 3756
+no "
+char174 13173,19635 2 3758
+rg "
+char178 10245,18465 2 3762
+S2 "
+char179 10245,18465 2 3763
+S3 "
+char184 16587,194958,5025 3 3768
+ac "
+char185 10245,18345 2 3769
+S1 "
+char215 26346,14010 0 3799
+char247 26346,12315 0 3831
+char183 8781,10509 0 3767
+fm 8781,18105 2 51873
+sd 16587,18105 2 51874
+dg 16587,18135 2 51755
+tm 16128,17850 2 51796
+ah 16587,17985 2 51935
+ao 16587,20412 2 51930
+f/ 1464,18465,1020 2 51759
+em 26346,7425 0 51789
+en 16587,7425 0 51790
+dd 16587,18135 2 51773
+.i 6342,12630 0 51957
+aq 8781,18237 2 3623
+bu 13173,14226 0 51889
+'C 18540,23085,360 2 20166
+'c 14148,18075,360 2 20198
+lq 13173,18135 2 51838
+rq 13173,18135 2 51746
+Bq 13173,3015,3060 0 51772
+vz 12684,17985 2 51834
+fi 16101,18315 2 51881
+fl 16101,18315 2 51882
+ff 18051,18315 2 51883
+Fi 24396,18315 2 51884
+Fl 24396,18315 2 51885
+ij 12684,18165,4995 3 51958
+bq 8781,3015,3060 0 51756
+%0 26346,18720,840 2 51901
+char175 16587,16845 2 3759
+a- "
+ab 16587,17985 2 51926
+a. 16587,17775 2 51927
+oe 23907,12990,360 0 51823
+OE 26346,18270,135 2 51791
+fo 9759,11085 0 51886
+fc 9759,11085 0 51887
+sq 19029,15624 0 51899
+/L 14148,18135 2 51944
+/l 6342,18165 2 51960
+a" 16587,18075 2 51933
+ho 16587,1425,4704 1 51934
+vZ 16101,23085 2 51802
+IJ 21354,18135,360 2 51942
diff --git a/font/devlj4/generate/Makefile b/font/devlj4/generate/Makefile
new file mode 100644
index 00000000..09c6ac0a
--- /dev/null
+++ b/font/devlj4/generate/Makefile
@@ -0,0 +1,163 @@
+#Copyright (C) 1994 Free Software Foundation, Inc.
+# Written by James Clark (jjc@jclark.com)
+#
+#This file is part of groff.
+#
+#groff 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.
+#
+#groff 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 groff; see the file COPYING. If not, write to the Free Software
+#Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Directory containing Autofont TFM files.
+# The TFM files I used are available for ftp as
+# ftp-boi.external.hp.com:/pub/printers/laserjet/win.dos/tfmlj4p.exe
+# This is a self-extracting MS-DOS archive.
+AUTOFONT=/u/jjc/autofont
+HPFTODIT=hpftodit
+# .05 em
+IFLAG=-i 439
+SFLAG=-s
+srcdir=.
+TEXTMAP=$(srcdir)/text.map
+SPECIALMAP=$(srcdir)/special.map
+
+FONTS=\
+ ALBB ALBR \
+ AOB AOI AOR \
+ CB CBI CI CR \
+ GB GBI GI GR \
+ LGB LGI LGR \
+ OB OBI OI OR \
+ TB TBI TI TR \
+ UB UBI UI UR \
+ UCB UCBI UCI UCR \
+ CLARENDON CORONET MARIGOLD S
+
+all: $(FONTS)
+
+TR: $(AUTOFONT)/9nb00086.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00086.tfm $(TEXTMAP) $@
+
+TI: $(AUTOFONT)/9nb00084.tfm $(TEXTMAP)
+ $(HPFTODIT) $(IFLAG) $(AUTOFONT)/9nb00084.tfm $(TEXTMAP) $@
+
+TB: $(AUTOFONT)/9nb00083.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00083.tfm $(TEXTMAP) $@
+
+TBI: $(AUTOFONT)/9nb00085.tfm $(TEXTMAP)
+ $(HPFTODIT) $(IFLAG) $(AUTOFONT)/9nb00085.tfm $(TEXTMAP) $@
+
+CR: $(AUTOFONT)/9nb00064.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00064.tfm $(TEXTMAP) $@
+
+CI: $(AUTOFONT)/9nb00062.tfm $(TEXTMAP)
+ $(HPFTODIT) $(IFLAG) $(AUTOFONT)/9nb00062.tfm $(TEXTMAP) $@
+
+CB: $(AUTOFONT)/9nb00061.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00061.tfm $(TEXTMAP) $@
+
+CBI: $(AUTOFONT)/9nb00063.tfm $(TEXTMAP)
+ $(HPFTODIT) $(IFLAG) $(AUTOFONT)/9nb00063.tfm $(TEXTMAP) $@
+
+GR: $(AUTOFONT)/9nb00068.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00068.tfm $(TEXTMAP) $@
+
+GI: $(AUTOFONT)/9nb00066.tfm $(TEXTMAP)
+ $(HPFTODIT) $(IFLAG) $(AUTOFONT)/9nb00066.tfm $(TEXTMAP) $@
+
+GB: $(AUTOFONT)/9nb00065.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00065.tfm $(TEXTMAP) $@
+
+GBI: $(AUTOFONT)/9nb00067.tfm $(TEXTMAP)
+ $(HPFTODIT) $(IFLAG) $(AUTOFONT)/9nb00067.tfm $(TEXTMAP) $@
+
+OR: $(AUTOFONT)/9nb00076.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00076.tfm $(TEXTMAP) $@
+
+OI: $(AUTOFONT)/9nb00074.tfm $(TEXTMAP)
+ $(HPFTODIT) $(IFLAG) $(AUTOFONT)/9nb00074.tfm $(TEXTMAP) $@
+
+OB: $(AUTOFONT)/9nb00073.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00073.tfm $(TEXTMAP) $@
+
+OBI: $(AUTOFONT)/9nb00075.tfm $(TEXTMAP)
+ $(HPFTODIT) $(IFLAG) $(AUTOFONT)/9nb00075.tfm $(TEXTMAP) $@
+
+UR: $(AUTOFONT)/9nb00094.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00094.tfm $(TEXTMAP) $@
+
+UI: $(AUTOFONT)/9nb00092.tfm $(TEXTMAP)
+ $(HPFTODIT) $(IFLAG) $(AUTOFONT)/9nb00092.tfm $(TEXTMAP) $@
+
+UB: $(AUTOFONT)/9nb00088.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00088.tfm $(TEXTMAP) $@
+
+UBI: $(AUTOFONT)/9nb00093.tfm $(TEXTMAP)
+ $(HPFTODIT) $(IFLAG) $(AUTOFONT)/9nb00093.tfm $(TEXTMAP) $@
+
+UCR: $(AUTOFONT)/9nb00089.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00089.tfm $(TEXTMAP) $@
+
+UCI: $(AUTOFONT)/9nb00087.tfm $(TEXTMAP)
+ $(HPFTODIT) $(IFLAG) $(AUTOFONT)/9nb00087.tfm $(TEXTMAP) $@
+
+UCB: $(AUTOFONT)/9nb00090.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00090.tfm $(TEXTMAP) $@
+
+UCBI: $(AUTOFONT)/9nb00091.tfm $(TEXTMAP)
+ $(HPFTODIT) $(IFLAG) $(AUTOFONT)/9nb00091.tfm $(TEXTMAP) $@
+
+ALBR: $(AUTOFONT)/9nb00052.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00052.tfm $(TEXTMAP) $@
+
+ALBB: $(AUTOFONT)/9nb00051.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00051.tfm $(TEXTMAP) $@
+
+LGR: $(AUTOFONT)/9nb00071.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00071.tfm $(TEXTMAP) $@
+
+LGB: $(AUTOFONT)/9nb00069.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00069.tfm $(TEXTMAP) $@
+
+LGI: $(AUTOFONT)/9nb00070.tfm $(TEXTMAP)
+ $(HPFTODIT) $(IFLAG) $(AUTOFONT)/9nb00070.tfm $(TEXTMAP) $@
+
+AOR: $(AUTOFONT)/9nb00055.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00055.tfm $(TEXTMAP) $@
+
+AOI: $(AUTOFONT)/9nb00054.tfm $(TEXTMAP)
+ $(HPFTODIT) $(IFLAG) $(AUTOFONT)/9nb00054.tfm $(TEXTMAP) $@
+
+AOB: $(AUTOFONT)/9nb00053.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00053.tfm $(TEXTMAP) $@
+
+MARIGOLD: $(AUTOFONT)/9nb00072.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00072.tfm $(TEXTMAP) $@
+
+CORONET: $(AUTOFONT)/9nb00070.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00070.tfm $(TEXTMAP) $@
+
+CLARENDON: $(AUTOFONT)/9nb00060.tfm $(TEXTMAP)
+ $(HPFTODIT) $(AUTOFONT)/9nb00060.tfm $(TEXTMAP) $@
+
+S: $(AUTOFONT)/9nb00086.tfm $(SPECIALMAP)
+ $(HPFTODIT) $(SFLAG) $(AUTOFONT)/9nb00086.tfm $(SPECIALMAP) $@
+
+clean:
+
+realclean:
+ -rm -f $(FONTS)
+
+extraclean: realclean
+ -rm -f core *~ \#*
+
+.PHONY: clean realclean extraclean all
diff --git a/font/devlj4/generate/special.map b/font/devlj4/generate/special.map
new file mode 100644
index 00000000..ea23337b
--- /dev/null
+++ b/font/devlj4/generate/special.map
@@ -0,0 +1,178 @@
+# Map MSL numbers to troff names for a special font.
+12 pl
+30 eq
+34 *A
+35 *B
+38 *E
+41 *Y
+42 *I
+44 *K
+46 *M
+47 *N
+48 *O
+49 *R
+53 *T
+57 *X
+59 *Z
+94 or
+96 ap
+183 mi
+191 +-
+194 no
+201 mu
+202 di
+206 DI
+207 CL
+205 HE
+208 SP
+220 va
+224 ua
+225 da
+226 ->
+227 <-
+229 <>
+292 if
+295 ca
+296 ==
+297 >=
+298 <=
+301 ~~
+302 md
+500 sr
+501 pt
+503 +e
+504 3d
+504 tf
+505 *G
+506 *D
+507 *H
+508 *L
+509 *C
+510 *P
+511 *S
+512 *U
+513 *F
+514 *Q
+515 *W
+516 gr
+517 pd
+518 ts
+519 !=
+522 *a
+523 *b
+524 *g
+525 *d
+526 *e
+527 *z
+528 *y
+529 *h
+530 *i
+531 *k
+532 *l
+533 *m
+534 *n
+535 *c
+536 *o
+537 *p
+538 *r
+539 *s
+540 *t
+541 *u
+542 *f
+543 *x
+544 *q
+545 *w
+546 +h
+547 +f
+548 +p
+549 ~=
+550 ne
+551 arrowverttp
+551 uA
+552 rA
+552 rh
+553 arrowvertbt
+553 dA
+554 lA
+554 lh
+555 vA
+556 hA
+560 radicalex
+561 fa
+562 te
+564 pp
+565 cu
+566 mo
+568 nm
+569 sb
+570 sp
+571 nb
+572 nc
+573 ib
+574 ip
+575 c+
+577 c*
+580 AN
+581 OR
+584 ci
+587 is
+589 /_
+590 es
+591 Ah
+595 Im
+596 Re
+598 bracketlefttp
+598 lc
+599 bracketleftbt
+599 lf
+600 bracelefttp
+600 parenlefttp
+600 lt
+601 braceleftmid
+601 lk
+602 braceleftbt
+602 parenleftbt
+602 lb
+605 arrowvertex
+608 bracketrighttp
+608 rc
+609 bracketrightbt
+609 rf
+610 bracerighttp
+610 parenrighttp
+610 rt
+611 bracerightmid
+611 rk
+612 bracerightbt
+612 parenrightbt
+612 rb
+613 braceleftex
+613 bracerightex
+613 bv
+614 barex
+614 bracketleftex
+614 bracketrightex
+614 parenleftex
+614 parenrightex
+620 -+
+621 la
+622 ra
+624 =~
+633 <<
+634 >>
+638 -h
+641 wp
+654 lz
+663 st
+664 **
+665 an
+680 AN
+1099 CR
+
+#637 digamma
+#655 parenrighttp
+#656 parenrightbt
+#642 sum
+#644 bardblex
+#646 parenlefttp
+#647 parenleftbt
diff --git a/font/devlj4/generate/text.map b/font/devlj4/generate/text.map
new file mode 100644
index 00000000..fc70b63d
--- /dev/null
+++ b/font/devlj4/generate/text.map
@@ -0,0 +1,341 @@
+# Map MSL numbers to troff names for a text font.
+1 !
+2 "
+3 #
+3 sh
+4 $
+4 Do
+5 %
+6 &
+8 '
+9 (
+10 )
+11 *
+12 +
+13 ,
+14 -
+14 hy
+14 char173
+15 .
+16 /
+16 sl
+17 0
+18 1
+19 2
+20 3
+21 4
+22 5
+23 6
+24 7
+25 8
+26 9
+27 :
+28 ;
+29 <
+30 =
+31 >
+32 ?
+33 @
+33 at
+34 A
+35 B
+36 C
+37 D
+38 E
+39 F
+40 G
+41 H
+42 I
+43 J
+44 K
+45 L
+46 M
+47 N
+48 O
+49 P
+50 Q
+51 R
+52 S
+53 T
+54 U
+55 V
+56 W
+57 X
+58 Y
+59 Z
+60 [
+60 lB
+61 \
+61 rs
+62 ]
+62 rB
+63 ha
+64 _
+66 `
+66 oq
+67 a
+68 b
+69 c
+70 d
+71 e
+72 f
+73 g
+74 h
+75 i
+76 j
+77 k
+78 l
+79 m
+80 n
+81 o
+82 p
+83 q
+84 r
+85 s
+86 t
+87 u
+88 v
+89 w
+90 x
+91 y
+92 z
+93 {
+93 lC
+94 |
+94 ba
+95 }
+95 rC
+96 ti
+99 `A
+99 char192
+100 ^A
+100 char194
+101 `E
+101 char200
+102 ^E
+102 char202
+103 :E
+103 char203
+104 ^I
+104 char206
+105 :I
+105 char207
+106 aa
+106 char180
+107 ga
+108 ^
+108 a^
+109 ad
+109 char168
+110 ~
+110 a~
+111 `U
+111 char217
+112 ^U
+112 char219
+114 'Y
+114 char221
+115 'y
+115 char253
+116 de
+116 char176
+117 ,C
+117 char199
+118 ,c
+118 char231
+119 ~N
+119 char209
+120 ~n
+120 char241
+121 r!
+121 char161
+122 r?
+122 char191
+123 Cs
+123 char164
+124 Po
+124 char163
+125 Ye
+125 char165
+126 sc
+126 char167
+127 Fn
+128 ct
+128 char162
+129 ^a
+129 char226
+130 ^e
+130 char234
+131 ^o
+131 char244
+132 ^u
+132 char251
+133 'a
+133 char225
+134 'e
+134 char233
+135 'o
+135 char243
+136 'u
+136 char250
+137 `a
+137 char224
+138 `e
+138 char232
+139 `o
+139 char242
+140 `u
+140 char249
+141 :a
+141 char228
+142 :e
+142 char235
+143 :o
+143 char246
+144 :u
+144 char252
+145 oA
+145 char197
+146 ^i
+146 char238
+147 /O
+147 char216
+148 AE
+148 char198
+149 oa
+149 char229
+150 'i
+150 char237
+151 /o
+151 char248
+152 ae
+152 char230
+153 :A
+153 char196
+154 `i
+154 char236
+155 :O
+155 char214
+156 :U
+156 char220
+157 'E
+157 char201
+158 :i
+158 char239
+159 ss
+159 char223
+160 ^O
+160 char212
+161 'A
+161 char193
+162 ~A
+162 char195
+163 ~a
+163 char227
+164 -D
+164 char208
+165 Sd
+165 char240
+166 'I
+166 char205
+167 `I
+167 char204
+168 'O
+168 char211
+169 `O
+169 char210
+170 ~O
+170 char213
+171 ~o
+171 char245
+172 vS
+173 vs
+174 'U
+174 char218
+175 :Y
+176 :y
+176 char255
+177 TP
+177 char222
+178 Tp
+178 char254
+180 char181
+181 ps
+181 char182
+182 34
+182 char190
+183 \-
+184 14
+184 char188
+185 12
+185 char189
+186 Of
+186 char170
+187 Om
+187 char186
+188 Fo
+188 char171
+190 Fc
+190 char187
+191 char177
+192 bb
+192 char166
+193 co
+193 char169
+194 no
+194 char172
+196 rg
+196 char174
+197 S2
+197 char178
+198 S3
+198 char179
+199 ac
+199 char184
+200 S1
+200 char185
+201 char215
+202 char247
+302 char183
+310 fm
+311 sd
+312 dg
+313 tm
+315 ah
+316 ao
+324 f/
+325 em
+326 en
+327 dd
+328 .i
+329 aq
+331 bu
+406 'C
+407 'c
+1017 lq
+1018 rq
+1019 Bq
+1031 vz
+1040 fi
+1041 fl
+1042 ff
+1043 Fi
+1044 Fl
+1047 ij
+1067 bq
+1068 %0
+1084 a-
+1084 char175
+1086 ab
+1088 a.
+1090 oe
+1091 OE
+1092 fo
+1093 fc
+1094 sq
+1095 /L
+1096 /l
+1097 a"
+1098 ho
+1106 vZ
+1107 IJ
diff --git a/font/devps/AB b/font/devps/AB
new file mode 100644
index 00000000..9ff0dff7
--- /dev/null
+++ b/font/devps/AB
@@ -0,0 +1,559 @@
+name AB
+internalname AvantGarde-Demi
+spacewidth 280
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -50
+A w -65
+A v -70
+A u -20
+A ' -90
+A Y -80
+A W -60
+A V -102
+A U -40
+A T -25
+A Q -50
+A O -50
+A G -40
+A C -40
+B A -10
+C A -40
+D . -20
+D , -20
+D Y -45
+D W -25
+D V -50
+D A -50
+F . -129
+F e -20
+F , -162
+F a -20
+F A -75
+G . -20
+G , -20
+G Y -15
+J . -15
+J a -20
+J A -30
+K y -20
+K u -15
+K o -45
+K e -40
+K O -30
+L y -23
+L ' -30
+L rq -30
+L Y -80
+L W -55
+L V -85
+L T -46
+O . -30
+O , -30
+O Y -30
+O X -30
+O W -20
+O V -45
+O T -15
+O A -60
+P . -200
+P o -20
+P e -20
+P , -220
+P a -20
+P A -100
+Q , 20
+R W 25
+R V -10
+R U 25
+R T 40
+R O 25
+S , 20
+T y -10
+T w -55
+T u -46
+T ; -29
+T r -30
+T . -91
+T o -49
+T - -75
+T hy -75
+T char173 -75
+T e -49
+T , -82
+T : -15
+T a -70
+T O -15
+T A -25
+U . -20
+U , -20
+U A -40
+V u -55
+V ; -33
+V . -145
+V o -101
+V i -15
+V - -75
+V hy -75
+V char173 -75
+V e -101
+V , -145
+V : -18
+V a -95
+V O -45
+V G -20
+V A -102
+W y -15
+W u -30
+W ; -33
+W . -106
+W o -46
+W i -10
+W - -35
+W hy -35
+W char173 -35
+W e -47
+W , -106
+W : -15
+W a -50
+W O -20
+W A -58
+Y u -52
+Y ; -23
+Y . -145
+Y o -89
+Y - -100
+Y hy -100
+Y char173 -100
+Y e -89
+Y , -145
+Y : -10
+Y a -93
+Y O -30
+Y A -80
+a t 5
+a p 20
+a b 5
+b y -20
+b v -20
+c y -20
+c l -15
+c k -15
+, ' -70
+, rq -70
+e y -20
+e x -20
+e w -20
+e v -20
+f . -40
+f o -20
+f l -15
+f i -15
+f f -20
+f .i -15
+f , -40
+f a -15
+g i 25
+g a 15
+h y -30
+k y -5
+k o -30
+k e -40
+m y -20
+m u -20
+n y -15
+n v -30
+o y -20
+o x -30
+o w -20
+o v -30
+p y -20
+. ' -70
+. rq -70
+lq A -50
+` ` -80
+` oq -80
+oq ` -80
+oq oq -80
+` A -50
+oq A -50
+' v -10
+' t 10
+' s -15
+' r -20
+' ' -80
+' d -50
+r y 40
+r v 40
+r u 20
+r t 20
+r s 20
+r q -8
+r . -73
+r p 20
+r o -15
+r n 21
+r m 15
+r l 20
+r k 5
+r i 20
+r - -60
+r hy -60
+r char173 -60
+r g 1
+r e -4
+r d -6
+r , -75
+r c -7
+s . 20
+s , 20
+v . -90
+v o -20
+v e -20
+v , -90
+v a -30
+w . -90
+w o -30
+w e -20
+w , -90
+w a -30
+x e -20
+y . -100
+y o -30
+y e -20
+y , -100
+y c -35
+y a -30
+charset
+ha 600,740 2 0000 -- asciicircum
+ti 600,347 0 0001 -- asciitilde
+vS 520,944,15 2 0002 -- Scaron
+vZ 500,944 2 0003 -- Zcaron
+vs 440,774,18 2 0004 -- scaron
+vz 460,774 2 0005 -- zcaron
+:Y 620,939 2 0006 -- Ydieresis
+tm 1000,740 2 0007 -- trademark
+aq 220,740 2 0010 -- quotesingle
+space 280 0 0040
+! 280,740 2 0041 -- exclam
+" 360,740 2 0042 -- quotedbl
+# 560,700 0 0043 -- numbersign
+sh "
+$ 560,857,86 2 0044 -- dollar
+Do "
+% 860,755,15 2 0045 -- percent
+& 680,755,15 2 0046 -- ampersand
+' 280,740 2 0047 -- quoteright
+( 380,754,157 2 0050 -- parenleft
+) 380,754,157 2 0051 -- parenright
+* 440,755 2 0052 -- asterisk
++ 600,506 0 0053 -- plus
+, 280,133,141 0 0054 -- comma
+- 420,348 0 0055 -- hyphen
+hy "
+char173 "
+. 280,133 0 0056 -- period
+/ 460,740,100 2 0057 -- slash
+sl "
+0 560,755,15 2 0060 -- zero
+1 560,740 2 0061 -- one
+2 560,755 2 0062 -- two
+3 560,755,15 2 0063 -- three
+4 560,740 2 0064 -- four
+5 560,740,15 2 0065 -- five
+6 560,739,15 2 0066 -- six
+7 560,740 2 0067 -- seven
+8 560,755,15 2 0070 -- eight
+9 560,754 2 0071 -- nine
+: 280,555 0 0072 -- colon
+; 280,555,141 0 0073 -- semicolon
+< 600,514,8 0 0074 -- less
+= 600,425 0 0075 -- equal
+> 600,514,8 0 0076 -- greater
+? 560,755 2 0077 -- question
+@ 740,712,12 0 0100 -- at
+at "
+A 740,740 2 0101 -- A
+B 580,740 2 0102 -- B
+C 780,755,15 2 0103 -- C
+D 700,740 2 0104 -- D
+E 520,740 2 0105 -- E
+F 480,740 2 0106 -- F
+G 840,755,15 2 0107 -- G
+H 680,740 2 0110 -- H
+I 280,740 2 0111 -- I
+J 480,740,15 2 0112 -- J
+K 620,740 2 0113 -- K
+L 440,740 2 0114 -- L
+M 900,740 2 0115 -- M
+N 740,740 2 0116 -- N
+O 840,755,15 2 0117 -- O
+P 560,740 2 0120 -- P
+Q 840,755,15 2 0121 -- Q
+R 580,740 2 0122 -- R
+S 520,755,15 2 0123 -- S
+T 420,740 2 0124 -- T
+U 640,740,15 2 0125 -- U
+V 700,740 2 0126 -- V
+W 900,740 2 0127 -- W
+X 680,740 2 0130 -- X
+Y 620,740 2 0131 -- Y
+Z 500,740 2 0132 -- Z
+[ 320,754,157 2 0133 -- bracketleft
+lB "
+\ 640,740,100 2 0134 -- backslash
+rs "
+] 320,754,157 2 0135 -- bracketright
+rB "
+a^ 540,774 2 0136 -- circumflex
+^ "
+_ 500,0,125 0 0137 -- underscore
+` 280,740 2 0140 -- quoteleft
+oq "
+a 660,574,18 0 0141 -- a
+b 660,740,18 2 0142 -- b
+c 640,574,18 0 0143 -- c
+d 660,740,18 2 0144 -- d
+e 640,577,18 0 0145 -- e
+f 280,755 2 0146 -- f
+g 660,574,226 1 0147 -- g
+h 600,740 2 0150 -- h
+i 240,740 2 0151 -- i
+j 260,740,185 3 0152 -- j
+k 580,740 2 0153 -- k
+l 240,740 2 0154 -- l
+m 940,574 0 0155 -- m
+n 600,574 0 0156 -- n
+o 640,574,18 0 0157 -- o
+p 660,574,185 1 0160 -- p
+q 660,574,185 1 0161 -- q
+r 320,574 0 0162 -- r
+s 440,574,18 0 0163 -- s
+t 300,740 2 0164 -- t
+u 600,555,18 0 0165 -- u
+v 560,555 0 0166 -- v
+w 800,555 0 0167 -- w
+x 560,555 0 0170 -- x
+y 580,555,185 1 0171 -- y
+z 460,555 0 0172 -- z
+lC 340,747,191 3 0173 -- braceleft
+{ "
+ba 600,740,100 2 0174 -- bar
+| "
+rC 340,747,191 3 0175 -- braceright
+} "
+a~ 480,767 2 0176 -- tilde
+~ "
+bq 280,133,141 0 0200 -- quotesinglbase
+Fo 460,469 0 0201 -- guillemotleft
+char171 "
+Fc 460,469 0 0202 -- guillemotright
+char187 "
+bu 600,532 0 0203 -- bullet
+Fn 560,824,151 2 0204 -- florin
+f/ 160,740 2 0205 -- fraction
+%0 1280,755,15 2 0206 -- perthousand
+dg 560,740,142 2 0207 -- dagger
+dd 560,740,142 2 0210 -- daggerdbl
+en 500,348 0 0211 -- endash
+em 1000,348 0 0212 -- emdash
+fi 520,755 2 0214 -- fi
+fl 520,755 2 0215 -- fl
+.i 240,555 0 0220 -- dotlessi
+ga 420,851 2 0222 -- grave
+a" 700,862 2 0223 -- hungarumlaut
+a. 280,769 2 0224 -- dotaccent
+ab 480,770 2 0225 -- breve
+ah 540,774 2 0226 -- caron
+ao 360,834 2 0227 -- ring
+ho 340,9,195 1 0230 -- ogonek
+lq 480,740 2 0231 -- quotedblleft
+rq 480,740 2 0232 -- quotedblright
+oe 1080,574,18 0 0233 -- oe
+/l 320,740 2 0234 -- lslash
+Bq 480,133,141 0 0235 -- quotedblbase
+OE 1060,755,15 2 0236 -- OE
+/L 480,740 2 0237 -- Lslash
+r! 280,555,185 1 0241 -- exclamdown
+char161 "
+ct 560,715 0 0242 -- cent
+char162 "
+Po 560,755 2 0243 -- sterling
+char163 "
+Cs 560,577 0 0244 -- currency
+char164 "
+Ye 560,740 2 0245 -- yen
+char165 "
+bb 600,740,100 2 0246 -- brokenbar
+char166 "
+sc 560,755,158 2 0247 -- section
+char167 "
+ad 500,769 2 0250 -- dieresis
+char168 "
+co 740,752,12 2 0251 -- copyright
+char169 "
+Of 360,755 2 0252 -- ordfeminine
+char170 "
+fo 240,469 0 0253 -- guilsinglleft
+no 600,425 0 0254 -- logicalnot
+char172 "
+\- 600,313 0 0255 -- minus
+rg 740,752,12 2 0256 -- registered
+char174 "
+a- 420,759 2 0257 -- macron
+char175 "
+de 400,712 0 0260 -- degree
+char176 "
+char177 600,556,62 0 0261 -- plusminus
+S2 336,749 2 0262 -- twosuperior
+char178 "
+S3 336,749 2 0263 -- threesuperior
+char179 "
+aa 420,849 2 0264 -- acute
+char180 "
+char181 576,555,187 1 0265 -- mu
+ps 600,740,103 2 0266 -- paragraph
+char182 "
+char183 280,320 0 0267 -- periodcentered
+ac 340,6,251 1 0270 -- cedilla
+char184 "
+S1 336,740 2 0271 -- onesuperior
+char185 "
+Om 360,755 2 0272 -- ordmasculine
+char186 "
+fc 240,469 0 0273 -- guilsinglright
+14 840,740 2 0274 -- onequarter
+char188 "
+12 840,740 2 0275 -- onehalf
+char189 "
+34 840,749 2 0276 -- threequarters
+char190 "
+r? 560,555,200 1 0277 -- questiondown
+char191 "
+`A 740,1021 2 0300 -- Agrave
+char192 "
+'A 740,1019 2 0301 -- Aacute
+char193 "
+^A 740,944 2 0302 -- Acircumflex
+char194 "
+~A 740,937 2 0303 -- Atilde
+char195 "
+:A 740,939 2 0304 -- Adieresis
+char196 "
+oA 740,969 2 0305 -- Aring
+char197 "
+AE 900,740 2 0306 -- AE
+char198 "
+,C 780,755,251 3 0307 -- Ccedilla
+char199 "
+`E 520,1021 2 0310 -- Egrave
+char200 "
+'E 520,1019 2 0311 -- Eacute
+char201 "
+^E 520,944 2 0312 -- Ecircumflex
+char202 "
+:E 520,939 2 0313 -- Edieresis
+char203 "
+`I 280,1021 2 0314 -- Igrave
+char204 "
+'I 280,1019 2 0315 -- Iacute
+char205 "
+^I 280,944 2 0316 -- Icircumflex
+char206 "
+:I 280,939 2 0317 -- Idieresis
+char207 "
+-D 742,740 2 0320 -- Eth
+char208 "
+~N 740,937 2 0321 -- Ntilde
+char209 "
+`O 840,1021,15 2 0322 -- Ograve
+char210 "
+'O 840,1019,15 2 0323 -- Oacute
+char211 "
+^O 840,944,15 2 0324 -- Ocircumflex
+char212 "
+~O 840,937,15 2 0325 -- Otilde
+char213 "
+:O 840,939,15 2 0326 -- Odieresis
+char214 "
+char215 600,494 0 0327 -- multiply
+/O 840,814,71 2 0330 -- Oslash
+char216 "
+`U 640,1021,15 2 0331 -- Ugrave
+char217 "
+'U 640,1019,15 2 0332 -- Uacute
+char218 "
+^U 640,944,15 2 0333 -- Ucircumflex
+char219 "
+:U 640,939,15 2 0334 -- Udieresis
+char220 "
+'Y 620,1019 2 0335 -- Yacute
+char221 "
+TP 560,740 2 0336 -- Thorn
+char222 "
+ss 600,755,18 2 0337 -- germandbls
+char223 "
+`a 660,851,18 2 0340 -- agrave
+char224 "
+'a 660,849,18 2 0341 -- aacute
+char225 "
+^a 660,774,18 2 0342 -- acircumflex
+char226 "
+~a 660,767,18 2 0343 -- atilde
+char227 "
+:a 660,769,18 2 0344 -- adieresis
+char228 "
+oa 660,834,18 2 0345 -- aring
+char229 "
+ae 1080,574,18 0 0346 -- ae
+char230 "
+,c 640,574,251 1 0347 -- ccedilla
+char231 "
+`e 640,851,18 2 0350 -- egrave
+char232 "
+'e 640,849,18 2 0351 -- eacute
+char233 "
+^e 640,774,18 2 0352 -- ecircumflex
+char234 "
+:e 640,769,18 2 0353 -- edieresis
+char235 "
+`i 240,851 2 0354 -- igrave
+char236 "
+'i 240,849 2 0355 -- iacute
+char237 "
+^i 240,774 2 0356 -- icircumflex
+char238 "
+:i 240,769 2 0357 -- idieresis
+char239 "
+Sd 640,754,18 2 0360 -- eth
+char240 "
+~n 600,767 2 0361 -- ntilde
+char241 "
+`o 640,851,18 2 0362 -- ograve
+char242 "
+'o 640,849,18 2 0363 -- oacute
+char243 "
+^o 640,774,18 2 0364 -- ocircumflex
+char244 "
+~o 640,767,18 2 0365 -- otilde
+char245 "
+:o 640,769,18 2 0366 -- odieresis
+char246 "
+char247 600,526,20 0 0367 -- divide
+/o 660,608,50 0 0370 -- oslash
+char248 "
+`u 600,851,18 2 0371 -- ugrave
+char249 "
+'u 600,849,18 2 0372 -- uacute
+char250 "
+^u 600,774,18 2 0373 -- ucircumflex
+char251 "
+:u 600,769,18 2 0374 -- udieresis
+char252 "
+'y 580,849,185 3 0375 -- yacute
+char253 "
+Tp 660,740,185 3 0376 -- thorn
+char254 "
+:y 580,769,185 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/ABI b/font/devps/ABI
new file mode 100644
index 00000000..087bb8b0
--- /dev/null
+++ b/font/devps/ABI
@@ -0,0 +1,560 @@
+name ABI
+internalname AvantGarde-DemiOblique
+slant 10.5
+spacewidth 280
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -50
+A w -65
+A v -70
+A u -20
+A ' -90
+A Y -80
+A W -60
+A V -102
+A U -40
+A T -25
+A Q -50
+A O -50
+A G -40
+A C -40
+B A -10
+C A -40
+D . -20
+D , -20
+D Y -45
+D W -25
+D V -50
+D A -50
+F . -129
+F e -20
+F , -162
+F a -20
+F A -75
+G . -20
+G , -20
+G Y -15
+J . -15
+J a -20
+J A -30
+K y -20
+K u -15
+K o -45
+K e -40
+K O -30
+L y -23
+L ' -30
+L rq -30
+L Y -80
+L W -55
+L V -85
+L T -46
+O . -30
+O , -30
+O Y -30
+O X -30
+O W -20
+O V -45
+O T -15
+O A -60
+P . -200
+P o -20
+P e -20
+P , -220
+P a -20
+P A -100
+Q , 20
+R W 25
+R V -10
+R U 25
+R T 40
+R O 25
+S , 20
+T y -10
+T w -55
+T u -46
+T ; -29
+T r -30
+T . -91
+T o -49
+T - -75
+T hy -75
+T char173 -75
+T e -49
+T , -82
+T : -15
+T a -70
+T O -15
+T A -25
+U . -20
+U , -20
+U A -40
+V u -55
+V ; -33
+V . -145
+V o -101
+V i -15
+V - -75
+V hy -75
+V char173 -75
+V e -101
+V , -145
+V : -18
+V a -95
+V O -45
+V G -20
+V A -102
+W y -15
+W u -30
+W ; -33
+W . -106
+W o -46
+W i -10
+W - -35
+W hy -35
+W char173 -35
+W e -47
+W , -106
+W : -15
+W a -50
+W O -20
+W A -58
+Y u -52
+Y ; -23
+Y . -145
+Y o -89
+Y - -100
+Y hy -100
+Y char173 -100
+Y e -89
+Y , -145
+Y : -10
+Y a -93
+Y O -30
+Y A -80
+a t 5
+a p 20
+a b 5
+b y -20
+b v -20
+c y -20
+c l -15
+c k -15
+, ' -70
+, rq -70
+e y -20
+e x -20
+e w -20
+e v -20
+f . -40
+f o -20
+f l -15
+f i -15
+f f -20
+f .i -15
+f , -40
+f a -15
+g i 25
+g a 15
+h y -30
+k y -5
+k o -30
+k e -40
+m y -20
+m u -20
+n y -15
+n v -30
+o y -20
+o x -30
+o w -20
+o v -30
+p y -20
+. ' -70
+. rq -70
+lq A -50
+` ` -80
+` oq -80
+oq ` -80
+oq oq -80
+` A -50
+oq A -50
+' v -10
+' t 10
+' s -15
+' r -20
+' ' -80
+' d -50
+r y 40
+r v 40
+r u 20
+r t 20
+r s 20
+r q -8
+r . -73
+r p 20
+r o -15
+r n 21
+r m 15
+r l 20
+r k 5
+r i 20
+r - -60
+r hy -60
+r char173 -60
+r g 1
+r e -4
+r d -6
+r , -75
+r c -7
+s . 20
+s , 20
+v . -90
+v o -20
+v e -20
+v , -90
+v a -30
+w . -90
+w o -30
+w e -20
+w , -90
+w a -30
+x e -20
+y . -100
+y o -30
+y e -20
+y , -100
+y c -35
+y a -30
+charset
+ha 600,740,0,46,-92,46 2 0000 -- asciicircum
+ti 600,347,0,29,-64,29 0 0001 -- asciitilde
+vS 520,944,15,165,1,82 2 0002 -- Scaron
+vZ 500,944,0,200,31,82 2 0003 -- Zcaron
+vs 440,774,18,173,1,82 2 0004 -- scaron
+vz 460,774,0,188,30,82 2 0005 -- zcaron
+:Y 620,939,0,189,-85,82 2 0006 -- Ydieresis
+tm 1000,740,0,8,-81,8 2 0007 -- trademark
+aq 220,740,0,144,-102,82 2 0010 -- quotesingle
+space 280 0 0040
+! 280,740,0,113,-23,82 2 0041 -- exclam
+" 360,740,0,168,-77,82 2 0042 -- quotedbl
+# 560,700,0,108,-16,82 0 0043 -- numbersign
+sh "
+$ 560,857,86,72,-49,72 2 0044 -- dollar
+Do "
+% 860,755,15,46,-89,46 2 0045 -- percent
+& 680,755,15,112,-21,82 2 0046 -- ampersand
+' 280,740,0,112,-109,82 2 0047 -- quoteright
+( 380,754,157,160,-70,82 2 0050 -- parenleft
+) 380,754,157,48,42,48 2 0051 -- parenright
+* 440,755,0,102,-124,82 2 0052 -- asterisk
++ 600,506,0,60,-34,60 0 0053 -- plus
+, 280,133,141,1,2,1 0 0054 -- comma
+- 420,348,0,43,-64,43 0 0055 -- hyphen
+hy "
+char173 "
+. 280,133,0,1,-23,1 0 0056 -- period
+/ 460,740,100,181,63,82 2 0057 -- slash
+sl "
+0 560,755,15,118,-20,82 2 0060 -- zero
+1 560,740,0,0,-180 2 0061 -- one
+2 560,755,0,112,6,82 2 0062 -- two
+3 560,755,15,75,-17,75 2 0063 -- three
+4 560,740,0,94,14,82 2 0064 -- four
+5 560,740,15,90,-14,82 2 0065 -- five
+6 560,739,15,77,-14,77 2 0066 -- six
+7 560,740,0,125,-33,82 2 0067 -- seven
+8 560,755,15,80,-21,80 2 0070 -- eight
+9 560,754,0,123,-60,82 2 0071 -- nine
+: 280,555,0,79,-23,79 0 0072 -- colon
+; 280,555,141,79,2,79 0 0073 -- semicolon
+< 600,514,8,99,-34,82 0 0074 -- less
+= 600,425,0,81,-13,81 0 0075 -- equal
+> 600,514,8,60,5,60 0 0076 -- greater
+? 560,755,0,83,-85,82 2 0077 -- question
+@ 740,712,12,142,-59,82 0 0100 -- at
+at "
+A 740,740,0,42,43,42 2 0101 -- A
+B 580,740,0,80,-20,80 2 0102 -- B
+C 780,755,15,134,-47,82 2 0103 -- C
+D 700,740,0,82,-13,82 2 0104 -- D
+E 520,740,0,126,-11,82 2 0105 -- E
+F 480,740,0,145,-11,82 2 0106 -- F
+G 840,755,15,97,-39,82 2 0107 -- G
+H 680,740,0,117,-21,82 2 0110 -- H
+I 280,740,0,116,-22,82 2 0111 -- I
+J 480,740,15,116,16,82 2 0112 -- J
+K 620,740,0,187,-39,82 2 0113 -- K
+L 440,740,0,69,-22,69 2 0114 -- L
+M 900,740,0,124,-13,82 2 0115 -- M
+N 740,740,0,118,-20,82 2 0116 -- N
+O 840,755,15,92,-45,82 2 0117 -- O
+P 560,740,0,135,-22,82 2 0120 -- P
+Q 840,755,15,92,-44,82 2 0121 -- Q
+R 580,740,0,126,-14,82 2 0122 -- R
+S 520,755,15,108,1,82 2 0123 -- S
+T 420,740,0,185,-69,82 2 0124 -- T
+U 640,740,15,132,-47,82 2 0125 -- U
+V 700,740,0,182,-95,82 2 0126 -- V
+W 900,740,0,186,-94,82 2 0127 -- W
+X 680,740,0,183,46,82 2 0130 -- X
+Y 620,740,0,189,-85,82 2 0131 -- Y
+Z 500,740,0,149,31,82 2 0132 -- Z
+[ 320,754,157,154,-39,82 2 0133 -- bracketleft
+lB "
+\ 640,740,100,0,-183 2 0134 -- backslash
+rs "
+] 320,754,157,72,43,72 2 0135 -- bracketright
+rB "
+a^ 540,774,0,98,-139,82 2 0136 -- circumflex
+^ "
+_ 500,0,125,36,73,36 0 0137 -- underscore
+` 280,740,0,111,-108,82 2 0140 -- quoteleft
+oq "
+a 660,574,18,106,-23,82 0 0141 -- a
+b 660,740,18,79,3,79 2 0142 -- b
+c 640,574,18,89,-34,82 0 0143 -- c
+d 660,740,18,145,-30,82 2 0144 -- d
+e 640,577,18,77,-27,77 0 0145 -- e
+f 280,755,0,190,-12,82 2 0146 -- f
+g 660,574,226,116,17,82 1 0147 -- g
+h 600,740,0,64,-4,64 2 0150 -- h
+i 240,740,0,133,-3,82 2 0151 -- i
+j 260,740,185,132,68,82 3 0152 -- j
+k 580,740,0,118,-30,82 2 0153 -- k
+l 240,740,0,134,-4,82 2 0154 -- l
+m 940,574,0,64,-4,64 0 0155 -- m
+n 600,574,0,63,-4,63 0 0156 -- n
+o 640,574,18,82,-21,82 0 0157 -- o
+p 660,574,185,76,37,76 1 0160 -- p
+q 660,574,185,106,-28,82 1 0161 -- q
+r 320,574,0,153,-13,82 0 0162 -- r
+s 440,574,18,93,1,82 0 0163 -- s
+t 300,740,0,152,-36,82 2 0164 -- t
+u 600,555,18,97,-37,82 0 0165 -- u
+v 560,555,0,149,-56,82 0 0166 -- v
+w 800,555,0,142,-64,82 0 0167 -- w
+x 560,555,0,122,47,82 0 0170 -- x
+y 580,555,185,144,-25,82 1 0171 -- y
+z 460,555,0,118,30,82 0 0172 -- z
+lC 340,747,191,165,10,82 3 0173 -- braceleft
+{ "
+ba 600,740,100,0,-164 2 0174 -- bar
+| "
+rC 340,747,191,115,62,82 3 0175 -- braceright
+} "
+a~ 480,767,0,134,-128,82 2 0176 -- tilde
+~ "
+bq 280,133,141,0,3 0 0200 -- quotesinglbase
+Fo 460,469,0,77,-55,77 0 0201 -- guillemotleft
+char171 "
+Fc 460,469,0,53,-31,53 0 0202 -- guillemotright
+char187 "
+bu 600,532,0,0,-165 0 0203 -- bullet
+Fn 560,824,151,154,77,82 2 0204 -- florin
+f/ 160,740,0,309,173,82 2 0205 -- fraction
+%0 1280,755,15,26,-89,26 2 0206 -- perthousand
+dg 560,740,142,102,-83,82 2 0207 -- dagger
+dd 560,740,142,108,-13,82 2 0210 -- daggerdbl
+en 500,348,0,79,-28,79 0 0211 -- endash
+em 1000,348,0,79,-28,79 0 0212 -- emdash
+fi 520,755,0,128,-22,82 2 0214 -- fi
+fl 520,755,0,128,-22,82 2 0215 -- fl
+.i 240,555,0,99,-3,82 0 0220 -- dotlessi
+ga 420,851,0,92,-139,82 2 0222 -- grave
+a" 700,862,0,104,-208,82 2 0223 -- hungarumlaut
+a. 280,769,0,120,-142,82 2 0224 -- dotaccent
+ab 480,770,0,152,-135,82 2 0225 -- breve
+ah 540,774,0,123,-164,82 2 0226 -- caron
+ao 360,834,0,114,-156,82 2 0227 -- ring
+ho 340,9,195,0,-9 1 0230 -- ogonek
+lq 480,740,0,116,-106,82 2 0231 -- quotedblleft
+rq 480,740,0,117,-107,82 2 0232 -- quotedblright
+oe 1080,574,18,78,-26,78 0 0233 -- oe
+/l 320,740,0,134,-24,82 2 0234 -- lslash
+Bq 480,133,141,5,5,5 0 0235 -- quotedblbase
+OE 1060,755,15,134,-48,82 2 0236 -- OE
+/L 480,740,0,54,-18,54 2 0237 -- Lslash
+r! 280,555,185,80,10,80 1 0241 -- exclamdown
+char161 "
+ct 560,715,0,89,-60,82 0 0242 -- cent
+char162 "
+Po 560,755,0,105,12,82 2 0243 -- sterling
+char163 "
+Cs 560,577,0,118,-3,82 0 0244 -- currency
+char164 "
+Ye 560,740,0,197,-33,82 2 0245 -- yen
+char165 "
+bb 600,740,100,0,-164 2 0246 -- brokenbar
+char166 "
+sc 560,755,158,92,-15,82 2 0247 -- section
+char167 "
+ad 500,769,0,115,-146,82 2 0250 -- dieresis
+char168 "
+co 740,752,12,137,0,82 2 0251 -- copyright
+char169 "
+Of 360,755,0,162,-77,82 2 0252 -- ordfeminine
+char170 "
+fo 240,469,0,87,-44,82 0 0253 -- guilsinglleft
+no 600,425,0,81,-55,81 0 0254 -- logicalnot
+char172 "
+\- 600,313,0,60,-34,60 0 0255 -- minus
+rg 740,752,12,137,0,82 2 0256 -- registered
+char174 "
+a- 420,759,0,120,-142,82 2 0257 -- macron
+char175 "
+de 400,712,0,101,-110,82 0 0260 -- degree
+char176 "
+char177 600,556,62,76,13,76 0 0261 -- plusminus
+S2 336,749,0,150,-23,82 2 0262 -- twosuperior
+char178 "
+S3 336,749,0,127,-37,82 2 0263 -- threesuperior
+char179 "
+aa 420,849,0,138,-174,82 2 0264 -- acute
+char180 "
+char181 576,555,187,116,47,82 1 0265 -- mu
+ps 600,740,103,194,-40,82 2 0266 -- paragraph
+char182 "
+char183 280,320,0,35,-58,35 0 0267 -- periodcentered
+ac 340,6,251,0,-17 1 0270 -- cedilla
+char184 "
+S1 336,740,0,74,-132,74 2 0271 -- onesuperior
+char185 "
+Om 360,755,0,141,-81,82 2 0272 -- ordmasculine
+char186 "
+fc 240,469,0,63,-20,63 0 0273 -- guilsinglright
+14 840,740,0,0,-137 2 0274 -- onequarter
+char188 "
+12 840,740,0,40,-107,40 2 0275 -- onehalf
+char189 "
+34 840,749,0,46,-47,46 2 0276 -- threequarters
+char190 "
+r? 560,555,200,17,-19,17 1 0277 -- questiondown
+char191 "
+`A 740,1021,0,42,43,42 2 0300 -- Agrave
+char192 "
+'A 740,1019,0,42,43,42 2 0301 -- Aacute
+char193 "
+^A 740,944,0,42,43,42 2 0302 -- Acircumflex
+char194 "
+~A 740,937,0,42,43,42 2 0303 -- Atilde
+char195 "
+:A 740,939,0,42,43,42 2 0304 -- Adieresis
+char196 "
+oA 740,969,0,42,43,42 2 0305 -- Aring
+char197 "
+AE 900,740,0,111,55,82 2 0306 -- AE
+char198 "
+,C 780,755,251,134,-47,82 3 0307 -- Ccedilla
+char199 "
+`E 520,1021,0,126,-11,82 2 0310 -- Egrave
+char200 "
+'E 520,1019,0,126,-11,82 2 0311 -- Eacute
+char201 "
+^E 520,944,0,139,-11,82 2 0312 -- Ecircumflex
+char202 "
+:E 520,939,0,136,-11,82 2 0313 -- Edieresis
+char203 "
+`I 280,1021,0,168,-22,82 2 0314 -- Igrave
+char204 "
+'I 280,1019,0,264,-22,82 2 0315 -- Iacute
+char205 "
+^I 280,944,0,259,-22,82 2 0316 -- Icircumflex
+char206 "
+:I 280,939,0,256,-22,82 2 0317 -- Idieresis
+char207 "
+-D 742,740,0,74,-33,74 2 0320 -- Eth
+char208 "
+~N 740,937,0,118,-20,82 2 0321 -- Ntilde
+char209 "
+`O 840,1021,15,92,-45,82 2 0322 -- Ograve
+char210 "
+'O 840,1019,15,92,-45,82 2 0323 -- Oacute
+char211 "
+^O 840,944,15,92,-45,82 2 0324 -- Ocircumflex
+char212 "
+~O 840,937,15,92,-45,82 2 0325 -- Otilde
+char213 "
+:O 840,939,15,92,-45,82 2 0326 -- Odieresis
+char214 "
+char215 600,494,0,67,-26,67 0 0327 -- multiply
+/O 840,814,71,101,-44,82 2 0330 -- Oslash
+char216 "
+`U 640,1021,15,132,-47,82 2 0331 -- Ugrave
+char217 "
+'U 640,1019,15,132,-47,82 2 0332 -- Uacute
+char218 "
+^U 640,944,15,132,-47,82 2 0333 -- Ucircumflex
+char219 "
+:U 640,939,15,132,-47,82 2 0334 -- Udieresis
+char220 "
+'Y 620,1019,0,189,-85,82 2 0335 -- Yacute
+char221 "
+TP 560,740,0,109,-22,82 2 0336 -- Thorn
+char222 "
+ss 600,755,18,79,-1,79 2 0337 -- germandbls
+char223 "
+`a 660,851,18,106,-23,82 2 0340 -- agrave
+char224 "
+'a 660,849,18,106,-23,82 2 0341 -- aacute
+char225 "
+^a 660,774,18,106,-23,82 2 0342 -- acircumflex
+char226 "
+~a 660,767,18,106,-23,82 2 0343 -- atilde
+char227 "
+:a 660,769,18,106,-23,82 2 0344 -- adieresis
+char228 "
+oa 660,834,18,106,-23,82 2 0345 -- aring
+char229 "
+ae 1080,574,18,75,-25,75 0 0346 -- ae
+char230 "
+,c 640,574,251,89,-33,82 1 0347 -- ccedilla
+char231 "
+`e 640,851,18,77,-27,77 2 0350 -- egrave
+char232 "
+'e 640,849,18,77,-27,77 2 0351 -- eacute
+char233 "
+^e 640,774,18,77,-27,77 2 0352 -- ecircumflex
+char234 "
+:e 640,769,18,77,-27,77 2 0353 -- edieresis
+char235 "
+`i 240,851,0,157,-3,82 2 0354 -- igrave
+char236 "
+'i 240,849,0,253,-3,82 2 0355 -- iacute
+char237 "
+^i 240,774,0,248,11,82 2 0356 -- icircumflex
+char238 "
+:i 240,769,0,245,-3,82 2 0357 -- idieresis
+char239 "
+Sd 640,754,18,109,-23,82 2 0360 -- eth
+char240 "
+~n 600,767,0,74,-4,74 2 0361 -- ntilde
+char241 "
+`o 640,851,18,82,-21,82 2 0362 -- ograve
+char242 "
+'o 640,849,18,82,-21,82 2 0363 -- oacute
+char243 "
+^o 640,774,18,82,-21,82 2 0364 -- ocircumflex
+char244 "
+~o 640,767,18,82,-21,82 2 0365 -- otilde
+char245 "
+:o 640,769,18,82,-21,82 2 0366 -- odieresis
+char246 "
+char247 600,526,20,60,-34,60 0 0367 -- divide
+/o 660,608,50,75,-31,75 0 0370 -- oslash
+char248 "
+`u 600,851,18,97,-37,82 2 0371 -- ugrave
+char249 "
+'u 600,849,18,97,-37,82 2 0372 -- uacute
+char250 "
+^u 600,774,18,97,-37,82 2 0373 -- ucircumflex
+char251 "
+:u 600,769,18,97,-37,82 2 0374 -- udieresis
+char252 "
+'y 580,849,185,144,-25,82 3 0375 -- yacute
+char253 "
+Tp 660,740,185,76,37,76 3 0376 -- thorn
+char254 "
+:y 580,769,185,144,-25,82 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/AI b/font/devps/AI
new file mode 100644
index 00000000..55b789c0
--- /dev/null
+++ b/font/devps/AI
@@ -0,0 +1,559 @@
+name AI
+internalname AvantGarde-BookOblique
+slant 10.5
+spacewidth 277
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -62
+A w -65
+A v -70
+A u -20
+A ' -100
+A rq -100
+A Y -92
+A W -60
+A V -102
+A U -40
+A T -45
+A Q -40
+A O -50
+A G -40
+A C -40
+B A -10
+C A -40
+D . -20
+D , -20
+D Y -30
+D W -10
+D V -50
+D A -50
+F . -160
+F e -20
+F , -180
+F a -20
+F A -75
+G . -20
+G , -20
+G Y -20
+J . -15
+J a -20
+J A -30
+K o -15
+K e -20
+K O -20
+L y -23
+L ' -130
+L rq -130
+L Y -91
+L W -67
+L V -113
+L T -46
+O . -30
+O , -30
+O Y -30
+O X -30
+O W -20
+O V -60
+O T -30
+O A -60
+P . -300
+P o -60
+P e -20
+P , -280
+P a -20
+P A -114
+Q , 20
+R Y -10
+R W 10
+R V -10
+R T 6
+S , 20
+T y -50
+T w -55
+T u -46
+T ; -29
+T r -30
+T . -91
+T o -70
+T i 10
+T - -75
+T hy -75
+T char173 -75
+T e -49
+T , -82
+T : -15
+T a -90
+T O -30
+T A -45
+U . -20
+U , -20
+U A -40
+V u -40
+V ; -33
+V . -165
+V o -101
+V i -5
+V - -75
+V hy -75
+V char173 -75
+V e -101
+V , -145
+V : -18
+V a -104
+V O -60
+V G -20
+V A -102
+W y -2
+W u -30
+W ; -33
+W . -106
+W o -46
+W i 6
+W - -35
+W hy -35
+W char173 -35
+W e -47
+W , -106
+W : -15
+W a -50
+W O -20
+W A -58
+Y u -52
+Y ; -23
+Y . -175
+Y o -89
+Y - -85
+Y hy -85
+Y char173 -85
+Y e -89
+Y , -145
+Y : -10
+Y a -93
+Y O -30
+Y A -92
+a p 20
+a b 20
+b y -20
+b v -20
+c y -20
+c k -15
+, ' -120
+, rq -120
+e y -20
+e w -20
+e v -20
+f . -50
+f o -40
+f l -30
+f i -34
+f f -60
+f e -20
+f .i -34
+f , -50
+f a -40
+g a -15
+h y -30
+k y -5
+k e -15
+m y -20
+m u -20
+m a -20
+n y -15
+n v -20
+o y -20
+o x -15
+o w -20
+o v -30
+p y -20
+. ' -120
+. rq -120
+lq ` -35
+lq oq -35
+lq A -100
+` ` -203
+` oq -203
+oq ` -203
+oq oq -203
+` A -100
+oq A -100
+' v -30
+' t 10
+' s -15
+' r -20
+' ' -203
+' rq -35
+' d -110
+r y 40
+r v 40
+r u 20
+r t 20
+r s 20
+r q -8
+r . -73
+r p 20
+r o -20
+r n 21
+r m 28
+r l 20
+r k 20
+r i 20
+r - -60
+r hy -60
+r char173 -60
+r g -15
+r e -4
+r d -6
+r , -75
+r c -20
+r a -20
+s . 20
+s , 20
+v . -130
+v o -30
+v e -20
+v , -100
+v a -30
+w . -100
+w o -30
+w h 15
+w e -20
+w , -90
+w a -30
+y . -125
+y o -30
+y e -20
+y , -110
+y a -30
+charset
+ha 606,740,0,54,-60,54 2 0000 -- asciicircum
+ti 606,319,0,28,-64,28 0 0001 -- asciitilde
+vS 498,927,13,145,-7,81 2 0002 -- Scaron
+vZ 480,927,0,166,38,81 2 0003 -- Zcaron
+vs 388,764,13,170,1,81 2 0004 -- scaron
+vz 425,764,0,152,40,81 2 0005 -- zcaron
+:Y 592,928,0,187,-88,81 2 0006 -- Ydieresis
+tm 1000,740,0,3,-87,3 2 0007 -- trademark
+aq 198,740,0,129,-103,81 2 0010 -- quotesingle
+space 277 0 0040
+! 295,740,0,77,-61,77 2 0041 -- exclam
+" 309,740,0,151,-80,81 2 0042 -- quotedbl
+# 554,740,0,116,-21,81 2 0043 -- numbersign
+sh "
+$ 554,811,70,77,-57,77 2 0044 -- dollar
+Do "
+% 775,751,13,62,-74,62 2 0045 -- percent
+& 757,753,12,68,-42,68 2 0046 -- ampersand
+' 351,740,0,92,-145,81 2 0047 -- quoteright
+( 369,757,205,176,-39,81 3 0050 -- parenleft
+) 369,757,205,63,74,63 3 0051 -- parenright
+* 425,740,0,104,-120,81 2 0052 -- asterisk
++ 606,506,0,52,-42,52 0 0053 -- plus
+, 277,126,67,0,48 0 0054 -- comma
+- 332,315,0,78,-26,78 0 0055 -- hyphen
+hy "
+char173 "
+. 277,126,0,0,-52 0 0056 -- period
+/ 437,740,100,153,25,81 2 0057 -- slash
+sl "
+0 554,753,13,118,-21,81 2 0060 -- zero
+1 554,740,0,0,-210 2 0061 -- one
+2 554,753,0,111,10,81 2 0062 -- two
+3 554,753,13,61,-23,61 2 0063 -- three
+4 554,740,0,94,11,81 2 0064 -- four
+5 554,740,13,101,-19,81 2 0065 -- five
+6 554,739,13,76,-15,76 2 0066 -- six
+7 554,740,0,124,-60,81 2 0067 -- seven
+8 554,753,13,76,-27,76 2 0070 -- eight
+9 554,752,0,122,-61,81 2 0071 -- nine
+: 277,548,0,51,-52,51 0 0072 -- colon
+; 277,548,67,51,48,51 0 0073 -- semicolon
+< 606,514,8,93,-37,81 0 0074 -- less
+= 606,388,0,71,-23,71 0 0075 -- equal
+> 606,514,8,57,-1,57 0 0076 -- greater
+? 591,752,0,87,-108,81 2 0077 -- question
+@ 867,753,13,71,-76,71 2 0100 -- at
+at "
+A 740,740,0,39,38,39 2 0101 -- A
+B 574,740,0,82,-24,81 2 0102 -- B
+C 813,752,13,107,-55,81 2 0103 -- C
+D 744,740,0,79,-24,79 2 0104 -- D
+E 536,740,0,126,-20,81 2 0105 -- E
+F 485,740,0,146,-20,81 2 0106 -- F
+G 872,753,13,69,-53,69 2 0107 -- G
+H 683,740,0,111,-26,81 2 0110 -- H
+I 226,740,0,111,-26,81 2 0111 -- I
+J 482,740,13,107,13,81 2 0112 -- J
+K 591,740,0,187,-31,81 2 0113 -- K
+L 462,740,0,62,-32,62 2 0114 -- L
+M 919,740,0,111,-26,81 2 0115 -- M
+N 740,740,0,111,-25,81 2 0116 -- N
+O 869,753,13,82,-55,81 2 0117 -- O
+P 592,740,0,122,-25,81 2 0120 -- P
+Q 871,753,13,91,-52,81 2 0121 -- Q
+R 607,740,0,112,-20,81 2 0122 -- R
+S 498,753,13,113,-7,81 2 0123 -- S
+T 426,740,0,180,-81,81 2 0124 -- T
+U 655,740,13,111,-68,81 2 0125 -- U
+V 702,740,0,178,-95,81 2 0126 -- V
+W 960,740,0,177,-98,81 2 0127 -- W
+X 609,740,0,165,42,81 2 0130 -- X
+Y 592,740,0,187,-88,81 2 0131 -- Y
+Z 480,740,0,166,38,81 2 0132 -- Z
+[ 351,753,179,176,-95,81 2 0133 -- bracketleft
+lB "
+\ 605,740,100,0,-205 2 0134 -- backslash
+rs "
+] 351,753,179,11,69,11 2 0135 -- bracketright
+rB "
+a^ 502,764,0,94,-142,81 2 0136 -- circumflex
+^ "
+_ 500,0,125,36,73,36 0 0137 -- underscore
+` 351,740,0,57,-182,57 2 0140 -- quoteleft
+oq "
+a 683,561,13,89,-38,81 0 0141 -- a
+b 682,740,13,71,-18,71 2 0142 -- b
+c 647,561,13,81,-37,81 0 0143 -- c
+d 685,740,13,120,-35,81 2 0144 -- d
+e 650,561,13,64,-34,64 0 0145 -- e
+f 314,753,0,190,-54,81 2 0146 -- f
+g 673,561,215,84,-6,81 1 0147 -- g
+h 610,740,0,46,-12,46 2 0150 -- h
+i 200,740,0,122,-15,81 2 0151 -- i
+j 203,740,192,121,130,81 3 0152 -- j
+k 502,740,0,136,-20,81 2 0153 -- k
+l 200,740,0,122,-15,81 2 0154 -- l
+m 938,561,0,50,-16,50 0 0155 -- m
+n 610,561,0,49,-15,49 0 0156 -- n
+o 655,561,13,64,-38,64 0 0157 -- o
+p 682,561,192,67,22,67 1 0160 -- p
+q 682,561,192,85,-33,81 1 0161 -- q
+r 301,561,0,144,-15,81 0 0162 -- r
+s 388,561,13,86,1,81 0 0163 -- s
+t 339,740,0,142,-54,81 2 0164 -- t
+u 608,547,13,84,-50,81 0 0165 -- u
+v 554,547,0,143,-58,81 0 0166 -- v
+w 831,547,0,140,-64,81 0 0167 -- w
+x 480,547,0,139,38,81 0 0170 -- x
+y 536,547,192,138,-47,81 1 0171 -- y
+z 425,547,0,123,40,81 0 0172 -- z
+lC 351,740,189,167,-65,81 2 0173 -- braceleft
+{ "
+ba 672,740,100,0,-230 2 0174 -- bar
+| "
+rC 351,740,189,37,65,37 2 0175 -- braceright
+} "
+a~ 439,754,0,131,-129,81 2 0176 -- tilde
+~ "
+bq 354,126,68,0,-26 0 0200 -- quotesinglbase
+Fo 425,481,0,94,-42,81 0 0201 -- guillemotleft
+char171 "
+Fc 425,481,0,62,-10,62 0 0202 -- guillemotright
+char187 "
+bu 606,532,0,0,-167 0 0203 -- bullet
+Fn 554,818,153,165,89,81 2 0204 -- florin
+f/ 166,740,0,301,163,81 2 0205 -- fraction
+%0 1174,751,13,58,-78,58 2 0206 -- perthousand
+dg 553,740,133,90,-96,81 2 0207 -- dagger
+dd 553,740,133,90,-22,81 2 0210 -- daggerdbl
+en 500,315,0,73,-31,73 0 0211 -- endash
+em 1000,315,0,73,-31,73 0 0212 -- emdash
+fi 487,753,0,122,-54,81 2 0214 -- fi
+fl 485,753,0,122,-54,81 2 0215 -- fl
+.i 200,547,0,86,-15,81 0 0220 -- dotlessi
+ga 378,786,0,97,-154,81 2 0222 -- grave
+a" 552,800,0,92,-189,81 2 0223 -- hungarumlaut
+a. 222,765,0,118,-142,81 2 0224 -- dotaccent
+ab 453,754,0,138,-142,81 2 0225 -- breve
+ah 502,764,0,113,-160,81 2 0226 -- caron
+ao 332,807,0,119,-141,81 2 0227 -- ring
+ho 302,0,191,0,-3 1 0230 -- ogonek
+lq 502,740,0,55,-184,55 2 0231 -- quotedblleft
+rq 484,740,0,108,-147,81 2 0232 -- quotedblright
+oe 1137,561,13,73,-30,73 0 0233 -- oe
+/l 300,740,0,104,-45,81 2 0234 -- lslash
+Bq 502,126,68,0,-26 0 0235 -- quotedblbase
+OE 1194,753,13,135,-57,81 2 0236 -- OE
+/L 517,740,0,62,-57,62 2 0237 -- Lslash
+r! 295,548,192,41,-24,41 1 0241 -- exclamdown
+char161 "
+ct 554,707,0,92,-65,81 0 0242 -- cent
+char162 "
+Po 554,753,0,110,21,81 2 0243 -- sterling
+char163 "
+Cs 554,580,0,141,26,81 0 0244 -- currency
+char164 "
+Ye 554,740,0,183,-25,81 2 0245 -- yen
+char165 "
+bb 672,740,100,0,-230 2 0246 -- brokenbar
+char166 "
+sc 615,753,141,32,-68,32 2 0247 -- section
+char167 "
+ad 369,765,0,118,-141,81 2 0250 -- dieresis
+char168 "
+co 747,752,12,133,-3,81 2 0251 -- copyright
+char169 "
+Of 369,753,0,175,-52,81 2 0252 -- ordfeminine
+char170 "
+fo 251,481,0,94,-42,81 0 0253 -- guilsinglleft
+no 606,388,0,71,-60,71 0 0254 -- logicalnot
+char172 "
+\- 606,287,0,52,-42,52 0 0255 -- minus
+rg 747,752,12,133,-3,81 2 0256 -- registered
+char174 "
+a- 485,736,0,112,-147,81 0 0257 -- macron
+char175 "
+de 400,709,0,101,-108,81 0 0260 -- degree
+char176 "
+char177 606,518,24,62,3,62 0 0261 -- plusminus
+S2 332,747,0,151,-24,81 2 0262 -- twosuperior
+char178 "
+S3 332,747,0,126,-48,81 2 0263 -- threesuperior
+char179 "
+aa 375,786,0,119,-153,81 2 0264 -- acute
+char180 "
+char181 608,547,184,70,4,70 0 0265 -- mu
+ps 564,740,110,174,-69,81 2 0266 -- paragraph
+char182 "
+char183 277,316,0,8,-87,8 0 0267 -- periodcentered
+ac 324,0,222,0,-2 1 0270 -- cedilla
+char184 "
+S1 332,740,0,53,-140,53 2 0271 -- onesuperior
+char185 "
+Om 369,753,0,147,-66,81 2 0272 -- ordmasculine
+char186 "
+fc 251,481,0,62,-10,62 0 0273 -- guilsinglright
+14 831,740,0,0,-133 2 0274 -- onequarter
+char188 "
+12 831,740,0,29,-114,29 2 0275 -- onehalf
+char189 "
+34 831,747,0,44,-76,44 2 0276 -- threequarters
+char190 "
+r? 591,548,205,0,-14 1 0277 -- questiondown
+char191 "
+`A 740,949,0,39,38,39 2 0300 -- Agrave
+char192 "
+'A 740,949,0,39,38,39 2 0301 -- Aacute
+char193 "
+^A 740,927,0,39,38,39 2 0302 -- Acircumflex
+char194 "
+~A 740,917,0,39,38,39 2 0303 -- Atilde
+char195 "
+:A 740,928,0,39,38,39 2 0304 -- Adieresis
+char196 "
+oA 740,955,0,39,38,39 2 0305 -- Aring
+char197 "
+AE 992,740,0,102,70,81 2 0306 -- AE
+char198 "
+,C 813,752,222,107,-55,81 3 0307 -- Ccedilla
+char199 "
+`E 536,949,0,126,-20,81 2 0310 -- Egrave
+char200 "
+'E 536,949,0,126,-20,81 2 0311 -- Eacute
+char201 "
+^E 536,927,0,126,-20,81 2 0312 -- Ecircumflex
+char202 "
+:E 536,928,0,126,-20,81 2 0313 -- Edieresis
+char203 "
+`I 226,949,0,164,-26,81 2 0314 -- Igrave
+char204 "
+'I 226,949,0,264,-26,81 2 0315 -- Iacute
+char205 "
+^I 226,927,0,263,-26,81 2 0316 -- Icircumflex
+char206 "
+:I 226,928,0,220,-26,81 2 0317 -- Idieresis
+char207 "
+-D 790,740,0,73,-54,73 2 0320 -- Eth
+char208 "
+~N 740,917,0,111,-25,81 2 0321 -- Ntilde
+char209 "
+`O 869,949,13,82,-55,81 2 0322 -- Ograve
+char210 "
+'O 869,949,13,82,-55,81 2 0323 -- Oacute
+char211 "
+^O 869,927,13,82,-55,81 2 0324 -- Ocircumflex
+char212 "
+~O 869,917,13,82,-55,81 2 0325 -- Otilde
+char213 "
+:O 869,928,13,82,-55,81 2 0326 -- Odieresis
+char214 "
+char215 606,482,0,56,-37,56 0 0327 -- multiply
+/O 868,819,83,111,-26,81 2 0330 -- Oslash
+char216 "
+`U 655,949,13,111,-68,81 2 0331 -- Ugrave
+char217 "
+'U 655,949,13,111,-68,81 2 0332 -- Uacute
+char218 "
+^U 655,927,13,111,-68,81 2 0333 -- Ucircumflex
+char219 "
+:U 655,928,13,111,-68,81 2 0334 -- Udieresis
+char220 "
+'Y 592,949,0,187,-88,81 2 0335 -- Yacute
+char221 "
+TP 592,740,0,79,-10,79 2 0336 -- Thorn
+char222 "
+ss 554,753,13,74,-11,74 2 0337 -- germandbls
+char223 "
+`a 683,786,13,89,-38,81 2 0340 -- agrave
+char224 "
+'a 683,786,13,89,-38,81 2 0341 -- aacute
+char225 "
+^a 683,764,13,89,-38,81 2 0342 -- acircumflex
+char226 "
+~a 683,754,13,89,-38,81 2 0343 -- atilde
+char227 "
+:a 683,765,13,89,-38,81 2 0344 -- adieresis
+char228 "
+oa 683,807,13,89,-38,81 2 0345 -- aring
+char229 "
+ae 1157,561,13,62,-30,62 0 0346 -- ae
+char230 "
+,c 647,561,222,81,-37,81 1 0347 -- ccedilla
+char231 "
+`e 650,786,13,64,-34,64 2 0350 -- egrave
+char232 "
+'e 650,786,13,64,-34,64 2 0351 -- eacute
+char233 "
+^e 650,764,13,64,-34,64 2 0352 -- ecircumflex
+char234 "
+:e 650,765,13,64,-34,64 2 0353 -- edieresis
+char235 "
+`i 200,786,0,146,-15,81 2 0354 -- igrave
+char236 "
+'i 200,786,0,247,-15,81 2 0355 -- iacute
+char237 "
+^i 200,764,0,245,9,81 2 0356 -- icircumflex
+char238 "
+:i 200,765,0,203,-15,81 2 0357 -- idieresis
+char239 "
+Sd 655,753,12,70,-38,70 2 0360 -- eth
+char240 "
+~n 610,754,0,49,-15,49 2 0361 -- ntilde
+char241 "
+`o 655,786,13,64,-38,64 2 0362 -- ograve
+char242 "
+'o 655,786,13,64,-38,64 2 0363 -- oacute
+char243 "
+^o 655,764,13,64,-38,64 2 0364 -- ocircumflex
+char244 "
+~o 655,754,13,64,-38,64 2 0365 -- otilde
+char245 "
+:o 655,765,13,64,-38,64 2 0366 -- odieresis
+char246 "
+char247 606,519,13,52,-42,52 0 0367 -- divide
+/o 653,614,64,100,-1,81 0 0370 -- oslash
+char248 "
+`u 608,786,13,84,-50,81 2 0371 -- ugrave
+char249 "
+'u 608,786,13,84,-50,81 2 0372 -- uacute
+char250 "
+^u 608,764,13,84,-50,81 2 0373 -- ucircumflex
+char251 "
+:u 608,765,13,84,-50,81 2 0374 -- udieresis
+char252 "
+'y 536,786,192,138,-47,81 3 0375 -- yacute
+char253 "
+Tp 682,740,192,67,22,67 3 0376 -- thorn
+char254 "
+:y 536,765,192,138,-47,81 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/AR b/font/devps/AR
new file mode 100644
index 00000000..8d34316d
--- /dev/null
+++ b/font/devps/AR
@@ -0,0 +1,558 @@
+name AR
+internalname AvantGarde-Book
+spacewidth 277
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -62
+A w -65
+A v -70
+A u -20
+A ' -100
+A rq -100
+A Y -92
+A W -60
+A V -102
+A U -40
+A T -45
+A Q -40
+A O -50
+A G -40
+A C -40
+B A -10
+C A -40
+D . -20
+D , -20
+D Y -30
+D W -10
+D V -50
+D A -50
+F . -160
+F e -20
+F , -180
+F a -20
+F A -75
+G . -20
+G , -20
+G Y -20
+J . -15
+J a -20
+J A -30
+K o -15
+K e -20
+K O -20
+L y -23
+L ' -130
+L rq -130
+L Y -91
+L W -67
+L V -113
+L T -46
+O . -30
+O , -30
+O Y -30
+O X -30
+O W -20
+O V -60
+O T -30
+O A -60
+P . -300
+P o -60
+P e -20
+P , -280
+P a -20
+P A -114
+Q , 20
+R Y -10
+R W 10
+R V -10
+R T 6
+S , 20
+T y -50
+T w -55
+T u -46
+T ; -29
+T r -30
+T . -91
+T o -70
+T i 10
+T - -75
+T hy -75
+T char173 -75
+T e -49
+T , -82
+T : -15
+T a -90
+T O -30
+T A -45
+U . -20
+U , -20
+U A -40
+V u -40
+V ; -33
+V . -165
+V o -101
+V i -5
+V - -75
+V hy -75
+V char173 -75
+V e -101
+V , -145
+V : -18
+V a -104
+V O -60
+V G -20
+V A -102
+W y -2
+W u -30
+W ; -33
+W . -106
+W o -46
+W i 6
+W - -35
+W hy -35
+W char173 -35
+W e -47
+W , -106
+W : -15
+W a -50
+W O -20
+W A -58
+Y u -52
+Y ; -23
+Y . -175
+Y o -89
+Y - -85
+Y hy -85
+Y char173 -85
+Y e -89
+Y , -145
+Y : -10
+Y a -93
+Y O -30
+Y A -92
+a p 20
+a b 20
+b y -20
+b v -20
+c y -20
+c k -15
+, ' -120
+, rq -120
+e y -20
+e w -20
+e v -20
+f . -50
+f o -40
+f l -30
+f i -34
+f f -60
+f e -20
+f .i -34
+f , -50
+f a -40
+g a -15
+h y -30
+k y -5
+k e -15
+m y -20
+m u -20
+m a -20
+n y -15
+n v -20
+o y -20
+o x -15
+o w -20
+o v -30
+p y -20
+. ' -120
+. rq -120
+lq ` -35
+lq oq -35
+lq A -100
+` ` -203
+` oq -203
+oq ` -203
+oq oq -203
+` A -100
+oq A -100
+' v -30
+' t 10
+' s -15
+' r -20
+' ' -203
+' rq -35
+' d -110
+r y 40
+r v 40
+r u 20
+r t 20
+r s 20
+r q -8
+r . -73
+r p 20
+r o -20
+r n 21
+r m 28
+r l 20
+r k 20
+r i 20
+r - -60
+r hy -60
+r char173 -60
+r g -15
+r e -4
+r d -6
+r , -75
+r c -20
+r a -20
+s . 20
+s , 20
+v . -130
+v o -30
+v e -20
+v , -100
+v a -30
+w . -100
+w o -30
+w h 15
+w e -20
+w , -90
+w a -30
+y . -125
+y o -30
+y e -20
+y , -110
+y a -30
+charset
+ha 606,740 2 0000 -- asciicircum
+ti 606,319 0 0001 -- asciitilde
+vS 498,927,13 2 0002 -- Scaron
+vZ 480,927 2 0003 -- Zcaron
+vs 388,764,13 2 0004 -- scaron
+vz 425,764 2 0005 -- zcaron
+:Y 592,928 2 0006 -- Ydieresis
+tm 1000,740 2 0007 -- trademark
+aq 198,740 2 0010 -- quotesingle
+space 277 0 0040
+! 295,740 2 0041 -- exclam
+" 309,740 2 0042 -- quotedbl
+# 554,740 2 0043 -- numbersign
+sh "
+$ 554,811,70 2 0044 -- dollar
+Do "
+% 775,751,13 2 0045 -- percent
+& 757,753,12 2 0046 -- ampersand
+' 351,740 2 0047 -- quoteright
+( 369,757,205 3 0050 -- parenleft
+) 369,757,205 3 0051 -- parenright
+* 425,740 2 0052 -- asterisk
++ 606,506 0 0053 -- plus
+, 277,126,67 0 0054 -- comma
+- 332,315 0 0055 -- hyphen
+hy "
+char173 "
+. 277,126 0 0056 -- period
+/ 437,740,100 2 0057 -- slash
+sl "
+0 554,753,13 2 0060 -- zero
+1 554,740 2 0061 -- one
+2 554,753 2 0062 -- two
+3 554,753,13 2 0063 -- three
+4 554,740 2 0064 -- four
+5 554,740,13 2 0065 -- five
+6 554,739,13 2 0066 -- six
+7 554,740 2 0067 -- seven
+8 554,753,13 2 0070 -- eight
+9 554,752 2 0071 -- nine
+: 277,548 0 0072 -- colon
+; 277,548,67 0 0073 -- semicolon
+< 606,514,8 0 0074 -- less
+= 606,388 0 0075 -- equal
+> 606,514,8 0 0076 -- greater
+? 591,752 2 0077 -- question
+@ 867,753,13 2 0100 -- at
+at "
+A 740,740 2 0101 -- A
+B 574,740 2 0102 -- B
+C 813,752,13 2 0103 -- C
+D 744,740 2 0104 -- D
+E 536,740 2 0105 -- E
+F 485,740 2 0106 -- F
+G 872,753,13 2 0107 -- G
+H 683,740 2 0110 -- H
+I 226,740 2 0111 -- I
+J 482,740,13 2 0112 -- J
+K 591,740 2 0113 -- K
+L 462,740 2 0114 -- L
+M 919,740 2 0115 -- M
+N 740,740 2 0116 -- N
+O 869,753,13 2 0117 -- O
+P 592,740 2 0120 -- P
+Q 871,753,13 2 0121 -- Q
+R 607,740 2 0122 -- R
+S 498,753,13 2 0123 -- S
+T 426,740 2 0124 -- T
+U 655,740,13 2 0125 -- U
+V 702,740 2 0126 -- V
+W 960,740 2 0127 -- W
+X 609,740 2 0130 -- X
+Y 592,740 2 0131 -- Y
+Z 480,740 2 0132 -- Z
+[ 351,753,179 2 0133 -- bracketleft
+lB "
+\ 605,740,100 2 0134 -- backslash
+rs "
+] 351,753,179 2 0135 -- bracketright
+rB "
+a^ 502,764 2 0136 -- circumflex
+^ "
+_ 500,0,125 0 0137 -- underscore
+` 351,740 2 0140 -- quoteleft
+oq "
+a 683,561,13 0 0141 -- a
+b 682,740,13 2 0142 -- b
+c 647,561,13 0 0143 -- c
+d 685,740,13 2 0144 -- d
+e 650,561,13 0 0145 -- e
+f 314,753 2 0146 -- f
+g 673,561,215 1 0147 -- g
+h 610,740 2 0150 -- h
+i 200,740 2 0151 -- i
+j 203,740,192 3 0152 -- j
+k 502,740 2 0153 -- k
+l 200,740 2 0154 -- l
+m 938,561 0 0155 -- m
+n 610,561 0 0156 -- n
+o 655,561,13 0 0157 -- o
+p 682,561,192 1 0160 -- p
+q 682,561,192 1 0161 -- q
+r 301,561 0 0162 -- r
+s 388,561,13 0 0163 -- s
+t 339,740 2 0164 -- t
+u 608,547,13 0 0165 -- u
+v 554,547 0 0166 -- v
+w 831,547 0 0167 -- w
+x 480,547 0 0170 -- x
+y 536,547,192 1 0171 -- y
+z 425,547 0 0172 -- z
+lC 351,740,189 2 0173 -- braceleft
+{ "
+ba 672,740,100 2 0174 -- bar
+| "
+rC 351,740,189 2 0175 -- braceright
+} "
+a~ 439,754 2 0176 -- tilde
+~ "
+bq 354,126,68 0 0200 -- quotesinglbase
+Fo 425,481 0 0201 -- guillemotleft
+char171 "
+Fc 425,481 0 0202 -- guillemotright
+char187 "
+bu 606,532 0 0203 -- bullet
+Fn 554,818,153 2 0204 -- florin
+f/ 166,740 2 0205 -- fraction
+%0 1174,751,13 2 0206 -- perthousand
+dg 553,740,133 2 0207 -- dagger
+dd 553,740,133 2 0210 -- daggerdbl
+en 500,315 0 0211 -- endash
+em 1000,315 0 0212 -- emdash
+fi 487,753 2 0214 -- fi
+fl 485,753 2 0215 -- fl
+.i 200,547 0 0220 -- dotlessi
+ga 378,786 2 0222 -- grave
+a" 552,800 2 0223 -- hungarumlaut
+a. 222,765 2 0224 -- dotaccent
+ab 453,754 2 0225 -- breve
+ah 502,764 2 0226 -- caron
+ao 332,807 2 0227 -- ring
+ho 302,0,191 1 0230 -- ogonek
+lq 502,740 2 0231 -- quotedblleft
+rq 484,740 2 0232 -- quotedblright
+oe 1137,561,13 0 0233 -- oe
+/l 300,740 2 0234 -- lslash
+Bq 502,126,68 0 0235 -- quotedblbase
+OE 1194,753,13 2 0236 -- OE
+/L 517,740 2 0237 -- Lslash
+r! 295,548,192 1 0241 -- exclamdown
+char161 "
+ct 554,707 0 0242 -- cent
+char162 "
+Po 554,753 2 0243 -- sterling
+char163 "
+Cs 554,580 0 0244 -- currency
+char164 "
+Ye 554,740 2 0245 -- yen
+char165 "
+bb 672,740,100 2 0246 -- brokenbar
+char166 "
+sc 615,753,141 2 0247 -- section
+char167 "
+ad 369,765 2 0250 -- dieresis
+char168 "
+co 747,752,12 2 0251 -- copyright
+char169 "
+Of 369,753 2 0252 -- ordfeminine
+char170 "
+fo 251,481 0 0253 -- guilsinglleft
+no 606,388 0 0254 -- logicalnot
+char172 "
+\- 606,287 0 0255 -- minus
+rg 747,752,12 2 0256 -- registered
+char174 "
+a- 485,736 0 0257 -- macron
+char175 "
+de 400,709 0 0260 -- degree
+char176 "
+char177 606,518,24 0 0261 -- plusminus
+S2 332,747 2 0262 -- twosuperior
+char178 "
+S3 332,747 2 0263 -- threesuperior
+char179 "
+aa 375,786 2 0264 -- acute
+char180 "
+char181 608,547,184 0 0265 -- mu
+ps 564,740,110 2 0266 -- paragraph
+char182 "
+char183 277,316 0 0267 -- periodcentered
+ac 324,0,222 1 0270 -- cedilla
+char184 "
+S1 332,740 2 0271 -- onesuperior
+char185 "
+Om 369,753 2 0272 -- ordmasculine
+char186 "
+fc 251,481 0 0273 -- guilsinglright
+14 831,740 2 0274 -- onequarter
+char188 "
+12 831,740 2 0275 -- onehalf
+char189 "
+34 831,747 2 0276 -- threequarters
+char190 "
+r? 591,548,205 1 0277 -- questiondown
+char191 "
+`A 740,949 2 0300 -- Agrave
+char192 "
+'A 740,949 2 0301 -- Aacute
+char193 "
+^A 740,927 2 0302 -- Acircumflex
+char194 "
+~A 740,917 2 0303 -- Atilde
+char195 "
+:A 740,928 2 0304 -- Adieresis
+char196 "
+oA 740,955 2 0305 -- Aring
+char197 "
+AE 992,740 2 0306 -- AE
+char198 "
+,C 813,752,222 3 0307 -- Ccedilla
+char199 "
+`E 536,949 2 0310 -- Egrave
+char200 "
+'E 536,949 2 0311 -- Eacute
+char201 "
+^E 536,927 2 0312 -- Ecircumflex
+char202 "
+:E 536,928 2 0313 -- Edieresis
+char203 "
+`I 226,949 2 0314 -- Igrave
+char204 "
+'I 226,949 2 0315 -- Iacute
+char205 "
+^I 226,927 2 0316 -- Icircumflex
+char206 "
+:I 226,928 2 0317 -- Idieresis
+char207 "
+-D 790,740 2 0320 -- Eth
+char208 "
+~N 740,917 2 0321 -- Ntilde
+char209 "
+`O 869,949,13 2 0322 -- Ograve
+char210 "
+'O 869,949,13 2 0323 -- Oacute
+char211 "
+^O 869,927,13 2 0324 -- Ocircumflex
+char212 "
+~O 869,917,13 2 0325 -- Otilde
+char213 "
+:O 869,928,13 2 0326 -- Odieresis
+char214 "
+char215 606,482 0 0327 -- multiply
+/O 868,819,83 2 0330 -- Oslash
+char216 "
+`U 655,949,13 2 0331 -- Ugrave
+char217 "
+'U 655,949,13 2 0332 -- Uacute
+char218 "
+^U 655,927,13 2 0333 -- Ucircumflex
+char219 "
+:U 655,928,13 2 0334 -- Udieresis
+char220 "
+'Y 592,949 2 0335 -- Yacute
+char221 "
+TP 592,740 2 0336 -- Thorn
+char222 "
+ss 554,753,13 2 0337 -- germandbls
+char223 "
+`a 683,786,13 2 0340 -- agrave
+char224 "
+'a 683,786,13 2 0341 -- aacute
+char225 "
+^a 683,764,13 2 0342 -- acircumflex
+char226 "
+~a 683,754,13 2 0343 -- atilde
+char227 "
+:a 683,765,13 2 0344 -- adieresis
+char228 "
+oa 683,807,13 2 0345 -- aring
+char229 "
+ae 1157,561,13 0 0346 -- ae
+char230 "
+,c 647,561,222 1 0347 -- ccedilla
+char231 "
+`e 650,786,13 2 0350 -- egrave
+char232 "
+'e 650,786,13 2 0351 -- eacute
+char233 "
+^e 650,764,13 2 0352 -- ecircumflex
+char234 "
+:e 650,765,13 2 0353 -- edieresis
+char235 "
+`i 200,786 2 0354 -- igrave
+char236 "
+'i 200,786 2 0355 -- iacute
+char237 "
+^i 200,764 2 0356 -- icircumflex
+char238 "
+:i 200,765 2 0357 -- idieresis
+char239 "
+Sd 655,753,12 2 0360 -- eth
+char240 "
+~n 610,754 2 0361 -- ntilde
+char241 "
+`o 655,786,13 2 0362 -- ograve
+char242 "
+'o 655,786,13 2 0363 -- oacute
+char243 "
+^o 655,764,13 2 0364 -- ocircumflex
+char244 "
+~o 655,754,13 2 0365 -- otilde
+char245 "
+:o 655,765,13 2 0366 -- odieresis
+char246 "
+char247 606,519,13 0 0367 -- divide
+/o 653,614,64 0 0370 -- oslash
+char248 "
+`u 608,786,13 2 0371 -- ugrave
+char249 "
+'u 608,786,13 2 0372 -- uacute
+char250 "
+^u 608,764,13 2 0373 -- ucircumflex
+char251 "
+:u 608,765,13 2 0374 -- udieresis
+char252 "
+'y 536,786,192 3 0375 -- yacute
+char253 "
+Tp 682,740,192 3 0376 -- thorn
+char254 "
+:y 536,765,192 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/BMB b/font/devps/BMB
new file mode 100644
index 00000000..b0e0d86e
--- /dev/null
+++ b/font/devps/BMB
@@ -0,0 +1,438 @@
+name BMB
+internalname Bookman-Demi
+spacewidth 340
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -1
+A w -9
+A v -8
+A Y -52
+A W -20
+A V -68
+A T -40
+F . -132
+F , -130
+F A -59
+L y 19
+L Y -35
+L W -41
+L V -50
+L T -4
+P . -128
+P , -129
+P A -46
+R y -8
+R Y -20
+R W -24
+R V -29
+R T -4
+T ; 5
+T s -10
+T r 27
+T . -122
+T o -28
+T i 27
+T - -10
+T hy -10
+T char173 -10
+T e -29
+T , -122
+T : 7
+T c -29
+T a -24
+T A -42
+V y 12
+V u -11
+V ; -38
+V r -15
+V . -105
+V o -79
+V i 15
+V - -10
+V hy -10
+V char173 -10
+V e -80
+V , -103
+V : -37
+V a -74
+V A -88
+W y 12
+W u -11
+W ; -38
+W r -15
+W . -105
+W o -78
+W i 15
+W - -10
+W hy -10
+W char173 -10
+W e -79
+W , -103
+W : -37
+W a -73
+W A -60
+Y v 24
+Y u -13
+Y ; -34
+Y q -66
+Y . -105
+Y p -23
+Y o -66
+Y i 2
+Y - -10
+Y hy -10
+Y char173 -10
+Y e -67
+Y , -103
+Y : -32
+Y a -60
+Y A -56
+f f 21
+r q -9
+r . -102
+r o -9
+r n 20
+r m 20
+r - -10
+r hy -10
+r char173 -10
+r h -23
+r g -9
+r f 20
+r e -10
+r d -10
+r , -101
+r c -9
+charset
+ha 600,681 2 0000 -- asciicircum
+ti 600,368 0 0001 -- asciitilde
+vS 660,896,17 2 0002 -- Scaron
+vZ 640,896 2 0003 -- Zcaron
+vs 520,717,8 2 0004 -- scaron
+vz 560,717 2 0005 -- zcaron
+:Y 700,877 2 0006 -- Ydieresis
+tm 980,681 2 0007 -- trademark
+aq 240,698 2 0010 -- quotesingle
+space 340 0 0040
+! 360,698,8 2 0041 -- exclam
+" 420,698 2 0042 -- quotedbl
+# 660,681 2 0043 -- numbersign
+sh "
+$ 660,805,119 2 0044 -- dollar
+Do "
+% 940,698,8 2 0045 -- percent
+& 800,698,17 2 0046 -- ampersand
+' 320,698 2 0047 -- quoteright
+( 320,749,150 2 0050 -- parenleft
+) 320,749,150 2 0051 -- parenright
+* 460,697 2 0052 -- asterisk
++ 600,514 0 0053 -- plus
+, 340,162,124 0 0054 -- comma
+- 360,318 0 0055 -- hyphen
+hy "
+char173 "
+. 340,172,8 0 0056 -- period
+/ 600,725,149 2 0057 -- slash
+sl "
+0 660,698,17 2 0060 -- zero
+1 660,681 2 0061 -- one
+2 660,698 2 0062 -- two
+3 660,698,17 2 0063 -- three
+4 660,681 2 0064 -- four
+5 660,723,17 2 0065 -- five
+6 660,698,17 2 0066 -- six
+7 660,681 2 0067 -- seven
+8 660,698,17 2 0070 -- eight
+9 660,698,17 2 0071 -- nine
+: 340,515,8 0 0072 -- colon
+; 340,515,124 0 0073 -- semicolon
+< 600,542,9 0 0074 -- less
+= 600,421 0 0075 -- equal
+> 600,542,9 0 0076 -- greater
+? 660,698,8 2 0077 -- question
+@ 820,698,17 2 0100 -- at
+at "
+A 720,681 2 0101 -- A
+B 720,681 2 0102 -- B
+C 740,698,17 2 0103 -- C
+D 780,681 2 0104 -- D
+E 720,681 2 0105 -- E
+F 680,681 2 0106 -- F
+G 780,698,17 2 0107 -- G
+H 820,681 2 0110 -- H
+I 400,681 2 0111 -- I
+J 640,681,17 2 0112 -- J
+K 800,681 2 0113 -- K
+L 640,681 2 0114 -- L
+M 940,681 2 0115 -- M
+N 740,681 2 0116 -- N
+O 800,698,17 2 0117 -- O
+P 660,681 2 0120 -- P
+Q 800,698,226 3 0121 -- Q
+R 780,681 2 0122 -- R
+S 660,698,17 2 0123 -- S
+T 700,681 2 0124 -- T
+U 740,681,17 2 0125 -- U
+V 720,681 2 0126 -- V
+W 940,681 2 0127 -- W
+X 780,681 2 0130 -- X
+Y 700,681 2 0131 -- Y
+Z 640,681 2 0132 -- Z
+[ 300,725,138 2 0133 -- bracketleft
+lB "
+\ 600,725 2 0134 -- backslash
+rs "
+] 300,725,138 2 0135 -- bracketright
+rB "
+a^ 500,731 2 0136 -- circumflex
+^ "
+_ 500,0,155 0 0137 -- underscore
+` 320,698 2 0140 -- quoteleft
+oq "
+a 580,515,8 0 0141 -- a
+b 600,725,8 2 0142 -- b
+c 580,515,8 0 0143 -- c
+d 640,725,8 2 0144 -- d
+e 580,515,8 0 0145 -- e
+f 380,741 2 0146 -- f
+g 580,595,243 1 0147 -- g
+h 680,725 2 0150 -- h
+i 360,729 2 0151 -- i
+j 340,729,221 3 0152 -- j
+k 660,725 2 0153 -- k
+l 340,725 2 0154 -- l
+m 1000,515 0 0155 -- m
+n 680,515 0 0156 -- n
+o 620,515,8 0 0157 -- o
+p 640,515,212 1 0160 -- p
+q 620,515,212 1 0161 -- q
+r 460,502 0 0162 -- r
+s 520,515,8 0 0163 -- s
+t 460,660,8 2 0164 -- t
+u 660,502,8 0 0165 -- u
+v 600,502 0 0166 -- v
+w 800,502 0 0167 -- w
+x 600,502 0 0170 -- x
+y 620,502,221 1 0171 -- y
+z 560,502 0 0172 -- z
+lC 320,726,139 2 0173 -- braceleft
+{ "
+ba 600,725 2 0174 -- bar
+| "
+rC 320,726,139 2 0175 -- braceright
+} "
+a~ 480,691 2 0176 -- tilde
+~ "
+bq 320,144,114 0 0200 -- quotesinglbase
+Fo 400,457 0 0201 -- guillemotleft
+char171 "
+Fc 400,457 0 0202 -- guillemotright
+char187 "
+bu 460,511 0 0203 -- bullet
+Fn 660,749,209 2 0204 -- florin
+f/ 120,681 2 0205 -- fraction
+%0 1360,698,8 2 0206 -- perthousand
+dg 440,698,156 2 0207 -- dagger
+dd 380,698,156 2 0210 -- daggerdbl
+en 500,318 0 0211 -- endash
+em 1000,318 0 0212 -- emdash
+fi 740,741 2 0214 -- fi
+fl 740,741 2 0215 -- fl
+.i 360,502 0 0220 -- dotlessi
+ga 400,730 2 0222 -- grave
+a" 440,741 2 0223 -- hungarumlaut
+a. 320,730 2 0224 -- dotaccent
+ab 500,722 2 0225 -- breve
+ah 500,717 2 0226 -- caron
+ao 340,755 2 0227 -- ring
+ho 320,0,163 0 0230 -- ogonek
+lq 540,698 2 0231 -- quotedblleft
+rq 540,698 2 0232 -- quotedblright
+oe 940,515,8 0 0233 -- oe
+/l 340,725 2 0234 -- lslash
+Bq 540,144,114 0 0235 -- quotedblbase
+OE 1220,698,17 2 0236 -- OE
+/L 640,681 2 0237 -- Lslash
+r! 360,515,191 0 0241 -- exclamdown
+char161 "
+ct 660,674 2 0242 -- cent
+char162 "
+Po 660,698,17 2 0243 -- sterling
+char163 "
+Cs 660,593 0 0244 -- currency
+char164 "
+Ye 660,681 2 0245 -- yen
+char165 "
+bb 600,725 2 0246 -- brokenbar
+char166 "
+sc 600,698,153 2 0247 -- section
+char167 "
+ad 500,698 2 0250 -- dieresis
+char168 "
+co 740,698,17 2 0251 -- copyright
+char169 "
+Of 400,698 2 0252 -- ordfeminine
+char170 "
+fo 220,457 0 0253 -- guilsinglleft
+no 600,421 0 0254 -- logicalnot
+char172 "
+\- 600,323 0 0255 -- minus
+rg 740,698,17 2 0256 -- registered
+char174 "
+a- 460,663 2 0257 -- macron
+char175 "
+de 400,698 2 0260 -- degree
+char176 "
+char177 600,514 0 0261 -- plusminus
+S2 396,698 2 0262 -- twosuperior
+char178 "
+S3 396,698 2 0263 -- threesuperior
+char179 "
+aa 400,731 2 0264 -- acute
+char180 "
+char181 660,502,221 1 0265 -- mu
+ps 800,681,101 2 0266 -- paragraph
+char182 "
+char183 340,355 0 0267 -- periodcentered
+ac 360,0,213 1 0270 -- cedilla
+char184 "
+S1 396,687 2 0271 -- onesuperior
+char185 "
+Om 400,698 2 0272 -- ordmasculine
+char186 "
+fc 220,457 0 0273 -- guilsinglright
+14 990,681 2 0274 -- onequarter
+char188 "
+12 990,681 2 0275 -- onehalf
+char189 "
+34 990,692 2 0276 -- threequarters
+char190 "
+r? 660,515,191 0 0277 -- questiondown
+char191 "
+`A 720,909 2 0300 -- Agrave
+char192 "
+'A 720,910 2 0301 -- Aacute
+char193 "
+^A 720,910 2 0302 -- Acircumflex
+char194 "
+~A 720,870 2 0303 -- Atilde
+char195 "
+:A 720,877 2 0304 -- Adieresis
+char196 "
+oA 720,934 2 0305 -- Aring
+char197 "
+AE 1140,681 2 0306 -- AE
+char198 "
+,C 740,698,213 3 0307 -- Ccedilla
+char199 "
+`E 720,909 2 0310 -- Egrave
+char200 "
+'E 720,910 2 0311 -- Eacute
+char201 "
+^E 720,910 2 0312 -- Ecircumflex
+char202 "
+:E 720,877 2 0313 -- Edieresis
+char203 "
+`I 400,909 2 0314 -- Igrave
+char204 "
+'I 400,910 2 0315 -- Iacute
+char205 "
+^I 400,910 2 0316 -- Icircumflex
+char206 "
+:I 400,877 2 0317 -- Idieresis
+char207 "
+-D 780,681 2 0320 -- Eth
+char208 "
+~N 740,870 2 0321 -- Ntilde
+char209 "
+`O 800,909,17 2 0322 -- Ograve
+char210 "
+'O 800,910,17 2 0323 -- Oacute
+char211 "
+^O 800,910,17 2 0324 -- Ocircumflex
+char212 "
+~O 800,870,17 2 0325 -- Otilde
+char213 "
+:O 800,877,17 2 0326 -- Odieresis
+char214 "
+char215 600,514 0 0327 -- multiply
+/O 800,781,110 2 0330 -- Oslash
+char216 "
+`U 740,909,17 2 0331 -- Ugrave
+char217 "
+'U 740,910,17 2 0332 -- Uacute
+char218 "
+^U 740,910,17 2 0333 -- Ucircumflex
+char219 "
+:U 740,877,17 2 0334 -- Udieresis
+char220 "
+'Y 700,910 2 0335 -- Yacute
+char221 "
+TP 660,681 2 0336 -- Thorn
+char222 "
+ss 660,699,91 2 0337 -- germandbls
+char223 "
+`a 580,730,8 2 0340 -- agrave
+char224 "
+'a 580,731,8 2 0341 -- aacute
+char225 "
+^a 580,731,8 2 0342 -- acircumflex
+char226 "
+~a 580,691,8 2 0343 -- atilde
+char227 "
+:a 580,698,8 2 0344 -- adieresis
+char228 "
+oa 580,755,8 2 0345 -- aring
+char229 "
+ae 880,515,8 0 0346 -- ae
+char230 "
+,c 580,515,213 1 0347 -- ccedilla
+char231 "
+`e 580,730,8 2 0350 -- egrave
+char232 "
+'e 580,731,8 2 0351 -- eacute
+char233 "
+^e 580,731,8 2 0352 -- ecircumflex
+char234 "
+:e 580,698,8 2 0353 -- edieresis
+char235 "
+`i 360,730 2 0354 -- igrave
+char236 "
+'i 360,731 2 0355 -- iacute
+char237 "
+^i 360,731 2 0356 -- icircumflex
+char238 "
+:i 360,698 2 0357 -- idieresis
+char239 "
+Sd 620,741,8 2 0360 -- eth
+char240 "
+~n 680,691 2 0361 -- ntilde
+char241 "
+`o 620,730,8 2 0362 -- ograve
+char242 "
+'o 620,731,8 2 0363 -- oacute
+char243 "
+^o 620,731,8 2 0364 -- ocircumflex
+char244 "
+~o 620,691,8 2 0365 -- otilde
+char245 "
+:o 620,698,8 2 0366 -- odieresis
+char246 "
+char247 600,521 0 0367 -- divide
+/o 620,551,40 0 0370 -- oslash
+char248 "
+`u 660,730,8 2 0371 -- ugrave
+char249 "
+'u 660,731,8 2 0372 -- uacute
+char250 "
+^u 660,731,8 2 0373 -- ucircumflex
+char251 "
+:u 660,698,8 2 0374 -- udieresis
+char252 "
+'y 620,731,221 3 0375 -- yacute
+char253 "
+Tp 640,725,212 3 0376 -- thorn
+char254 "
+:y 620,698,221 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/BMBI b/font/devps/BMBI
new file mode 100644
index 00000000..854032bf
--- /dev/null
+++ b/font/devps/BMBI
@@ -0,0 +1,441 @@
+name BMBI
+internalname Bookman-DemiItalic
+slant 10
+spacewidth 340
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y 20
+A w 20
+A v 20
+A Y -25
+A W -35
+A V -40
+A T -17
+F . -105
+F , -98
+F A -35
+L y 62
+L Y -5
+L W -15
+L V -19
+L T -26
+P . -105
+P , -98
+P A -31
+R y 27
+R Y 4
+R W -4
+R V -8
+R T -3
+T y 56
+T w 69
+T u 42
+T ; 31
+T s -1
+T r 41
+T . -107
+T o -5
+T i 42
+T - -20
+T hy -20
+T char173 -20
+T e -10
+T , -100
+T : 26
+T c -8
+T a -8
+T A -42
+V y 17
+V u -1
+V ; -22
+V r 2
+V . -115
+V o -50
+V i 32
+V - -20
+V hy -20
+V char173 -20
+V e -50
+V , -137
+V : -28
+V a -50
+V A -50
+W y -51
+W u -69
+W ; -81
+W r -66
+W . -183
+W o -100
+W i -36
+W - -22
+W hy -22
+W char173 -22
+W e -100
+W , -201
+W : -86
+W a -100
+W A -77
+Y v 26
+Y u -1
+Y ; -4
+Y q -43
+Y . -113
+Y o -41
+Y i 20
+Y - -20
+Y hy -20
+Y char173 -20
+Y e -46
+Y , -106
+Y : -9
+Y a -45
+Y A -30
+f f 10
+r q -3
+r . -120
+r o -1
+r n 39
+r m 39
+r - -20
+r hy -20
+r char173 -20
+r h -35
+r g -23
+r f 42
+r e -6
+r d -3
+r , -113
+r c -5
+charset
+ha 620,681,0,24,-42,24 2 0000 -- asciicircum
+ti 620,368,0,35,-51,35 0 0001 -- asciitilde
+vS 700,915,17,81,-9,73 2 0002 -- Scaron
+vZ 680,915,0,110,27,73 2 0003 -- Zcaron
+vs 540,749,8,83,18,73 2 0004 -- scaron
+vz 560,749,8,76,14,73 2 0005 -- zcaron
+:Y 660,900,0,207,-22,73 2 0006 -- Ydieresis
+tm 940,681,0,92,8,73 2 0007 -- trademark
+aq 180,696,0,165,-76,73 2 0010 -- quotesingle
+space 340 0 0040
+! 320,698,8,96,-36,73 2 0041 -- exclam
+" 380,697,0,177,-90,73 2 0042 -- quotedbl
+# 680,681,0,19,-107,19 2 0043 -- numbersign
+sh "
+$ 680,790,164,67,5,67 2 0044 -- dollar
+Do "
+% 880,698,17,69,-56,69 2 0045 -- percent
+& 980,698,17,86,2,73 2 0046 -- ampersand
+' 320,698,0,79,-121,73 2 0047 -- quoteright
+( 260,741,134,178,19,73 2 0050 -- parenleft
+) 260,741,134,112,85,73 2 0051 -- parenright
+* 460,698,0,98,-76,73 2 0052 -- asterisk
++ 600,514,0,45,-41,45 0 0053 -- plus
+, 340,185,124,8,-50,8 0 0054 -- comma
+- 280,313,0,89,-9,73 0 0055 -- hyphen
+hy "
+char173 "
+. 340,177,8,6,-56,6 0 0056 -- period
+/ 360,742,106,192,41,73 2 0057 -- slash
+sl "
+0 680,698,17,73,-37,73 2 0060 -- zero
+1 680,681,0,0,-73 2 0061 -- one
+2 680,698,0,44,-17,44 2 0062 -- two
+3 680,698,17,53,-22,53 2 0063 -- three
+4 680,681,0,78,-13,73 2 0064 -- four
+5 680,681,17,39,-28,39 2 0065 -- five
+6 680,698,17,74,-38,73 2 0066 -- six
+7 680,681,0,109,-73,73 2 0067 -- seven
+8 680,698,17,56,-18,56 2 0070 -- eight
+9 680,698,17,82,-21,73 2 0071 -- nine
+: 340,515,8,66,-56,66 0 0072 -- colon
+; 340,515,124,62,-50,62 0 0073 -- semicolon
+< 620,540,9,18,-29,18 0 0074 -- less
+= 600,421,0,45,-41,45 0 0075 -- equal
+> 620,540,9,28,-39,28 0 0076 -- greater
+? 620,698,8,98,-95,73 2 0077 -- question
+@ 780,698,17,60,-30,60 2 0100 -- at
+at "
+A 720,681,0,99,77,73 2 0101 -- A
+B 720,681,0,92,36,73 2 0102 -- B
+C 700,698,17,104,-28,73 2 0103 -- C
+D 760,681,0,95,36,73 2 0104 -- D
+E 720,681,0,107,36,73 2 0105 -- E
+F 660,681,0,153,36,73 2 0106 -- F
+G 760,698,17,118,-27,73 2 0107 -- G
+H 800,681,0,160,36,73 2 0110 -- H
+I 380,681,0,155,36,73 2 0111 -- I
+J 620,681,17,151,42,73 2 0112 -- J
+K 780,681,0,149,36,73 2 0113 -- K
+L 640,681,0,135,36,73 2 0114 -- L
+M 860,681,0,160,36,73 2 0115 -- M
+N 740,681,0,155,36,73 2 0116 -- N
+O 760,698,17,96,-28,73 2 0117 -- O
+P 640,681,0,134,56,73 2 0120 -- P
+Q 760,698,213,95,13,73 3 0121 -- Q
+R 740,681,0,75,36,73 2 0122 -- R
+S 700,698,17,81,-9,73 2 0123 -- S
+T 700,681,0,152,-20,73 2 0124 -- T
+U 740,681,17,165,-62,73 2 0125 -- U
+V 660,681,0,209,-22,73 2 0126 -- V
+W 1000,681,0,140,-22,73 2 0127 -- W
+X 740,681,0,145,57,73 2 0130 -- X
+Y 660,681,0,207,-22,73 2 0131 -- Y
+Z 680,681,0,110,27,73 2 0132 -- Z
+[ 260,741,118,164,41,73 2 0133 -- bracketleft
+lB "
+\ 580,741,0,45,-23,45 2 0134 -- backslash
+rs "
+] 260,741,118,137,68,73 2 0135 -- bracketright
+rB "
+a^ 480,749,0,93,-133,73 2 0136 -- circumflex
+^ "
+_ 500,0,155,50,50,50 0 0137 -- underscore
+` 320,698,0,63,-105,63 2 0140 -- quoteleft
+oq "
+a 680,515,8,105,-34,73 0 0141 -- a
+b 600,732,8,83,-7,73 2 0142 -- b
+c 560,515,8,87,-8,73 0 0143 -- c
+d 680,732,8,84,-10,73 2 0144 -- d
+e 560,515,8,86,-9,73 0 0145 -- e
+f 420,741,213,271,242,73 3 0146 -- f
+g 620,515,213,99,29,73 1 0147 -- g
+h 700,732,8,86,-43,73 2 0150 -- h
+i 380,755,8,90,-33,73 2 0151 -- i
+j 320,755,213,122,210,73 3 0152 -- j
+k 700,732,8,82,-47,73 2 0153 -- k
+l 380,732,8,80,-59,73 2 0154 -- l
+m 960,515,8,86,-33,73 0 0155 -- m
+n 680,515,8,85,-33,73 0 0156 -- n
+o 600,515,8,77,-9,73 0 0157 -- o
+p 660,515,213,72,74,72 1 0160 -- p
+q 620,515,213,70,-10,70 1 0161 -- q
+r 500,515,0,132,-34,73 0 0162 -- r
+s 540,515,8,83,18,73 0 0163 -- s
+t 440,658,8,98,-56,73 2 0164 -- t
+u 680,507,8,90,-33,73 0 0165 -- u
+v 540,515,8,82,-6,73 0 0166 -- v
+w 860,515,8,81,-6,73 0 0167 -- w
+x 620,515,8,84,40,73 0 0170 -- x
+y 600,507,213,92,25,73 1 0171 -- y
+z 560,515,8,76,14,73 0 0172 -- z
+lC 300,742,123,159,-3,73 2 0173 -- braceleft
+{ "
+ba 620,741,0,0,-253 2 0174 -- bar
+| "
+rC 300,742,123,102,54,73 2 0175 -- braceright
+} "
+a~ 480,709,0,103,-128,73 2 0176 -- tilde
+~ "
+bq 300,166,112,34,-56,34 0 0200 -- quotesinglbase
+Fo 380,503,0,76,-12,73 0 0201 -- guillemotleft
+char171 "
+Fc 380,503,0,76,-12,73 0 0202 -- guillemotright
+char187 "
+bu 360,511,0,94,-10,73 0 0203 -- bullet
+Fn 680,741,199,113,78,73 2 0204 -- florin
+f/ 120,681,0,312,194,73 2 0205 -- fraction
+%0 1360,698,17,23,-56,23 2 0206 -- perthousand
+dg 420,698,137,96,-39,73 2 0207 -- dagger
+dd 420,698,137,116,-29,73 2 0210 -- daggerdbl
+en 500,311,0,123,10,73 0 0211 -- endash
+em 1000,311,0,123,10,73 0 0212 -- emdash
+fi 820,741,213,80,241,73 3 0214 -- fi
+fl 820,741,213,80,241,73 3 0215 -- fl
+.i 380,507,8,90,-33,73 0 0220 -- dotlessi
+ga 380,771,0,94,-143,73 2 0222 -- grave
+a" 560,775,0,106,-131,73 2 0223 -- hungarumlaut
+a. 380,734,0,15,-130,15 2 0224 -- dotaccent
+ab 460,707,0,106,-127,73 2 0225 -- breve
+ah 480,749,0,93,-133,73 2 0226 -- caron
+ao 360,775,0,96,-135,73 2 0227 -- ring
+ho 320,0,182,0,-18 0 0230 -- ogonek
+lq 520,698,0,75,-106,73 2 0231 -- quotedblleft
+rq 520,698,0,90,-121,73 2 0232 -- quotedblright
+oe 920,515,8,91,2,73 0 0233 -- oe
+/l 380,732,8,82,-13,73 2 0234 -- lslash
+Bq 520,166,112,25,-56,25 0 0235 -- quotedblbase
+OE 1180,698,17,115,-44,73 2 0236 -- OE
+/L 640,681,0,134,36,73 2 0237 -- Lslash
+r! 320,515,191,74,-14,73 0 0241 -- exclamdown
+char161 "
+ct 680,718,0,0,-111 2 0242 -- cent
+char162 "
+Po 680,698,17,157,50,73 2 0243 -- sterling
+char163 "
+Cs 680,571,0,7,-98,7 0 0244 -- currency
+char164 "
+Ye 680,681,0,152,-42,73 2 0245 -- yen
+char165 "
+bb 620,741,0,0,-253 2 0246 -- brokenbar
+char166 "
+sc 620,698,137,68,4,68 2 0247 -- section
+char167 "
+ad 520,734,0,99,-130,73 2 0250 -- dieresis
+char168 "
+co 780,698,17,53,-33,53 2 0251 -- copyright
+char169 "
+Of 440,685,0,105,-5,73 2 0252 -- ordfeminine
+char170 "
+fo 220,503,0,79,-12,73 0 0253 -- guilsinglleft
+no 620,421,0,15,-31,15 0 0254 -- logicalnot
+char172 "
+\- 600,323,0,45,-41,45 0 0255 -- minus
+rg 780,698,17,53,-33,53 2 0256 -- registered
+char174 "
+a- 480,691,0,101,-127,73 2 0257 -- macron
+char175 "
+de 400,698,0,80,-80,73 2 0260 -- degree
+char176 "
+char177 600,514,0,45,-41,45 0 0261 -- plusminus
+S2 408,698,0,127,-41,73 2 0262 -- twosuperior
+char178 "
+S3 408,698,0,125,-36,73 2 0263 -- threesuperior
+char179 "
+aa 340,771,0,117,-126,73 2 0264 -- acute
+char180 "
+char181 680,507,213,90,-4,73 1 0265 -- mu
+ps 680,681,204,96,-20,73 2 0266 -- paragraph
+char182 "
+char183 340,358,0,26,-76,26 0 0267 -- periodcentered
+ac 360,0,220,0,-18 1 0270 -- cedilla
+char184 "
+S1 408,688,0,48,-68,48 2 0271 -- onesuperior
+char185 "
+Om 440,685,0,77,3,73 2 0272 -- ordmasculine
+char186 "
+fc 220,503,0,79,-12,73 0 0273 -- guilsinglright
+14 1020,681,0,84,-68,73 2 0274 -- onequarter
+char188 "
+12 1020,681,0,66,-68,66 2 0275 -- onehalf
+char189 "
+34 1020,691,0,84,-36,73 2 0276 -- threequarters
+char190 "
+r? 620,515,189,36,-33,36 0 0277 -- questiondown
+char191 "
+`A 720,937,0,99,77,73 2 0300 -- Agrave
+char192 "
+'A 720,937,0,99,77,73 2 0301 -- Aacute
+char193 "
+^A 720,915,0,99,77,73 2 0302 -- Acircumflex
+char194 "
+~A 720,875,0,99,77,73 2 0303 -- Atilde
+char195 "
+:A 720,900,0,99,77,73 2 0304 -- Adieresis
+char196 "
+oA 720,941,0,99,77,73 2 0305 -- Aring
+char197 "
+AE 1140,681,0,117,77,73 2 0306 -- AE
+char198 "
+,C 700,698,220,104,-28,73 3 0307 -- Ccedilla
+char199 "
+`E 720,937,0,107,36,73 2 0310 -- Egrave
+char200 "
+'E 720,937,0,107,36,73 2 0311 -- Eacute
+char201 "
+^E 720,915,0,107,36,73 2 0312 -- Ecircumflex
+char202 "
+:E 720,900,0,107,36,73 2 0313 -- Edieresis
+char203 "
+`I 380,937,0,155,36,73 2 0314 -- Igrave
+char204 "
+'I 380,937,0,155,36,73 2 0315 -- Iacute
+char205 "
+^I 380,915,0,163,36,73 2 0316 -- Icircumflex
+char206 "
+:I 380,900,0,169,36,73 2 0317 -- Idieresis
+char207 "
+-D 760,681,0,95,36,73 2 0320 -- Eth
+char208 "
+~N 740,875,0,155,36,73 2 0321 -- Ntilde
+char209 "
+`O 760,937,17,96,-28,73 2 0322 -- Ograve
+char210 "
+'O 760,937,17,96,-28,73 2 0323 -- Oacute
+char211 "
+^O 760,915,17,96,-28,73 2 0324 -- Ocircumflex
+char212 "
+~O 760,875,17,96,-28,73 2 0325 -- Otilde
+char213 "
+:O 760,900,17,96,-28,73 2 0326 -- Odieresis
+char214 "
+char215 600,514,0,45,-41,45 0 0327 -- multiply
+/O 760,725,29,137,29,73 2 0330 -- Oslash
+char216 "
+`U 740,937,17,165,-62,73 2 0331 -- Ugrave
+char217 "
+'U 740,937,17,165,-62,73 2 0332 -- Uacute
+char218 "
+^U 740,915,17,165,-62,73 2 0333 -- Ucircumflex
+char219 "
+:U 740,900,17,165,-62,73 2 0334 -- Udieresis
+char220 "
+'Y 660,937,0,207,-22,73 2 0335 -- Yacute
+char221 "
+TP 640,681,0,111,56,73 2 0336 -- Thorn
+char222 "
+ss 660,741,213,92,281,73 3 0337 -- germandbls
+char223 "
+`a 680,771,8,105,-34,73 2 0340 -- agrave
+char224 "
+'a 680,771,8,105,-34,73 2 0341 -- aacute
+char225 "
+^a 680,749,8,105,-34,73 2 0342 -- acircumflex
+char226 "
+~a 680,709,8,105,-34,73 2 0343 -- atilde
+char227 "
+:a 680,734,8,105,-34,73 2 0344 -- adieresis
+char228 "
+oa 680,775,8,105,-34,73 2 0345 -- aring
+char229 "
+ae 880,515,8,83,11,73 0 0346 -- ae
+char230 "
+,c 560,515,220,87,-8,73 1 0347 -- ccedilla
+char231 "
+`e 560,771,8,86,-9,73 2 0350 -- egrave
+char232 "
+'e 560,771,8,86,-9,73 2 0351 -- eacute
+char233 "
+^e 560,749,8,86,-9,73 2 0352 -- ecircumflex
+char234 "
+:e 560,734,8,86,-9,73 2 0353 -- edieresis
+char235 "
+`i 380,771,8,94,-33,73 2 0354 -- igrave
+char236 "
+'i 380,771,8,90,-33,73 2 0355 -- iacute
+char237 "
+^i 380,749,8,103,-33,73 2 0356 -- icircumflex
+char238 "
+:i 380,734,8,149,-33,73 2 0357 -- idieresis
+char239 "
+Sd 600,741,8,112,-9,73 2 0360 -- eth
+char240 "
+~n 680,709,8,85,-33,73 2 0361 -- ntilde
+char241 "
+`o 600,771,8,77,-9,73 2 0362 -- ograve
+char242 "
+'o 600,771,8,77,-9,73 2 0363 -- oacute
+char243 "
+^o 600,749,8,77,-9,73 2 0364 -- ocircumflex
+char244 "
+~o 600,709,8,77,-9,73 2 0365 -- otilde
+char245 "
+:o 600,734,8,77,-9,73 2 0366 -- odieresis
+char246 "
+char247 600,521,0,45,-41,45 0 0367 -- divide
+/o 600,571,54,111,33,73 0 0370 -- oslash
+char248 "
+`u 680,771,8,90,-33,73 2 0371 -- ugrave
+char249 "
+'u 680,771,8,90,-33,73 2 0372 -- uacute
+char250 "
+^u 680,749,8,90,-33,73 2 0373 -- ucircumflex
+char251 "
+:u 680,734,8,90,-33,73 2 0374 -- udieresis
+char252 "
+'y 600,771,213,92,25,73 3 0375 -- yacute
+char253 "
+Tp 660,732,213,72,74,72 3 0376 -- thorn
+char254 "
+:y 600,734,213,92,25,73 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/BMI b/font/devps/BMI
new file mode 100644
index 00000000..4de77ef7
--- /dev/null
+++ b/font/devps/BMI
@@ -0,0 +1,434 @@
+name BMI
+internalname Bookman-LightItalic
+slant 10
+spacewidth 300
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A Y -62
+A W -73
+A V -78
+A T -5
+F . -97
+F , -98
+F A -16
+L y 20
+L Y 7
+L W 9
+L V 4
+P . -105
+P , -106
+P A -30
+R Y 11
+R W 2
+R V 2
+R T 65
+T ; 48
+T s -7
+T r 67
+T . -78
+T o 14
+T i 71
+T - 20
+T hy 20
+T char173 20
+T e 10
+T , -79
+T : 48
+T c 16
+T a 9
+T A -14
+V y -14
+V u -10
+V ; -44
+V r -20
+V . -100
+V o -70
+V i 3
+V - 20
+V hy 20
+V char173 20
+V e -70
+V , -109
+V : -35
+V a -70
+V A -70
+W y -14
+W u -20
+W ; -42
+W r -30
+W . -100
+W o -60
+W i 3
+W - 20
+W hy 20
+W char173 20
+W e -60
+W , -109
+W : -35
+W a -60
+W A -60
+Y v -19
+Y u -31
+Y ; -40
+Y q -72
+Y . -100
+Y p -37
+Y o -75
+Y i -11
+Y - 20
+Y hy 20
+Y char173 20
+Y e -78
+Y , -109
+Y : -35
+Y a -79
+Y A -82
+f f -19
+r q -14
+r . -134
+r o -10
+r n 38
+r m 37
+r - 20
+r hy 20
+r char173 20
+r h -20
+r g -3
+r f -9
+r e -15
+r d -9
+r , -143
+r c -8
+charset
+ha 600,681,0,49,-47,49 2 0000 -- asciicircum
+ti 600,386,0,45,-41,45 0 0001 -- asciitilde
+vS 640,871,17,78,-11,70 2 0002 -- Scaron
+vZ 580,871,0,165,42,70 2 0003 -- Zcaron
+vs 540,684,8,57,-15,57 2 0004 -- scaron
+vz 520,684,8,91,12,70 2 0005 -- zcaron
+:Y 660,875,0,199,-37,70 2 0006 -- Ydieresis
+tm 980,681,0,35,-19,35 2 0007 -- trademark
+aq 200,698,0,97,-49,70 2 0010 -- quotesingle
+space 300 0 0040
+! 320,698,8,72,-53,70 2 0041 -- exclam
+" 360,698,0,92,-57,70 2 0042 -- quotedbl
+# 620,681,0,28,-57,28 2 0043 -- numbersign
+sh "
+$ 620,762,85,49,-28,49 2 0044 -- dollar
+Do "
+% 800,691,8,61,-6,61 2 0045 -- percent
+& 820,698,18,78,-15,70 2 0046 -- ampersand
+' 280,698,0,58,-98,58 2 0047 -- quoteright
+( 280,727,146,153,-46,70 2 0050 -- parenleft
+) 280,727,146,49,58,49 2 0051 -- parenright
+* 440,698,0,115,-89,70 2 0052 -- asterisk
++ 600,548,0,45,-41,45 0 0053 -- plus
+, 300,112,115,0,-38 0 0054 -- comma
+- 320,325,0,66,-28,66 0 0055 -- hyphen
+hy "
+char173 "
+. 300,127,8,0,-46 0 0056 -- period
+/ 600,717,149,12,-54,12 2 0057 -- slash
+sl "
+0 620,698,17,76,-36,70 2 0060 -- zero
+1 620,681,0,0,-104 2 0061 -- one
+2 620,698,0,66,-16,66 2 0062 -- two
+3 620,698,17,52,-5,52 2 0063 -- three
+4 620,681,0,64,-19,64 2 0064 -- four
+5 620,681,17,44,-20,44 2 0065 -- five
+6 620,698,17,87,-39,70 2 0066 -- six
+7 620,681,0,102,-93,70 2 0067 -- seven
+8 620,698,17,85,-11,70 2 0070 -- eight
+9 620,698,17,79,-27,70 2 0071 -- nine
+: 300,494,8,42,-46,42 0 0072 -- colon
+; 300,494,114,42,-38,42 0 0073 -- semicolon
+< 600,561,0,38,-29,38 0 0074 -- less
+= 600,433,0,45,-41,45 0 0075 -- equal
+> 600,561,0,52,-43,52 0 0076 -- greater
+? 540,698,8,114,-64,70 2 0077 -- question
+@ 780,698,17,72,-52,70 2 0100 -- at
+at "
+A 700,681,0,70,75,70 2 0101 -- A
+B 720,681,0,76,29,70 2 0102 -- B
+C 720,698,17,76,-38,70 2 0103 -- C
+D 740,681,0,92,29,70 2 0104 -- D
+E 680,681,0,106,29,70 2 0105 -- E
+F 620,681,0,173,29,70 2 0106 -- F
+G 760,698,17,103,-38,70 2 0107 -- G
+H 800,681,0,138,29,70 2 0110 -- H
+I 320,681,0,142,29,70 2 0111 -- I
+J 560,681,17,156,52,70 2 0112 -- J
+K 720,681,0,134,29,70 2 0113 -- K
+L 580,681,0,126,29,70 2 0114 -- L
+M 860,681,0,146,32,70 2 0115 -- M
+N 720,681,0,153,32,70 2 0116 -- N
+O 760,698,17,89,-38,70 2 0117 -- O
+P 600,681,0,131,29,70 2 0120 -- P
+Q 780,698,191,82,-11,70 2 0121 -- Q
+R 700,681,0,86,29,70 2 0122 -- R
+S 640,698,17,78,-11,70 2 0123 -- S
+T 600,681,0,175,0,70 2 0124 -- T
+U 720,681,17,172,-68,70 2 0125 -- U
+V 680,681,0,185,-37,70 2 0126 -- V
+W 960,681,0,185,-37,70 2 0127 -- W
+X 700,681,0,165,75,70 2 0130 -- X
+Y 660,681,0,199,-37,70 2 0131 -- Y
+Z 580,681,0,165,42,70 2 0132 -- Z
+[ 260,717,136,141,-6,70 2 0133 -- bracketleft
+lB "
+\ 600,717,0,0,-34 2 0134 -- backslash
+rs "
+] 260,717,136,99,35,70 2 0135 -- bracketright
+rB "
+a^ 440,685,0,89,-126,70 2 0136 -- circumflex
+^ "
+_ 500,0,155,50,50,50 0 0137 -- underscore
+` 280,698,0,100,-141,70 2 0140 -- quoteleft
+oq "
+a 620,494,8,116,-21,70 0 0141 -- a
+b 600,717,8,71,-38,70 2 0142 -- b
+c 480,494,8,92,-15,70 0 0143 -- c
+d 640,717,8,105,-15,70 2 0144 -- d
+e 540,494,8,85,-15,70 0 0145 -- e
+f 340,725,218,267,210,70 3 0146 -- f
+g 560,494,221,71,46,70 1 0147 -- g
+h 620,717,8,119,-38,70 2 0150 -- h
+i 280,663,8,121,-38,70 2 0151 -- i
+j 280,663,221,78,250,70 3 0152 -- j
+k 600,717,8,107,-38,70 2 0153 -- k
+l 280,717,8,112,-50,70 2 0154 -- l
+m 880,494,8,122,-38,70 0 0155 -- m
+n 620,494,8,103,-38,70 0 0156 -- n
+o 540,494,8,82,-15,70 0 0157 -- o
+p 600,494,212,70,74,70 1 0160 -- p
+q 560,494,212,74,-15,70 1 0161 -- q
+r 400,494,0,131,-38,70 0 0162 -- r
+s 540,494,8,57,-15,57 0 0163 -- s
+t 340,664,8,121,-38,70 2 0164 -- t
+u 620,484,8,116,-38,70 0 0165 -- u
+v 540,494,8,72,-38,70 0 0166 -- v
+w 880,494,8,63,-38,63 0 0167 -- w
+x 540,494,8,136,41,70 0 0170 -- x
+y 600,484,221,59,-10,59 1 0171 -- y
+z 520,494,8,91,12,70 0 0172 -- z
+lC 360,717,191,129,-75,70 2 0173 -- braceleft
+{ "
+ba 600,717,0,0,-244 2 0174 -- bar
+| "
+rC 380,717,191,0,35 2 0175 -- braceright
+} "
+a~ 440,671,0,98,-130,70 2 0176 -- tilde
+~ "
+bq 320,113,114,0,-37 0 0200 -- quotesinglbase
+Fo 300,434,0,63,-20,63 0 0201 -- guillemotleft
+char171 "
+Fc 300,434,0,53,-10,53 0 0202 -- guillemotright
+char187 "
+bu 460,511,0,34,-50,34 0 0203 -- bullet
+Fn 620,725,218,122,76,70 3 0204 -- florin
+f/ 20,681,0,353,278,70 2 0205 -- fraction
+%0 1180,691,8,69,-6,69 2 0206 -- perthousand
+dg 620,698,130,0,-142 2 0207 -- dagger
+dd 620,698,122,0,-94 2 0210 -- daggerdbl
+en 500,325,0,111,17,70 0 0211 -- endash
+em 1000,325,0,111,17,70 0 0212 -- emdash
+fi 640,725,222,119,209,70 3 0214 -- fi
+fl 660,725,218,103,209,70 3 0215 -- fl
+.i 280,484,8,121,-38,70 0 0220 -- dotlessi
+ga 340,706,0,87,-132,70 2 0222 -- grave
+a" 340,738,0,112,-117,70 2 0223 -- hungarumlaut
+a. 260,664,0,80,-119,70 2 0224 -- dotaccent
+ab 440,680,0,110,-141,70 2 0225 -- breve
+ah 440,684,0,91,-128,70 2 0226 -- caron
+ao 300,706,0,84,-128,70 2 0227 -- ring
+ho 260,0,173,0,-1 0 0230 -- ogonek
+lq 440,698,0,103,-141,70 2 0231 -- quotedblleft
+rq 440,698,0,61,-98,61 2 0232 -- quotedblright
+oe 900,494,8,98,-15,70 0 0233 -- oe
+/l 340,717,8,108,0,70 2 0234 -- lslash
+Bq 480,113,114,0,-37 0 0235 -- quotedblbase
+OE 1180,698,17,107,-38,70 2 0236 -- OE
+/L 580,681,0,126,29,70 2 0237 -- Lslash
+r! 320,494,213,31,-23,31 1 0241 -- exclamdown
+char161 "
+ct 620,715,29,26,-98,26 2 0242 -- cent
+char162 "
+Po 620,698,17,132,46,70 2 0243 -- sterling
+char163 "
+Cs 620,591,0,35,-50,35 0 0244 -- currency
+char164 "
+Ye 620,681,0,165,-21,70 2 0245 -- yen
+char165 "
+bb 600,717,0,0,-244 2 0246 -- brokenbar
+char166 "
+sc 620,698,178,68,12,68 2 0247 -- section
+char167 "
+ad 420,688,0,97,-135,70 2 0250 -- dieresis
+char168 "
+co 740,698,17,94,-34,70 2 0251 -- copyright
+char169 "
+Of 440,698,0,123,-44,70 2 0252 -- ordfeminine
+char170 "
+fo 180,434,0,78,-25,70 0 0253 -- guilsinglleft
+no 600,433,0,45,-41,45 0 0254 -- logicalnot
+char172 "
+\- 600,335,0,45,-41,45 0 0255 -- minus
+rg 740,698,17,94,-34,70 2 0256 -- registered
+char174 "
+a- 440,658,0,94,-128,70 0 0257 -- macron
+char175 "
+de 400,698,0,70,-70,70 2 0260 -- degree
+char176 "
+char177 600,548,0,45,-41,45 0 0261 -- plusminus
+S2 372,698,0,117,-18,70 2 0262 -- twosuperior
+char178 "
+S3 372,698,0,117,-20,70 2 0263 -- threesuperior
+char179 "
+aa 320,706,0,103,-128,70 2 0264 -- acute
+char180 "
+char181 620,484,221,116,-3,70 1 0265 -- mu
+ps 620,681,0,148,-62,70 2 0266 -- paragraph
+char182 "
+char183 300,364,0,22,-87,22 0 0267 -- periodcentered
+ac 320,0,178,0,5 0 0270 -- cedilla
+char184 "
+S1 372,688,0,17,-64,17 2 0271 -- onesuperior
+char185 "
+Om 400,698,0,105,-44,70 2 0272 -- ordmasculine
+char186 "
+fc 180,434,0,73,-20,70 0 0273 -- guilsinglright
+14 930,681,0,33,-41,33 2 0274 -- onequarter
+char188 "
+12 930,681,0,45,-41,45 2 0275 -- onehalf
+char189 "
+34 930,691,0,33,-49,33 2 0276 -- threequarters
+char190 "
+r? 540,494,212,18,32,18 1 0277 -- questiondown
+char191 "
+`A 700,893,0,70,75,70 2 0300 -- Agrave
+char192 "
+'A 700,893,0,70,75,70 2 0301 -- Aacute
+char193 "
+^A 700,872,0,70,75,70 2 0302 -- Acircumflex
+char194 "
+~A 700,858,0,70,75,70 2 0303 -- Atilde
+char195 "
+:A 700,875,0,70,75,70 2 0304 -- Adieresis
+char196 "
+oA 700,893,0,70,75,70 2 0305 -- Aring
+char197 "
+AE 1220,681,0,99,95,70 2 0306 -- AE
+char198 "
+,C 720,698,178,76,-38,70 2 0307 -- Ccedilla
+char199 "
+`E 680,893,0,106,29,70 2 0310 -- Egrave
+char200 "
+'E 680,893,0,106,29,70 2 0311 -- Eacute
+char201 "
+^E 680,872,0,106,29,70 2 0312 -- Ecircumflex
+char202 "
+:E 680,875,0,106,29,70 2 0313 -- Edieresis
+char203 "
+`I 320,893,0,142,29,70 2 0314 -- Igrave
+char204 "
+'I 320,893,0,142,29,70 2 0315 -- Iacute
+char205 "
+^I 320,872,0,149,29,70 2 0316 -- Icircumflex
+char206 "
+:I 320,875,0,147,29,70 2 0317 -- Idieresis
+char207 "
+-D 740,681,0,92,29,70 2 0320 -- Eth
+char208 "
+~N 720,858,0,153,32,70 2 0321 -- Ntilde
+char209 "
+`O 760,893,17,89,-38,70 2 0322 -- Ograve
+char210 "
+'O 760,893,17,89,-38,70 2 0323 -- Oacute
+char211 "
+^O 760,872,17,89,-38,70 2 0324 -- Ocircumflex
+char212 "
+~O 760,858,17,89,-38,70 2 0325 -- Otilde
+char213 "
+:O 760,875,17,89,-38,70 2 0326 -- Odieresis
+char214 "
+char215 600,548,0,45,-41,45 0 0327 -- multiply
+/O 760,777,95,89,-38,70 2 0330 -- Oslash
+char216 "
+`U 720,893,17,172,-68,70 2 0331 -- Ugrave
+char217 "
+'U 720,893,17,172,-68,70 2 0332 -- Uacute
+char218 "
+^U 720,872,17,172,-68,70 2 0333 -- Ucircumflex
+char219 "
+:U 720,875,17,172,-68,70 2 0334 -- Udieresis
+char220 "
+'Y 660,893,0,199,-37,70 2 0335 -- Yacute
+char221 "
+TP 600,681,0,106,29,70 2 0336 -- Thorn
+char222 "
+ss 620,698,111,83,171,70 2 0337 -- germandbls
+char223 "
+`a 620,706,8,116,-21,70 2 0340 -- agrave
+char224 "
+'a 620,706,8,116,-21,70 2 0341 -- aacute
+char225 "
+^a 620,685,8,116,-21,70 2 0342 -- acircumflex
+char226 "
+~a 620,671,8,116,-21,70 2 0343 -- atilde
+char227 "
+:a 620,688,8,116,-21,70 2 0344 -- adieresis
+char228 "
+oa 620,706,8,116,-21,70 2 0345 -- aring
+char229 "
+ae 880,494,8,88,-21,70 0 0346 -- ae
+char230 "
+,c 480,494,178,92,-15,70 0 0347 -- ccedilla
+char231 "
+`e 540,706,8,85,-15,70 2 0350 -- egrave
+char232 "
+'e 540,706,8,85,-15,70 2 0351 -- eacute
+char233 "
+^e 540,685,8,85,-15,70 2 0352 -- ecircumflex
+char234 "
+:e 540,688,8,85,-15,70 2 0353 -- edieresis
+char235 "
+`i 280,706,8,121,-38,70 2 0354 -- igrave
+char236 "
+'i 280,706,8,121,-38,70 2 0355 -- iacute
+char237 "
+^i 280,685,8,149,-26,70 2 0356 -- icircumflex
+char238 "
+:i 280,688,8,147,-38,70 2 0357 -- idieresis
+char239 "
+Sd 540,725,8,152,-15,70 2 0360 -- eth
+char240 "
+~n 620,671,8,103,-38,70 2 0361 -- ntilde
+char241 "
+`o 540,706,8,82,-15,70 2 0362 -- ograve
+char242 "
+'o 540,706,8,82,-15,70 2 0363 -- oacute
+char243 "
+^o 540,685,8,82,-15,70 2 0364 -- ocircumflex
+char244 "
+~o 540,671,8,82,-15,70 2 0365 -- otilde
+char245 "
+:o 540,688,8,82,-15,70 2 0366 -- odieresis
+char246 "
+char247 600,548,0,45,-41,45 0 0367 -- divide
+/o 540,532,49,81,-15,70 0 0370 -- oslash
+char248 "
+`u 620,706,8,116,-38,70 2 0371 -- ugrave
+char249 "
+'u 620,706,8,116,-38,70 2 0372 -- uacute
+char250 "
+^u 620,685,8,116,-38,70 2 0373 -- ucircumflex
+char251 "
+:u 620,688,8,116,-38,70 2 0374 -- udieresis
+char252 "
+'y 600,706,221,59,-10,59 3 0375 -- yacute
+char253 "
+Tp 600,717,212,70,74,70 3 0376 -- thorn
+char254 "
+:y 600,688,221,59,-10,59 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/BMR b/font/devps/BMR
new file mode 100644
index 00000000..b484f688
--- /dev/null
+++ b/font/devps/BMR
@@ -0,0 +1,430 @@
+name BMR
+internalname Bookman-Light
+spacewidth 320
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y 32
+A w 4
+A v 7
+A Y -35
+A W -40
+A V -56
+A T 1
+F . -46
+F , -41
+F A -21
+L y 79
+L Y 13
+L W 1
+L V -4
+L T 28
+P . -60
+P , -55
+P A -8
+R y 59
+R Y 26
+R W 13
+R V 8
+R T 71
+T s 16
+T r 38
+T . -33
+T o 15
+T i 42
+T - 90
+T hy 90
+T char173 90
+T e 13
+T , -28
+T c 14
+T a 17
+T A 1
+V y 15
+V u -38
+V r -41
+V . -40
+V o -71
+V i -20
+V - 11
+V hy 11
+V char173 11
+V e -72
+V , -34
+V a -69
+V A -66
+W y 15
+W u -38
+W r -41
+W . -40
+W o -68
+W i -20
+W - 11
+W hy 11
+W char173 11
+W e -69
+W , -34
+W a -66
+W A -64
+Y v 15
+Y u -38
+Y q -55
+Y . -40
+Y p -31
+Y o -57
+Y i -37
+Y - 11
+Y hy 11
+Y char173 11
+Y e -58
+Y , -34
+Y a -54
+Y A -53
+f f 29
+r q 9
+r . -64
+r o 8
+r n 31
+r m 31
+r - 70
+r hy 70
+r char173 70
+r h -21
+r g -4
+r f 33
+r e 7
+r d 7
+r , -58
+r c 7
+charset
+ha 600,681 2 0000 -- asciicircum
+ti 600,352 0 0001 -- asciitilde
+vS 660,869,17 2 0002 -- Scaron
+vZ 640,869 2 0003 -- Zcaron
+vs 520,672,8 2 0004 -- scaron
+vz 480,672 2 0005 -- zcaron
+:Y 640,871 2 0006 -- Ydieresis
+tm 980,681 2 0007 -- trademark
+aq 220,698 2 0010 -- quotesingle
+space 320 0 0040
+! 300,698,8 2 0041 -- exclam
+" 380,698 2 0042 -- quotedbl
+# 620,681 2 0043 -- numbersign
+sh "
+$ 620,791,109 2 0044 -- dollar
+Do "
+% 900,698,8 2 0045 -- percent
+& 800,698,17 2 0046 -- ampersand
+' 220,698 2 0047 -- quoteright
+( 300,727,145 2 0050 -- parenleft
+) 300,727,146 2 0051 -- parenright
+* 440,698 2 0052 -- asterisk
++ 600,513 0 0053 -- plus
+, 320,114,114 0 0054 -- comma
+- 400,292 0 0055 -- hyphen
+hy "
+char173 "
+. 320,123,8 0 0056 -- period
+/ 600,717,149 2 0057 -- slash
+sl "
+0 620,698,17 2 0060 -- zero
+1 620,681 2 0061 -- one
+2 620,698 2 0062 -- two
+3 620,698,17 2 0063 -- three
+4 620,681 2 0064 -- four
+5 620,717,17 2 0065 -- five
+6 620,698,17 2 0066 -- six
+7 620,681 2 0067 -- seven
+8 620,698,17 2 0070 -- eight
+9 620,698,17 2 0071 -- nine
+: 320,494,8 0 0072 -- colon
+; 320,494,114 0 0073 -- semicolon
+< 600,526,2 0 0074 -- less
+= 600,398 0 0075 -- equal
+> 600,526,2 0 0076 -- greater
+? 540,698,8 2 0077 -- question
+@ 820,698,17 2 0100 -- at
+at "
+A 680,681 2 0101 -- A
+B 740,681 2 0102 -- B
+C 740,698,17 2 0103 -- C
+D 800,681 2 0104 -- D
+E 720,681 2 0105 -- E
+F 640,681 2 0106 -- F
+G 800,698,17 2 0107 -- G
+H 800,681 2 0110 -- H
+I 340,681 2 0111 -- I
+J 600,681,17 2 0112 -- J
+K 720,681 2 0113 -- K
+L 600,681 2 0114 -- L
+M 920,681 2 0115 -- M
+N 740,681 2 0116 -- N
+O 800,698,17 2 0117 -- O
+P 620,681 2 0120 -- P
+Q 820,698,189 2 0121 -- Q
+R 720,681 2 0122 -- R
+S 660,698,17 2 0123 -- S
+T 620,681 2 0124 -- T
+U 780,681,17 2 0125 -- U
+V 700,681 2 0126 -- V
+W 960,681 2 0127 -- W
+X 720,681 2 0130 -- X
+Y 640,681 2 0131 -- Y
+Z 640,681 2 0132 -- Z
+[ 300,717,136 2 0133 -- bracketleft
+lB "
+\ 600,717 2 0134 -- backslash
+rs "
+] 300,717,136 2 0135 -- bracketright
+rB "
+a^ 420,685 2 0136 -- circumflex
+^ "
+_ 500,0,155 0 0137 -- underscore
+` 220,698 2 0140 -- quoteleft
+oq "
+a 580,494,8 0 0141 -- a
+b 620,717,8 2 0142 -- b
+c 520,494,8 0 0143 -- c
+d 620,717,8 2 0144 -- d
+e 520,494,8 0 0145 -- e
+f 320,734 2 0146 -- f
+g 540,567,243 1 0147 -- g
+h 660,717 2 0150 -- h
+i 300,654 0 0151 -- i
+j 300,654,251 1 0152 -- j
+k 620,717 2 0153 -- k
+l 300,717 2 0154 -- l
+m 940,494 0 0155 -- m
+n 660,494 0 0156 -- n
+o 560,494,8 0 0157 -- o
+p 620,494,228 1 0160 -- p
+q 580,494,228 1 0161 -- q
+r 440,494 0 0162 -- r
+s 520,494,8 0 0163 -- s
+t 380,667,8 2 0164 -- t
+u 680,484,8 0 0165 -- u
+v 520,484 0 0166 -- v
+w 780,484 0 0167 -- w
+x 560,484 0 0170 -- x
+y 540,484,236 1 0171 -- y
+z 480,484 0 0172 -- z
+lC 280,717,136 2 0173 -- braceleft
+{ "
+ba 600,717 2 0174 -- bar
+| "
+rC 280,717,136 2 0175 -- braceright
+} "
+a~ 440,661 0 0176 -- tilde
+~ "
+bq 220,110,108 0 0200 -- quotesinglbase
+Fo 360,437 0 0201 -- guillemotleft
+char171 "
+Fc 360,437 0 0202 -- guillemotright
+char187 "
+bu 460,511 0 0203 -- bullet
+Fn 620,749,155 2 0204 -- florin
+f/ 140,681 2 0205 -- fraction
+%0 1280,698,8 2 0206 -- perthousand
+dg 540,698,156 2 0207 -- dagger
+dd 540,698,156 2 0210 -- daggerdbl
+en 500,292 0 0211 -- endash
+em 1000,292 0 0212 -- emdash
+fi 620,734 2 0214 -- fi
+fl 620,734 2 0215 -- fl
+.i 300,484 0 0220 -- dotlessi
+ga 340,689 2 0222 -- grave
+a" 380,699 2 0223 -- hungarumlaut
+a. 260,672 2 0224 -- dotaccent
+ab 460,687 2 0225 -- breve
+ah 420,672 2 0226 -- caron
+ao 320,731 2 0227 -- ring
+ho 320,0,145 0 0230 -- ogonek
+lq 400,698 2 0231 -- quotedblleft
+rq 400,698 2 0232 -- quotedblright
+oe 900,494,8 0 0233 -- oe
+/l 320,717 2 0234 -- lslash
+Bq 400,110,108 0 0235 -- quotedblbase
+OE 1240,698,17 2 0236 -- OE
+/L 600,681 2 0237 -- Lslash
+r! 300,494,214 0 0241 -- exclamdown
+char161 "
+ct 620,651 0 0242 -- cent
+char162 "
+Po 620,698,17 2 0243 -- sterling
+char163 "
+Cs 620,591 0 0244 -- currency
+char164 "
+Ye 620,681 2 0245 -- yen
+char165 "
+bb 600,717 2 0246 -- brokenbar
+char166 "
+sc 520,698,178 2 0247 -- section
+char167 "
+ad 420,674 2 0250 -- dieresis
+char168 "
+co 740,698,17 2 0251 -- copyright
+char169 "
+Of 420,698 2 0252 -- ordfeminine
+char170 "
+fo 240,437 0 0253 -- guilsinglleft
+no 600,398 0 0254 -- logicalnot
+char172 "
+\- 600,300 0 0255 -- minus
+rg 740,698,17 2 0256 -- registered
+char174 "
+a- 440,635 0 0257 -- macron
+char175 "
+de 400,698 2 0260 -- degree
+char176 "
+char177 600,513 0 0261 -- plusminus
+S2 372,698 2 0262 -- twosuperior
+char178 "
+S3 372,698 2 0263 -- threesuperior
+char179 "
+aa 340,689 2 0264 -- acute
+char180 "
+char181 680,484,251 1 0265 -- mu
+ps 600,681 2 0266 -- paragraph
+char182 "
+char183 320,327 0 0267 -- periodcentered
+ac 320,0,200 0 0270 -- cedilla
+char184 "
+S1 372,688 2 0271 -- onesuperior
+char185 "
+Om 420,698 2 0272 -- ordmasculine
+char186 "
+fc 240,437 0 0273 -- guilsinglright
+14 930,681 2 0274 -- onequarter
+char188 "
+12 930,681 2 0275 -- onehalf
+char189 "
+34 930,691 2 0276 -- threequarters
+char190 "
+r? 540,494,217 0 0277 -- questiondown
+char191 "
+`A 680,886 2 0300 -- Agrave
+char192 "
+'A 680,886 2 0301 -- Aacute
+char193 "
+^A 680,882 2 0302 -- Acircumflex
+char194 "
+~A 680,858 2 0303 -- Atilde
+char195 "
+:A 680,871 2 0304 -- Adieresis
+char196 "
+oA 680,928 2 0305 -- Aring
+char197 "
+AE 1260,681 2 0306 -- AE
+char198 "
+,C 740,698,200 2 0307 -- Ccedilla
+char199 "
+`E 720,886 2 0310 -- Egrave
+char200 "
+'E 720,886 2 0311 -- Eacute
+char201 "
+^E 720,882 2 0312 -- Ecircumflex
+char202 "
+:E 720,871 2 0313 -- Edieresis
+char203 "
+`I 340,886 2 0314 -- Igrave
+char204 "
+'I 340,886 2 0315 -- Iacute
+char205 "
+^I 340,882 2 0316 -- Icircumflex
+char206 "
+:I 340,871 2 0317 -- Idieresis
+char207 "
+-D 800,681 2 0320 -- Eth
+char208 "
+~N 740,858 2 0321 -- Ntilde
+char209 "
+`O 800,886,17 2 0322 -- Ograve
+char210 "
+'O 800,886,17 2 0323 -- Oacute
+char211 "
+^O 800,882,17 2 0324 -- Ocircumflex
+char212 "
+~O 800,858,17 2 0325 -- Otilde
+char213 "
+:O 800,871,17 2 0326 -- Odieresis
+char214 "
+char215 600,513 0 0327 -- multiply
+/O 800,733,53 2 0330 -- Oslash
+char216 "
+`U 780,886,17 2 0331 -- Ugrave
+char217 "
+'U 780,886,17 2 0332 -- Uacute
+char218 "
+^U 780,882,17 2 0333 -- Ucircumflex
+char219 "
+:U 780,871,17 2 0334 -- Udieresis
+char220 "
+'Y 640,886 2 0335 -- Yacute
+char221 "
+TP 620,681 2 0336 -- Thorn
+char222 "
+ss 660,698,110 2 0337 -- germandbls
+char223 "
+`a 580,689,8 2 0340 -- agrave
+char224 "
+'a 580,689,8 2 0341 -- aacute
+char225 "
+^a 580,685,8 2 0342 -- acircumflex
+char226 "
+~a 580,661,8 0 0343 -- atilde
+char227 "
+:a 580,674,8 2 0344 -- adieresis
+char228 "
+oa 580,731,8 2 0345 -- aring
+char229 "
+ae 860,494,8 0 0346 -- ae
+char230 "
+,c 520,494,200 0 0347 -- ccedilla
+char231 "
+`e 520,689,8 2 0350 -- egrave
+char232 "
+'e 520,689,8 2 0351 -- eacute
+char233 "
+^e 520,685,8 2 0352 -- ecircumflex
+char234 "
+:e 520,674,8 2 0353 -- edieresis
+char235 "
+`i 300,689 2 0354 -- igrave
+char236 "
+'i 300,689 2 0355 -- iacute
+char237 "
+^i 300,685 2 0356 -- icircumflex
+char238 "
+:i 300,674 2 0357 -- idieresis
+char239 "
+Sd 560,734,8 2 0360 -- eth
+char240 "
+~n 660,661 0 0361 -- ntilde
+char241 "
+`o 560,689,8 2 0362 -- ograve
+char242 "
+'o 560,689,8 2 0363 -- oacute
+char243 "
+^o 560,685,8 2 0364 -- ocircumflex
+char244 "
+~o 560,661,8 0 0365 -- otilde
+char245 "
+:o 560,674,8 2 0366 -- odieresis
+char246 "
+char247 600,514 0 0367 -- divide
+/o 560,534,40 0 0370 -- oslash
+char248 "
+`u 680,689,8 2 0371 -- ugrave
+char249 "
+'u 680,689,8 2 0372 -- uacute
+char250 "
+^u 680,685,8 2 0373 -- ucircumflex
+char251 "
+:u 680,674,8 2 0374 -- udieresis
+char252 "
+'y 540,689,236 3 0375 -- yacute
+char253 "
+Tp 620,717,228 3 0376 -- thorn
+char254 "
+:y 540,674,236 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/CB b/font/devps/CB
new file mode 100644
index 00000000..fa80a711
--- /dev/null
+++ b/font/devps/CB
@@ -0,0 +1,336 @@
+name CB
+internalname Courier-Bold
+spacewidth 600
+encoding text.enc
+charset
+ha 600,616 2 0000 -- asciicircum
+ti 600,356 0 0001 -- asciitilde
+vS 600,790,22 2 0002 -- Scaron
+vZ 600,790 2 0003 -- Zcaron
+vs 600,667,17 2 0004 -- scaron
+vz 600,667 2 0005 -- zcaron
+:Y 600,748 2 0006 -- Ydieresis
+tm 600,562 2 0007 -- trademark
+aq 600,562 2 0010 -- quotesingle
+space 600 0 0040
+! 600,572,15 2 0041 -- exclam
+" 600,562 2 0042 -- quotedbl
+# 600,651,45 2 0043 -- numbersign
+sh "
+$ 600,666,126 2 0044 -- dollar
+Do "
+% 600,616,15 2 0045 -- percent
+& 600,543,15 0 0046 -- ampersand
+' 600,562 2 0047 -- quoteright
+( 600,616,102 2 0050 -- parenleft
+) 600,616,102 2 0051 -- parenright
+* 600,601 2 0052 -- asterisk
++ 600,478 0 0053 -- plus
+, 600,174,111 0 0054 -- comma
+- 600,313 0 0055 -- hyphen
+hy "
+char173 "
+. 600,171,15 0 0056 -- period
+/ 600,626,77 2 0057 -- slash
+sl "
+0 600,616,15 2 0060 -- zero
+1 600,616 2 0061 -- one
+2 600,616 2 0062 -- two
+3 600,616,15 2 0063 -- three
+4 600,616 2 0064 -- four
+5 600,601,15 2 0065 -- five
+6 600,616,15 2 0066 -- six
+7 600,601 2 0067 -- seven
+8 600,616,15 2 0070 -- eight
+9 600,616,15 2 0071 -- nine
+: 600,425,15 0 0072 -- colon
+; 600,425,111 0 0073 -- semicolon
+< 600,501 0 0074 -- less
+= 600,398 0 0075 -- equal
+> 600,501 0 0076 -- greater
+? 600,580,14 2 0077 -- question
+@ 600,616,15 2 0100 -- at
+at "
+A 600,562 2 0101 -- A
+B 600,562 2 0102 -- B
+C 600,580,18 2 0103 -- C
+D 600,562 2 0104 -- D
+E 600,562 2 0105 -- E
+F 600,562 2 0106 -- F
+G 600,580,18 2 0107 -- G
+H 600,562 2 0110 -- H
+I 600,562 2 0111 -- I
+J 600,562,18 2 0112 -- J
+K 600,562 2 0113 -- K
+L 600,562 2 0114 -- L
+M 600,562 2 0115 -- M
+N 600,562,12 2 0116 -- N
+O 600,580,18 2 0117 -- O
+P 600,562 2 0120 -- P
+Q 600,580,138 2 0121 -- Q
+R 600,562 2 0122 -- R
+S 600,582,22 2 0123 -- S
+T 600,562 2 0124 -- T
+U 600,562,18 2 0125 -- U
+V 600,562 2 0126 -- V
+W 600,562 2 0127 -- W
+X 600,562 2 0130 -- X
+Y 600,562 2 0131 -- Y
+Z 600,562 2 0132 -- Z
+[ 600,616,102 2 0133 -- bracketleft
+lB "
+\ 600,626,77 2 0134 -- backslash
+rs "
+] 600,616,102 2 0135 -- bracketright
+rB "
+a^ 600,657 2 0136 -- circumflex
+^ "
+_ 600,0,125 0 0137 -- underscore
+` 600,562 2 0140 -- quoteleft
+oq "
+a 600,454,15 0 0141 -- a
+b 600,626,15 2 0142 -- b
+c 600,459,15 0 0143 -- c
+d 600,626,15 2 0144 -- d
+e 600,454,15 0 0145 -- e
+f 600,626 2 0146 -- f
+g 600,454,146 1 0147 -- g
+h 600,626 2 0150 -- h
+i 600,658 2 0151 -- i
+j 600,658,146 3 0152 -- j
+k 600,626 2 0153 -- k
+l 600,626 2 0154 -- l
+m 600,454 0 0155 -- m
+n 600,454 0 0156 -- n
+o 600,454,15 0 0157 -- o
+p 600,454,142 1 0160 -- p
+q 600,454,142 1 0161 -- q
+r 600,454 0 0162 -- r
+s 600,459,17 0 0163 -- s
+t 600,562,15 2 0164 -- t
+u 600,439,15 0 0165 -- u
+v 600,439 0 0166 -- v
+w 600,439 0 0167 -- w
+x 600,439 0 0170 -- x
+y 600,439,142 1 0171 -- y
+z 600,439 0 0172 -- z
+lC 600,616,102 2 0173 -- braceleft
+{ "
+ba 600,750,250 3 0174 -- bar
+| "
+rC 600,616,102 2 0175 -- braceright
+} "
+a~ 600,636 2 0176 -- tilde
+~ "
+bq 600,143,142 1 0200 -- quotesinglbase
+Fo 600,446 0 0201 -- guillemotleft
+char171 "
+Fc 600,446 0 0202 -- guillemotright
+char187 "
+bu 600,430 0 0203 -- bullet
+Fn 600,616,131 2 0204 -- florin
+f/ 600,661,60 2 0205 -- fraction
+%0 600,616,15 2 0206 -- perthousand
+dg 600,580,70 2 0207 -- dagger
+dd 600,580,70 2 0210 -- daggerdbl
+en 600,313 0 0211 -- endash
+em 600,313 0 0212 -- emdash
+fi 600,626 2 0214 -- fi
+fl 600,626 2 0215 -- fl
+.i 600,439 0 0220 -- dotlessi
+ga 600,661 2 0222 -- grave
+a" 600,661 2 0223 -- hungarumlaut
+a. 600,625 2 0224 -- dotaccent
+ab 600,631 2 0225 -- breve
+ah 600,667 2 0226 -- caron
+ao 600,678 2 0227 -- ring
+ho 600,0,199 1 0230 -- ogonek
+lq 600,562 2 0231 -- quotedblleft
+rq 600,562 2 0232 -- quotedblright
+oe 600,454,15 0 0233 -- oe
+/l 600,626 2 0234 -- lslash
+Bq 600,143,142 1 0235 -- quotedblbase
+OE 600,562 2 0236 -- OE
+/L 600,562 2 0237 -- Lslash
+r! 600,449,146 1 0241 -- exclamdown
+char161 "
+ct 600,614,49 2 0242 -- cent
+char162 "
+Po 600,611,28 2 0243 -- sterling
+char163 "
+Cs 600,517 0 0244 -- currency
+char164 "
+Ye 600,562 2 0245 -- yen
+char165 "
+bb 600,675,175 3 0246 -- brokenbar
+char166 "
+sc 600,580,70 2 0247 -- section
+char167 "
+ad 600,625 2 0250 -- dieresis
+char168 "
+co 600,580,18 2 0251 -- copyright
+char169 "
+Of 600,580 2 0252 -- ordfeminine
+char170 "
+fo 600,446 0 0253 -- guilsinglleft
+no 600,413 0 0254 -- logicalnot
+char172 "
+\- 600,313 0 0255 -- minus
+rg 600,580,18 2 0256 -- registered
+char174 "
+a- 600,585 2 0257 -- macron
+char175 "
+de 600,616 2 0260 -- degree
+char176 "
+char177 600,515 0 0261 -- plusminus
+S2 600,616 2 0262 -- twosuperior
+char178 "
+S3 600,616 2 0263 -- threesuperior
+char179 "
+aa 600,661 2 0264 -- acute
+char180 "
+char181 600,439,142 1 0265 -- mu
+ps 600,580,70 2 0266 -- paragraph
+char182 "
+char183 600,351 0 0267 -- periodcentered
+ac 600,0,206 1 0270 -- cedilla
+char184 "
+S1 600,616 2 0271 -- onesuperior
+char185 "
+Om 600,580 2 0272 -- ordmasculine
+char186 "
+fc 600,446 0 0273 -- guilsinglright
+14 600,661,60 2 0274 -- onequarter
+char188 "
+12 600,661,60 2 0275 -- onehalf
+char189 "
+34 600,661,60 2 0276 -- threequarters
+char190 "
+r? 600,449,146 1 0277 -- questiondown
+char191 "
+`A 600,784 2 0300 -- Agrave
+char192 "
+'A 600,784 2 0301 -- Aacute
+char193 "
+^A 600,780 2 0302 -- Acircumflex
+char194 "
+~A 600,759 2 0303 -- Atilde
+char195 "
+:A 600,748 2 0304 -- Adieresis
+char196 "
+oA 600,801 2 0305 -- Aring
+char197 "
+AE 600,562 2 0306 -- AE
+char198 "
+,C 600,580,206 3 0307 -- Ccedilla
+char199 "
+`E 600,784 2 0310 -- Egrave
+char200 "
+'E 600,784 2 0311 -- Eacute
+char201 "
+^E 600,780 2 0312 -- Ecircumflex
+char202 "
+:E 600,748 2 0313 -- Edieresis
+char203 "
+`I 600,784 2 0314 -- Igrave
+char204 "
+'I 600,784 2 0315 -- Iacute
+char205 "
+^I 600,780 2 0316 -- Icircumflex
+char206 "
+:I 600,748 2 0317 -- Idieresis
+char207 "
+-D 600,562 2 0320 -- Eth
+char208 "
+~N 600,759,12 2 0321 -- Ntilde
+char209 "
+`O 600,784,18 2 0322 -- Ograve
+char210 "
+'O 600,784,18 2 0323 -- Oacute
+char211 "
+^O 600,780,18 2 0324 -- Ocircumflex
+char212 "
+~O 600,759,18 2 0325 -- Otilde
+char213 "
+:O 600,748,18 2 0326 -- Odieresis
+char214 "
+char215 600,478 0 0327 -- multiply
+/O 600,584,22 2 0330 -- Oslash
+char216 "
+`U 600,784,18 2 0331 -- Ugrave
+char217 "
+'U 600,784,18 2 0332 -- Uacute
+char218 "
+^U 600,780,18 2 0333 -- Ucircumflex
+char219 "
+:U 600,748,18 2 0334 -- Udieresis
+char220 "
+'Y 600,784 2 0335 -- Yacute
+char221 "
+TP 600,562 2 0336 -- Thorn
+char222 "
+ss 600,626,15 2 0337 -- germandbls
+char223 "
+`a 600,661,15 2 0340 -- agrave
+char224 "
+'a 600,661,15 2 0341 -- aacute
+char225 "
+^a 600,657,15 2 0342 -- acircumflex
+char226 "
+~a 600,636,15 2 0343 -- atilde
+char227 "
+:a 600,625,15 2 0344 -- adieresis
+char228 "
+oa 600,678,15 2 0345 -- aring
+char229 "
+ae 600,454,15 0 0346 -- ae
+char230 "
+,c 600,459,206 1 0347 -- ccedilla
+char231 "
+`e 600,661,15 2 0350 -- egrave
+char232 "
+'e 600,661,15 2 0351 -- eacute
+char233 "
+^e 600,657,15 2 0352 -- ecircumflex
+char234 "
+:e 600,625,15 2 0353 -- edieresis
+char235 "
+`i 600,661 2 0354 -- igrave
+char236 "
+'i 600,661 2 0355 -- iacute
+char237 "
+^i 600,657 2 0356 -- icircumflex
+char238 "
+:i 600,625 2 0357 -- idieresis
+char239 "
+Sd 600,626,27 2 0360 -- eth
+char240 "
+~n 600,636 2 0361 -- ntilde
+char241 "
+`o 600,661,15 2 0362 -- ograve
+char242 "
+'o 600,661,15 2 0363 -- oacute
+char243 "
+^o 600,657,15 2 0364 -- ocircumflex
+char244 "
+~o 600,636,15 2 0365 -- otilde
+char245 "
+:o 600,625,15 2 0366 -- odieresis
+char246 "
+char247 600,500 0 0367 -- divide
+/o 600,463,24 0 0370 -- oslash
+char248 "
+`u 600,661,15 2 0371 -- ugrave
+char249 "
+'u 600,661,15 2 0372 -- uacute
+char250 "
+^u 600,657,15 2 0373 -- ucircumflex
+char251 "
+:u 600,625,15 2 0374 -- udieresis
+char252 "
+'y 600,661,142 3 0375 -- yacute
+char253 "
+Tp 600,626,142 3 0376 -- thorn
+char254 "
+:y 600,625,142 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/CBI b/font/devps/CBI
new file mode 100644
index 00000000..0f5fe468
--- /dev/null
+++ b/font/devps/CBI
@@ -0,0 +1,337 @@
+name CBI
+internalname Courier-BoldOblique
+slant 12
+spacewidth 600
+encoding text.enc
+charset
+ha 600,616,0,5,-121,5 2 0000 -- asciicircum
+ti 600,356,0,39,-70,39 0 0001 -- asciitilde
+vS 600,790,22,122,-4,75 2 0002 -- Scaron
+vZ 600,790,0,109,-12,75 2 0003 -- Zcaron
+vs 600,667,17,82,-17,75 2 0004 -- scaron
+vz 600,667,0,82,-31,75 2 0005 -- zcaron
+:Y 600,748,0,158,-59,75 2 0006 -- Ydieresis
+tm 600,562,0,318,-36,75 2 0007 -- trademark
+aq 600,562,0,0,-254 2 0010 -- quotesingle
+space 600 0 0040
+! 600,572,15,0,-166 2 0041 -- exclam
+" 600,562,0,34,-162,34 2 0042 -- quotedbl
+# 600,651,45,90,-38,75 2 0043 -- numbersign
+sh "
+$ 600,666,126,79,-37,75 2 0044 -- dollar
+Do "
+% 600,616,15,74,-52,74 2 0045 -- percent
+& 600,543,15,44,-12,44 0 0046 -- ampersand
+' 600,562,0,0,-180 2 0047 -- quoteright
+( 600,616,102,42,-216,42 2 0050 -- parenleft
+) 600,616,102,0,-67 2 0051 -- parenright
+* 600,601,0,47,-129,47 2 0052 -- asterisk
++ 600,478,0,46,-64,46 0 0053 -- plus
+, 600,174,111,0,-49 0 0054 -- comma
+- 600,313,0,17,-93,17 0 0055 -- hyphen
+hy "
+char173 "
+. 600,171,15,0,-157 0 0056 -- period
+/ 600,626,77,76,-41,75 2 0057 -- slash
+sl "
+0 600,616,15,42,-86,42 2 0060 -- zero
+1 600,616,0,11,-43,11 2 0061 -- one
+2 600,616,0,43,-11,43 2 0062 -- two
+3 600,616,15,21,-22,21 2 0063 -- three
+4 600,616,0,8,-32,8 2 0064 -- four
+5 600,601,15,71,-27,71 2 0065 -- five
+6 600,616,15,102,-86,75 2 0066 -- six
+7 600,601,0,72,-97,72 2 0067 -- seven
+8 600,616,15,54,-65,54 2 0070 -- eight
+9 600,616,15,42,-26,42 2 0071 -- nine
+: 600,425,15,0,-156 0 0072 -- colon
+; 600,425,111,0,-49 0 0073 -- semicolon
+< 600,501,0,62,-71,62 0 0074 -- less
+= 600,398,0,64,-46,64 0 0075 -- equal
+> 600,501,0,39,-47,39 0 0076 -- greater
+? 600,580,14,41,-133,41 2 0077 -- question
+@ 600,616,15,91,-16,75 2 0100 -- at
+at "
+A 600,562,0,81,59,75 2 0101 -- A
+B 600,562,0,79,20,75 2 0102 -- B
+C 600,580,18,124,-25,75 2 0103 -- C
+D 600,562,0,114,20,75 2 0104 -- D
+E 600,562,0,119,25,75 2 0105 -- E
+F 600,562,0,133,11,75 2 0106 -- F
+G 600,580,18,124,-25,75 2 0107 -- G
+H 600,562,0,149,30,75 2 0110 -- H
+I 600,562,0,92,-27,75 2 0111 -- I
+J 600,562,18,170,-9,75 2 0112 -- J
+K 600,562,0,141,29,75 2 0113 -- K
+L 600,562,0,85,11,75 2 0114 -- L
+M 600,562,0,171,52,75 2 0115 -- M
+N 600,562,12,179,42,75 2 0116 -- N
+O 600,580,18,95,-24,75 2 0117 -- O
+P 600,562,0,92,2,75 2 0120 -- P
+Q 600,580,138,86,-34,75 2 0121 -- Q
+R 600,562,0,67,26,67 2 0122 -- R
+S 600,582,22,122,-4,75 2 0123 -- S
+T 600,562,0,128,-36,75 2 0124 -- T
+U 600,562,18,165,-51,75 2 0125 -- U
+V 600,562,0,182,-34,75 2 0126 -- V
+W 600,562,0,187,-34,75 2 0127 -- W
+X 600,562,0,139,38,75 2 0130 -- X
+Y 600,562,0,158,-59,75 2 0131 -- Y
+Z 600,562,0,86,-12,75 2 0132 -- Z
+[ 600,616,102,56,-173,56 2 0133 -- bracketleft
+lB "
+\ 600,626,77,0,-173 2 0134 -- backslash
+rs "
+] 600,616,102,0,-53 2 0135 -- bracketright
+rB "
+a^ 600,657,0,56,-162,56 2 0136 -- circumflex
+^ "
+_ 600,0,125,34,77,34 0 0137 -- underscore
+` 600,562,0,0,-247 2 0140 -- quoteleft
+oq "
+a 600,454,15,42,-12,42 0 0141 -- a
+b 600,626,15,86,37,75 2 0142 -- b
+c 600,459,15,81,-31,75 0 0143 -- c
+d 600,626,15,94,-11,75 2 0144 -- d
+e 600,454,15,54,-31,54 0 0145 -- e
+f 600,626,0,127,-33,75 2 0146 -- f
+g 600,454,146,123,9,75 1 0147 -- g
+h 600,626,0,64,32,64 2 0150 -- h
+i 600,658,0,0,-27 2 0151 -- i
+j 600,658,146,30,13,30 3 0152 -- j
+k 600,626,0,92,17,75 2 0153 -- k
+l 600,626,0,0,-27 2 0154 -- l
+m 600,454,0,98,72,75 0 0155 -- m
+n 600,454,0,64,32,64 0 0156 -- n
+o 600,454,15,72,-21,72 0 0157 -- o
+p 600,454,142,72,81,72 1 0160 -- p
+q 600,454,142,134,-11,75 1 0161 -- q
+r 600,454,0,104,3,75 0 0162 -- r
+s 600,459,17,57,-17,57 0 0163 -- s
+t 600,562,15,16,-68,16 2 0164 -- t
+u 600,439,15,41,-20,41 0 0165 -- u
+v 600,439,0,144,-20,75 0 0166 -- v
+w 600,439,0,161,-3,75 0 0167 -- w
+x 600,439,0,120,44,75 0 0170 -- x
+y 600,439,142,144,70,75 1 0171 -- y
+z 600,439,0,63,-31,63 0 0172 -- z
+lC 600,616,102,45,-154,45 2 0173 -- braceleft
+{ "
+ba 600,750,250,0,-152 3 0174 -- bar
+| "
+rC 600,616,102,0,-64 2 0175 -- braceright
+} "
+a~ 600,636,0,92,-150,75 2 0176 -- tilde
+~ "
+bq 600,143,142,0,-95 1 0200 -- quotesinglbase
+Fo 600,446,0,88,-13,75 0 0201 -- guillemotleft
+char171 "
+Fc 600,446,0,97,-22,75 0 0202 -- guillemotright
+char187 "
+bu 600,430,0,0,-147 0 0203 -- bullet
+Fn 600,616,131,151,106,75 2 0204 -- florin
+f/ 600,661,60,157,28,75 2 0205 -- fraction
+%0 600,616,15,192,94,75 2 0206 -- perthousand
+dg 600,580,70,36,-126,36 2 0207 -- dagger
+dd 600,580,70,36,-72,36 2 0210 -- daggerdbl
+en 600,313,0,52,-58,52 0 0211 -- endash
+em 600,313,0,127,17,75 0 0212 -- emdash
+fi 600,626,0,93,38,75 2 0214 -- fi
+fl 600,626,0,93,38,75 2 0215 -- fl
+.i 600,439,0,0,-27 0 0220 -- dotlessi
+ga 600,661,0,0,-222 2 0222 -- grave
+a" 600,661,0,178,-122,75 2 0223 -- hungarumlaut
+a. 600,625,0,0,-296 2 0224 -- dotaccent
+ab 600,631,0,101,-167,75 2 0225 -- breve
+ah 600,667,0,82,-188,75 2 0226 -- caron
+ao 600,678,0,0,-269 2 0227 -- ring
+ho 600,0,199,0,-94 1 0230 -- ogonek
+lq 600,562,0,44,-140,44 2 0231 -- quotedblleft
+rq 600,562,0,94,-70,75 2 0232 -- quotedblright
+oe 600,454,15,111,31,75 0 0233 -- oe
+/l 600,626,0,28,-27,28 2 0234 -- lslash
+Bq 600,143,142,9,15,9 1 0235 -- quotedblbase
+OE 600,562,0,150,24,75 2 0236 -- OE
+/L 600,562,0,85,11,75 2 0237 -- Lslash
+r! 600,449,146,0,-147 1 0241 -- exclamdown
+char161 "
+ct 600,614,49,54,-71,54 2 0242 -- cent
+char162 "
+Po 600,611,28,100,-57,75 2 0243 -- sterling
+char163 "
+Cs 600,517,0,93,-27,75 0 0244 -- currency
+char164 "
+Ye 600,562,0,159,-48,75 2 0245 -- yen
+char165 "
+bb 600,675,175,0,-168 3 0246 -- brokenbar
+char166 "
+sc 600,580,70,69,-24,69 2 0247 -- section
+char167 "
+ad 600,625,0,42,-194,42 2 0250 -- dieresis
+char168 "
+co 600,580,18,117,-3,75 2 0251 -- copyright
+char169 "
+Of 600,580,0,0,-139 2 0252 -- ordfeminine
+char170 "
+fo 600,446,0,0,-146 0 0253 -- guilsinglleft
+no 600,413,0,67,-85,67 0 0254 -- logicalnot
+char172 "
+\- 600,313,0,46,-64,46 0 0255 -- minus
+rg 600,580,18,117,-3,75 2 0256 -- registered
+char174 "
+a- 600,585,0,86,-145,75 2 0257 -- macron
+char175 "
+de 600,616,0,19,-123,19 2 0260 -- degree
+char176 "
+char177 600,515,0,64,-26,64 0 0261 -- plusminus
+S2 600,616,0,0,-142 2 0262 -- twosuperior
+char178 "
+S3 600,616,0,0,-143 2 0263 -- threesuperior
+char179 "
+aa 600,661,0,58,-263,58 2 0264 -- acute
+char180 "
+char181 600,439,142,41,0,41 1 0265 -- mu
+ps 600,580,70,149,-11,75 2 0266 -- paragraph
+char182 "
+char183 600,351,0,0,-199 0 0267 -- periodcentered
+ac 600,0,206,0,-119 1 0270 -- cedilla
+char184 "
+S1 600,616,0,0,-163 2 0271 -- onesuperior
+char185 "
+Om 600,580,0,0,-139 2 0272 -- ordmasculine
+char186 "
+fc 600,446,0,0,-116 0 0273 -- guilsinglright
+14 600,661,60,156,36,75 2 0274 -- onequarter
+char188 "
+12 600,661,60,165,27,75 2 0275 -- onehalf
+char189 "
+34 600,661,60,148,42,75 2 0276 -- threequarters
+char190 "
+r? 600,449,146,0,-51 1 0277 -- questiondown
+char191 "
+`A 600,784,0,81,59,75 2 0300 -- Agrave
+char192 "
+'A 600,784,0,115,59,75 2 0301 -- Aacute
+char193 "
+^A 600,780,0,81,59,75 2 0302 -- Acircumflex
+char194 "
+~A 600,759,0,88,59,75 2 0303 -- Atilde
+char195 "
+:A 600,748,0,81,59,75 2 0304 -- Adieresis
+char196 "
+oA 600,801,0,81,59,75 2 0305 -- Aring
+char197 "
+AE 600,562,0,157,79,75 2 0306 -- AE
+char198 "
+,C 600,580,206,124,-24,75 3 0307 -- Ccedilla
+char199 "
+`E 600,784,0,119,25,75 2 0310 -- Egrave
+char200 "
+'E 600,784,0,119,25,75 2 0311 -- Eacute
+char201 "
+^E 600,780,0,119,25,75 2 0312 -- Ecircumflex
+char202 "
+:E 600,748,0,119,25,75 2 0313 -- Edieresis
+char203 "
+`I 600,784,0,92,-27,75 2 0314 -- Igrave
+char204 "
+'I 600,784,0,92,-27,75 2 0315 -- Iacute
+char205 "
+^I 600,780,0,92,-27,75 2 0316 -- Icircumflex
+char206 "
+:I 600,748,0,92,-27,75 2 0317 -- Idieresis
+char207 "
+-D 600,562,0,114,20,75 2 0320 -- Eth
+char208 "
+~N 600,759,12,179,42,75 2 0321 -- Ntilde
+char209 "
+`O 600,784,18,95,-24,75 2 0322 -- Ograve
+char210 "
+'O 600,784,18,95,-24,75 2 0323 -- Oacute
+char211 "
+^O 600,780,18,95,-24,75 2 0324 -- Ocircumflex
+char212 "
+~O 600,759,18,118,-24,75 2 0325 -- Otilde
+char213 "
+:O 600,748,18,95,-24,75 2 0326 -- Odieresis
+char214 "
+char215 600,478,0,56,-55,56 0 0327 -- multiply
+/O 600,584,22,122,2,75 2 0330 -- Oslash
+char216 "
+`U 600,784,18,165,-51,75 2 0331 -- Ugrave
+char217 "
+'U 600,784,18,165,-51,75 2 0332 -- Uacute
+char218 "
+^U 600,780,18,165,-51,75 2 0333 -- Ucircumflex
+char219 "
+:U 600,748,18,165,-51,75 2 0334 -- Udieresis
+char220 "
+'Y 600,784,0,158,-59,75 2 0335 -- Yacute
+char221 "
+TP 600,562,0,69,2,69 2 0336 -- Thorn
+char222 "
+ss 600,626,15,78,28,75 2 0337 -- germandbls
+char223 "
+`a 600,661,15,42,-12,42 2 0340 -- agrave
+char224 "
+'a 600,661,15,58,-12,58 2 0341 -- aacute
+char225 "
+^a 600,657,15,42,-12,42 2 0342 -- acircumflex
+char226 "
+~a 600,636,15,92,-12,75 2 0343 -- atilde
+char227 "
+:a 600,625,15,42,-12,42 2 0344 -- adieresis
+char228 "
+oa 600,678,15,42,-12,42 2 0345 -- aring
+char229 "
+ae 600,454,15,101,29,75 0 0346 -- ae
+char230 "
+,c 600,459,206,81,-31,75 1 0347 -- ccedilla
+char231 "
+`e 600,661,15,54,-31,54 2 0350 -- egrave
+char232 "
+'e 600,661,15,58,-31,58 2 0351 -- eacute
+char233 "
+^e 600,657,15,56,-31,56 2 0352 -- ecircumflex
+char234 "
+:e 600,625,15,54,-31,54 2 0353 -- edieresis
+char235 "
+`i 600,661,0,0,-27 2 0354 -- igrave
+char236 "
+'i 600,661,0,58,-27,58 2 0355 -- iacute
+char237 "
+^i 600,657,0,16,-27,16 2 0356 -- icircumflex
+char238 "
+:i 600,625,0,2,-27,2 2 0357 -- idieresis
+char239 "
+Sd 600,626,27,111,-43,75 2 0360 -- eth
+char240 "
+~n 600,636,0,92,32,75 2 0361 -- ntilde
+char241 "
+`o 600,661,15,72,-21,72 2 0362 -- ograve
+char242 "
+'o 600,661,15,72,-21,72 2 0363 -- oacute
+char243 "
+^o 600,657,15,72,-21,72 2 0364 -- ocircumflex
+char244 "
+~o 600,636,15,92,-21,75 2 0365 -- otilde
+char245 "
+:o 600,625,15,72,-21,72 2 0366 -- odieresis
+char246 "
+char247 600,500,0,46,-64,46 0 0367 -- divide
+/o 600,463,24,87,-5,75 0 0370 -- oslash
+char248 "
+`u 600,661,15,41,-20,41 2 0371 -- ugrave
+char249 "
+'u 600,661,15,58,-20,58 2 0372 -- uacute
+char250 "
+^u 600,657,15,41,-20,41 2 0373 -- ucircumflex
+char251 "
+:u 600,625,15,41,-20,41 2 0374 -- udieresis
+char252 "
+'y 600,661,142,144,70,75 3 0375 -- yacute
+char253 "
+Tp 600,626,142,72,81,72 3 0376 -- thorn
+char254 "
+:y 600,625,142,144,70,75 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/CI b/font/devps/CI
new file mode 100644
index 00000000..b01873b0
--- /dev/null
+++ b/font/devps/CI
@@ -0,0 +1,337 @@
+name CI
+internalname Courier-Oblique
+slant 12
+spacewidth 600
+encoding text.enc
+charset
+ha 600,622,0,37,-125,37 2 0000 -- asciicircum
+ti 600,320,0,50,-66,50 0 0001 -- asciitilde
+vS 600,805,20,123,-26,72 2 0002 -- Scaron
+vZ 600,805,0,93,-36,72 2 0003 -- Zcaron
+vs 600,669,15,64,-28,64 2 0004 -- scaron
+vz 600,669,0,74,-49,72 2 0005 -- zcaron
+:Y 600,731,0,145,-83,72 2 0006 -- Ydieresis
+tm 600,562,0,192,-25,72 2 0007 -- trademark
+aq 600,562,0,0,-295 2 0010 -- quotesingle
+space 600 0 0040
+! 600,572,15,0,-193 2 0041 -- exclam
+" 600,562,0,0,-223 2 0042 -- quotedbl
+# 600,639,32,46,-83,46 2 0043 -- numbersign
+sh "
+$ 600,662,126,46,-58,46 2 0044 -- dollar
+Do "
+% 600,622,15,49,-84,49 2 0045 -- percent
+& 600,543,15,30,-37,30 0 0046 -- ampersand
+' 600,562,0,0,-233 2 0047 -- quoteright
+( 600,622,108,22,-263,22 2 0050 -- parenleft
+) 600,622,108,0,-87 2 0051 -- parenright
+* 600,607,0,30,-162,30 2 0052 -- asterisk
++ 600,470,0,30,-79,30 0 0053 -- plus
+, 600,122,112,0,-107 0 0054 -- comma
+- 600,285,0,8,-102,8 0 0055 -- hyphen
+hy "
+char173 "
+. 600,109,15,0,-188 0 0056 -- period
+/ 600,629,80,54,-62,54 2 0057 -- slash
+sl "
+0 600,622,15,25,-104,25 2 0060 -- zero
+1 600,622,0,0,-48 2 0061 -- one
+2 600,622,0,18,-20,18 2 0062 -- two
+3 600,622,15,0,-32 2 0063 -- three
+4 600,622,0,0,-58 2 0064 -- four
+5 600,607,15,39,-49,39 2 0065 -- five
+6 600,622,15,79,-105,72 2 0066 -- six
+7 600,607,0,62,-132,62 2 0067 -- seven
+8 600,622,15,38,-82,38 2 0070 -- eight
+9 600,622,15,24,-43,24 2 0071 -- nine
+: 600,385,15,0,-188 0 0072 -- colon
+; 600,385,112,0,-107 0 0073 -- semicolon
+< 600,472,0,60,-46,60 0 0074 -- less
+= 600,376,0,50,-59,50 0 0075 -- equal
+> 600,472,0,49,-35,49 0 0076 -- greater
+? 600,572,15,33,-172,33 2 0077 -- question
+@ 600,622,15,32,-77,32 2 0100 -- at
+at "
+A 600,562,0,57,47,57 2 0101 -- A
+B 600,562,0,66,7,66 2 0102 -- B
+C 600,580,18,105,-43,72 2 0103 -- C
+D 600,562,0,95,7,72 2 0104 -- D
+E 600,562,0,110,-3,72 2 0105 -- E
+F 600,562,0,110,-3,72 2 0106 -- F
+G 600,580,18,95,-33,72 2 0107 -- G
+H 600,562,0,137,18,72 2 0110 -- H
+I 600,562,0,73,-46,72 2 0111 -- I
+J 600,562,18,135,-2,72 2 0112 -- J
+K 600,562,0,121,12,72 2 0113 -- K
+L 600,562,0,57,3,57 2 0114 -- L
+M 600,562,0,165,46,72 2 0115 -- M
+N 600,562,13,162,43,72 2 0116 -- N
+O 600,580,18,75,-44,72 2 0117 -- O
+P 600,562,0,94,-29,72 2 0120 -- P
+Q 600,580,138,75,-45,72 2 0121 -- Q
+R 600,562,0,48,12,48 2 0122 -- R
+S 600,580,20,100,-26,72 2 0123 -- S
+T 600,562,0,115,-58,72 2 0124 -- T
+U 600,562,18,152,-75,72 2 0125 -- U
+V 600,562,13,173,-55,72 2 0126 -- V
+W 600,562,13,172,-56,72 2 0127 -- W
+X 600,562,0,125,27,72 2 0130 -- X
+Y 600,562,0,145,-83,72 2 0131 -- Y
+Z 600,562,0,60,-36,60 2 0132 -- Z
+[ 600,622,108,24,-196,24 2 0133 -- bracketleft
+lB "
+\ 600,629,80,0,-199 2 0134 -- backslash
+rs "
+] 600,622,108,0,-85 2 0135 -- bracketright
+rB "
+a^ 600,654,0,31,-179,31 2 0136 -- circumflex
+^ "
+_ 600,0,125,34,77,34 0 0137 -- underscore
+` 600,562,0,0,-293 2 0140 -- quoteleft
+oq "
+a 600,441,15,19,-26,19 0 0141 -- a
+b 600,629,15,75,21,72 2 0142 -- b
+c 600,441,15,58,-56,58 0 0143 -- c
+d 600,629,15,90,-35,72 2 0144 -- d
+e 600,441,15,48,-56,48 0 0145 -- e
+f 600,629,0,112,-64,72 2 0146 -- f
+g 600,441,157,107,-11,72 1 0147 -- g
+h 600,629,0,42,17,42 2 0150 -- h
+i 600,657,0,0,-45 2 0151 -- i
+j 600,657,157,0,-2 3 0152 -- j
+k 600,629,0,83,-8,72 2 0153 -- k
+l 600,629,0,0,-45 2 0154 -- l
+m 600,441,0,65,55,65 0 0155 -- m
+n 600,441,0,35,24,35 0 0156 -- n
+o 600,441,15,38,-52,38 0 0157 -- o
+p 600,441,157,55,74,55 1 0160 -- p
+q 600,441,157,132,-35,72 1 0161 -- q
+r 600,441,0,86,-10,72 0 0162 -- r
+s 600,441,15,34,-28,34 0 0163 -- s
+t 600,561,15,11,-117,11 2 0164 -- t
+u 600,426,15,22,-51,22 0 0165 -- u
+v 600,426,10,131,-40,72 0 0166 -- v
+w 600,426,10,145,-26,72 0 0167 -- w
+x 600,426,0,105,30,72 0 0170 -- x
+y 600,426,157,133,54,72 1 0171 -- y
+z 600,426,0,43,-49,43 0 0172 -- z
+lC 600,622,108,19,-183,19 2 0173 -- braceleft
+{ "
+ba 600,750,250,0,-172 3 0174 -- bar
+| "
+rC 600,622,108,0,-90 2 0175 -- braceright
+} "
+a~ 600,606,0,79,-162,72 2 0176 -- tilde
+~ "
+bq 600,100,134,0,-135 0 0200 -- quotesinglbase
+Fo 600,446,0,102,-42,72 0 0201 -- guillemotleft
+char171 "
+Fc 600,446,0,68,-8,68 0 0202 -- guillemotright
+char187 "
+bu 600,383,0,0,-174 0 0203 -- bullet
+Fn 600,622,143,121,76,72 2 0204 -- florin
+f/ 600,665,57,96,-34,72 2 0205 -- fraction
+%0 600,622,15,77,-9,72 2 0206 -- perthousand
+dg 600,580,78,0,-167 2 0207 -- dagger
+dd 600,580,78,0,-113 2 0210 -- daggerdbl
+en 600,285,0,36,-74,36 0 0211 -- endash
+em 600,285,0,111,1,72 0 0212 -- emdash
+fi 600,629,0,69,47,69 2 0214 -- fi
+fl 600,629,0,69,47,69 2 0215 -- fl
+.i 600,426,0,0,-45 0 0220 -- dotlessi
+ga 600,672,0,0,-244 2 0222 -- grave
+a" 600,672,0,133,-189,72 2 0223 -- hungarumlaut
+a. 600,580,0,0,-310 2 0224 -- dotaccent
+ab 600,609,0,26,-229,26 2 0225 -- breve
+ah 600,669,0,64,-212,64 2 0226 -- caron
+ao 600,627,0,0,-282 2 0227 -- ring
+ho 600,0,151,0,-157 0 0230 -- ogonek
+lq 600,562,0,0,-212 2 0231 -- quotedblleft
+rq 600,562,0,26,-163,26 2 0232 -- quotedblright
+oe 600,441,15,65,-4,65 0 0233 -- oe
+/l 600,629,0,33,-45,33 2 0234 -- lslash
+Bq 600,100,134,0,-65 0 0235 -- quotedblbase
+OE 600,562,0,122,-9,72 2 0236 -- OE
+/L 600,562,0,57,3,57 2 0237 -- Lslash
+r! 600,430,157,0,-175 1 0241 -- exclamdown
+char161 "
+ct 600,614,49,38,-101,38 2 0242 -- cent
+char162 "
+Po 600,611,21,71,-74,71 2 0243 -- sterling
+char163 "
+Cs 600,506,0,78,-44,72 0 0244 -- currency
+char164 "
+Ye 600,562,0,143,-70,72 2 0245 -- yen
+char165 "
+bb 600,675,175,0,-188 3 0246 -- brokenbar
+char166 "
+sc 600,580,78,40,-54,40 2 0247 -- section
+char167 "
+ad 600,595,0,20,-212,20 2 0250 -- dieresis
+char168 "
+co 600,580,18,117,-3,72 2 0251 -- copyright
+char169 "
+Of 600,580,0,0,-159 2 0252 -- ordfeminine
+char170 "
+fo 600,446,0,0,-154 0 0253 -- guilsinglleft
+no 600,369,0,41,-105,41 0 0254 -- logicalnot
+char172 "
+\- 600,283,0,30,-79,30 0 0255 -- minus
+rg 600,580,18,117,-3,72 2 0256 -- registered
+char174 "
+a- 600,565,0,50,-182,50 2 0257 -- macron
+char175 "
+de 600,622,0,26,-164,26 2 0260 -- degree
+char176 "
+char177 600,558,0,44,-46,44 0 0261 -- plusminus
+S2 600,622,0,0,-180 2 0262 -- twosuperior
+char178 "
+S3 600,622,0,0,-163 2 0263 -- threesuperior
+char179 "
+aa 600,672,0,62,-298,62 2 0264 -- acute
+char180 "
+char181 600,426,157,22,-22,22 1 0265 -- mu
+ps 600,562,78,80,-50,72 2 0266 -- paragraph
+char182 "
+char183 600,327,0,0,-225 0 0267 -- periodcentered
+ac 600,10,151,0,-147 0 0270 -- cedilla
+char184 "
+S1 600,622,0,0,-181 2 0271 -- onesuperior
+char185 "
+Om 600,580,0,0,-160 2 0272 -- ordmasculine
+char186 "
+fc 600,446,0,0,-120 0 0273 -- guilsinglright
+14 600,665,57,124,-15,72 2 0274 -- onequarter
+char188 "
+12 600,665,57,119,-15,72 2 0275 -- onehalf
+char189 "
+34 600,666,56,109,-23,72 2 0276 -- threequarters
+char190 "
+r? 600,430,157,0,-55 1 0277 -- questiondown
+char191 "
+`A 600,793,0,57,47,57 2 0300 -- Agrave
+char192 "
+'A 600,793,0,108,47,72 2 0301 -- Aacute
+char193 "
+^A 600,775,0,57,47,57 2 0302 -- Acircumflex
+char194 "
+~A 600,732,0,106,47,72 2 0303 -- Atilde
+char195 "
+:A 600,731,0,57,47,57 2 0304 -- Adieresis
+char196 "
+oA 600,753,0,57,47,57 2 0305 -- Aring
+char197 "
+AE 600,562,0,105,47,72 2 0306 -- AE
+char198 "
+,C 600,580,151,108,-43,72 2 0307 -- Ccedilla
+char199 "
+`E 600,793,0,110,-3,72 2 0310 -- Egrave
+char200 "
+'E 600,793,0,118,-3,72 2 0311 -- Eacute
+char201 "
+^E 600,775,0,110,-3,72 2 0312 -- Ecircumflex
+char202 "
+:E 600,731,0,110,-3,72 2 0313 -- Edieresis
+char203 "
+`I 600,793,0,73,-46,72 2 0314 -- Igrave
+char204 "
+'I 600,793,0,88,-46,72 2 0315 -- Iacute
+char205 "
+^I 600,775,0,73,-46,72 2 0316 -- Icircumflex
+char206 "
+:I 600,731,0,73,-46,72 2 0317 -- Idieresis
+char207 "
+-D 600,562,0,95,7,72 2 0320 -- Eth
+char208 "
+~N 600,732,13,162,43,72 2 0321 -- Ntilde
+char209 "
+`O 600,793,18,75,-44,72 2 0322 -- Ograve
+char210 "
+'O 600,793,18,88,-44,72 2 0323 -- Oacute
+char211 "
+^O 600,775,18,75,-44,72 2 0324 -- Ocircumflex
+char212 "
+~O 600,732,18,106,-44,72 2 0325 -- Otilde
+char213 "
+:O 600,731,18,75,-44,72 2 0326 -- Odieresis
+char214 "
+char215 600,470,0,57,-53,57 0 0327 -- multiply
+/O 600,629,80,75,-44,72 2 0330 -- Oslash
+char216 "
+`U 600,793,18,152,-75,72 2 0331 -- Ugrave
+char217 "
+'U 600,793,18,152,-75,72 2 0332 -- Uacute
+char218 "
+^U 600,775,18,152,-75,72 2 0333 -- Ucircumflex
+char219 "
+:U 600,731,18,152,-75,72 2 0334 -- Udieresis
+char220 "
+'Y 600,793,0,145,-83,72 2 0335 -- Yacute
+char221 "
+TP 600,562,0,56,-29,56 2 0336 -- Thorn
+char222 "
+ss 600,629,15,67,2,67 2 0337 -- germandbls
+char223 "
+`a 600,672,15,19,-26,19 2 0340 -- agrave
+char224 "
+'a 600,672,15,62,-26,62 2 0341 -- aacute
+char225 "
+^a 600,654,15,31,-26,31 2 0342 -- acircumflex
+char226 "
+~a 600,606,15,79,-26,72 2 0343 -- atilde
+char227 "
+:a 600,595,15,20,-26,20 2 0344 -- adieresis
+char228 "
+oa 600,627,15,19,-26,19 2 0345 -- aring
+char229 "
+ae 600,441,15,76,9,72 0 0346 -- ae
+char230 "
+,c 600,441,151,64,-56,64 0 0347 -- ccedilla
+char231 "
+`e 600,672,15,48,-56,48 2 0350 -- egrave
+char232 "
+'e 600,672,15,62,-56,62 2 0351 -- eacute
+char233 "
+^e 600,654,15,48,-56,48 2 0352 -- ecircumflex
+char234 "
+:e 600,595,15,48,-56,48 2 0353 -- edieresis
+char235 "
+`i 600,672,0,0,-45 2 0354 -- igrave
+char236 "
+'i 600,672,0,62,-45,62 2 0355 -- iacute
+char237 "
+^i 600,654,0,1,-45,1 2 0356 -- icircumflex
+char238 "
+:i 600,595,0,0,-45 2 0357 -- idieresis
+char239 "
+Sd 600,629,15,89,-52,72 2 0360 -- eth
+char240 "
+~n 600,606,0,79,24,72 2 0361 -- ntilde
+char241 "
+`o 600,672,15,38,-52,38 2 0362 -- ograve
+char242 "
+'o 600,672,15,62,-52,62 2 0363 -- oacute
+char243 "
+^o 600,654,15,38,-52,38 2 0364 -- ocircumflex
+char244 "
+~o 600,606,15,79,-52,72 2 0365 -- otilde
+char245 "
+:o 600,595,15,38,-52,38 2 0366 -- odieresis
+char246 "
+char247 600,467,0,23,-86,23 0 0367 -- divide
+/o 600,506,80,38,-52,38 0 0370 -- oslash
+char248 "
+`u 600,672,15,22,-51,22 2 0371 -- ugrave
+char249 "
+'u 600,672,15,52,-51,52 2 0372 -- uacute
+char250 "
+^u 600,654,15,22,-51,22 2 0373 -- ucircumflex
+char251 "
+:u 600,595,15,22,-51,22 2 0374 -- udieresis
+char252 "
+'y 600,672,157,133,54,72 3 0375 -- yacute
+char253 "
+Tp 600,629,157,55,74,55 3 0376 -- thorn
+char254 "
+:y 600,595,157,133,54,72 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/CR b/font/devps/CR
new file mode 100644
index 00000000..beb4a80c
--- /dev/null
+++ b/font/devps/CR
@@ -0,0 +1,336 @@
+name CR
+internalname Courier
+spacewidth 600
+encoding text.enc
+charset
+ha 600,622 2 0000 -- asciicircum
+ti 600,320 0 0001 -- asciitilde
+vS 600,805,20 2 0002 -- Scaron
+vZ 600,805 2 0003 -- Zcaron
+vs 600,669,15 2 0004 -- scaron
+vz 600,669 2 0005 -- zcaron
+:Y 600,731 2 0006 -- Ydieresis
+tm 600,562 2 0007 -- trademark
+aq 600,562 2 0010 -- quotesingle
+space 600 0 0040
+! 600,572,15 2 0041 -- exclam
+" 600,562 2 0042 -- quotedbl
+# 600,639,32 2 0043 -- numbersign
+sh "
+$ 600,662,126 2 0044 -- dollar
+Do "
+% 600,622,15 2 0045 -- percent
+& 600,543,15 0 0046 -- ampersand
+' 600,562 2 0047 -- quoteright
+( 600,622,108 2 0050 -- parenleft
+) 600,622,108 2 0051 -- parenright
+* 600,607 2 0052 -- asterisk
++ 600,470 0 0053 -- plus
+, 600,122,112 0 0054 -- comma
+- 600,285 0 0055 -- hyphen
+hy "
+char173 "
+. 600,109,15 0 0056 -- period
+/ 600,629,80 2 0057 -- slash
+sl "
+0 600,622,15 2 0060 -- zero
+1 600,622 2 0061 -- one
+2 600,622 2 0062 -- two
+3 600,622,15 2 0063 -- three
+4 600,622 2 0064 -- four
+5 600,607,15 2 0065 -- five
+6 600,622,15 2 0066 -- six
+7 600,607 2 0067 -- seven
+8 600,622,15 2 0070 -- eight
+9 600,622,15 2 0071 -- nine
+: 600,385,15 0 0072 -- colon
+; 600,385,112 0 0073 -- semicolon
+< 600,472 0 0074 -- less
+= 600,376 0 0075 -- equal
+> 600,472 0 0076 -- greater
+? 600,572,15 2 0077 -- question
+@ 600,622,15 2 0100 -- at
+at "
+A 600,562 2 0101 -- A
+B 600,562 2 0102 -- B
+C 600,580,18 2 0103 -- C
+D 600,562 2 0104 -- D
+E 600,562 2 0105 -- E
+F 600,562 2 0106 -- F
+G 600,580,18 2 0107 -- G
+H 600,562 2 0110 -- H
+I 600,562 2 0111 -- I
+J 600,562,18 2 0112 -- J
+K 600,562 2 0113 -- K
+L 600,562 2 0114 -- L
+M 600,562 2 0115 -- M
+N 600,562,13 2 0116 -- N
+O 600,580,18 2 0117 -- O
+P 600,562 2 0120 -- P
+Q 600,580,138 2 0121 -- Q
+R 600,562 2 0122 -- R
+S 600,580,20 2 0123 -- S
+T 600,562 2 0124 -- T
+U 600,562,18 2 0125 -- U
+V 600,562,13 2 0126 -- V
+W 600,562,13 2 0127 -- W
+X 600,562 2 0130 -- X
+Y 600,562 2 0131 -- Y
+Z 600,562 2 0132 -- Z
+[ 600,622,108 2 0133 -- bracketleft
+lB "
+\ 600,629,80 2 0134 -- backslash
+rs "
+] 600,622,108 2 0135 -- bracketright
+rB "
+a^ 600,654 2 0136 -- circumflex
+^ "
+_ 600,0,125 0 0137 -- underscore
+` 600,562 2 0140 -- quoteleft
+oq "
+a 600,441,15 0 0141 -- a
+b 600,629,15 2 0142 -- b
+c 600,441,15 0 0143 -- c
+d 600,629,15 2 0144 -- d
+e 600,441,15 0 0145 -- e
+f 600,629 2 0146 -- f
+g 600,441,157 1 0147 -- g
+h 600,629 2 0150 -- h
+i 600,657 2 0151 -- i
+j 600,657,157 3 0152 -- j
+k 600,629 2 0153 -- k
+l 600,629 2 0154 -- l
+m 600,441 0 0155 -- m
+n 600,441 0 0156 -- n
+o 600,441,15 0 0157 -- o
+p 600,441,157 1 0160 -- p
+q 600,441,157 1 0161 -- q
+r 600,441 0 0162 -- r
+s 600,441,15 0 0163 -- s
+t 600,561,15 2 0164 -- t
+u 600,426,15 0 0165 -- u
+v 600,426,10 0 0166 -- v
+w 600,426,10 0 0167 -- w
+x 600,426 0 0170 -- x
+y 600,426,157 1 0171 -- y
+z 600,426 0 0172 -- z
+lC 600,622,108 2 0173 -- braceleft
+{ "
+ba 600,750,250 3 0174 -- bar
+| "
+rC 600,622,108 2 0175 -- braceright
+} "
+a~ 600,606 2 0176 -- tilde
+~ "
+bq 600,100,134 0 0200 -- quotesinglbase
+Fo 600,446 0 0201 -- guillemotleft
+char171 "
+Fc 600,446 0 0202 -- guillemotright
+char187 "
+bu 600,383 0 0203 -- bullet
+Fn 600,622,143 2 0204 -- florin
+f/ 600,665,57 2 0205 -- fraction
+%0 600,622,15 2 0206 -- perthousand
+dg 600,580,78 2 0207 -- dagger
+dd 600,580,78 2 0210 -- daggerdbl
+en 600,285 0 0211 -- endash
+em 600,285 0 0212 -- emdash
+fi 600,629 2 0214 -- fi
+fl 600,629 2 0215 -- fl
+.i 600,426 0 0220 -- dotlessi
+ga 600,672 2 0222 -- grave
+a" 600,672 2 0223 -- hungarumlaut
+a. 600,580 2 0224 -- dotaccent
+ab 600,609 2 0225 -- breve
+ah 600,669 2 0226 -- caron
+ao 600,627 2 0227 -- ring
+ho 600,0,151 0 0230 -- ogonek
+lq 600,562 2 0231 -- quotedblleft
+rq 600,562 2 0232 -- quotedblright
+oe 600,441,15 0 0233 -- oe
+/l 600,629 2 0234 -- lslash
+Bq 600,100,134 0 0235 -- quotedblbase
+OE 600,562 2 0236 -- OE
+/L 600,562 2 0237 -- Lslash
+r! 600,430,157 1 0241 -- exclamdown
+char161 "
+ct 600,614,49 2 0242 -- cent
+char162 "
+Po 600,611,21 2 0243 -- sterling
+char163 "
+Cs 600,506 0 0244 -- currency
+char164 "
+Ye 600,562 2 0245 -- yen
+char165 "
+bb 600,675,175 3 0246 -- brokenbar
+char166 "
+sc 600,580,78 2 0247 -- section
+char167 "
+ad 600,595 2 0250 -- dieresis
+char168 "
+co 600,580,18 2 0251 -- copyright
+char169 "
+Of 600,580 2 0252 -- ordfeminine
+char170 "
+fo 600,446 0 0253 -- guilsinglleft
+no 600,369 0 0254 -- logicalnot
+char172 "
+\- 600,283 0 0255 -- minus
+rg 600,580,18 2 0256 -- registered
+char174 "
+a- 600,565 2 0257 -- macron
+char175 "
+de 600,622 2 0260 -- degree
+char176 "
+char177 600,558 0 0261 -- plusminus
+S2 600,622 2 0262 -- twosuperior
+char178 "
+S3 600,622 2 0263 -- threesuperior
+char179 "
+aa 600,672 2 0264 -- acute
+char180 "
+char181 600,426,157 1 0265 -- mu
+ps 600,562,78 2 0266 -- paragraph
+char182 "
+char183 600,327 0 0267 -- periodcentered
+ac 600,10,151 0 0270 -- cedilla
+char184 "
+S1 600,622 2 0271 -- onesuperior
+char185 "
+Om 600,580 2 0272 -- ordmasculine
+char186 "
+fc 600,446 0 0273 -- guilsinglright
+14 600,665,57 2 0274 -- onequarter
+char188 "
+12 600,665,57 2 0275 -- onehalf
+char189 "
+34 600,666,56 2 0276 -- threequarters
+char190 "
+r? 600,430,157 1 0277 -- questiondown
+char191 "
+`A 600,793 2 0300 -- Agrave
+char192 "
+'A 600,793 2 0301 -- Aacute
+char193 "
+^A 600,775 2 0302 -- Acircumflex
+char194 "
+~A 600,732 2 0303 -- Atilde
+char195 "
+:A 600,731 2 0304 -- Adieresis
+char196 "
+oA 600,753 2 0305 -- Aring
+char197 "
+AE 600,562 2 0306 -- AE
+char198 "
+,C 600,580,151 2 0307 -- Ccedilla
+char199 "
+`E 600,793 2 0310 -- Egrave
+char200 "
+'E 600,793 2 0311 -- Eacute
+char201 "
+^E 600,775 2 0312 -- Ecircumflex
+char202 "
+:E 600,731 2 0313 -- Edieresis
+char203 "
+`I 600,793 2 0314 -- Igrave
+char204 "
+'I 600,793 2 0315 -- Iacute
+char205 "
+^I 600,775 2 0316 -- Icircumflex
+char206 "
+:I 600,731 2 0317 -- Idieresis
+char207 "
+-D 600,562 2 0320 -- Eth
+char208 "
+~N 600,732,13 2 0321 -- Ntilde
+char209 "
+`O 600,793,18 2 0322 -- Ograve
+char210 "
+'O 600,793,18 2 0323 -- Oacute
+char211 "
+^O 600,775,18 2 0324 -- Ocircumflex
+char212 "
+~O 600,732,18 2 0325 -- Otilde
+char213 "
+:O 600,731,18 2 0326 -- Odieresis
+char214 "
+char215 600,470 0 0327 -- multiply
+/O 600,629,80 2 0330 -- Oslash
+char216 "
+`U 600,793,18 2 0331 -- Ugrave
+char217 "
+'U 600,793,18 2 0332 -- Uacute
+char218 "
+^U 600,775,18 2 0333 -- Ucircumflex
+char219 "
+:U 600,731,18 2 0334 -- Udieresis
+char220 "
+'Y 600,793 2 0335 -- Yacute
+char221 "
+TP 600,562 2 0336 -- Thorn
+char222 "
+ss 600,629,15 2 0337 -- germandbls
+char223 "
+`a 600,672,15 2 0340 -- agrave
+char224 "
+'a 600,672,15 2 0341 -- aacute
+char225 "
+^a 600,654,15 2 0342 -- acircumflex
+char226 "
+~a 600,606,15 2 0343 -- atilde
+char227 "
+:a 600,595,15 2 0344 -- adieresis
+char228 "
+oa 600,627,15 2 0345 -- aring
+char229 "
+ae 600,441,15 0 0346 -- ae
+char230 "
+,c 600,441,151 0 0347 -- ccedilla
+char231 "
+`e 600,672,15 2 0350 -- egrave
+char232 "
+'e 600,672,15 2 0351 -- eacute
+char233 "
+^e 600,654,15 2 0352 -- ecircumflex
+char234 "
+:e 600,595,15 2 0353 -- edieresis
+char235 "
+`i 600,672 2 0354 -- igrave
+char236 "
+'i 600,672 2 0355 -- iacute
+char237 "
+^i 600,654 2 0356 -- icircumflex
+char238 "
+:i 600,595 2 0357 -- idieresis
+char239 "
+Sd 600,629,15 2 0360 -- eth
+char240 "
+~n 600,606 2 0361 -- ntilde
+char241 "
+`o 600,672,15 2 0362 -- ograve
+char242 "
+'o 600,672,15 2 0363 -- oacute
+char243 "
+^o 600,654,15 2 0364 -- ocircumflex
+char244 "
+~o 600,606,15 2 0365 -- otilde
+char245 "
+:o 600,595,15 2 0366 -- odieresis
+char246 "
+char247 600,467 0 0367 -- divide
+/o 600,506,80 0 0370 -- oslash
+char248 "
+`u 600,672,15 2 0371 -- ugrave
+char249 "
+'u 600,672,15 2 0372 -- uacute
+char250 "
+^u 600,654,15 2 0373 -- ucircumflex
+char251 "
+:u 600,595,15 2 0374 -- udieresis
+char252 "
+'y 600,672,157 3 0375 -- yacute
+char253 "
+Tp 600,629,157 3 0376 -- thorn
+char254 "
+:y 600,595,157 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/DESC.in b/font/devps/DESC.in
new file mode 100644
index 00000000..e9d26c84
--- /dev/null
+++ b/font/devps/DESC.in
@@ -0,0 +1,11 @@
+res 72000
+hor 1
+vert 1
+sizescale 1000
+unitwidth 1000
+sizes 1000-10000000 0
+styles R I B BI
+family T
+fonts 9 0 0 0 0 0 SS S ZD ZDR
+tcommand
+postpro grops
diff --git a/font/devps/HB b/font/devps/HB
new file mode 100644
index 00000000..cbdccf14
--- /dev/null
+++ b/font/devps/HB
@@ -0,0 +1,546 @@
+name HB
+internalname Helvetica-Bold
+spacewidth 278
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -30
+A w -30
+A v -40
+A u -30
+A Y -110
+A W -60
+A V -80
+A U -50
+A T -90
+A Q -40
+A O -40
+A G -50
+A C -40
+B U -10
+B A -30
+D . -30
+D , -30
+D Y -70
+D W -40
+D V -40
+D A -40
+F . -100
+F , -100
+F a -20
+F A -80
+J u -20
+J . -20
+J , -20
+J A -20
+K y -40
+K u -30
+K o -35
+K e -15
+K O -30
+L y -30
+L ' -140
+L rq -140
+L Y -120
+L W -80
+L V -110
+L T -90
+O . -40
+O , -40
+O Y -70
+O X -50
+O W -50
+O V -50
+O T -40
+O A -50
+P . -120
+P o -40
+P e -30
+P , -120
+P a -30
+P A -100
+Q . 20
+Q , 20
+Q U -10
+R Y -50
+R W -40
+R V -50
+R U -20
+R T -20
+R O -20
+T y -60
+T w -60
+T u -90
+T ; -40
+T r -80
+T . -80
+T o -80
+T - -120
+T hy -120
+T char173 -120
+T e -60
+T , -80
+T : -40
+T a -80
+T O -40
+T A -90
+U . -30
+U , -30
+U A -50
+V u -60
+V ; -40
+V . -120
+V o -90
+V - -80
+V hy -80
+V char173 -80
+V e -50
+V , -120
+V : -40
+V a -60
+V O -50
+V G -50
+V A -80
+W y -20
+W u -45
+W ; -10
+W . -80
+W o -60
+W - -40
+W hy -40
+W char173 -40
+W e -35
+W , -80
+W : -10
+W a -40
+W O -20
+W A -60
+Y u -100
+Y ; -50
+Y . -100
+Y o -100
+Y e -80
+Y , -100
+Y : -50
+Y a -90
+Y O -70
+Y A -110
+a y -20
+a w -15
+a v -15
+a g -10
+b y -20
+b v -20
+b u -20
+b l -10
+c y -10
+c l -20
+c k -20
+c h -10
+, ' -120
+, rq -120
+d y -15
+d w -15
+d v -15
+d d -10
+e y -15
+e x -15
+e w -15
+e v -15
+e . 20
+e , 10
+f ' 30
+f rq 30
+f . -10
+f o -20
+f e -10
+f , -10
+g g -10
+g e 10
+h y -20
+k o -15
+l y -15
+l w -15
+m y -30
+m u -20
+n y -20
+n v -40
+n u -10
+o y -20
+o x -30
+o w -15
+o v -20
+p y -15
+. ' -120
+. rq -120
+` ` -46
+` oq -46
+oq ` -46
+oq oq -46
+' v -20
+' s -60
+' r -40
+' ' -46
+' l -20
+' d -80
+r y 10
+r v 10
+r t 20
+r s -15
+r q -20
+r . -60
+r o -20
+r - -20
+r hy -20
+r char173 -20
+r g -15
+r d -20
+r , -60
+r c -20
+s w -15
+v . -80
+v o -30
+v , -80
+v a -20
+w . -40
+w o -20
+w , -40
+x e -10
+y . -80
+y o -25
+y e -10
+y , -80
+y a -30
+z e 10
+charset
+ha 584,698 2 0000 -- asciicircum
+ti 584,343 0 0001 -- asciitilde
+vS 667,936,19 2 0002 -- Scaron
+vZ 611,936 2 0003 -- Zcaron
+vs 556,750,14 2 0004 -- scaron
+vz 500,750 2 0005 -- zcaron
+:Y 667,915 2 0006 -- Ydieresis
+tm 1000,718 2 0007 -- trademark
+aq 238,718 2 0010 -- quotesingle
+space 278 0 0040
+! 333,718 2 0041 -- exclam
+" 474,718 2 0042 -- quotedbl
+# 556,698 2 0043 -- numbersign
+sh "
+$ 556,775,115 2 0044 -- dollar
+Do "
+% 889,710,19 2 0045 -- percent
+& 722,718,19 2 0046 -- ampersand
+' 278,718 2 0047 -- quoteright
+( 333,734,208 3 0050 -- parenleft
+) 333,734,208 3 0051 -- parenright
+* 389,718 2 0052 -- asterisk
++ 584,506 0 0053 -- plus
+, 278,146,168 0 0054 -- comma
+- 333,345 0 0055 -- hyphen
+hy "
+char173 "
+. 278,146 0 0056 -- period
+/ 278,737,19 2 0057 -- slash
+sl "
+0 556,710,19 2 0060 -- zero
+1 556,710 2 0061 -- one
+2 556,710 2 0062 -- two
+3 556,710,19 2 0063 -- three
+4 556,710 2 0064 -- four
+5 556,698,19 2 0065 -- five
+6 556,710,19 2 0066 -- six
+7 556,698 2 0067 -- seven
+8 556,710,19 2 0070 -- eight
+9 556,710,19 2 0071 -- nine
+: 333,512 0 0072 -- colon
+; 333,512,168 0 0073 -- semicolon
+< 584,514,8 0 0074 -- less
+= 584,419 0 0075 -- equal
+> 584,514,8 0 0076 -- greater
+? 611,727 2 0077 -- question
+@ 975,737,19 2 0100 -- at
+at "
+A 722,718 2 0101 -- A
+B 722,718 2 0102 -- B
+C 722,737,19 2 0103 -- C
+D 722,718 2 0104 -- D
+E 667,718 2 0105 -- E
+F 611,718 2 0106 -- F
+G 778,737,19 2 0107 -- G
+H 722,718 2 0110 -- H
+I 278,718 2 0111 -- I
+J 556,718,18 2 0112 -- J
+K 722,718 2 0113 -- K
+L 611,718 2 0114 -- L
+M 833,718 2 0115 -- M
+N 722,718 2 0116 -- N
+O 778,737,19 2 0117 -- O
+P 667,718 2 0120 -- P
+Q 778,737,52 2 0121 -- Q
+R 722,718 2 0122 -- R
+S 667,737,19 2 0123 -- S
+T 611,718 2 0124 -- T
+U 722,718,19 2 0125 -- U
+V 667,718 2 0126 -- V
+W 944,718 2 0127 -- W
+X 667,718 2 0130 -- X
+Y 667,718 2 0131 -- Y
+Z 611,718 2 0132 -- Z
+[ 333,722,196 2 0133 -- bracketleft
+lB "
+\ 278,737,19 2 0134 -- backslash
+rs "
+] 333,722,196 2 0135 -- bracketright
+rB "
+a^ 333,750 2 0136 -- circumflex
+^ "
+_ 556,0,125 0 0137 -- underscore
+` 278,727 2 0140 -- quoteleft
+oq "
+a 556,546,14 0 0141 -- a
+b 611,718,14 2 0142 -- b
+c 556,546,14 0 0143 -- c
+d 611,718,14 2 0144 -- d
+e 556,546,14 0 0145 -- e
+f 333,727 2 0146 -- f
+g 611,546,217 1 0147 -- g
+h 611,718 2 0150 -- h
+i 278,725 2 0151 -- i
+j 278,725,214 3 0152 -- j
+k 556,718 2 0153 -- k
+l 278,718 2 0154 -- l
+m 889,546 0 0155 -- m
+n 611,546 0 0156 -- n
+o 611,546,14 0 0157 -- o
+p 611,546,207 1 0160 -- p
+q 611,546,207 1 0161 -- q
+r 389,546 0 0162 -- r
+s 556,546,14 0 0163 -- s
+t 333,676,6 2 0164 -- t
+u 611,532,14 0 0165 -- u
+v 556,532 0 0166 -- v
+w 778,532 0 0167 -- w
+x 556,532 0 0170 -- x
+y 556,532,214 1 0171 -- y
+z 500,532 0 0172 -- z
+lC 389,722,196 2 0173 -- braceleft
+{ "
+ba 280,737,19 2 0174 -- bar
+| "
+rC 389,722,196 2 0175 -- braceright
+} "
+a~ 333,737 2 0176 -- tilde
+~ "
+bq 278,127,146 0 0200 -- quotesinglbase
+Fo 556,484 0 0201 -- guillemotleft
+char171 "
+Fc 556,484 0 0202 -- guillemotright
+char187 "
+bu 350,524 0 0203 -- bullet
+Fn 556,737,210 3 0204 -- florin
+f/ 167,710,19 2 0205 -- fraction
+%0 1000,710,19 2 0206 -- perthousand
+dg 556,718,171 2 0207 -- dagger
+dd 556,718,171 2 0210 -- daggerdbl
+en 556,333 0 0211 -- endash
+em 1000,333 0 0212 -- emdash
+fi 611,727 2 0214 -- fi
+fl 611,727 2 0215 -- fl
+.i 278,532 0 0220 -- dotlessi
+ga 333,750 2 0222 -- grave
+a" 333,750 2 0223 -- hungarumlaut
+a. 333,729 2 0224 -- dotaccent
+ab 333,750 2 0225 -- breve
+ah 333,750 2 0226 -- caron
+ao 333,776 2 0227 -- ring
+ho 333,0,228 1 0230 -- ogonek
+lq 500,727 2 0231 -- quotedblleft
+rq 500,718 2 0232 -- quotedblright
+oe 944,546,14 0 0233 -- oe
+/l 278,718 2 0234 -- lslash
+Bq 500,127,146 0 0235 -- quotedblbase
+OE 1000,737,19 2 0236 -- OE
+/L 611,718 2 0237 -- Lslash
+r! 333,532,186 0 0241 -- exclamdown
+char161 "
+ct 556,628,118 0 0242 -- cent
+char162 "
+Po 556,718,16 2 0243 -- sterling
+char163 "
+Cs 556,636 0 0244 -- currency
+char164 "
+Ye 556,698 2 0245 -- yen
+char165 "
+bb 280,737,19 2 0246 -- brokenbar
+char166 "
+sc 556,727,184 2 0247 -- section
+char167 "
+ad 333,729 2 0250 -- dieresis
+char168 "
+co 737,737,19 2 0251 -- copyright
+char169 "
+Of 370,737 2 0252 -- ordfeminine
+char170 "
+fo 333,484 0 0253 -- guilsinglleft
+no 584,419 0 0254 -- logicalnot
+char172 "
+\- 584,309 0 0255 -- minus
+rg 737,737,19 2 0256 -- registered
+char174 "
+a- 333,678 2 0257 -- macron
+char175 "
+de 400,712 2 0260 -- degree
+char176 "
+char177 584,506 0 0261 -- plusminus
+S2 333,710 2 0262 -- twosuperior
+char178 "
+S3 333,710 2 0263 -- threesuperior
+char179 "
+aa 333,750 2 0264 -- acute
+char180 "
+char181 611,532,207 1 0265 -- mu
+ps 556,700,191 2 0266 -- paragraph
+char182 "
+char183 278,334 0 0267 -- periodcentered
+ac 333,0,228 1 0270 -- cedilla
+char184 "
+S1 333,710 2 0271 -- onesuperior
+char185 "
+Om 365,737 2 0272 -- ordmasculine
+char186 "
+fc 333,484 0 0273 -- guilsinglright
+14 834,710,19 2 0274 -- onequarter
+char188 "
+12 834,710,19 2 0275 -- onehalf
+char189 "
+34 834,710,19 2 0276 -- threequarters
+char190 "
+r? 611,532,195 0 0277 -- questiondown
+char191 "
+`A 722,936 2 0300 -- Agrave
+char192 "
+'A 722,936 2 0301 -- Aacute
+char193 "
+^A 722,936 2 0302 -- Acircumflex
+char194 "
+~A 722,923 2 0303 -- Atilde
+char195 "
+:A 722,915 2 0304 -- Adieresis
+char196 "
+oA 722,962 2 0305 -- Aring
+char197 "
+AE 1000,718 2 0306 -- AE
+char198 "
+,C 722,737,228 3 0307 -- Ccedilla
+char199 "
+`E 667,936 2 0310 -- Egrave
+char200 "
+'E 667,936 2 0311 -- Eacute
+char201 "
+^E 667,936 2 0312 -- Ecircumflex
+char202 "
+:E 667,915 2 0313 -- Edieresis
+char203 "
+`I 278,936 2 0314 -- Igrave
+char204 "
+'I 278,936 2 0315 -- Iacute
+char205 "
+^I 278,936 2 0316 -- Icircumflex
+char206 "
+:I 278,915 2 0317 -- Idieresis
+char207 "
+-D 722,718 2 0320 -- Eth
+char208 "
+~N 722,923 2 0321 -- Ntilde
+char209 "
+`O 778,936,19 2 0322 -- Ograve
+char210 "
+'O 778,936,19 2 0323 -- Oacute
+char211 "
+^O 778,936,19 2 0324 -- Ocircumflex
+char212 "
+~O 778,923,19 2 0325 -- Otilde
+char213 "
+:O 778,915,19 2 0326 -- Odieresis
+char214 "
+char215 584,505 0 0327 -- multiply
+/O 778,745,27 2 0330 -- Oslash
+char216 "
+`U 722,936,19 2 0331 -- Ugrave
+char217 "
+'U 722,936,19 2 0332 -- Uacute
+char218 "
+^U 722,936,19 2 0333 -- Ucircumflex
+char219 "
+:U 722,915,19 2 0334 -- Udieresis
+char220 "
+'Y 667,936 2 0335 -- Yacute
+char221 "
+TP 667,718 2 0336 -- Thorn
+char222 "
+ss 611,731,14 2 0337 -- germandbls
+char223 "
+`a 556,750,14 2 0340 -- agrave
+char224 "
+'a 556,750,14 2 0341 -- aacute
+char225 "
+^a 556,750,14 2 0342 -- acircumflex
+char226 "
+~a 556,737,14 2 0343 -- atilde
+char227 "
+:a 556,729,14 2 0344 -- adieresis
+char228 "
+oa 556,776,14 2 0345 -- aring
+char229 "
+ae 889,546,14 0 0346 -- ae
+char230 "
+,c 556,546,228 1 0347 -- ccedilla
+char231 "
+`e 556,750,14 2 0350 -- egrave
+char232 "
+'e 556,750,14 2 0351 -- eacute
+char233 "
+^e 556,750,14 2 0352 -- ecircumflex
+char234 "
+:e 556,729,14 2 0353 -- edieresis
+char235 "
+`i 278,750 2 0354 -- igrave
+char236 "
+'i 278,750 2 0355 -- iacute
+char237 "
+^i 278,750 2 0356 -- icircumflex
+char238 "
+:i 278,729 2 0357 -- idieresis
+char239 "
+Sd 611,737,14 2 0360 -- eth
+char240 "
+~n 611,737 2 0361 -- ntilde
+char241 "
+`o 611,750,14 2 0362 -- ograve
+char242 "
+'o 611,750,14 2 0363 -- oacute
+char243 "
+^o 611,750,14 2 0364 -- ocircumflex
+char244 "
+~o 611,737,14 2 0365 -- otilde
+char245 "
+:o 611,729,14 2 0366 -- odieresis
+char246 "
+char247 584,548,42 0 0367 -- divide
+/o 611,560,29 0 0370 -- oslash
+char248 "
+`u 611,750,14 2 0371 -- ugrave
+char249 "
+'u 611,750,14 2 0372 -- uacute
+char250 "
+^u 611,750,14 2 0373 -- ucircumflex
+char251 "
+:u 611,729,14 2 0374 -- udieresis
+char252 "
+'y 556,750,214 3 0375 -- yacute
+char253 "
+Tp 611,718,208 3 0376 -- thorn
+char254 "
+:y 556,729,214 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/HBI b/font/devps/HBI
new file mode 100644
index 00000000..835db047
--- /dev/null
+++ b/font/devps/HBI
@@ -0,0 +1,547 @@
+name HBI
+internalname Helvetica-BoldOblique
+slant 12
+spacewidth 278
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -30
+A w -30
+A v -40
+A u -30
+A Y -110
+A W -60
+A V -80
+A U -50
+A T -90
+A Q -40
+A O -40
+A G -50
+A C -40
+B U -10
+B A -30
+D . -30
+D , -30
+D Y -70
+D W -40
+D V -40
+D A -40
+F . -100
+F , -100
+F a -20
+F A -80
+J u -20
+J . -20
+J , -20
+J A -20
+K y -40
+K u -30
+K o -35
+K e -15
+K O -30
+L y -30
+L ' -140
+L rq -140
+L Y -120
+L W -80
+L V -110
+L T -90
+O . -40
+O , -40
+O Y -70
+O X -50
+O W -50
+O V -50
+O T -40
+O A -50
+P . -120
+P o -40
+P e -30
+P , -120
+P a -30
+P A -100
+Q . 20
+Q , 20
+Q U -10
+R Y -50
+R W -40
+R V -50
+R U -20
+R T -20
+R O -20
+T y -60
+T w -60
+T u -90
+T ; -40
+T r -80
+T . -80
+T o -80
+T - -120
+T hy -120
+T char173 -120
+T e -60
+T , -80
+T : -40
+T a -80
+T O -40
+T A -90
+U . -30
+U , -30
+U A -50
+V u -60
+V ; -40
+V . -120
+V o -90
+V - -80
+V hy -80
+V char173 -80
+V e -50
+V , -120
+V : -40
+V a -60
+V O -50
+V G -50
+V A -80
+W y -20
+W u -45
+W ; -10
+W . -80
+W o -60
+W - -40
+W hy -40
+W char173 -40
+W e -35
+W , -80
+W : -10
+W a -40
+W O -20
+W A -60
+Y u -100
+Y ; -50
+Y . -100
+Y o -100
+Y e -80
+Y , -100
+Y : -50
+Y a -90
+Y O -70
+Y A -110
+a y -20
+a w -15
+a v -15
+a g -10
+b y -20
+b v -20
+b u -20
+b l -10
+c y -10
+c l -20
+c k -20
+c h -10
+, ' -120
+, rq -120
+d y -15
+d w -15
+d v -15
+d d -10
+e y -15
+e x -15
+e w -15
+e v -15
+e . 20
+e , 10
+f ' 30
+f rq 30
+f . -10
+f o -20
+f e -10
+f , -10
+g g -10
+g e 10
+h y -20
+k o -15
+l y -15
+l w -15
+m y -30
+m u -20
+n y -20
+n v -40
+n u -10
+o y -20
+o x -30
+o w -15
+o v -20
+p y -15
+. ' -120
+. rq -120
+` ` -46
+` oq -46
+oq ` -46
+oq oq -46
+' v -20
+' s -60
+' r -40
+' ' -46
+' l -20
+' d -80
+r y 10
+r v 10
+r t 20
+r s -15
+r q -20
+r . -60
+r o -20
+r - -20
+r hy -20
+r char173 -20
+r g -15
+r d -20
+r , -60
+r c -20
+s w -15
+v . -80
+v o -30
+v , -80
+v a -20
+w . -40
+w o -20
+w , -40
+x e -10
+y . -80
+y o -25
+y e -10
+y , -80
+y a -30
+z e 10
+charset
+ha 584,698,0,57,-81,57 2 0000 -- asciicircum
+ti 584,343,0,43,-65,43 0 0001 -- asciitilde
+vS 667,936,19,101,-31,90 2 0002 -- Scaron
+vZ 611,936,0,176,25,90 2 0003 -- Zcaron
+vs 556,750,14,108,-13,90 2 0004 -- scaron
+vz 500,750,0,136,30,90 2 0005 -- zcaron
+:Y 667,915,0,189,-118,90 2 0006 -- Ydieresis
+tm 1000,718,0,159,-129,90 2 0007 -- trademark
+aq 238,718,0,133,-115,90 2 0010 -- quotesingle
+space 278 0 0040
+! 333,718,0,114,-44,90 2 0041 -- exclam
+" 474,718,0,105,-143,90 2 0042 -- quotedbl
+# 556,698,0,138,-10,90 2 0043 -- numbersign
+sh "
+$ 556,775,115,116,-17,90 2 0044 -- dollar
+Do "
+% 889,710,19,62,-86,62 2 0045 -- percent
+& 722,718,19,60,-39,60 2 0046 -- ampersand
+' 278,718,0,134,-117,90 2 0047 -- quoteright
+( 333,734,208,187,-26,90 3 0050 -- parenleft
+) 333,734,208,86,75,86 3 0051 -- parenright
+* 389,718,0,142,-96,90 2 0052 -- asterisk
++ 584,506,0,76,-32,76 0 0053 -- plus
+, 278,146,168,17,22,17 0 0054 -- comma
+- 333,345,0,96,-23,90 0 0055 -- hyphen
+hy "
+char173 "
+. 278,146,0,17,-14,17 0 0056 -- period
+/ 278,737,19,240,87,90 2 0057 -- slash
+sl "
+0 556,710,19,111,-36,90 2 0060 -- zero
+1 556,710,0,23,-123,23 2 0061 -- one
+2 556,710,0,113,24,90 2 0062 -- two
+3 556,710,19,102,-15,90 2 0063 -- three
+4 556,710,0,92,-10,90 2 0064 -- four
+5 556,698,19,130,-14,90 2 0065 -- five
+6 556,710,19,113,-35,90 2 0066 -- six
+7 556,698,0,170,-75,90 2 0067 -- seven
+8 556,710,19,110,-19,90 2 0070 -- eight
+9 556,710,19,109,-28,90 2 0071 -- nine
+: 333,512,0,68,-42,68 0 0072 -- colon
+; 333,512,168,68,-6,68 0 0073 -- semicolon
+< 584,514,8,121,-32,90 0 0074 -- less
+= 584,419,0,99,-8,90 0 0075 -- equal
+> 584,514,8,75,14,75 0 0076 -- greater
+? 611,727,0,110,-115,90 2 0077 -- question
+@ 975,737,19,29,-136,29 2 0100 -- at
+at "
+A 722,718,0,30,30,30 2 0101 -- A
+B 722,718,0,92,-26,90 2 0102 -- B
+C 722,737,19,117,-57,90 2 0103 -- C
+D 722,718,0,105,-26,90 2 0104 -- D
+E 667,718,0,140,-26,90 2 0105 -- E
+F 611,718,0,179,-26,90 2 0106 -- F
+G 778,737,19,89,-58,89 2 0107 -- G
+H 722,718,0,132,-21,90 2 0110 -- H
+I 278,718,0,139,-14,90 2 0111 -- I
+J 556,718,18,131,-10,90 2 0112 -- J
+K 722,718,0,186,-37,90 2 0113 -- K
+L 611,718,0,50,-26,50 2 0114 -- L
+M 833,718,0,135,-19,90 2 0115 -- M
+N 722,718,0,135,-19,90 2 0116 -- N
+O 778,737,19,95,-57,90 2 0117 -- O
+P 667,718,0,121,-26,90 2 0120 -- P
+Q 778,737,52,95,-57,90 2 0121 -- Q
+R 722,718,0,106,-26,90 2 0122 -- R
+S 667,737,19,101,-31,90 2 0123 -- S
+T 611,718,0,190,-90,90 2 0124 -- T
+U 722,718,19,132,-66,90 2 0125 -- U
+V 667,718,0,184,-122,90 2 0126 -- V
+W 944,718,0,188,-119,90 2 0127 -- W
+X 667,718,0,174,36,90 2 0130 -- X
+Y 667,718,0,189,-118,90 2 0131 -- Y
+Z 611,718,0,176,25,90 2 0132 -- Z
+[ 333,722,196,179,29,90 2 0133 -- bracketleft
+lB "
+\ 278,737,19,79,-74,79 2 0134 -- backslash
+rs "
+] 333,722,196,140,68,90 2 0135 -- bracketright
+rB "
+a^ 333,750,0,188,-68,90 2 0136 -- circumflex
+^ "
+_ 556,0,125,34,77,34 0 0137 -- underscore
+` 278,727,0,133,-115,90 2 0140 -- quoteleft
+oq "
+a 556,546,14,77,-5,77 0 0141 -- a
+b 611,718,14,84,-11,84 2 0142 -- b
+c 556,546,14,93,-29,90 0 0143 -- c
+d 611,718,14,143,-32,90 2 0144 -- d
+e 556,546,14,87,-20,87 0 0145 -- e
+f 333,727,0,186,-37,90 2 0146 -- f
+g 611,546,217,105,12,90 1 0147 -- g
+h 611,718,0,68,-15,68 2 0150 -- h
+i 278,725,0,135,-19,90 2 0151 -- i
+j 278,725,214,135,92,90 3 0152 -- j
+k 556,718,0,164,-19,90 2 0153 -- k
+l 278,718,0,134,-19,90 2 0154 -- l
+m 889,546,0,70,-14,70 0 0155 -- m
+n 611,546,0,68,-15,68 0 0156 -- n
+o 611,546,14,82,-32,82 0 0157 -- o
+p 611,546,207,84,32,84 1 0160 -- p
+q 611,546,207,104,-30,90 1 0161 -- q
+r 389,546,0,150,-14,90 0 0162 -- r
+s 556,546,14,78,-13,78 0 0163 -- s
+t 333,676,6,139,-50,90 2 0164 -- t
+u 611,532,14,97,-48,90 0 0165 -- u
+v 556,532,0,150,-76,90 0 0166 -- v
+w 778,532,0,154,-73,90 0 0167 -- w
+x 556,532,0,142,35,90 0 0170 -- x
+y 556,532,214,146,8,90 1 0171 -- y
+z 500,532,0,133,30,90 0 0172 -- z
+lC 389,722,196,179,-44,90 2 0173 -- braceleft
+{ "
+ba 280,737,19,123,-30,90 2 0174 -- bar
+| "
+rC 389,722,196,68,68,68 2 0175 -- braceright
+} "
+a~ 333,737,0,224,-63,90 2 0176 -- tilde
+~ "
+bq 278,127,146,8,9,8 0 0200 -- quotesinglbase
+Fo 556,484,0,65,-85,65 0 0201 -- guillemotleft
+char171 "
+Fc 556,484,0,34,-54,34 0 0202 -- guillemotright
+char187 "
+bu 350,524,0,120,-33,90 0 0203 -- bullet
+Fn 556,737,210,163,100,90 3 0204 -- florin
+f/ 167,710,19,370,224,90 2 0205 -- fraction
+%0 1000,710,19,88,-26,88 2 0206 -- perthousand
+dg 556,718,171,120,-68,90 2 0207 -- dagger
+dd 556,718,171,122,4,90 2 0210 -- daggerdbl
+en 556,333,0,121,2,90 0 0211 -- endash
+em 1000,333,0,121,2,90 0 0212 -- emdash
+fi 611,727,0,135,-37,90 2 0214 -- fi
+fl 611,727,0,134,-37,90 2 0215 -- fl
+.i 278,532,0,94,-19,90 0 0220 -- dotlessi
+ga 333,750,0,70,-86,70 2 0222 -- grave
+a" 333,750,0,362,-87,90 2 0223 -- hungarumlaut
+a. 333,729,0,102,-185,90 2 0224 -- dotaccent
+ab 333,750,0,211,-106,90 2 0225 -- breve
+ah 333,750,0,219,-99,90 2 0226 -- caron
+ao 333,776,0,137,-150,90 2 0227 -- ring
+ho 333,0,228,0,9 1 0230 -- ogonek
+lq 500,727,0,138,-110,90 2 0231 -- quotedblleft
+rq 500,718,0,139,-112,90 2 0232 -- quotedblright
+oe 944,546,14,83,-32,83 0 0233 -- oe
+/l 278,718,0,179,10,90 2 0234 -- lslash
+Bq 500,127,146,13,14,13 0 0235 -- quotedblbase
+OE 1000,737,19,164,-49,90 2 0236 -- OE
+/L 611,718,0,50,16,50 2 0237 -- Lslash
+r! 333,532,186,70,0,70 0 0241 -- exclamdown
+char161 "
+ct 556,628,118,93,-29,90 0 0242 -- cent
+char162 "
+Po 556,718,16,129,0,90 2 0243 -- sterling
+char163 "
+Cs 556,636,0,174,23,90 0 0244 -- currency
+char164 "
+Ye 556,698,0,207,-10,90 2 0245 -- yen
+char165 "
+bb 280,737,19,123,-30,90 2 0246 -- brokenbar
+char166 "
+sc 556,727,184,92,-11,90 2 0247 -- section
+char167 "
+ad 333,729,0,199,-87,90 2 0250 -- dieresis
+char168 "
+co 737,737,19,148,-6,90 2 0251 -- copyright
+char169 "
+Of 370,737,0,145,-42,90 2 0252 -- ordfeminine
+char170 "
+fo 333,484,0,70,-80,70 0 0253 -- guilsinglleft
+no 584,419,0,99,-55,90 0 0254 -- logicalnot
+char172 "
+\- 584,309,0,76,-32,76 0 0255 -- minus
+rg 737,737,19,147,-5,90 2 0256 -- registered
+char174 "
+a- 333,678,0,200,-72,90 2 0257 -- macron
+char175 "
+de 400,712,0,117,-125,90 2 0260 -- degree
+char176 "
+char177 584,506,0,91,10,90 0 0261 -- plusminus
+S2 333,710,0,166,-19,90 2 0262 -- twosuperior
+char178 "
+S3 333,710,0,158,-41,90 2 0263 -- threesuperior
+char179 "
+aa 333,750,0,232,-186,90 2 0264 -- acute
+char180 "
+char181 611,532,207,97,28,90 1 0265 -- mu
+ps 556,700,191,182,-48,90 2 0266 -- paragraph
+char182 "
+char183 278,334,0,48,-60,48 0 0267 -- periodcentered
+ac 333,0,228,0,87 1 0270 -- cedilla
+char184 "
+S1 333,710,0,105,-98,90 2 0271 -- onesuperior
+char185 "
+Om 365,737,0,170,-42,90 2 0272 -- ordmasculine
+char186 "
+fc 333,484,0,39,-49,39 0 0273 -- guilsinglright
+14 834,710,19,22,-82,22 2 0274 -- onequarter
+char188 "
+12 834,710,19,74,-82,74 2 0275 -- onehalf
+char189 "
+34 834,710,19,55,-49,55 2 0276 -- threequarters
+char190 "
+r? 611,532,195,0,-3 0 0277 -- questiondown
+char191 "
+`A 722,936,0,30,30,30 2 0300 -- Agrave
+char192 "
+'A 722,936,0,78,30,78 2 0301 -- Aacute
+char193 "
+^A 722,936,0,34,30,34 2 0302 -- Acircumflex
+char194 "
+~A 722,923,0,69,30,69 2 0303 -- Atilde
+char195 "
+:A 722,915,0,44,30,44 2 0304 -- Adieresis
+char196 "
+oA 722,962,0,30,30,30 2 0305 -- Aring
+char197 "
+AE 1000,718,0,150,45,90 2 0306 -- AE
+char198 "
+,C 722,737,228,117,-57,90 3 0307 -- Ccedilla
+char199 "
+`E 667,936,0,140,-26,90 2 0310 -- Egrave
+char200 "
+'E 667,936,0,140,-26,90 2 0311 -- Eacute
+char201 "
+^E 667,936,0,140,-26,90 2 0312 -- Ecircumflex
+char202 "
+:E 667,915,0,140,-26,90 2 0313 -- Edieresis
+char203 "
+`I 278,936,0,139,-14,90 2 0314 -- Igrave
+char204 "
+'I 278,936,0,300,-14,90 2 0315 -- Iacute
+char205 "
+^I 278,936,0,256,-14,90 2 0316 -- Icircumflex
+char206 "
+:I 278,915,0,266,-14,90 2 0317 -- Idieresis
+char207 "
+-D 722,718,0,105,-12,90 2 0320 -- Eth
+char208 "
+~N 722,923,0,135,-19,90 2 0321 -- Ntilde
+char209 "
+`O 778,936,19,95,-57,90 2 0322 -- Ograve
+char210 "
+'O 778,936,19,95,-57,90 2 0323 -- Oacute
+char211 "
+^O 778,936,19,95,-57,90 2 0324 -- Ocircumflex
+char212 "
+~O 778,923,19,95,-57,90 2 0325 -- Otilde
+char213 "
+:O 778,915,19,95,-57,90 2 0326 -- Odieresis
+char214 "
+char215 584,505,0,101,-7,90 0 0327 -- multiply
+/O 778,745,27,166,15,90 2 0330 -- Oslash
+char216 "
+`U 722,936,19,132,-66,90 2 0331 -- Ugrave
+char217 "
+'U 722,936,19,132,-66,90 2 0332 -- Uacute
+char218 "
+^U 722,936,19,132,-66,90 2 0333 -- Ucircumflex
+char219 "
+:U 722,915,19,132,-66,90 2 0334 -- Udieresis
+char220 "
+'Y 667,936,0,189,-118,90 2 0335 -- Yacute
+char221 "
+TP 667,718,0,99,-26,90 2 0336 -- Thorn
+char222 "
+ss 611,731,14,96,-19,90 2 0337 -- germandbls
+char223 "
+`a 556,750,14,77,-5,77 2 0340 -- agrave
+char224 "
+'a 556,750,14,121,-5,90 2 0341 -- aacute
+char225 "
+^a 556,750,14,77,-5,77 2 0342 -- acircumflex
+char226 "
+~a 556,737,14,113,-5,90 2 0343 -- atilde
+char227 "
+:a 556,729,14,88,-5,88 2 0344 -- adieresis
+char228 "
+oa 556,776,14,77,-5,77 2 0345 -- aring
+char229 "
+ae 889,546,14,84,-6,84 0 0346 -- ae
+char230 "
+,c 556,546,228,93,-29,90 1 0347 -- ccedilla
+char231 "
+`e 556,750,14,87,-20,87 2 0350 -- egrave
+char232 "
+'e 556,750,14,121,-20,90 2 0351 -- eacute
+char233 "
+^e 556,750,14,87,-20,87 2 0352 -- ecircumflex
+char234 "
+:e 556,729,14,88,-20,88 2 0353 -- edieresis
+char235 "
+`i 278,750,0,98,-19,90 2 0354 -- igrave
+char236 "
+'i 278,750,0,260,-19,90 2 0355 -- iacute
+char237 "
+^i 278,750,0,216,-19,90 2 0356 -- icircumflex
+char238 "
+:i 278,729,0,227,-19,90 2 0357 -- idieresis
+char239 "
+Sd 611,737,14,109,-32,90 2 0360 -- eth
+char240 "
+~n 611,737,0,85,-15,85 2 0361 -- ntilde
+char241 "
+`o 611,750,14,82,-32,82 2 0362 -- ograve
+char242 "
+'o 611,750,14,93,-32,90 2 0363 -- oacute
+char243 "
+^o 611,750,14,82,-32,82 2 0364 -- ocircumflex
+char244 "
+~o 611,737,14,85,-32,85 2 0365 -- otilde
+char245 "
+:o 611,729,14,82,-32,82 2 0366 -- odieresis
+char246 "
+char247 584,548,42,76,-32,76 0 0367 -- divide
+/o 611,560,29,140,28,90 0 0370 -- oslash
+char248 "
+`u 611,750,14,97,-48,90 2 0371 -- ugrave
+char249 "
+'u 611,750,14,97,-48,90 2 0372 -- uacute
+char250 "
+^u 611,750,14,97,-48,90 2 0373 -- ucircumflex
+char251 "
+:u 611,729,14,97,-48,90 2 0374 -- udieresis
+char252 "
+'y 556,750,214,146,8,90 3 0375 -- yacute
+char253 "
+Tp 611,718,208,84,32,84 3 0376 -- thorn
+char254 "
+:y 556,729,214,146,8,90 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/HI b/font/devps/HI
new file mode 100644
index 00000000..8c87ce2e
--- /dev/null
+++ b/font/devps/HI
@@ -0,0 +1,617 @@
+name HI
+internalname Helvetica-Oblique
+slant 12
+spacewidth 278
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -40
+A w -40
+A v -40
+A u -30
+A Y -100
+A W -50
+A V -70
+A U -50
+A T -120
+A Q -30
+A O -30
+A G -30
+A C -30
+B . -20
+B , -20
+B U -10
+C . -30
+C , -30
+D . -70
+D , -70
+D Y -90
+D W -40
+D V -70
+D A -40
+F r -45
+F . -150
+F o -30
+F e -30
+F , -150
+F a -50
+F A -80
+J u -20
+J . -30
+J , -30
+J a -20
+J A -20
+K y -50
+K u -30
+K o -40
+K e -40
+K O -50
+L y -30
+L ' -160
+L rq -140
+L Y -140
+L W -70
+L V -110
+L T -110
+O . -40
+O , -40
+O Y -70
+O X -60
+O W -30
+O V -50
+O T -40
+O A -20
+P . -180
+P o -50
+P e -50
+P , -180
+P a -40
+P A -120
+Q U -10
+R Y -50
+R W -30
+R V -50
+R U -40
+R T -30
+R O -20
+S . -20
+S , -20
+T y -120
+T w -120
+T u -120
+T ; -20
+T r -120
+T . -120
+T o -120
+T - -140
+T hy -140
+T char173 -140
+T e -120
+T , -120
+T : -20
+T a -120
+T O -40
+T A -120
+U . -40
+U , -40
+U A -40
+V u -70
+V ; -40
+V . -125
+V o -80
+V - -80
+V hy -80
+V char173 -80
+V e -80
+V , -125
+V : -40
+V a -70
+V O -40
+V G -40
+V A -80
+W y -20
+W u -30
+W . -80
+W o -30
+W - -40
+W hy -40
+W char173 -40
+W e -30
+W , -80
+W a -40
+W O -20
+W A -50
+Y u -110
+Y ; -60
+Y . -140
+Y o -140
+Y i -20
+Y - -140
+Y hy -140
+Y char173 -140
+Y e -140
+Y , -140
+Y : -60
+Y a -140
+Y O -85
+Y A -110
+a y -30
+a w -20
+a v -20
+b y -20
+b v -20
+b u -20
+b . -40
+b l -20
+b , -40
+b b -10
+c k -20
+c , -15
+, ' -100
+, rq -100
+e y -20
+e x -30
+e w -20
+e v -30
+e . -15
+e , -15
+f ' 50
+f rq 60
+f . -30
+f o -30
+f e -30
+f .i -28
+f , -30
+f a -30
+g r -10
+h y -30
+k o -20
+k e -20
+m y -15
+m u -10
+n y -15
+n v -20
+n u -10
+o y -30
+o x -30
+o w -15
+o v -15
+o . -40
+o , -40
+/o z -55
+char248 z -55
+/o y -70
+char248 y -70
+/o x -85
+char248 x -85
+/o w -70
+char248 w -70
+/o v -70
+char248 v -70
+/o u -55
+char248 u -55
+/o t -55
+char248 t -55
+/o s -55
+char248 s -55
+/o r -55
+char248 r -55
+/o q -55
+char248 q -55
+/o . -95
+char248 . -95
+/o p -55
+char248 p -55
+/o o -55
+char248 o -55
+/o n -55
+char248 n -55
+/o m -55
+char248 m -55
+/o l -55
+char248 l -55
+/o k -55
+char248 k -55
+/o j -55
+char248 j -55
+/o i -55
+char248 i -55
+/o h -55
+char248 h -55
+/o g -55
+char248 g -55
+/o f -55
+char248 f -55
+/o e -55
+char248 e -55
+/o d -55
+char248 d -55
+/o , -95
+char248 , -95
+/o c -55
+char248 c -55
+/o b -55
+char248 b -55
+/o a -55
+char248 a -55
+p y -30
+p . -35
+p , -35
+. ' -100
+. rq -100
+` ` -57
+` oq -57
+oq ` -57
+oq oq -57
+' s -50
+' r -50
+' ' -57
+' d -50
+r y 30
+r v 30
+r u 15
+r t 40
+r ; 30
+r . -50
+r p 30
+r n 25
+r m 25
+r l 15
+r k 15
+r i 15
+r , -50
+r : 30
+r a -10
+s w -30
+s . -15
+s , -15
+v . -80
+v o -25
+v e -25
+v , -80
+v a -25
+w . -60
+w o -10
+w e -10
+w , -60
+w a -15
+x e -30
+y . -100
+y o -20
+y e -20
+y , -100
+y a -20
+z o -15
+z e -15
+charset
+ha 469,688,0,120,8,89 2 0000 -- asciicircum
+ti 584,326,0,46,-61,46 0 0001 -- asciitilde
+vS 667,929,19,96,-40,89 2 0002 -- Scaron
+vZ 611,929,0,180,27,89 2 0003 -- Zcaron
+vs 500,734,15,102,-13,89 2 0004 -- scaron
+vz 500,734,0,121,19,89 2 0005 -- zcaron
+:Y 667,901,0,189,-117,89 2 0006 -- Ydieresis
+tm 1000,718,0,106,-136,89 2 0007 -- trademark
+aq 191,718,0,144,-107,89 2 0010 -- quotesingle
+space 278 0 0040
+! 278,718,0,112,-40,89 2 0041 -- exclam
+" 355,718,0,133,-118,89 2 0042 -- quotedbl
+# 556,688,0,125,-23,89 2 0043 -- numbersign
+sh "
+$ 556,775,115,111,-19,89 2 0044 -- dollar
+Do "
+% 889,703,19,50,-97,50 2 0045 -- percent
+& 667,718,15,30,-27,30 2 0046 -- ampersand
+' 222,718,0,138,-101,89 2 0047 -- quoteright
+( 333,733,207,171,-58,89 3 0050 -- parenleft
+) 333,733,207,54,59,54 3 0051 -- parenright
+* 389,718,0,136,-115,89 2 0052 -- asterisk
++ 584,505,0,72,-35,72 0 0053 -- plus
+, 278,106,147,0,-6 0 0054 -- comma
+- 333,322,0,74,-43,74 0 0055 -- hyphen
+hy "
+char173 "
+. 278,106,0,0,-37 0 0056 -- period
+/ 278,737,19,224,71,89 2 0057 -- slash
+sl "
+0 556,703,19,102,-43,89 2 0060 -- zero
+1 556,703,0,2,-157,2 2 0061 -- one
+2 556,703,0,111,24,89 2 0062 -- two
+3 556,703,19,104,-25,89 2 0063 -- three
+4 556,703,0,70,-11,70 2 0064 -- four
+5 556,688,19,115,-18,89 2 0065 -- five
+6 556,703,19,109,-41,89 2 0066 -- six
+7 556,688,0,163,-87,89 2 0067 -- seven
+8 556,703,19,101,-24,89 2 0070 -- eight
+9 556,703,19,103,-32,89 2 0071 -- nine
+: 278,516,0,73,-37,73 0 0072 -- colon
+; 278,516,147,73,-6,73 0 0073 -- semicolon
+< 584,495,0,107,-44,89 0 0074 -- less
+= 584,390,0,94,-13,89 0 0075 -- equal
+> 584,495,0,63,0,63 0 0076 -- greater
+? 556,727,0,104,-111,89 2 0077 -- question
+@ 1015,737,19,0,-165 2 0100 -- at
+at "
+A 667,718,0,37,36,37 2 0101 -- A
+B 667,718,0,95,-24,89 2 0102 -- B
+C 722,737,19,110,-58,89 2 0103 -- C
+D 722,718,0,92,-31,89 2 0104 -- D
+E 667,718,0,145,-36,89 2 0105 -- E
+F 611,718,0,175,-36,89 2 0106 -- F
+G 778,737,19,71,-61,71 2 0107 -- G
+H 722,718,0,127,-27,89 2 0110 -- H
+I 278,718,0,113,-41,89 2 0111 -- I
+J 500,718,19,131,3,89 2 0112 -- J
+K 667,718,0,191,-26,89 2 0113 -- K
+L 556,718,0,49,-26,49 2 0114 -- L
+M 833,718,0,131,-23,89 2 0115 -- M
+N 722,718,0,127,-26,89 2 0116 -- N
+O 778,737,19,98,-55,89 2 0117 -- O
+P 667,718,0,120,-36,89 2 0120 -- P
+Q 778,737,56,98,-55,89 2 0121 -- Q
+R 722,718,0,101,-38,89 2 0122 -- R
+S 667,737,19,96,-40,89 2 0123 -- S
+T 611,718,0,189,-98,89 2 0124 -- T
+U 722,718,19,125,-73,89 2 0125 -- U
+V 667,718,0,183,-123,89 2 0126 -- V
+W 944,718,0,187,-119,89 2 0127 -- W
+X 667,718,0,173,31,89 2 0130 -- X
+Y 667,718,0,189,-117,89 2 0131 -- Y
+Z 611,718,0,180,27,89 2 0132 -- Z
+[ 278,722,196,175,29,89 2 0133 -- bracketleft
+lB "
+\ 278,737,19,63,-90,63 2 0134 -- backslash
+rs "
+] 278,722,196,140,64,89 2 0135 -- bracketright
+rB "
+a^ 333,734,0,155,-97,89 2 0136 -- circumflex
+^ "
+_ 556,0,125,34,77,34 0 0137 -- underscore
+` 222,725,0,151,-115,89 2 0140 -- quoteleft
+oq "
+a 556,538,15,53,-11,53 0 0141 -- a
+b 556,718,15,78,-8,78 2 0142 -- b
+c 500,538,15,103,-24,89 0 0143 -- c
+d 556,718,15,146,-34,89 2 0144 -- d
+e 556,538,15,72,-34,72 0 0145 -- e
+f 278,728,0,188,-36,89 2 0146 -- f
+g 556,538,220,104,8,89 1 0147 -- g
+h 556,718,0,67,-15,67 2 0150 -- h
+i 222,718,0,136,-17,89 2 0151 -- i
+j 222,718,210,136,110,89 3 0152 -- j
+k 500,718,0,150,-17,89 2 0153 -- k
+l 222,718,0,136,-17,89 2 0154 -- l
+m 833,538,0,69,-15,69 0 0155 -- m
+n 556,538,0,67,-15,67 0 0156 -- n
+o 556,538,14,79,-33,79 0 0157 -- o
+p 556,538,207,78,36,78 1 0160 -- p
+q 556,538,207,99,-34,89 1 0161 -- q
+r 333,538,0,163,-27,89 0 0162 -- r
+s 500,538,15,79,-13,79 0 0163 -- s
+t 278,669,7,140,-52,89 2 0164 -- t
+u 556,523,15,94,-44,89 0 0165 -- u
+v 500,523,0,153,-69,89 0 0166 -- v
+w 722,523,0,148,-75,89 0 0167 -- w
+x 500,523,0,144,39,89 0 0170 -- x
+y 500,523,214,150,35,89 1 0171 -- y
+z 500,523,0,121,19,89 0 0172 -- z
+lC 334,722,196,161,-42,89 2 0173 -- braceleft
+{ "
+ba 260,737,19,114,-40,89 2 0174 -- bar
+| "
+rC 334,722,196,70,50,70 2 0175 -- braceright
+} "
+a~ 333,722,0,207,-75,89 2 0176 -- tilde
+~ "
+bq 222,106,149,8,29,8 0 0200 -- quotesinglbase
+Fo 556,446,0,48,-96,48 0 0201 -- guillemotleft
+char171 "
+Fc 556,446,0,22,-70,22 0 0202 -- guillemotright
+char187 "
+bu 350,517,0,113,-41,89 0 0203 -- bullet
+Fn 556,737,207,148,102,89 3 0204 -- florin
+f/ 167,703,19,365,220,89 2 0205 -- fraction
+%0 1000,703,19,79,-38,79 2 0206 -- perthousand
+dg 556,718,159,116,-85,89 2 0207 -- dagger
+dd 556,718,159,117,-2,89 2 0210 -- daggerdbl
+en 556,313,0,117,-1,89 0 0211 -- endash
+em 1000,313,0,117,-1,89 0 0212 -- emdash
+fi 500,728,0,137,-36,89 2 0214 -- fi
+fl 500,728,0,135,-36,89 2 0215 -- fl
+.i 278,523,0,66,-45,66 0 0220 -- dotlessi
+ga 333,734,0,54,-120,54 2 0222 -- grave
+a" 333,734,0,282,-107,89 2 0223 -- hungarumlaut
+a. 333,706,0,79,-199,79 2 0224 -- dotaccent
+ab 333,731,0,193,-117,89 2 0225 -- breve
+ah 333,734,0,185,-127,89 2 0226 -- caron
+ao 333,756,0,119,-164,89 2 0227 -- ring
+ho 333,0,225,0,7 1 0230 -- ogonek
+lq 333,725,0,178,-88,89 2 0231 -- quotedblleft
+rq 333,718,0,165,-74,89 2 0232 -- quotedblright
+oe 944,538,15,70,-33,70 0 0233 -- oe
+/l 222,718,0,175,9,89 2 0234 -- lslash
+Bq 333,106,149,35,56,35 0 0235 -- quotedblbase
+OE 1000,737,19,166,-48,89 2 0236 -- OE
+/L 556,718,0,49,9,49 2 0237 -- Lslash
+r! 333,523,195,43,-27,43 0 0241 -- exclamdown
+char161 "
+ct 556,623,115,78,-45,78 0 0242 -- cent
+char162 "
+Po 556,718,16,128,1,89 2 0243 -- sterling
+char163 "
+Cs 556,603,0,140,-10,89 0 0244 -- currency
+char164 "
+Ye 556,688,0,193,-31,89 2 0245 -- yen
+char165 "
+bb 260,737,19,114,-40,89 2 0246 -- brokenbar
+char166 "
+sc 556,737,191,78,-26,78 2 0247 -- section
+char167 "
+ad 333,706,0,160,-118,89 2 0250 -- dieresis
+char168 "
+co 737,737,19,150,-4,89 2 0251 -- copyright
+char169 "
+Of 370,737,0,129,-50,89 2 0252 -- ordfeminine
+char170 "
+fo 333,446,0,57,-87,57 0 0253 -- guilsinglleft
+no 584,390,0,94,-56,89 0 0254 -- logicalnot
+char172 "
+\- 584,289,0,72,-35,72 0 0255 -- minus
+rg 737,737,19,150,-4,89 2 0256 -- registered
+char174 "
+a- 333,684,0,185,-93,89 2 0257 -- macron
+char175 "
+de 400,703,0,118,-119,89 2 0260 -- degree
+char176 "
+char177 584,506,0,84,11,84 0 0261 -- plusminus
+S2 333,703,0,166,-14,89 2 0262 -- twosuperior
+char178 "
+S3 333,703,0,153,-40,89 2 0263 -- threesuperior
+char179 "
+aa 333,734,0,192,-198,89 2 0264 -- acute
+char180 "
+char181 556,523,207,94,26,89 1 0265 -- mu
+ps 537,718,173,163,-76,89 2 0266 -- paragraph
+char182 "
+char183 278,315,0,29,-79,29 0 0267 -- periodcentered
+ac 333,0,225,0,48 1 0270 -- cedilla
+char184 "
+S1 333,703,0,88,-116,88 2 0271 -- onesuperior
+char185 "
+Om 365,737,0,153,-50,89 2 0272 -- ordmasculine
+char186 "
+fc 333,446,0,31,-61,31 0 0273 -- guilsinglright
+14 834,703,19,18,-100,18 2 0274 -- onequarter
+char188 "
+12 834,703,19,55,-64,55 2 0275 -- onehalf
+char189 "
+34 834,703,19,77,-80,77 2 0276 -- threequarters
+char190 "
+r? 611,525,201,0,-35 0 0277 -- questiondown
+char191 "
+`A 667,929,0,37,36,37 2 0300 -- Agrave
+char192 "
+'A 667,929,0,66,36,66 2 0301 -- Aacute
+char193 "
+^A 667,929,0,37,36,37 2 0302 -- Acircumflex
+char194 "
+~A 667,917,0,82,36,82 2 0303 -- Atilde
+char195 "
+:A 667,901,0,37,36,37 2 0304 -- Adieresis
+char196 "
+oA 667,931,0,37,36,37 2 0305 -- Aring
+char197 "
+AE 1000,718,0,147,42,89 2 0306 -- AE
+char198 "
+,C 722,737,225,110,-58,89 3 0307 -- Ccedilla
+char199 "
+`E 667,929,0,145,-36,89 2 0310 -- Egrave
+char200 "
+'E 667,929,0,145,-36,89 2 0311 -- Eacute
+char201 "
+^E 667,929,0,145,-36,89 2 0312 -- Ecircumflex
+char202 "
+:E 667,901,0,145,-36,89 2 0313 -- Edieresis
+char203 "
+`I 278,929,0,123,-41,89 2 0314 -- Igrave
+char204 "
+'I 278,929,0,261,-41,89 2 0315 -- Iacute
+char205 "
+^I 278,929,0,224,-41,89 2 0316 -- Icircumflex
+char206 "
+:I 278,901,0,230,-41,89 2 0317 -- Idieresis
+char207 "
+-D 722,718,0,92,-19,89 2 0320 -- Eth
+char208 "
+~N 722,917,0,127,-26,89 2 0321 -- Ntilde
+char209 "
+`O 778,929,19,98,-55,89 2 0322 -- Ograve
+char210 "
+'O 778,929,19,98,-55,89 2 0323 -- Oacute
+char211 "
+^O 778,929,19,98,-55,89 2 0324 -- Ocircumflex
+char212 "
+~O 778,917,19,98,-55,89 2 0325 -- Otilde
+char213 "
+:O 778,901,19,98,-55,89 2 0326 -- Odieresis
+char214 "
+char215 584,506,0,108,0,89 0 0327 -- multiply
+/O 778,737,19,162,7,89 2 0330 -- Oslash
+char216 "
+`U 722,929,19,125,-73,89 2 0331 -- Ugrave
+char217 "
+'U 722,929,19,125,-73,89 2 0332 -- Uacute
+char218 "
+^U 722,929,19,125,-73,89 2 0333 -- Ucircumflex
+char219 "
+:U 722,901,19,125,-73,89 2 0334 -- Udieresis
+char220 "
+'Y 667,929,0,189,-117,89 2 0335 -- Yacute
+char221 "
+TP 667,718,0,95,-36,89 2 0336 -- Thorn
+char222 "
+ss 611,728,15,97,-17,89 2 0337 -- germandbls
+char223 "
+`a 556,734,15,53,-11,53 2 0340 -- agrave
+char224 "
+'a 556,734,15,81,-11,81 2 0341 -- aacute
+char225 "
+^a 556,734,15,53,-11,53 2 0342 -- acircumflex
+char226 "
+~a 556,722,15,86,-11,86 2 0343 -- atilde
+char227 "
+:a 556,706,15,53,-11,53 2 0344 -- adieresis
+char228 "
+oa 556,756,15,53,-11,53 2 0345 -- aring
+char229 "
+ae 889,538,15,70,-11,70 0 0346 -- ae
+char230 "
+,c 500,538,225,103,-24,89 1 0347 -- ccedilla
+char231 "
+`e 556,734,15,72,-34,72 2 0350 -- egrave
+char232 "
+'e 556,734,15,81,-34,81 2 0351 -- eacute
+char233 "
+^e 556,734,15,72,-34,72 2 0352 -- ecircumflex
+char234 "
+:e 556,706,15,72,-34,72 2 0353 -- edieresis
+char235 "
+`i 278,734,0,82,-45,82 2 0354 -- igrave
+char236 "
+'i 278,734,0,220,-45,89 2 0355 -- iacute
+char237 "
+^i 278,734,0,183,-45,89 2 0356 -- icircumflex
+char238 "
+:i 278,706,0,188,-45,89 2 0357 -- idieresis
+char239 "
+Sd 556,737,15,111,-31,89 2 0360 -- eth
+char240 "
+~n 556,722,0,86,-15,86 2 0361 -- ntilde
+char241 "
+`o 556,734,14,79,-33,79 2 0362 -- ograve
+char242 "
+'o 556,734,14,81,-33,81 2 0363 -- oacute
+char243 "
+^o 556,734,14,79,-33,79 2 0364 -- ocircumflex
+char244 "
+~o 556,722,14,96,-33,89 2 0365 -- otilde
+char245 "
+:o 556,706,14,79,-33,79 2 0366 -- odieresis
+char246 "
+char247 584,524,19,72,-35,72 0 0367 -- divide
+/o 611,545,22,86,21,86 0 0370 -- oslash
+char248 "
+`u 556,734,15,94,-44,89 2 0371 -- ugrave
+char249 "
+'u 556,734,15,94,-44,89 2 0372 -- uacute
+char250 "
+^u 556,734,15,94,-44,89 2 0373 -- ucircumflex
+char251 "
+:u 556,706,15,94,-44,89 2 0374 -- udieresis
+char252 "
+'y 500,734,214,150,35,89 3 0375 -- yacute
+char253 "
+Tp 556,718,207,78,36,78 3 0376 -- thorn
+char254 "
+:y 500,706,214,150,35,89 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/HNB b/font/devps/HNB
new file mode 100644
index 00000000..2d55cfb7
--- /dev/null
+++ b/font/devps/HNB
@@ -0,0 +1,546 @@
+name HNB
+internalname Helvetica-Narrow-Bold
+spacewidth 228
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -24
+A w -24
+A v -32
+A u -24
+A Y -89
+A W -48
+A V -65
+A U -40
+A T -73
+A Q -32
+A O -32
+A G -40
+A C -32
+B U -7
+B A -24
+D . -24
+D , -24
+D Y -56
+D W -32
+D V -32
+D A -32
+F . -81
+F , -81
+F a -15
+F A -65
+J u -15
+J . -15
+J , -15
+J A -15
+K y -32
+K u -24
+K o -28
+K e -11
+K O -24
+L y -24
+L ' -114
+L rq -114
+L Y -97
+L W -65
+L V -89
+L T -73
+O . -32
+O , -32
+O Y -56
+O X -40
+O W -40
+O V -40
+O T -32
+O A -40
+P . -97
+P o -32
+P e -24
+P , -97
+P a -24
+P A -81
+Q . 16
+Q , 16
+Q U -7
+R Y -40
+R W -32
+R V -40
+R U -15
+R T -15
+R O -15
+T y -48
+T w -48
+T u -73
+T ; -32
+T r -65
+T . -65
+T o -65
+T - -97
+T hy -97
+T char173 -97
+T e -48
+T , -65
+T : -32
+T a -65
+T O -32
+T A -73
+U . -24
+U , -24
+U A -40
+V u -48
+V ; -32
+V . -97
+V o -73
+V - -65
+V hy -65
+V char173 -65
+V e -40
+V , -97
+V : -32
+V a -48
+V O -40
+V G -40
+V A -65
+W y -15
+W u -36
+W ; -7
+W . -65
+W o -48
+W - -32
+W hy -32
+W char173 -32
+W e -28
+W , -65
+W : -7
+W a -32
+W O -15
+W A -48
+Y u -81
+Y ; -40
+Y . -81
+Y o -81
+Y e -65
+Y , -81
+Y : -40
+Y a -73
+Y O -56
+Y A -89
+a y -15
+a w -11
+a v -11
+a g -7
+b y -15
+b v -15
+b u -15
+b l -7
+c y -7
+c l -15
+c k -15
+c h -7
+, ' -97
+, rq -97
+d y -11
+d w -11
+d v -11
+d d -7
+e y -11
+e x -11
+e w -11
+e v -11
+e . 16
+e , 8
+f ' 25
+f rq 25
+f . -7
+f o -15
+f e -7
+f , -7
+g g -7
+g e 8
+h y -15
+k o -11
+l y -11
+l w -11
+m y -24
+m u -15
+n y -15
+n v -32
+n u -7
+o y -15
+o x -24
+o w -11
+o v -15
+p y -11
+. ' -97
+. rq -97
+` ` -37
+` oq -37
+oq ` -37
+oq oq -37
+' v -15
+' s -48
+' r -32
+' ' -37
+' l -15
+' d -65
+r y 8
+r v 8
+r t 16
+r s -11
+r q -15
+r . -48
+r o -15
+r - -15
+r hy -15
+r char173 -15
+r g -11
+r d -15
+r , -48
+r c -15
+s w -11
+v . -65
+v o -24
+v , -65
+v a -15
+w . -32
+w o -15
+w , -32
+x e -7
+y . -65
+y o -20
+y e -7
+y , -65
+y a -24
+z e 8
+charset
+ha 479,698 2 0000 -- asciicircum
+ti 479,343 0 0001 -- asciitilde
+vS 547,936,19 2 0002 -- Scaron
+vZ 501,936 2 0003 -- Zcaron
+vs 456,750,14 2 0004 -- scaron
+vz 410,750 2 0005 -- zcaron
+:Y 547,915 2 0006 -- Ydieresis
+tm 820,718 2 0007 -- trademark
+aq 195,718 2 0010 -- quotesingle
+space 228 0 0040
+! 273,718 2 0041 -- exclam
+" 389,718 2 0042 -- quotedbl
+# 456,698 2 0043 -- numbersign
+sh "
+$ 456,775,115 2 0044 -- dollar
+Do "
+% 729,710,19 2 0045 -- percent
+& 592,718,19 2 0046 -- ampersand
+' 228,718 2 0047 -- quoteright
+( 273,734,208 3 0050 -- parenleft
+) 273,734,208 3 0051 -- parenright
+* 319,718 2 0052 -- asterisk
++ 479,506 0 0053 -- plus
+, 228,146,168 0 0054 -- comma
+- 273,345 0 0055 -- hyphen
+hy "
+char173 "
+. 228,146 0 0056 -- period
+/ 228,737,19 2 0057 -- slash
+sl "
+0 456,710,19 2 0060 -- zero
+1 456,710 2 0061 -- one
+2 456,710 2 0062 -- two
+3 456,710,19 2 0063 -- three
+4 456,710 2 0064 -- four
+5 456,698,19 2 0065 -- five
+6 456,710,19 2 0066 -- six
+7 456,698 2 0067 -- seven
+8 456,710,19 2 0070 -- eight
+9 456,710,19 2 0071 -- nine
+: 273,512 0 0072 -- colon
+; 273,512,168 0 0073 -- semicolon
+< 479,514,8 0 0074 -- less
+= 479,419 0 0075 -- equal
+> 479,514,8 0 0076 -- greater
+? 501,727 2 0077 -- question
+@ 800,737,19 2 0100 -- at
+at "
+A 592,718 2 0101 -- A
+B 592,718 2 0102 -- B
+C 592,737,19 2 0103 -- C
+D 592,718 2 0104 -- D
+E 547,718 2 0105 -- E
+F 501,718 2 0106 -- F
+G 638,737,19 2 0107 -- G
+H 592,718 2 0110 -- H
+I 228,718 2 0111 -- I
+J 456,718,18 2 0112 -- J
+K 592,718 2 0113 -- K
+L 501,718 2 0114 -- L
+M 683,718 2 0115 -- M
+N 592,718 2 0116 -- N
+O 638,737,19 2 0117 -- O
+P 547,718 2 0120 -- P
+Q 638,737,52 2 0121 -- Q
+R 592,718 2 0122 -- R
+S 547,737,19 2 0123 -- S
+T 501,718 2 0124 -- T
+U 592,718,19 2 0125 -- U
+V 547,718 2 0126 -- V
+W 774,718 2 0127 -- W
+X 547,718 2 0130 -- X
+Y 547,718 2 0131 -- Y
+Z 501,718 2 0132 -- Z
+[ 273,722,196 2 0133 -- bracketleft
+lB "
+\ 228,737,19 2 0134 -- backslash
+rs "
+] 273,722,196 2 0135 -- bracketright
+rB "
+a^ 273,750 2 0136 -- circumflex
+^ "
+_ 456,0,125 0 0137 -- underscore
+` 228,727 2 0140 -- quoteleft
+oq "
+a 456,546,14 0 0141 -- a
+b 501,718,14 2 0142 -- b
+c 456,546,14 0 0143 -- c
+d 501,718,14 2 0144 -- d
+e 456,546,14 0 0145 -- e
+f 273,727 2 0146 -- f
+g 501,546,217 1 0147 -- g
+h 501,718 2 0150 -- h
+i 228,725 2 0151 -- i
+j 228,725,214 3 0152 -- j
+k 456,718 2 0153 -- k
+l 228,718 2 0154 -- l
+m 729,546 0 0155 -- m
+n 501,546 0 0156 -- n
+o 501,546,14 0 0157 -- o
+p 501,546,207 1 0160 -- p
+q 501,546,207 1 0161 -- q
+r 319,546 0 0162 -- r
+s 456,546,14 0 0163 -- s
+t 273,676,6 2 0164 -- t
+u 501,532,14 0 0165 -- u
+v 456,532 0 0166 -- v
+w 638,532 0 0167 -- w
+x 456,532 0 0170 -- x
+y 456,532,214 1 0171 -- y
+z 410,532 0 0172 -- z
+lC 319,722,196 2 0173 -- braceleft
+{ "
+ba 230,737,19 2 0174 -- bar
+| "
+rC 319,722,196 2 0175 -- braceright
+} "
+a~ 273,737 2 0176 -- tilde
+~ "
+bq 228,127,146 0 0200 -- quotesinglbase
+Fo 456,484 0 0201 -- guillemotleft
+char171 "
+Fc 456,484 0 0202 -- guillemotright
+char187 "
+bu 287,524 0 0203 -- bullet
+Fn 456,737,210 3 0204 -- florin
+f/ 137,710,19 2 0205 -- fraction
+%0 820,710,19 2 0206 -- perthousand
+dg 456,718,171 2 0207 -- dagger
+dd 456,718,171 2 0210 -- daggerdbl
+en 456,333 0 0211 -- endash
+em 820,333 0 0212 -- emdash
+fi 501,727 2 0214 -- fi
+fl 501,727 2 0215 -- fl
+.i 228,532 0 0220 -- dotlessi
+ga 273,750 2 0222 -- grave
+a" 273,750 2 0223 -- hungarumlaut
+a. 273,729 2 0224 -- dotaccent
+ab 273,750 2 0225 -- breve
+ah 273,750 2 0226 -- caron
+ao 273,776 2 0227 -- ring
+ho 273,0,228 1 0230 -- ogonek
+lq 410,727 2 0231 -- quotedblleft
+rq 410,718 2 0232 -- quotedblright
+oe 774,546,14 0 0233 -- oe
+/l 228,718 2 0234 -- lslash
+Bq 410,127,146 0 0235 -- quotedblbase
+OE 820,737,19 2 0236 -- OE
+/L 501,718 2 0237 -- Lslash
+r! 273,532,186 0 0241 -- exclamdown
+char161 "
+ct 456,628,118 0 0242 -- cent
+char162 "
+Po 456,718,16 2 0243 -- sterling
+char163 "
+Cs 456,636 0 0244 -- currency
+char164 "
+Ye 456,698 2 0245 -- yen
+char165 "
+bb 230,737,19 2 0246 -- brokenbar
+char166 "
+sc 456,727,184 2 0247 -- section
+char167 "
+ad 273,729 2 0250 -- dieresis
+char168 "
+co 604,737,19 2 0251 -- copyright
+char169 "
+Of 303,737 2 0252 -- ordfeminine
+char170 "
+fo 273,484 0 0253 -- guilsinglleft
+no 479,419 0 0254 -- logicalnot
+char172 "
+\- 479,309 0 0255 -- minus
+rg 604,737,19 2 0256 -- registered
+char174 "
+a- 273,678 2 0257 -- macron
+char175 "
+de 328,712 2 0260 -- degree
+char176 "
+char177 479,506 0 0261 -- plusminus
+S2 273,710 2 0262 -- twosuperior
+char178 "
+S3 273,710 2 0263 -- threesuperior
+char179 "
+aa 273,750 2 0264 -- acute
+char180 "
+char181 501,532,207 1 0265 -- mu
+ps 456,700,191 2 0266 -- paragraph
+char182 "
+char183 228,334 0 0267 -- periodcentered
+ac 273,0,228 1 0270 -- cedilla
+char184 "
+S1 273,710 2 0271 -- onesuperior
+char185 "
+Om 299,737 2 0272 -- ordmasculine
+char186 "
+fc 273,484 0 0273 -- guilsinglright
+14 684,710,19 2 0274 -- onequarter
+char188 "
+12 684,710,19 2 0275 -- onehalf
+char189 "
+34 684,710,19 2 0276 -- threequarters
+char190 "
+r? 501,532,195 0 0277 -- questiondown
+char191 "
+`A 592,936 2 0300 -- Agrave
+char192 "
+'A 592,936 2 0301 -- Aacute
+char193 "
+^A 592,936 2 0302 -- Acircumflex
+char194 "
+~A 592,923 2 0303 -- Atilde
+char195 "
+:A 592,915 2 0304 -- Adieresis
+char196 "
+oA 592,962 2 0305 -- Aring
+char197 "
+AE 820,718 2 0306 -- AE
+char198 "
+,C 592,737,228 3 0307 -- Ccedilla
+char199 "
+`E 547,936 2 0310 -- Egrave
+char200 "
+'E 547,936 2 0311 -- Eacute
+char201 "
+^E 547,936 2 0312 -- Ecircumflex
+char202 "
+:E 547,915 2 0313 -- Edieresis
+char203 "
+`I 228,936 2 0314 -- Igrave
+char204 "
+'I 228,936 2 0315 -- Iacute
+char205 "
+^I 228,936 2 0316 -- Icircumflex
+char206 "
+:I 228,915 2 0317 -- Idieresis
+char207 "
+-D 592,718 2 0320 -- Eth
+char208 "
+~N 592,923 2 0321 -- Ntilde
+char209 "
+`O 638,936,19 2 0322 -- Ograve
+char210 "
+'O 638,936,19 2 0323 -- Oacute
+char211 "
+^O 638,936,19 2 0324 -- Ocircumflex
+char212 "
+~O 638,923,19 2 0325 -- Otilde
+char213 "
+:O 638,915,19 2 0326 -- Odieresis
+char214 "
+char215 479,505 0 0327 -- multiply
+/O 638,745,27 2 0330 -- Oslash
+char216 "
+`U 592,936,19 2 0331 -- Ugrave
+char217 "
+'U 592,936,19 2 0332 -- Uacute
+char218 "
+^U 592,936,19 2 0333 -- Ucircumflex
+char219 "
+:U 592,915,19 2 0334 -- Udieresis
+char220 "
+'Y 547,936 2 0335 -- Yacute
+char221 "
+TP 547,718 2 0336 -- Thorn
+char222 "
+ss 501,731,14 2 0337 -- germandbls
+char223 "
+`a 456,750,14 2 0340 -- agrave
+char224 "
+'a 456,750,14 2 0341 -- aacute
+char225 "
+^a 456,750,14 2 0342 -- acircumflex
+char226 "
+~a 456,737,14 2 0343 -- atilde
+char227 "
+:a 456,729,14 2 0344 -- adieresis
+char228 "
+oa 456,776,14 2 0345 -- aring
+char229 "
+ae 729,546,14 0 0346 -- ae
+char230 "
+,c 456,546,228 1 0347 -- ccedilla
+char231 "
+`e 456,750,14 2 0350 -- egrave
+char232 "
+'e 456,750,14 2 0351 -- eacute
+char233 "
+^e 456,750,14 2 0352 -- ecircumflex
+char234 "
+:e 456,729,14 2 0353 -- edieresis
+char235 "
+`i 228,750 2 0354 -- igrave
+char236 "
+'i 228,750 2 0355 -- iacute
+char237 "
+^i 228,750 2 0356 -- icircumflex
+char238 "
+:i 228,729 2 0357 -- idieresis
+char239 "
+Sd 501,737,14 2 0360 -- eth
+char240 "
+~n 501,737 2 0361 -- ntilde
+char241 "
+`o 501,750,14 2 0362 -- ograve
+char242 "
+'o 501,750,14 2 0363 -- oacute
+char243 "
+^o 501,750,14 2 0364 -- ocircumflex
+char244 "
+~o 501,737,14 2 0365 -- otilde
+char245 "
+:o 501,729,14 2 0366 -- odieresis
+char246 "
+char247 479,548,42 0 0367 -- divide
+/o 501,560,29 0 0370 -- oslash
+char248 "
+`u 501,750,14 2 0371 -- ugrave
+char249 "
+'u 501,750,14 2 0372 -- uacute
+char250 "
+^u 501,750,14 2 0373 -- ucircumflex
+char251 "
+:u 501,729,14 2 0374 -- udieresis
+char252 "
+'y 456,750,214 3 0375 -- yacute
+char253 "
+Tp 501,718,208 3 0376 -- thorn
+char254 "
+:y 456,729,214 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/HNBI b/font/devps/HNBI
new file mode 100644
index 00000000..7ad1fdbd
--- /dev/null
+++ b/font/devps/HNBI
@@ -0,0 +1,547 @@
+name HNBI
+internalname Helvetica-Narrow-BoldOblique
+slant 12
+spacewidth 228
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -30
+A w -30
+A v -40
+A u -30
+A Y -110
+A W -60
+A V -80
+A U -50
+A T -90
+A Q -40
+A O -40
+A G -50
+A C -40
+B U -10
+B A -30
+D . -30
+D , -30
+D Y -70
+D W -40
+D V -40
+D A -40
+F . -100
+F , -100
+F a -20
+F A -80
+J u -20
+J . -20
+J , -20
+J A -20
+K y -40
+K u -30
+K o -35
+K e -15
+K O -30
+L y -30
+L ' -140
+L rq -140
+L Y -120
+L W -80
+L V -110
+L T -90
+O . -40
+O , -40
+O Y -70
+O X -50
+O W -50
+O V -50
+O T -40
+O A -50
+P . -120
+P o -40
+P e -30
+P , -120
+P a -30
+P A -100
+Q . 20
+Q , 20
+Q U -10
+R Y -50
+R W -40
+R V -50
+R U -20
+R T -20
+R O -20
+T y -60
+T w -60
+T u -90
+T ; -40
+T r -80
+T . -80
+T o -80
+T - -120
+T hy -120
+T char173 -120
+T e -60
+T , -80
+T : -40
+T a -80
+T O -40
+T A -90
+U . -30
+U , -30
+U A -50
+V u -60
+V ; -40
+V . -120
+V o -90
+V - -80
+V hy -80
+V char173 -80
+V e -50
+V , -120
+V : -40
+V a -60
+V O -50
+V G -50
+V A -80
+W y -20
+W u -45
+W ; -10
+W . -80
+W o -60
+W - -40
+W hy -40
+W char173 -40
+W e -35
+W , -80
+W : -10
+W a -40
+W O -20
+W A -60
+Y u -100
+Y ; -50
+Y . -100
+Y o -100
+Y e -80
+Y , -100
+Y : -50
+Y a -90
+Y O -70
+Y A -110
+a y -20
+a w -15
+a v -15
+a g -10
+b y -20
+b v -20
+b u -20
+b l -10
+c y -10
+c l -20
+c k -20
+c h -10
+, ' -120
+, rq -120
+d y -15
+d w -15
+d v -15
+d d -10
+e y -15
+e x -15
+e w -15
+e v -15
+e . 20
+e , 10
+f ' 30
+f rq 30
+f . -10
+f o -20
+f e -10
+f , -10
+g g -10
+g e 10
+h y -20
+k o -15
+l y -15
+l w -15
+m y -30
+m u -20
+n y -20
+n v -40
+n u -10
+o y -20
+o x -30
+o w -15
+o v -20
+p y -15
+. ' -120
+. rq -120
+` ` -46
+` oq -46
+oq ` -46
+oq oq -46
+' v -20
+' s -60
+' r -40
+' ' -46
+' l -20
+' d -80
+r y 10
+r v 10
+r t 20
+r s -15
+r q -20
+r . -60
+r o -20
+r - -20
+r hy -20
+r char173 -20
+r g -15
+r d -20
+r , -60
+r c -20
+s w -15
+v . -80
+v o -30
+v , -80
+v a -20
+w . -40
+w o -20
+w , -40
+x e -10
+y . -80
+y o -25
+y e -10
+y , -80
+y a -30
+z e 10
+charset
+ha 479,698,0,55,-57,55 2 0000 -- asciicircum
+ti 479,343,0,44,-44,44 0 0001 -- asciitilde
+vS 547,936,19,91,-16,90 2 0002 -- Scaron
+vZ 501,936,0,153,30,90 2 0003 -- Zcaron
+vs 456,750,14,98,-2,90 2 0004 -- scaron
+vz 410,750,0,121,34,90 2 0005 -- zcaron
+:Y 547,915,0,164,-87,90 2 0006 -- Ydieresis
+tm 820,718,0,139,-96,90 2 0007 -- trademark
+aq 195,718,0,118,-85,90 2 0010 -- quotesingle
+space 228 0 0040
+! 273,718,0,102,-27,90 2 0041 -- exclam
+" 389,718,0,94,-108,90 2 0042 -- quotedbl
+# 456,698,0,122,1,90 2 0043 -- numbersign
+sh "
+$ 456,775,115,104,-5,90 2 0044 -- dollar
+Do "
+% 729,710,19,60,-62,60 2 0045 -- percent
+& 592,718,19,58,-23,58 2 0046 -- ampersand
+' 228,718,0,119,-87,90 2 0047 -- quoteright
+( 273,734,208,162,-12,90 3 0050 -- parenleft
+) 273,734,208,79,71,79 3 0051 -- parenright
+* 319,718,0,125,-70,90 2 0052 -- asterisk
++ 479,506,0,71,-17,71 0 0053 -- plus
+, 228,146,168,23,27,23 0 0054 -- comma
+- 273,345,0,88,-10,88 0 0055 -- hyphen
+hy "
+char173 "
+. 228,146,0,23,-2,23 0 0056 -- period
+/ 228,737,19,205,80,90 2 0057 -- slash
+sl "
+0 456,710,19,100,-21,90 2 0060 -- zero
+1 456,710,0,28,-92,28 2 0061 -- one
+2 456,710,0,102,29,90 2 0062 -- two
+3 456,710,19,93,-4,90 2 0063 -- three
+4 456,710,0,84,0,84 2 0064 -- four
+5 456,698,19,116,-3,90 2 0065 -- five
+6 456,710,19,101,-20,90 2 0066 -- six
+7 456,698,0,149,-52,90 2 0067 -- seven
+8 456,710,19,99,-7,90 2 0070 -- eight
+9 456,710,19,98,-14,90 2 0071 -- nine
+: 273,512,0,65,-25,65 0 0072 -- colon
+; 273,512,168,65,4,65 0 0073 -- semicolon
+< 479,514,8,108,-17,90 0 0074 -- less
+= 479,419,0,90,2,90 0 0075 -- equal
+> 479,514,8,71,20,71 0 0076 -- greater
+? 501,727,0,99,-85,90 2 0077 -- question
+@ 800,737,19,32,-102,32 2 0100 -- at
+at "
+A 592,718,0,34,34,34 2 0101 -- A
+B 592,718,0,84,-12,84 2 0102 -- B
+C 592,737,19,105,-38,90 2 0103 -- C
+D 592,718,0,95,-12,90 2 0104 -- D
+E 547,718,0,123,-12,90 2 0105 -- E
+F 501,718,0,155,-12,90 2 0106 -- F
+G 638,737,19,82,-39,82 2 0107 -- G
+H 592,718,0,117,-8,90 2 0110 -- H
+I 228,718,0,123,-2,90 2 0111 -- I
+J 456,718,18,116,1,90 2 0112 -- J
+K 592,718,0,161,-21,90 2 0113 -- K
+L 501,718,0,50,-12,50 2 0114 -- L
+M 683,718,0,119,-7,90 2 0115 -- M
+N 592,718,0,119,-7,90 2 0116 -- N
+O 638,737,19,87,-38,87 2 0117 -- O
+P 547,718,0,108,-12,90 2 0120 -- P
+Q 638,737,52,87,-38,87 2 0121 -- Q
+R 592,718,0,96,-12,90 2 0122 -- R
+S 547,737,19,91,-16,90 2 0123 -- S
+T 501,718,0,164,-64,90 2 0124 -- T
+U 592,718,19,117,-46,90 2 0125 -- U
+V 547,718,0,159,-91,90 2 0126 -- V
+W 774,718,0,163,-88,90 2 0127 -- W
+X 547,718,0,151,39,90 2 0130 -- X
+Y 547,718,0,164,-87,90 2 0131 -- Y
+Z 501,718,0,153,30,90 2 0132 -- Z
+[ 273,722,196,156,33,90 2 0133 -- bracketleft
+lB "
+\ 228,737,19,74,-51,74 2 0134 -- backslash
+rs "
+] 273,722,196,124,64,90 2 0135 -- bracketright
+rB "
+a^ 273,750,0,164,-47,90 2 0136 -- circumflex
+^ "
+_ 456,0,125,37,72,37 0 0137 -- underscore
+` 228,727,0,118,-86,90 2 0140 -- quoteleft
+oq "
+a 456,546,14,72,5,72 0 0141 -- a
+b 501,718,14,78,0,78 2 0142 -- b
+c 456,546,14,85,-15,85 0 0143 -- c
+d 501,718,14,126,-17,90 2 0144 -- d
+e 456,546,14,80,-8,80 0 0145 -- e
+f 273,727,0,162,-21,90 2 0146 -- f
+g 501,546,217,95,19,90 1 0147 -- g
+h 501,718,0,65,-3,65 2 0150 -- h
+i 228,725,0,120,-7,90 2 0151 -- i
+j 228,725,214,120,85,90 3 0152 -- j
+k 456,718,0,143,-7,90 2 0153 -- k
+l 228,718,0,119,-7,90 2 0154 -- l
+m 729,546,0,67,-2,67 0 0155 -- m
+n 501,546,0,65,-3,65 0 0156 -- n
+o 501,546,14,76,-17,76 0 0157 -- o
+p 501,546,207,78,35,78 1 0160 -- p
+q 501,546,207,94,-16,90 1 0161 -- q
+r 319,546,0,132,-2,90 0 0162 -- r
+s 456,546,14,73,-2,73 0 0163 -- s
+t 273,676,6,123,-32,90 2 0164 -- t
+u 501,532,14,89,-30,89 0 0165 -- u
+v 456,532,0,132,-53,90 0 0166 -- v
+w 638,532,0,135,-51,90 0 0167 -- w
+x 456,532,0,125,38,90 0 0170 -- x
+y 456,532,214,129,16,90 1 0171 -- y
+z 410,532,0,118,34,90 0 0172 -- z
+lC 319,722,196,156,-27,90 2 0173 -- braceleft
+{ "
+ba 230,737,19,109,-16,90 2 0174 -- bar
+| "
+rC 319,722,196,64,64,64 2 0175 -- braceright
+} "
+a~ 273,737,0,192,-42,90 2 0176 -- tilde
+~ "
+bq 228,127,146,16,16,16 0 0200 -- quotesinglbase
+Fo 456,484,0,62,-61,62 0 0201 -- guillemotleft
+char171 "
+Fc 456,484,0,37,-35,37 0 0202 -- guillemotright
+char187 "
+bu 287,524,0,108,-18,90 0 0203 -- bullet
+Fn 456,737,210,142,91,90 3 0204 -- florin
+f/ 137,710,19,312,193,90 2 0205 -- fraction
+%0 820,710,19,81,-12,81 2 0206 -- perthousand
+dg 456,718,171,107,-47,90 2 0207 -- dagger
+dd 456,718,171,109,12,90 2 0210 -- daggerdbl
+en 456,333,0,108,10,90 0 0211 -- endash
+em 820,333,0,108,10,90 0 0212 -- emdash
+fi 501,727,0,120,-21,90 2 0214 -- fi
+fl 501,727,0,119,-21,90 2 0215 -- fl
+.i 228,532,0,86,-7,86 0 0220 -- dotlessi
+ga 273,750,0,67,-62,67 2 0222 -- grave
+a" 273,750,0,306,-63,90 2 0223 -- hungarumlaut
+a. 273,729,0,93,-142,90 2 0224 -- dotaccent
+ab 273,750,0,182,-78,90 2 0225 -- breve
+ah 273,750,0,189,-73,90 2 0226 -- caron
+ao 273,776,0,121,-114,90 2 0227 -- ring
+ho 273,0,228,0,17 1 0230 -- ogonek
+lq 410,727,0,122,-82,90 2 0231 -- quotedblleft
+rq 410,718,0,123,-82,90 2 0232 -- quotedblright
+oe 774,546,14,77,-17,77 0 0233 -- oe
+/l 228,718,0,156,17,90 2 0234 -- lslash
+Bq 410,127,146,20,21,20 0 0235 -- quotedblbase
+OE 820,737,19,143,-31,90 2 0236 -- OE
+/L 501,718,0,50,22,50 2 0237 -- Lslash
+r! 273,532,186,67,9,67 0 0241 -- exclamdown
+char161 "
+ct 456,628,118,85,-15,85 0 0242 -- cent
+char162 "
+Po 456,718,16,114,9,90 2 0243 -- sterling
+char163 "
+Cs 456,636,0,152,28,90 0 0244 -- currency
+char164 "
+Ye 456,698,0,179,1,90 2 0245 -- yen
+char165 "
+bb 230,737,19,109,-16,90 2 0246 -- brokenbar
+char166 "
+sc 456,727,184,85,0,85 2 0247 -- section
+char167 "
+ad 273,729,0,172,-62,90 2 0250 -- dieresis
+char168 "
+co 604,737,19,131,4,90 2 0251 -- copyright
+char169 "
+Of 303,737,0,128,-25,90 2 0252 -- ordfeminine
+char170 "
+fo 273,484,0,66,-56,66 0 0253 -- guilsinglleft
+no 479,419,0,90,-36,90 0 0254 -- logicalnot
+char172 "
+\- 479,309,0,71,-17,71 0 0255 -- minus
+rg 604,737,19,130,5,90 2 0256 -- registered
+char174 "
+a- 273,678,0,173,-50,90 2 0257 -- macron
+char175 "
+de 328,712,0,105,-93,90 2 0260 -- degree
+char176 "
+char177 479,506,0,83,17,83 0 0261 -- plusminus
+S2 273,710,0,145,-7,90 2 0262 -- twosuperior
+char178 "
+S3 273,710,0,138,-25,90 2 0263 -- threesuperior
+char179 "
+aa 273,750,0,200,-144,90 2 0264 -- acute
+char180 "
+char181 501,532,207,89,32,89 1 0265 -- mu
+ps 456,700,191,158,-30,90 2 0266 -- paragraph
+char182 "
+char183 228,334,0,48,-40,48 0 0267 -- periodcentered
+ac 273,0,228,0,80 1 0270 -- cedilla
+char184 "
+S1 273,710,0,95,-71,90 2 0271 -- onesuperior
+char185 "
+Om 299,737,0,149,-25,90 2 0272 -- ordmasculine
+char186 "
+fc 273,484,0,41,-31,41 0 0273 -- guilsinglright
+14 684,710,19,27,-58,27 2 0274 -- onequarter
+char188 "
+12 684,710,19,70,-58,70 2 0275 -- onehalf
+char189 "
+34 684,710,19,54,-32,54 2 0276 -- threequarters
+char190 "
+r? 501,532,195,8,6,8 0 0277 -- questiondown
+char191 "
+`A 592,936,0,34,34,34 2 0300 -- Agrave
+char192 "
+'A 592,936,0,73,34,73 2 0301 -- Aacute
+char193 "
+^A 592,936,0,37,34,37 2 0302 -- Acircumflex
+char194 "
+~A 592,923,0,66,34,66 2 0303 -- Atilde
+char195 "
+:A 592,915,0,46,34,46 2 0304 -- Adieresis
+char196 "
+oA 592,962,0,34,34,34 2 0305 -- Aring
+char197 "
+AE 820,718,0,132,46,90 2 0306 -- AE
+char198 "
+,C 592,737,228,105,-38,90 3 0307 -- Ccedilla
+char199 "
+`E 547,936,0,123,-12,90 2 0310 -- Egrave
+char200 "
+'E 547,936,0,123,-12,90 2 0311 -- Eacute
+char201 "
+^E 547,936,0,123,-12,90 2 0312 -- Ecircumflex
+char202 "
+:E 547,915,0,123,-12,90 2 0313 -- Edieresis
+char203 "
+`I 228,936,0,123,-2,90 2 0314 -- Igrave
+char204 "
+'I 228,936,0,255,-2,90 2 0315 -- Iacute
+char205 "
+^I 228,936,0,219,-2,90 2 0316 -- Icircumflex
+char206 "
+:I 228,915,0,227,-2,90 2 0317 -- Idieresis
+char207 "
+-D 592,718,0,95,-1,90 2 0320 -- Eth
+char208 "
+~N 592,923,0,119,-7,90 2 0321 -- Ntilde
+char209 "
+`O 638,936,19,87,-38,87 2 0322 -- Ograve
+char210 "
+'O 638,936,19,87,-38,87 2 0323 -- Oacute
+char211 "
+^O 638,936,19,87,-38,87 2 0324 -- Ocircumflex
+char212 "
+~O 638,923,19,87,-38,87 2 0325 -- Otilde
+char213 "
+:O 638,915,19,87,-38,87 2 0326 -- Odieresis
+char214 "
+char215 479,505,0,91,3,90 0 0327 -- multiply
+/O 638,745,27,145,21,90 2 0330 -- Oslash
+char216 "
+`U 592,936,19,117,-46,90 2 0331 -- Ugrave
+char217 "
+'U 592,936,19,117,-46,90 2 0332 -- Uacute
+char218 "
+^U 592,936,19,117,-46,90 2 0333 -- Ucircumflex
+char219 "
+:U 592,915,19,117,-46,90 2 0334 -- Udieresis
+char220 "
+'Y 547,936,0,164,-87,90 2 0335 -- Yacute
+char221 "
+TP 547,718,0,91,-12,90 2 0336 -- Thorn
+char222 "
+ss 501,731,14,88,-7,88 2 0337 -- germandbls
+char223 "
+`a 456,750,14,72,5,72 2 0340 -- agrave
+char224 "
+'a 456,750,14,108,5,90 2 0341 -- aacute
+char225 "
+^a 456,750,14,72,5,72 2 0342 -- acircumflex
+char226 "
+~a 456,737,14,101,5,90 2 0343 -- atilde
+char227 "
+:a 456,729,14,81,5,81 2 0344 -- adieresis
+char228 "
+oa 456,776,14,72,5,72 2 0345 -- aring
+char229 "
+ae 729,546,14,78,4,78 0 0346 -- ae
+char230 "
+,c 456,546,228,85,-15,85 1 0347 -- ccedilla
+char231 "
+`e 456,750,14,80,-8,80 2 0350 -- egrave
+char232 "
+'e 456,750,14,108,-8,90 2 0351 -- eacute
+char233 "
+^e 456,750,14,80,-8,80 2 0352 -- ecircumflex
+char234 "
+:e 456,729,14,81,-8,81 2 0353 -- edieresis
+char235 "
+`i 228,750,0,90,-7,90 2 0354 -- igrave
+char236 "
+'i 228,750,0,222,-7,90 2 0355 -- iacute
+char237 "
+^i 228,750,0,186,-7,90 2 0356 -- icircumflex
+char238 "
+:i 228,729,0,195,-7,90 2 0357 -- idieresis
+char239 "
+Sd 501,737,14,98,-17,90 2 0360 -- eth
+char240 "
+~n 501,737,0,78,-3,78 2 0361 -- ntilde
+char241 "
+`o 501,750,14,76,-17,76 2 0362 -- ograve
+char242 "
+'o 501,750,14,86,-17,86 2 0363 -- oacute
+char243 "
+^o 501,750,14,76,-17,76 2 0364 -- ocircumflex
+char244 "
+~o 501,737,14,78,-17,78 2 0365 -- otilde
+char245 "
+:o 501,729,14,76,-17,76 2 0366 -- odieresis
+char246 "
+char247 479,548,42,71,-17,71 0 0367 -- divide
+/o 501,560,29,124,32,90 0 0370 -- oslash
+char248 "
+`u 501,750,14,89,-30,89 2 0371 -- ugrave
+char249 "
+'u 501,750,14,89,-30,89 2 0372 -- uacute
+char250 "
+^u 501,750,14,89,-30,89 2 0373 -- ucircumflex
+char251 "
+:u 501,729,14,89,-30,89 2 0374 -- udieresis
+char252 "
+'y 456,750,214,129,16,90 3 0375 -- yacute
+char253 "
+Tp 501,718,208,78,35,78 3 0376 -- thorn
+char254 "
+:y 456,729,214,129,16,90 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/HNI b/font/devps/HNI
new file mode 100644
index 00000000..4f14c8c3
--- /dev/null
+++ b/font/devps/HNI
@@ -0,0 +1,617 @@
+name HNI
+internalname Helvetica-Narrow-Oblique
+slant 12
+spacewidth 228
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -40
+A w -40
+A v -40
+A u -30
+A Y -100
+A W -50
+A V -70
+A U -50
+A T -120
+A Q -30
+A O -30
+A G -30
+A C -30
+B . -20
+B , -20
+B U -10
+C . -30
+C , -30
+D . -70
+D , -70
+D Y -90
+D W -40
+D V -70
+D A -40
+F r -45
+F . -150
+F o -30
+F e -30
+F , -150
+F a -50
+F A -80
+J u -20
+J . -30
+J , -30
+J a -20
+J A -20
+K y -50
+K u -30
+K o -40
+K e -40
+K O -50
+L y -30
+L ' -160
+L rq -140
+L Y -140
+L W -70
+L V -110
+L T -110
+O . -40
+O , -40
+O Y -70
+O X -60
+O W -30
+O V -50
+O T -40
+O A -20
+P . -180
+P o -50
+P e -50
+P , -180
+P a -40
+P A -120
+Q U -10
+R Y -50
+R W -30
+R V -50
+R U -40
+R T -30
+R O -20
+S . -20
+S , -20
+T y -120
+T w -120
+T u -120
+T ; -20
+T r -120
+T . -120
+T o -120
+T - -140
+T hy -140
+T char173 -140
+T e -120
+T , -120
+T : -20
+T a -120
+T O -40
+T A -120
+U . -40
+U , -40
+U A -40
+V u -70
+V ; -40
+V . -125
+V o -80
+V - -80
+V hy -80
+V char173 -80
+V e -80
+V , -125
+V : -40
+V a -70
+V O -40
+V G -40
+V A -80
+W y -20
+W u -30
+W . -80
+W o -30
+W - -40
+W hy -40
+W char173 -40
+W e -30
+W , -80
+W a -40
+W O -20
+W A -50
+Y u -110
+Y ; -60
+Y . -140
+Y o -140
+Y i -20
+Y - -140
+Y hy -140
+Y char173 -140
+Y e -140
+Y , -140
+Y : -60
+Y a -140
+Y O -85
+Y A -110
+a y -30
+a w -20
+a v -20
+b y -20
+b v -20
+b u -20
+b . -40
+b l -20
+b , -40
+b b -10
+c k -20
+c , -15
+, ' -100
+, rq -100
+e y -20
+e x -30
+e w -20
+e v -30
+e . -15
+e , -15
+f ' 50
+f rq 60
+f . -30
+f o -30
+f e -30
+f .i -28
+f , -30
+f a -30
+g r -10
+h y -30
+k o -20
+k e -20
+m y -15
+m u -10
+n y -15
+n v -20
+n u -10
+o y -30
+o x -30
+o w -15
+o v -15
+o . -40
+o , -40
+/o z -55
+char248 z -55
+/o y -70
+char248 y -70
+/o x -85
+char248 x -85
+/o w -70
+char248 w -70
+/o v -70
+char248 v -70
+/o u -55
+char248 u -55
+/o t -55
+char248 t -55
+/o s -55
+char248 s -55
+/o r -55
+char248 r -55
+/o q -55
+char248 q -55
+/o . -95
+char248 . -95
+/o p -55
+char248 p -55
+/o o -55
+char248 o -55
+/o n -55
+char248 n -55
+/o m -55
+char248 m -55
+/o l -55
+char248 l -55
+/o k -55
+char248 k -55
+/o j -55
+char248 j -55
+/o i -55
+char248 i -55
+/o h -55
+char248 h -55
+/o g -55
+char248 g -55
+/o f -55
+char248 f -55
+/o e -55
+char248 e -55
+/o d -55
+char248 d -55
+/o , -95
+char248 , -95
+/o c -55
+char248 c -55
+/o b -55
+char248 b -55
+/o a -55
+char248 a -55
+p y -30
+p . -35
+p , -35
+. ' -100
+. rq -100
+` ` -57
+` oq -57
+oq ` -57
+oq oq -57
+' s -50
+' r -50
+' ' -57
+' d -50
+r y 30
+r v 30
+r u 15
+r t 40
+r ; 30
+r . -50
+r p 30
+r n 25
+r m 25
+r l 15
+r k 15
+r i 15
+r , -50
+r : 30
+r a -10
+s w -30
+s . -15
+s , -15
+v . -80
+v o -25
+v e -25
+v , -80
+v a -25
+w . -60
+w o -10
+w e -10
+w , -60
+w a -15
+x e -30
+y . -100
+y o -20
+y e -20
+y , -100
+y a -20
+z o -15
+z e -15
+charset
+ha 385,688,0,107,15,89 2 0000 -- asciicircum
+ti 479,326,0,47,-41,47 0 0001 -- asciitilde
+vS 547,929,19,87,-24,87 2 0002 -- Scaron
+vZ 501,929,0,156,31,89 2 0003 -- Zcaron
+vs 410,734,15,93,-2,89 2 0004 -- scaron
+vz 410,734,0,108,25,89 2 0005 -- zcaron
+:Y 547,901,0,164,-87,89 2 0006 -- Ydieresis
+tm 820,718,0,96,-102,89 2 0007 -- trademark
+aq 157,718,0,126,-79,89 2 0010 -- quotesingle
+space 228 0 0040
+! 228,718,0,100,-24,89 2 0041 -- exclam
+" 291,718,0,118,-88,89 2 0042 -- quotedbl
+# 456,688,0,111,-10,89 2 0043 -- numbersign
+sh "
+$ 456,775,115,100,-7,89 2 0044 -- dollar
+Do "
+% 729,703,19,50,-70,50 2 0045 -- percent
+& 547,718,15,33,-13,33 2 0046 -- ampersand
+' 182,718,0,122,-74,89 2 0047 -- quoteright
+( 273,733,207,149,-39,89 3 0050 -- parenleft
+) 273,733,207,53,57,53 3 0051 -- parenright
+* 319,718,0,120,-85,89 2 0052 -- asterisk
++ 479,505,0,68,-20,68 0 0053 -- plus
+, 228,106,147,0,4 0 0054 -- comma
+- 273,322,0,70,-27,70 0 0055 -- hyphen
+hy "
+char173 "
+. 228,106,0,0,-21 0 0056 -- period
+/ 228,737,19,192,67,89 2 0057 -- slash
+sl "
+0 456,703,19,93,-27,89 2 0060 -- zero
+1 456,703,0,11,-120,11 2 0061 -- one
+2 456,703,0,100,29,89 2 0062 -- two
+3 456,703,19,94,-11,89 2 0063 -- three
+4 456,703,0,66,0,66 2 0064 -- four
+5 456,688,19,103,-5,89 2 0065 -- five
+6 456,703,19,98,-24,89 2 0066 -- six
+7 456,688,0,143,-62,89 2 0067 -- seven
+8 456,703,19,91,-10,89 2 0070 -- eight
+9 456,703,19,93,-17,89 2 0071 -- nine
+: 228,516,0,69,-21,69 0 0072 -- colon
+; 228,516,147,69,4,69 0 0073 -- semicolon
+< 479,495,0,97,-27,89 0 0074 -- less
+= 479,390,0,86,-2,86 0 0075 -- equal
+> 479,495,0,61,9,61 0 0076 -- greater
+? 456,727,0,94,-82,89 2 0077 -- question
+@ 832,737,19,9,-126,9 2 0100 -- at
+at "
+A 547,718,0,39,39,39 2 0101 -- A
+B 547,718,0,86,-11,86 2 0102 -- B
+C 592,737,19,98,-38,89 2 0103 -- C
+D 592,718,0,84,-16,84 2 0104 -- D
+E 547,718,0,128,-21,89 2 0105 -- E
+F 501,718,0,152,-21,89 2 0106 -- F
+G 638,737,19,67,-41,67 2 0107 -- G
+H 592,718,0,113,-13,89 2 0110 -- H
+I 228,718,0,101,-25,89 2 0111 -- I
+J 410,718,19,116,11,89 2 0112 -- J
+K 547,718,0,165,-12,89 2 0113 -- K
+L 456,718,0,49,-12,49 2 0114 -- L
+M 683,718,0,116,-10,89 2 0115 -- M
+N 592,718,0,113,-12,89 2 0116 -- N
+O 638,737,19,89,-36,89 2 0117 -- O
+P 547,718,0,107,-21,89 2 0120 -- P
+Q 638,737,56,89,-36,89 2 0121 -- Q
+R 592,718,0,92,-22,89 2 0122 -- R
+S 547,737,19,87,-24,87 2 0123 -- S
+T 501,718,0,164,-72,89 2 0124 -- T
+U 592,718,19,111,-51,89 2 0125 -- U
+V 547,718,0,159,-92,89 2 0126 -- V
+W 774,718,0,162,-88,89 2 0127 -- W
+X 547,718,0,150,34,89 2 0130 -- X
+Y 547,718,0,164,-87,89 2 0131 -- Y
+Z 501,718,0,156,31,89 2 0132 -- Z
+[ 228,722,196,153,33,89 2 0133 -- bracketleft
+lB "
+\ 228,737,19,61,-65,61 2 0134 -- backslash
+rs "
+] 228,722,196,124,61,89 2 0135 -- bracketright
+rB "
+a^ 273,734,0,136,-71,89 2 0136 -- circumflex
+^ "
+_ 456,0,125,37,72,37 0 0137 -- underscore
+` 182,725,0,133,-85,89 2 0140 -- quoteleft
+oq "
+a 456,538,15,52,0,52 0 0141 -- a
+b 456,718,15,73,2,73 2 0142 -- b
+c 410,538,15,94,-11,89 0 0143 -- c
+d 456,718,15,128,-19,89 2 0144 -- d
+e 456,538,15,68,-19,68 0 0145 -- e
+f 228,728,0,163,-21,89 2 0146 -- f
+g 456,538,220,94,16,89 1 0147 -- g
+h 456,718,0,64,-3,64 2 0150 -- h
+i 182,718,0,120,-5,89 2 0151 -- i
+j 182,718,210,120,99,89 3 0152 -- j
+k 410,718,0,132,-5,89 2 0153 -- k
+l 182,718,0,120,-5,89 2 0154 -- l
+m 683,538,0,66,-3,66 0 0155 -- m
+n 456,538,0,64,-3,64 0 0156 -- n
+o 456,538,14,73,-18,73 0 0157 -- o
+p 456,538,207,73,39,73 1 0160 -- p
+q 456,538,207,90,-19,89 1 0161 -- q
+r 273,538,0,142,-13,89 0 0162 -- r
+s 410,538,15,74,-2,74 0 0163 -- s
+t 228,669,7,124,-34,89 2 0164 -- t
+u 456,523,15,86,-27,86 0 0165 -- u
+v 410,523,0,135,-48,89 0 0166 -- v
+w 592,523,0,131,-53,89 0 0167 -- w
+x 410,523,0,127,41,89 0 0170 -- x
+y 410,523,214,132,38,89 1 0171 -- y
+z 410,523,0,108,25,89 0 0172 -- z
+lC 274,722,196,141,-25,89 2 0173 -- braceleft
+{ "
+ba 213,737,19,102,-24,89 2 0174 -- bar
+| "
+rC 274,722,196,67,50,67 2 0175 -- braceright
+} "
+a~ 273,722,0,179,-52,89 2 0176 -- tilde
+~ "
+bq 182,106,149,15,33,15 0 0200 -- quotesinglbase
+Fo 456,446,0,48,-70,48 0 0201 -- guillemotleft
+char171 "
+Fc 456,446,0,27,-48,27 0 0202 -- guillemotright
+char187 "
+bu 287,517,0,102,-24,89 0 0203 -- bullet
+Fn 456,737,207,131,93,89 3 0204 -- florin
+f/ 137,703,19,309,189,89 2 0205 -- fraction
+%0 820,703,19,74,-22,74 2 0206 -- perthousand
+dg 456,718,159,104,-60,89 2 0207 -- dagger
+dd 456,718,159,105,7,89 2 0210 -- daggerdbl
+en 456,313,0,104,8,89 0 0211 -- endash
+em 820,313,0,105,8,89 0 0212 -- emdash
+fi 410,728,0,121,-21,89 2 0214 -- fi
+fl 410,728,0,119,-21,89 2 0215 -- fl
+.i 228,523,0,63,-28,63 0 0220 -- dotlessi
+ga 273,734,0,53,-89,53 2 0222 -- grave
+a" 273,734,0,240,-79,89 2 0223 -- hungarumlaut
+a. 273,706,0,74,-154,74 2 0224 -- dotaccent
+ab 273,731,0,168,-87,89 2 0225 -- breve
+ah 273,734,0,161,-95,89 2 0226 -- caron
+ao 273,756,0,107,-125,89 2 0227 -- ring
+ho 273,0,225,0,15 1 0230 -- ogonek
+lq 273,725,0,155,-63,89 2 0231 -- quotedblleft
+rq 273,718,0,144,-52,89 2 0232 -- quotedblright
+oe 774,538,15,67,-18,67 0 0233 -- oe
+/l 182,718,0,152,16,89 2 0234 -- lslash
+Bq 273,106,149,37,55,37 0 0235 -- quotedblbase
+OE 820,737,19,145,-30,89 2 0236 -- OE
+/L 456,718,0,49,16,49 2 0237 -- Lslash
+r! 273,523,195,44,-13,44 0 0241 -- exclamdown
+char161 "
+ct 456,623,115,73,-28,73 0 0242 -- cent
+char162 "
+Po 456,718,16,114,10,89 2 0243 -- sterling
+char163 "
+Cs 456,603,0,124,1,89 0 0244 -- currency
+char164 "
+Ye 456,688,0,167,-17,89 2 0245 -- yen
+char165 "
+bb 213,737,19,102,-24,89 2 0246 -- brokenbar
+char166 "
+sc 456,737,191,73,-13,73 2 0247 -- section
+char167 "
+ad 273,706,0,140,-88,89 2 0250 -- dieresis
+char168 "
+co 604,737,19,133,6,89 2 0251 -- copyright
+char169 "
+Of 303,737,0,115,-32,89 2 0252 -- ordfeminine
+char170 "
+fo 273,446,0,56,-62,56 0 0253 -- guilsinglleft
+no 479,390,0,86,-37,86 0 0254 -- logicalnot
+char172 "
+\- 479,289,0,68,-20,68 0 0255 -- minus
+rg 604,737,19,133,6,89 2 0256 -- registered
+char174 "
+a- 273,684,0,161,-67,89 2 0257 -- macron
+char175 "
+de 328,703,0,106,-88,89 2 0260 -- degree
+char176 "
+char177 479,506,0,78,18,78 0 0261 -- plusminus
+S2 273,703,0,145,-2,89 2 0262 -- twosuperior
+char178 "
+S3 273,703,0,135,-24,89 2 0263 -- threesuperior
+char179 "
+aa 273,734,0,167,-153,89 2 0264 -- acute
+char180 "
+char181 456,523,207,86,30,86 1 0265 -- mu
+ps 440,718,173,143,-53,89 2 0266 -- paragraph
+char182 "
+char183 228,315,0,33,-56,33 0 0267 -- periodcentered
+ac 273,0,225,0,48 1 0270 -- cedilla
+char184 "
+S1 273,703,0,82,-86,82 2 0271 -- onesuperior
+char185 "
+Om 299,737,0,135,-32,89 2 0272 -- ordmasculine
+char186 "
+fc 273,446,0,34,-41,34 0 0273 -- guilsinglright
+14 684,703,19,24,-73,24 2 0274 -- onequarter
+char188 "
+12 684,703,19,54,-43,54 2 0275 -- onehalf
+char189 "
+34 684,703,19,72,-56,72 2 0276 -- threequarters
+char190 "
+r? 501,525,201,0,-20 0 0277 -- questiondown
+char191 "
+`A 547,929,0,39,39,39 2 0300 -- Agrave
+char192 "
+'A 547,929,0,63,39,63 2 0301 -- Aacute
+char193 "
+^A 547,929,0,39,39,39 2 0302 -- Acircumflex
+char194 "
+~A 547,917,0,76,39,76 2 0303 -- Atilde
+char195 "
+:A 547,901,0,39,39,39 2 0304 -- Adieresis
+char196 "
+oA 547,931,0,39,39,39 2 0305 -- Aring
+char197 "
+AE 820,718,0,129,43,89 2 0306 -- AE
+char198 "
+,C 592,737,225,98,-38,89 3 0307 -- Ccedilla
+char199 "
+`E 547,929,0,128,-21,89 2 0310 -- Egrave
+char200 "
+'E 547,929,0,128,-21,89 2 0311 -- Eacute
+char201 "
+^E 547,929,0,128,-21,89 2 0312 -- Ecircumflex
+char202 "
+:E 547,901,0,128,-21,89 2 0313 -- Edieresis
+char203 "
+`I 228,929,0,110,-25,89 2 0314 -- Igrave
+char204 "
+'I 228,929,0,223,-25,89 2 0315 -- Iacute
+char205 "
+^I 228,929,0,193,-25,89 2 0316 -- Icircumflex
+char206 "
+:I 228,901,0,197,-25,89 2 0317 -- Idieresis
+char207 "
+-D 592,718,0,84,-7,84 2 0320 -- Eth
+char208 "
+~N 592,917,0,113,-12,89 2 0321 -- Ntilde
+char209 "
+`O 638,929,19,89,-36,89 2 0322 -- Ograve
+char210 "
+'O 638,929,19,89,-36,89 2 0323 -- Oacute
+char211 "
+^O 638,929,19,89,-36,89 2 0324 -- Ocircumflex
+char212 "
+~O 638,917,19,89,-36,89 2 0325 -- Otilde
+char213 "
+:O 638,901,19,89,-36,89 2 0326 -- Odieresis
+char214 "
+char215 479,506,0,97,9,89 0 0327 -- multiply
+/O 638,737,19,142,15,89 2 0330 -- Oslash
+char216 "
+`U 592,929,19,111,-51,89 2 0331 -- Ugrave
+char217 "
+'U 592,929,19,111,-51,89 2 0332 -- Uacute
+char218 "
+^U 592,929,19,111,-51,89 2 0333 -- Ucircumflex
+char219 "
+:U 592,901,19,111,-51,89 2 0334 -- Udieresis
+char220 "
+'Y 547,929,0,164,-87,89 2 0335 -- Yacute
+char221 "
+TP 547,718,0,87,-21,87 2 0336 -- Thorn
+char222 "
+ss 501,728,15,88,-5,88 2 0337 -- germandbls
+char223 "
+`a 456,734,15,52,0,52 2 0340 -- agrave
+char224 "
+'a 456,734,15,75,0,75 2 0341 -- aacute
+char225 "
+^a 456,734,15,52,0,52 2 0342 -- acircumflex
+char226 "
+~a 456,722,15,80,0,80 2 0343 -- atilde
+char227 "
+:a 456,706,15,52,0,52 2 0344 -- adieresis
+char228 "
+oa 456,756,15,52,0,52 2 0345 -- aring
+char229 "
+ae 729,538,15,67,0,67 0 0346 -- ae
+char230 "
+,c 410,538,225,94,-11,89 1 0347 -- ccedilla
+char231 "
+`e 456,734,15,68,-19,68 2 0350 -- egrave
+char232 "
+'e 456,734,15,75,-19,75 2 0351 -- eacute
+char233 "
+^e 456,734,15,68,-19,68 2 0352 -- ecircumflex
+char234 "
+:e 456,706,15,68,-19,68 2 0353 -- edieresis
+char235 "
+`i 228,734,0,76,-28,76 2 0354 -- igrave
+char236 "
+'i 228,734,0,189,-28,89 2 0355 -- iacute
+char237 "
+^i 228,734,0,159,-28,89 2 0356 -- icircumflex
+char238 "
+:i 228,706,0,163,-28,89 2 0357 -- idieresis
+char239 "
+Sd 456,737,15,100,-17,89 2 0360 -- eth
+char240 "
+~n 456,722,0,80,-3,80 2 0361 -- ntilde
+char241 "
+`o 456,734,14,73,-18,73 2 0362 -- ograve
+char242 "
+'o 456,734,14,75,-18,75 2 0363 -- oacute
+char243 "
+^o 456,734,14,73,-18,73 2 0364 -- ocircumflex
+char244 "
+~o 456,722,14,88,-18,88 2 0365 -- otilde
+char245 "
+:o 456,706,14,73,-18,73 2 0366 -- odieresis
+char246 "
+char247 479,524,19,68,-20,68 0 0367 -- divide
+/o 501,545,22,80,26,80 0 0370 -- oslash
+char248 "
+`u 456,734,15,86,-27,86 2 0371 -- ugrave
+char249 "
+'u 456,734,15,86,-27,86 2 0372 -- uacute
+char250 "
+^u 456,734,15,86,-27,86 2 0373 -- ucircumflex
+char251 "
+:u 456,706,15,86,-27,86 2 0374 -- udieresis
+char252 "
+'y 410,734,214,132,38,89 3 0375 -- yacute
+char253 "
+Tp 456,718,207,73,39,73 3 0376 -- thorn
+char254 "
+:y 410,706,214,132,38,89 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/HNR b/font/devps/HNR
new file mode 100644
index 00000000..ad7dc044
--- /dev/null
+++ b/font/devps/HNR
@@ -0,0 +1,616 @@
+name HNR
+internalname Helvetica-Narrow
+spacewidth 228
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -32
+A w -32
+A v -32
+A u -24
+A Y -81
+A W -40
+A V -56
+A U -40
+A T -97
+A Q -24
+A O -24
+A G -24
+A C -24
+B . -15
+B , -15
+B U -7
+C . -24
+C , -24
+D . -56
+D , -56
+D Y -73
+D W -32
+D V -56
+D A -32
+F r -36
+F . -122
+F o -24
+F e -24
+F , -122
+F a -40
+F A -65
+J u -15
+J . -24
+J , -24
+J a -15
+J A -15
+K y -40
+K u -24
+K o -32
+K e -32
+K O -40
+L y -24
+L ' -130
+L rq -114
+L Y -114
+L W -56
+L V -89
+L T -89
+O . -32
+O , -32
+O Y -56
+O X -48
+O W -24
+O V -40
+O T -32
+O A -15
+P . -147
+P o -40
+P e -40
+P , -147
+P a -32
+P A -97
+Q U -7
+R Y -40
+R W -24
+R V -40
+R U -32
+R T -24
+R O -15
+S . -15
+S , -15
+T y -97
+T w -97
+T u -97
+T ; -15
+T r -97
+T . -97
+T o -97
+T - -114
+T hy -114
+T char173 -114
+T e -97
+T , -97
+T : -15
+T a -97
+T O -32
+T A -97
+U . -32
+U , -32
+U A -32
+V u -56
+V ; -32
+V . -102
+V o -65
+V - -65
+V hy -65
+V char173 -65
+V e -65
+V , -102
+V : -32
+V a -56
+V O -32
+V G -32
+V A -65
+W y -15
+W u -24
+W . -65
+W o -24
+W - -32
+W hy -32
+W char173 -32
+W e -24
+W , -65
+W a -32
+W O -15
+W A -40
+Y u -89
+Y ; -48
+Y . -114
+Y o -114
+Y i -15
+Y - -114
+Y hy -114
+Y char173 -114
+Y e -114
+Y , -114
+Y : -48
+Y a -114
+Y O -69
+Y A -89
+a y -24
+a w -15
+a v -15
+b y -15
+b v -15
+b u -15
+b . -32
+b l -15
+b , -32
+b b -7
+c k -15
+c , -11
+, ' -81
+, rq -81
+e y -15
+e x -24
+e w -15
+e v -24
+e . -11
+e , -11
+f ' 41
+f rq 49
+f . -24
+f o -24
+f e -24
+f .i -22
+f , -24
+f a -24
+g r -7
+h y -24
+k o -15
+k e -15
+m y -11
+m u -7
+n y -11
+n v -15
+n u -7
+o y -24
+o x -24
+o w -11
+o v -11
+o . -32
+o , -32
+/o z -44
+char248 z -44
+/o y -56
+char248 y -56
+/o x -69
+char248 x -69
+/o w -56
+char248 w -56
+/o v -56
+char248 v -56
+/o u -44
+char248 u -44
+/o t -44
+char248 t -44
+/o s -44
+char248 s -44
+/o r -44
+char248 r -44
+/o q -44
+char248 q -44
+/o . -77
+char248 . -77
+/o p -44
+char248 p -44
+/o o -44
+char248 o -44
+/o n -44
+char248 n -44
+/o m -44
+char248 m -44
+/o l -44
+char248 l -44
+/o k -44
+char248 k -44
+/o j -44
+char248 j -44
+/o i -44
+char248 i -44
+/o h -44
+char248 h -44
+/o g -44
+char248 g -44
+/o f -44
+char248 f -44
+/o e -44
+char248 e -44
+/o d -44
+char248 d -44
+/o , -77
+char248 , -77
+/o c -44
+char248 c -44
+/o b -44
+char248 b -44
+/o a -44
+char248 a -44
+p y -24
+p . -28
+p , -28
+. ' -81
+. rq -81
+` ` -46
+` oq -46
+oq ` -46
+oq oq -46
+' s -40
+' r -40
+' ' -46
+' d -40
+r y 25
+r v 25
+r u 12
+r t 33
+r ; 25
+r . -40
+r p 25
+r n 21
+r m 21
+r l 12
+r k 12
+r i 12
+r , -40
+r : 25
+r a -7
+s w -24
+s . -11
+s , -11
+v . -65
+v o -20
+v e -20
+v , -65
+v a -20
+w . -48
+w o -7
+w e -7
+w , -48
+w a -11
+x e -24
+y . -81
+y o -15
+y e -15
+y , -81
+y a -15
+z o -11
+z e -11
+charset
+ha 385,688 2 0000 -- asciicircum
+ti 479,326 0 0001 -- asciitilde
+vS 547,929,19 2 0002 -- Scaron
+vZ 501,929 2 0003 -- Zcaron
+vs 410,734,15 2 0004 -- scaron
+vz 410,734 2 0005 -- zcaron
+:Y 547,901 2 0006 -- Ydieresis
+tm 820,718 2 0007 -- trademark
+aq 157,718 2 0010 -- quotesingle
+space 228 0 0040
+! 228,718 2 0041 -- exclam
+" 291,718 2 0042 -- quotedbl
+# 456,688 2 0043 -- numbersign
+sh "
+$ 456,775,115 2 0044 -- dollar
+Do "
+% 729,703,19 2 0045 -- percent
+& 547,718,15 2 0046 -- ampersand
+' 182,718 2 0047 -- quoteright
+( 273,733,207 3 0050 -- parenleft
+) 273,733,207 3 0051 -- parenright
+* 319,718 2 0052 -- asterisk
++ 479,505 0 0053 -- plus
+, 228,106,147 0 0054 -- comma
+- 273,322 0 0055 -- hyphen
+hy "
+char173 "
+. 228,106 0 0056 -- period
+/ 228,737,19 2 0057 -- slash
+sl "
+0 456,703,19 2 0060 -- zero
+1 456,703 2 0061 -- one
+2 456,703 2 0062 -- two
+3 456,703,19 2 0063 -- three
+4 456,703 2 0064 -- four
+5 456,688,19 2 0065 -- five
+6 456,703,19 2 0066 -- six
+7 456,688 2 0067 -- seven
+8 456,703,19 2 0070 -- eight
+9 456,703,19 2 0071 -- nine
+: 228,516 0 0072 -- colon
+; 228,516,147 0 0073 -- semicolon
+< 479,495 0 0074 -- less
+= 479,390 0 0075 -- equal
+> 479,495 0 0076 -- greater
+? 456,727 2 0077 -- question
+@ 832,737,19 2 0100 -- at
+at "
+A 547,718 2 0101 -- A
+B 547,718 2 0102 -- B
+C 592,737,19 2 0103 -- C
+D 592,718 2 0104 -- D
+E 547,718 2 0105 -- E
+F 501,718 2 0106 -- F
+G 638,737,19 2 0107 -- G
+H 592,718 2 0110 -- H
+I 228,718 2 0111 -- I
+J 410,718,19 2 0112 -- J
+K 547,718 2 0113 -- K
+L 456,718 2 0114 -- L
+M 683,718 2 0115 -- M
+N 592,718 2 0116 -- N
+O 638,737,19 2 0117 -- O
+P 547,718 2 0120 -- P
+Q 638,737,56 2 0121 -- Q
+R 592,718 2 0122 -- R
+S 547,737,19 2 0123 -- S
+T 501,718 2 0124 -- T
+U 592,718,19 2 0125 -- U
+V 547,718 2 0126 -- V
+W 774,718 2 0127 -- W
+X 547,718 2 0130 -- X
+Y 547,718 2 0131 -- Y
+Z 501,718 2 0132 -- Z
+[ 228,722,196 2 0133 -- bracketleft
+lB "
+\ 228,737,19 2 0134 -- backslash
+rs "
+] 228,722,196 2 0135 -- bracketright
+rB "
+a^ 273,734 2 0136 -- circumflex
+^ "
+_ 456,0,125 0 0137 -- underscore
+` 182,725 2 0140 -- quoteleft
+oq "
+a 456,538,15 0 0141 -- a
+b 456,718,15 2 0142 -- b
+c 410,538,15 0 0143 -- c
+d 456,718,15 2 0144 -- d
+e 456,538,15 0 0145 -- e
+f 228,728 2 0146 -- f
+g 456,538,220 1 0147 -- g
+h 456,718 2 0150 -- h
+i 182,718 2 0151 -- i
+j 182,718,210 3 0152 -- j
+k 410,718 2 0153 -- k
+l 182,718 2 0154 -- l
+m 683,538 0 0155 -- m
+n 456,538 0 0156 -- n
+o 456,538,14 0 0157 -- o
+p 456,538,207 1 0160 -- p
+q 456,538,207 1 0161 -- q
+r 273,538 0 0162 -- r
+s 410,538,15 0 0163 -- s
+t 228,669,7 2 0164 -- t
+u 456,523,15 0 0165 -- u
+v 410,523 0 0166 -- v
+w 592,523 0 0167 -- w
+x 410,523 0 0170 -- x
+y 410,523,214 1 0171 -- y
+z 410,523 0 0172 -- z
+lC 274,722,196 2 0173 -- braceleft
+{ "
+ba 213,737,19 2 0174 -- bar
+| "
+rC 274,722,196 2 0175 -- braceright
+} "
+a~ 273,722 2 0176 -- tilde
+~ "
+bq 182,106,149 0 0200 -- quotesinglbase
+Fo 456,446 0 0201 -- guillemotleft
+char171 "
+Fc 456,446 0 0202 -- guillemotright
+char187 "
+bu 287,517 0 0203 -- bullet
+Fn 456,737,207 3 0204 -- florin
+f/ 137,703,19 2 0205 -- fraction
+%0 820,703,19 2 0206 -- perthousand
+dg 456,718,159 2 0207 -- dagger
+dd 456,718,159 2 0210 -- daggerdbl
+en 456,313 0 0211 -- endash
+em 820,313 0 0212 -- emdash
+fi 410,728 2 0214 -- fi
+fl 410,728 2 0215 -- fl
+.i 228,523 0 0220 -- dotlessi
+ga 273,734 2 0222 -- grave
+a" 273,734 2 0223 -- hungarumlaut
+a. 273,706 2 0224 -- dotaccent
+ab 273,731 2 0225 -- breve
+ah 273,734 2 0226 -- caron
+ao 273,756 2 0227 -- ring
+ho 273,0,225 1 0230 -- ogonek
+lq 273,725 2 0231 -- quotedblleft
+rq 273,718 2 0232 -- quotedblright
+oe 774,538,15 0 0233 -- oe
+/l 182,718 2 0234 -- lslash
+Bq 273,106,149 0 0235 -- quotedblbase
+OE 820,737,19 2 0236 -- OE
+/L 456,718 2 0237 -- Lslash
+r! 273,523,195 0 0241 -- exclamdown
+char161 "
+ct 456,623,115 0 0242 -- cent
+char162 "
+Po 456,718,16 2 0243 -- sterling
+char163 "
+Cs 456,603 0 0244 -- currency
+char164 "
+Ye 456,688 2 0245 -- yen
+char165 "
+bb 213,737,19 2 0246 -- brokenbar
+char166 "
+sc 456,737,191 2 0247 -- section
+char167 "
+ad 273,706 2 0250 -- dieresis
+char168 "
+co 604,737,19 2 0251 -- copyright
+char169 "
+Of 303,737 2 0252 -- ordfeminine
+char170 "
+fo 273,446 0 0253 -- guilsinglleft
+no 479,390 0 0254 -- logicalnot
+char172 "
+\- 479,289 0 0255 -- minus
+rg 604,737,19 2 0256 -- registered
+char174 "
+a- 273,684 2 0257 -- macron
+char175 "
+de 328,703 2 0260 -- degree
+char176 "
+char177 479,506 0 0261 -- plusminus
+S2 273,703 2 0262 -- twosuperior
+char178 "
+S3 273,703 2 0263 -- threesuperior
+char179 "
+aa 273,734 2 0264 -- acute
+char180 "
+char181 456,523,207 1 0265 -- mu
+ps 440,718,173 2 0266 -- paragraph
+char182 "
+char183 228,315 0 0267 -- periodcentered
+ac 273,0,225 1 0270 -- cedilla
+char184 "
+S1 273,703 2 0271 -- onesuperior
+char185 "
+Om 299,737 2 0272 -- ordmasculine
+char186 "
+fc 273,446 0 0273 -- guilsinglright
+14 684,703,19 2 0274 -- onequarter
+char188 "
+12 684,703,19 2 0275 -- onehalf
+char189 "
+34 684,703,19 2 0276 -- threequarters
+char190 "
+r? 501,525,201 0 0277 -- questiondown
+char191 "
+`A 547,929 2 0300 -- Agrave
+char192 "
+'A 547,929 2 0301 -- Aacute
+char193 "
+^A 547,929 2 0302 -- Acircumflex
+char194 "
+~A 547,917 2 0303 -- Atilde
+char195 "
+:A 547,901 2 0304 -- Adieresis
+char196 "
+oA 547,931 2 0305 -- Aring
+char197 "
+AE 820,718 2 0306 -- AE
+char198 "
+,C 592,737,225 3 0307 -- Ccedilla
+char199 "
+`E 547,929 2 0310 -- Egrave
+char200 "
+'E 547,929 2 0311 -- Eacute
+char201 "
+^E 547,929 2 0312 -- Ecircumflex
+char202 "
+:E 547,901 2 0313 -- Edieresis
+char203 "
+`I 228,929 2 0314 -- Igrave
+char204 "
+'I 228,929 2 0315 -- Iacute
+char205 "
+^I 228,929 2 0316 -- Icircumflex
+char206 "
+:I 228,901 2 0317 -- Idieresis
+char207 "
+-D 592,718 2 0320 -- Eth
+char208 "
+~N 592,917 2 0321 -- Ntilde
+char209 "
+`O 638,929,19 2 0322 -- Ograve
+char210 "
+'O 638,929,19 2 0323 -- Oacute
+char211 "
+^O 638,929,19 2 0324 -- Ocircumflex
+char212 "
+~O 638,917,19 2 0325 -- Otilde
+char213 "
+:O 638,901,19 2 0326 -- Odieresis
+char214 "
+char215 479,506 0 0327 -- multiply
+/O 638,737,19 2 0330 -- Oslash
+char216 "
+`U 592,929,19 2 0331 -- Ugrave
+char217 "
+'U 592,929,19 2 0332 -- Uacute
+char218 "
+^U 592,929,19 2 0333 -- Ucircumflex
+char219 "
+:U 592,901,19 2 0334 -- Udieresis
+char220 "
+'Y 547,929 2 0335 -- Yacute
+char221 "
+TP 547,718 2 0336 -- Thorn
+char222 "
+ss 501,728,15 2 0337 -- germandbls
+char223 "
+`a 456,734,15 2 0340 -- agrave
+char224 "
+'a 456,734,15 2 0341 -- aacute
+char225 "
+^a 456,734,15 2 0342 -- acircumflex
+char226 "
+~a 456,722,15 2 0343 -- atilde
+char227 "
+:a 456,706,15 2 0344 -- adieresis
+char228 "
+oa 456,756,15 2 0345 -- aring
+char229 "
+ae 729,538,15 0 0346 -- ae
+char230 "
+,c 410,538,225 1 0347 -- ccedilla
+char231 "
+`e 456,734,15 2 0350 -- egrave
+char232 "
+'e 456,734,15 2 0351 -- eacute
+char233 "
+^e 456,734,15 2 0352 -- ecircumflex
+char234 "
+:e 456,706,15 2 0353 -- edieresis
+char235 "
+`i 228,734 2 0354 -- igrave
+char236 "
+'i 228,734 2 0355 -- iacute
+char237 "
+^i 228,734 2 0356 -- icircumflex
+char238 "
+:i 228,706 2 0357 -- idieresis
+char239 "
+Sd 456,737,15 2 0360 -- eth
+char240 "
+~n 456,722 2 0361 -- ntilde
+char241 "
+`o 456,734,14 2 0362 -- ograve
+char242 "
+'o 456,734,14 2 0363 -- oacute
+char243 "
+^o 456,734,14 2 0364 -- ocircumflex
+char244 "
+~o 456,722,14 2 0365 -- otilde
+char245 "
+:o 456,706,14 2 0366 -- odieresis
+char246 "
+char247 479,524,19 0 0367 -- divide
+/o 501,545,22 0 0370 -- oslash
+char248 "
+`u 456,734,15 2 0371 -- ugrave
+char249 "
+'u 456,734,15 2 0372 -- uacute
+char250 "
+^u 456,734,15 2 0373 -- ucircumflex
+char251 "
+:u 456,706,15 2 0374 -- udieresis
+char252 "
+'y 410,734,214 3 0375 -- yacute
+char253 "
+Tp 456,718,207 3 0376 -- thorn
+char254 "
+:y 410,706,214 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/HR b/font/devps/HR
new file mode 100644
index 00000000..2a87c132
--- /dev/null
+++ b/font/devps/HR
@@ -0,0 +1,616 @@
+name HR
+internalname Helvetica
+spacewidth 278
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -40
+A w -40
+A v -40
+A u -30
+A Y -100
+A W -50
+A V -70
+A U -50
+A T -120
+A Q -30
+A O -30
+A G -30
+A C -30
+B . -20
+B , -20
+B U -10
+C . -30
+C , -30
+D . -70
+D , -70
+D Y -90
+D W -40
+D V -70
+D A -40
+F r -45
+F . -150
+F o -30
+F e -30
+F , -150
+F a -50
+F A -80
+J u -20
+J . -30
+J , -30
+J a -20
+J A -20
+K y -50
+K u -30
+K o -40
+K e -40
+K O -50
+L y -30
+L ' -160
+L rq -140
+L Y -140
+L W -70
+L V -110
+L T -110
+O . -40
+O , -40
+O Y -70
+O X -60
+O W -30
+O V -50
+O T -40
+O A -20
+P . -180
+P o -50
+P e -50
+P , -180
+P a -40
+P A -120
+Q U -10
+R Y -50
+R W -30
+R V -50
+R U -40
+R T -30
+R O -20
+S . -20
+S , -20
+T y -120
+T w -120
+T u -120
+T ; -20
+T r -120
+T . -120
+T o -120
+T - -140
+T hy -140
+T char173 -140
+T e -120
+T , -120
+T : -20
+T a -120
+T O -40
+T A -120
+U . -40
+U , -40
+U A -40
+V u -70
+V ; -40
+V . -125
+V o -80
+V - -80
+V hy -80
+V char173 -80
+V e -80
+V , -125
+V : -40
+V a -70
+V O -40
+V G -40
+V A -80
+W y -20
+W u -30
+W . -80
+W o -30
+W - -40
+W hy -40
+W char173 -40
+W e -30
+W , -80
+W a -40
+W O -20
+W A -50
+Y u -110
+Y ; -60
+Y . -140
+Y o -140
+Y i -20
+Y - -140
+Y hy -140
+Y char173 -140
+Y e -140
+Y , -140
+Y : -60
+Y a -140
+Y O -85
+Y A -110
+a y -30
+a w -20
+a v -20
+b y -20
+b v -20
+b u -20
+b . -40
+b l -20
+b , -40
+b b -10
+c k -20
+c , -15
+, ' -100
+, rq -100
+e y -20
+e x -30
+e w -20
+e v -30
+e . -15
+e , -15
+f ' 50
+f rq 60
+f . -30
+f o -30
+f e -30
+f .i -28
+f , -30
+f a -30
+g r -10
+h y -30
+k o -20
+k e -20
+m y -15
+m u -10
+n y -15
+n v -20
+n u -10
+o y -30
+o x -30
+o w -15
+o v -15
+o . -40
+o , -40
+/o z -55
+char248 z -55
+/o y -70
+char248 y -70
+/o x -85
+char248 x -85
+/o w -70
+char248 w -70
+/o v -70
+char248 v -70
+/o u -55
+char248 u -55
+/o t -55
+char248 t -55
+/o s -55
+char248 s -55
+/o r -55
+char248 r -55
+/o q -55
+char248 q -55
+/o . -95
+char248 . -95
+/o p -55
+char248 p -55
+/o o -55
+char248 o -55
+/o n -55
+char248 n -55
+/o m -55
+char248 m -55
+/o l -55
+char248 l -55
+/o k -55
+char248 k -55
+/o j -55
+char248 j -55
+/o i -55
+char248 i -55
+/o h -55
+char248 h -55
+/o g -55
+char248 g -55
+/o f -55
+char248 f -55
+/o e -55
+char248 e -55
+/o d -55
+char248 d -55
+/o , -95
+char248 , -95
+/o c -55
+char248 c -55
+/o b -55
+char248 b -55
+/o a -55
+char248 a -55
+p y -30
+p . -35
+p , -35
+. ' -100
+. rq -100
+` ` -57
+` oq -57
+oq ` -57
+oq oq -57
+' s -50
+' r -50
+' ' -57
+' d -50
+r y 30
+r v 30
+r u 15
+r t 40
+r ; 30
+r . -50
+r p 30
+r n 25
+r m 25
+r l 15
+r k 15
+r i 15
+r , -50
+r : 30
+r a -10
+s w -30
+s . -15
+s , -15
+v . -80
+v o -25
+v e -25
+v , -80
+v a -25
+w . -60
+w o -10
+w e -10
+w , -60
+w a -15
+x e -30
+y . -100
+y o -20
+y e -20
+y , -100
+y a -20
+z o -15
+z e -15
+charset
+ha 469,688 2 0000 -- asciicircum
+ti 584,326 0 0001 -- asciitilde
+vS 667,929,19 2 0002 -- Scaron
+vZ 611,929 2 0003 -- Zcaron
+vs 500,734,15 2 0004 -- scaron
+vz 500,734 2 0005 -- zcaron
+:Y 667,901 2 0006 -- Ydieresis
+tm 1000,718 2 0007 -- trademark
+aq 191,718 2 0010 -- quotesingle
+space 278 0 0040
+! 278,718 2 0041 -- exclam
+" 355,718 2 0042 -- quotedbl
+# 556,688 2 0043 -- numbersign
+sh "
+$ 556,775,115 2 0044 -- dollar
+Do "
+% 889,703,19 2 0045 -- percent
+& 667,718,15 2 0046 -- ampersand
+' 222,718 2 0047 -- quoteright
+( 333,733,207 3 0050 -- parenleft
+) 333,733,207 3 0051 -- parenright
+* 389,718 2 0052 -- asterisk
++ 584,505 0 0053 -- plus
+, 278,106,147 0 0054 -- comma
+- 333,322 0 0055 -- hyphen
+hy "
+char173 "
+. 278,106 0 0056 -- period
+/ 278,737,19 2 0057 -- slash
+sl "
+0 556,703,19 2 0060 -- zero
+1 556,703 2 0061 -- one
+2 556,703 2 0062 -- two
+3 556,703,19 2 0063 -- three
+4 556,703 2 0064 -- four
+5 556,688,19 2 0065 -- five
+6 556,703,19 2 0066 -- six
+7 556,688 2 0067 -- seven
+8 556,703,19 2 0070 -- eight
+9 556,703,19 2 0071 -- nine
+: 278,516 0 0072 -- colon
+; 278,516,147 0 0073 -- semicolon
+< 584,495 0 0074 -- less
+= 584,390 0 0075 -- equal
+> 584,495 0 0076 -- greater
+? 556,727 2 0077 -- question
+@ 1015,737,19 2 0100 -- at
+at "
+A 667,718 2 0101 -- A
+B 667,718 2 0102 -- B
+C 722,737,19 2 0103 -- C
+D 722,718 2 0104 -- D
+E 667,718 2 0105 -- E
+F 611,718 2 0106 -- F
+G 778,737,19 2 0107 -- G
+H 722,718 2 0110 -- H
+I 278,718 2 0111 -- I
+J 500,718,19 2 0112 -- J
+K 667,718 2 0113 -- K
+L 556,718 2 0114 -- L
+M 833,718 2 0115 -- M
+N 722,718 2 0116 -- N
+O 778,737,19 2 0117 -- O
+P 667,718 2 0120 -- P
+Q 778,737,56 2 0121 -- Q
+R 722,718 2 0122 -- R
+S 667,737,19 2 0123 -- S
+T 611,718 2 0124 -- T
+U 722,718,19 2 0125 -- U
+V 667,718 2 0126 -- V
+W 944,718 2 0127 -- W
+X 667,718 2 0130 -- X
+Y 667,718 2 0131 -- Y
+Z 611,718 2 0132 -- Z
+[ 278,722,196 2 0133 -- bracketleft
+lB "
+\ 278,737,19 2 0134 -- backslash
+rs "
+] 278,722,196 2 0135 -- bracketright
+rB "
+a^ 333,734 2 0136 -- circumflex
+^ "
+_ 556,0,125 0 0137 -- underscore
+` 222,725 2 0140 -- quoteleft
+oq "
+a 556,538,15 0 0141 -- a
+b 556,718,15 2 0142 -- b
+c 500,538,15 0 0143 -- c
+d 556,718,15 2 0144 -- d
+e 556,538,15 0 0145 -- e
+f 278,728 2 0146 -- f
+g 556,538,220 1 0147 -- g
+h 556,718 2 0150 -- h
+i 222,718 2 0151 -- i
+j 222,718,210 3 0152 -- j
+k 500,718 2 0153 -- k
+l 222,718 2 0154 -- l
+m 833,538 0 0155 -- m
+n 556,538 0 0156 -- n
+o 556,538,14 0 0157 -- o
+p 556,538,207 1 0160 -- p
+q 556,538,207 1 0161 -- q
+r 333,538 0 0162 -- r
+s 500,538,15 0 0163 -- s
+t 278,669,7 2 0164 -- t
+u 556,523,15 0 0165 -- u
+v 500,523 0 0166 -- v
+w 722,523 0 0167 -- w
+x 500,523 0 0170 -- x
+y 500,523,214 1 0171 -- y
+z 500,523 0 0172 -- z
+lC 334,722,196 2 0173 -- braceleft
+{ "
+ba 260,737,19 2 0174 -- bar
+| "
+rC 334,722,196 2 0175 -- braceright
+} "
+a~ 333,722 2 0176 -- tilde
+~ "
+bq 222,106,149 0 0200 -- quotesinglbase
+Fo 556,446 0 0201 -- guillemotleft
+char171 "
+Fc 556,446 0 0202 -- guillemotright
+char187 "
+bu 350,517 0 0203 -- bullet
+Fn 556,737,207 3 0204 -- florin
+f/ 167,703,19 2 0205 -- fraction
+%0 1000,703,19 2 0206 -- perthousand
+dg 556,718,159 2 0207 -- dagger
+dd 556,718,159 2 0210 -- daggerdbl
+en 556,313 0 0211 -- endash
+em 1000,313 0 0212 -- emdash
+fi 500,728 2 0214 -- fi
+fl 500,728 2 0215 -- fl
+.i 278,523 0 0220 -- dotlessi
+ga 333,734 2 0222 -- grave
+a" 333,734 2 0223 -- hungarumlaut
+a. 333,706 2 0224 -- dotaccent
+ab 333,731 2 0225 -- breve
+ah 333,734 2 0226 -- caron
+ao 333,756 2 0227 -- ring
+ho 333,0,225 1 0230 -- ogonek
+lq 333,725 2 0231 -- quotedblleft
+rq 333,718 2 0232 -- quotedblright
+oe 944,538,15 0 0233 -- oe
+/l 222,718 2 0234 -- lslash
+Bq 333,106,149 0 0235 -- quotedblbase
+OE 1000,737,19 2 0236 -- OE
+/L 556,718 2 0237 -- Lslash
+r! 333,523,195 0 0241 -- exclamdown
+char161 "
+ct 556,623,115 0 0242 -- cent
+char162 "
+Po 556,718,16 2 0243 -- sterling
+char163 "
+Cs 556,603 0 0244 -- currency
+char164 "
+Ye 556,688 2 0245 -- yen
+char165 "
+bb 260,737,19 2 0246 -- brokenbar
+char166 "
+sc 556,737,191 2 0247 -- section
+char167 "
+ad 333,706 2 0250 -- dieresis
+char168 "
+co 737,737,19 2 0251 -- copyright
+char169 "
+Of 370,737 2 0252 -- ordfeminine
+char170 "
+fo 333,446 0 0253 -- guilsinglleft
+no 584,390 0 0254 -- logicalnot
+char172 "
+\- 584,289 0 0255 -- minus
+rg 737,737,19 2 0256 -- registered
+char174 "
+a- 333,684 2 0257 -- macron
+char175 "
+de 400,703 2 0260 -- degree
+char176 "
+char177 584,506 0 0261 -- plusminus
+S2 333,703 2 0262 -- twosuperior
+char178 "
+S3 333,703 2 0263 -- threesuperior
+char179 "
+aa 333,734 2 0264 -- acute
+char180 "
+char181 556,523,207 1 0265 -- mu
+ps 537,718,173 2 0266 -- paragraph
+char182 "
+char183 278,315 0 0267 -- periodcentered
+ac 333,0,225 1 0270 -- cedilla
+char184 "
+S1 333,703 2 0271 -- onesuperior
+char185 "
+Om 365,737 2 0272 -- ordmasculine
+char186 "
+fc 333,446 0 0273 -- guilsinglright
+14 834,703,19 2 0274 -- onequarter
+char188 "
+12 834,703,19 2 0275 -- onehalf
+char189 "
+34 834,703,19 2 0276 -- threequarters
+char190 "
+r? 611,525,201 0 0277 -- questiondown
+char191 "
+`A 667,929 2 0300 -- Agrave
+char192 "
+'A 667,929 2 0301 -- Aacute
+char193 "
+^A 667,929 2 0302 -- Acircumflex
+char194 "
+~A 667,917 2 0303 -- Atilde
+char195 "
+:A 667,901 2 0304 -- Adieresis
+char196 "
+oA 667,931 2 0305 -- Aring
+char197 "
+AE 1000,718 2 0306 -- AE
+char198 "
+,C 722,737,225 3 0307 -- Ccedilla
+char199 "
+`E 667,929 2 0310 -- Egrave
+char200 "
+'E 667,929 2 0311 -- Eacute
+char201 "
+^E 667,929 2 0312 -- Ecircumflex
+char202 "
+:E 667,901 2 0313 -- Edieresis
+char203 "
+`I 278,929 2 0314 -- Igrave
+char204 "
+'I 278,929 2 0315 -- Iacute
+char205 "
+^I 278,929 2 0316 -- Icircumflex
+char206 "
+:I 278,901 2 0317 -- Idieresis
+char207 "
+-D 722,718 2 0320 -- Eth
+char208 "
+~N 722,917 2 0321 -- Ntilde
+char209 "
+`O 778,929,19 2 0322 -- Ograve
+char210 "
+'O 778,929,19 2 0323 -- Oacute
+char211 "
+^O 778,929,19 2 0324 -- Ocircumflex
+char212 "
+~O 778,917,19 2 0325 -- Otilde
+char213 "
+:O 778,901,19 2 0326 -- Odieresis
+char214 "
+char215 584,506 0 0327 -- multiply
+/O 778,737,19 2 0330 -- Oslash
+char216 "
+`U 722,929,19 2 0331 -- Ugrave
+char217 "
+'U 722,929,19 2 0332 -- Uacute
+char218 "
+^U 722,929,19 2 0333 -- Ucircumflex
+char219 "
+:U 722,901,19 2 0334 -- Udieresis
+char220 "
+'Y 667,929 2 0335 -- Yacute
+char221 "
+TP 667,718 2 0336 -- Thorn
+char222 "
+ss 611,728,15 2 0337 -- germandbls
+char223 "
+`a 556,734,15 2 0340 -- agrave
+char224 "
+'a 556,734,15 2 0341 -- aacute
+char225 "
+^a 556,734,15 2 0342 -- acircumflex
+char226 "
+~a 556,722,15 2 0343 -- atilde
+char227 "
+:a 556,706,15 2 0344 -- adieresis
+char228 "
+oa 556,756,15 2 0345 -- aring
+char229 "
+ae 889,538,15 0 0346 -- ae
+char230 "
+,c 500,538,225 1 0347 -- ccedilla
+char231 "
+`e 556,734,15 2 0350 -- egrave
+char232 "
+'e 556,734,15 2 0351 -- eacute
+char233 "
+^e 556,734,15 2 0352 -- ecircumflex
+char234 "
+:e 556,706,15 2 0353 -- edieresis
+char235 "
+`i 278,734 2 0354 -- igrave
+char236 "
+'i 278,734 2 0355 -- iacute
+char237 "
+^i 278,734 2 0356 -- icircumflex
+char238 "
+:i 278,706 2 0357 -- idieresis
+char239 "
+Sd 556,737,15 2 0360 -- eth
+char240 "
+~n 556,722 2 0361 -- ntilde
+char241 "
+`o 556,734,14 2 0362 -- ograve
+char242 "
+'o 556,734,14 2 0363 -- oacute
+char243 "
+^o 556,734,14 2 0364 -- ocircumflex
+char244 "
+~o 556,722,14 2 0365 -- otilde
+char245 "
+:o 556,706,14 2 0366 -- odieresis
+char246 "
+char247 584,524,19 0 0367 -- divide
+/o 611,545,22 0 0370 -- oslash
+char248 "
+`u 556,734,15 2 0371 -- ugrave
+char249 "
+'u 556,734,15 2 0372 -- uacute
+char250 "
+^u 556,734,15 2 0373 -- ucircumflex
+char251 "
+:u 556,706,15 2 0374 -- udieresis
+char252 "
+'y 500,734,214 3 0375 -- yacute
+char253 "
+Tp 556,718,207 3 0376 -- thorn
+char254 "
+:y 500,706,214 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/Makefile.sub b/font/devps/Makefile.sub
new file mode 100644
index 00000000..a40f63f7
--- /dev/null
+++ b/font/devps/Makefile.sub
@@ -0,0 +1,35 @@
+DEV=ps
+DISTFILES=text.enc download \
+ S ZD ZDR SS AB ABI AI AR BMB BMBI BMI BMR \
+ CB CBI CI CR HB HBI HI HR HNB HNBI HNI HNR \
+ NB NBI NI NR PB PBI PI PR TB TBI TI TR ZCMI
+PSFILES=prologue symbolsl.pfa zapfdr.pfa
+DEVGENFILES=generate/Makefile generate/afmname generate/dingbatsmap \
+ generate/dingbatsrmap generate/lgreekmap generate/symbol.sed \
+ generate/symbolchars generate/symbolsl.afm generate/textmap
+DEVFILES=DESC $(PSFILES) $(DISTFILES) $(DEVGENFILES)
+
+CLEANADD=DESC $(PSFILES)
+
+DESC: DESC.in
+ -rm -f DESC
+ cat $(srcdir)/DESC.in >DESC
+ echo broken $(BROKEN_SPOOLER_FLAGS) >>DESC
+ if test "$(PAGE)" = A4; then \
+ echo "paperlength 841890" >>DESC; \
+ else \
+ echo "paperlength 792000" >>DESC; \
+ fi
+ test -z '$(PSPRINT)' || echo print '$(PSPRINT)' >>DESC
+
+fonts: DESC
+ $(MAKE) -f $(srcdir)/generate/Makefile \
+ srcdir=$(srcdir)/generate DESC=$(srcdir)/DESC.in
+
+prologue: prologue.ps
+zapfdr.pfa: zapfdr.ps
+symbolsl.pfa: symbolsl.ps
+
+$(PSFILES):
+ -rm -f $@
+ sed -f $(srcdir)/psstrip.sed $? >$@
diff --git a/font/devps/NB b/font/devps/NB
new file mode 100644
index 00000000..e5fb4360
--- /dev/null
+++ b/font/devps/NB
@@ -0,0 +1,446 @@
+name NB
+internalname NewCenturySchlbk-Bold
+spacewidth 287
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -74
+A w -74
+A v -74
+A ' -74
+A Y -92
+A W -74
+A V -92
+A T -55
+F . -111
+F , -111
+F A -74
+L y -55
+L ' -55
+L Y -92
+L W -74
+L V -92
+L T -55
+P . -129
+P , -129
+P A -74
+R y -18
+R Y -37
+R W -37
+R V -37
+T y -52
+T w -71
+T u -71
+T ; -55
+T s -62
+T r -62
+T . -92
+T o -92
+T i -25
+T - -92
+T hy -92
+T char173 -92
+T e -92
+T , -92
+T : -55
+T c -81
+T a -62
+T A -55
+V y -92
+V u -74
+V ; -74
+V r -74
+V . -129
+V o -92
+V i -44
+V - -92
+V hy -92
+V char173 -92
+V e -92
+V : -74
+V a -92
+V A -92
+W y -74
+W u -55
+W ; -37
+W r -55
+W . -111
+W o -55
+W i -37
+W - -37
+W hy -37
+W char173 -37
+W e -55
+W , -111
+W : -37
+W a -74
+W A -74
+Y v -81
+Y u -92
+Y ; -92
+Y q -111
+Y . -111
+Y p -81
+Y o -111
+Y i -44
+Y - -111
+Y hy -111
+Y char173 -111
+Y e -111
+Y , -111
+Y : -92
+Y a -111
+Y A -92
+f ' 94
+1 1 -55
+` ` -18
+` oq -18
+oq ` -18
+oq oq -18
+' t -18
+' s -37
+' ' -18
+r ' 55
+r . -74
+r - -18
+r hy -18
+r char173 -18
+r , -74
+v . -111
+v , -111
+w . -92
+w , -92
+y . -111
+y , -111
+charset
+ha 606,722 2 0000 -- asciicircum
+ti 606,347 0 0001 -- asciitilde
+vS 667,970,15 2 0002 -- Scaron
+vZ 667,970 2 0003 -- Zcaron
+vs 500,723,15 2 0004 -- scaron
+vz 537,723 2 0005 -- zcaron
+:Y 722,940 2 0006 -- Ydieresis
+tm 1000,722 2 0007 -- trademark
+aq 241,737 2 0010 -- quotesingle
+space 287 0 0040
+! 296,737,15 2 0041 -- exclam
+" 333,737 2 0042 -- quotedbl
+# 574,705 2 0043 -- numbersign
+sh "
+$ 574,801,140 2 0044 -- dollar
+Do "
+% 833,704,18 2 0045 -- percent
+& 852,737,15 2 0046 -- ampersand
+' 241,737 2 0047 -- quoteright
+( 389,737,122 2 0050 -- parenleft
+) 389,737,122 2 0051 -- parenright
+* 500,738 2 0052 -- asterisk
++ 606,514 0 0053 -- plus
+, 278,169,189 0 0054 -- comma
+- 333,309 0 0055 -- hyphen
+hy "
+char173 "
+. 278,172,15 0 0056 -- period
+/ 278,737,15 2 0057 -- slash
+sl "
+0 574,705,15 2 0060 -- zero
+1 574,705 2 0061 -- one
+2 574,705,4 2 0062 -- two
+3 574,705,15 2 0063 -- three
+4 574,705 2 0064 -- four
+5 574,705,15 2 0065 -- five
+6 574,705,15 2 0066 -- six
+7 574,705,15 2 0067 -- seven
+8 574,705,15 2 0070 -- eight
+9 574,705,15 2 0071 -- nine
+: 278,485,15 0 0072 -- colon
+; 278,485,189 0 0073 -- semicolon
+< 606,538,13 0 0074 -- less
+= 606,399 0 0075 -- equal
+> 606,538,13 0 0076 -- greater
+? 500,737,15 2 0077 -- question
+@ 747,737,15 2 0100 -- at
+at "
+A 759,737 2 0101 -- A
+B 778,722 2 0102 -- B
+C 778,737,15 2 0103 -- C
+D 833,722 2 0104 -- D
+E 759,722 2 0105 -- E
+F 722,722 2 0106 -- F
+G 833,737,15 2 0107 -- G
+H 870,722 2 0110 -- H
+I 444,722 2 0111 -- I
+J 648,722,15 2 0112 -- J
+K 815,722 2 0113 -- K
+L 722,722 2 0114 -- L
+M 981,722 2 0115 -- M
+N 833,722,8 2 0116 -- N
+O 833,737,15 2 0117 -- O
+P 759,722 2 0120 -- P
+Q 833,737,189 2 0121 -- Q
+R 815,722,15 2 0122 -- R
+S 667,737,15 2 0123 -- S
+T 722,722 2 0124 -- T
+U 833,722,15 2 0125 -- U
+V 759,722,15 2 0126 -- V
+W 981,722,15 2 0127 -- W
+X 722,722 2 0130 -- X
+Y 722,722 2 0131 -- Y
+Z 667,722 2 0132 -- Z
+[ 389,722,113 2 0133 -- bracketleft
+lB "
+\ 606,737 2 0134 -- backslash
+rs "
+] 389,722,113 2 0135 -- bracketright
+rB "
+a^ 333,723 2 0136 -- circumflex
+^ "
+_ 500,0,148 0 0137 -- underscore
+` 241,747 2 0140 -- quoteleft
+oq "
+a 611,485,15 0 0141 -- a
+b 648,737,15 2 0142 -- b
+c 556,485,15 0 0143 -- c
+d 667,737,15 2 0144 -- d
+e 574,485,15 0 0145 -- e
+f 389,737 2 0146 -- f
+g 611,536,205 1 0147 -- g
+h 685,737 2 0150 -- h
+i 370,737 2 0151 -- i
+j 352,737,205 3 0152 -- j
+k 667,737 2 0153 -- k
+l 352,737 2 0154 -- l
+m 963,485 0 0155 -- m
+n 685,485 0 0156 -- n
+o 611,485,15 0 0157 -- o
+p 667,485,205 1 0160 -- p
+q 648,485,205 1 0161 -- q
+r 519,485 0 0162 -- r
+s 500,485,15 0 0163 -- s
+t 426,675,15 2 0164 -- t
+u 685,475,15 0 0165 -- u
+v 611,475,8 0 0166 -- v
+w 889,475,8 0 0167 -- w
+x 611,475 0 0170 -- x
+y 611,475,207 1 0171 -- y
+z 537,475 0 0172 -- z
+lC 389,723,111 2 0173 -- braceleft
+{ "
+ba 606,737 2 0174 -- bar
+| "
+rC 389,723,111 2 0175 -- braceright
+} "
+a~ 333,704 2 0176 -- tilde
+~ "
+bq 241,169,189 0 0200 -- quotesinglbase
+Fo 500,405 0 0201 -- guillemotleft
+char171 "
+Fc 500,405 0 0202 -- guillemotright
+char187 "
+bu 606,511 0 0203 -- bullet
+Fn 574,737,205 3 0204 -- florin
+f/ 167,705 2 0205 -- fraction
+%0 1000,694,27 2 0206 -- perthousand
+dg 500,737,88 2 0207 -- dagger
+dd 500,736,89 2 0210 -- daggerdbl
+en 500,296 0 0211 -- endash
+em 1000,296 0 0212 -- emdash
+fi 685,737 2 0214 -- fi
+fl 685,737 2 0215 -- fl
+.i 370,475 0 0220 -- dotlessi
+ga 333,734 2 0222 -- grave
+a" 333,737 2 0223 -- hungarumlaut
+a. 333,693 2 0224 -- dotaccent
+ab 333,712 2 0225 -- breve
+ah 333,723 2 0226 -- caron
+ao 333,760 2 0227 -- ring
+ho 333,0,163 0 0230 -- ogonek
+lq 481,747 2 0231 -- quotedblleft
+rq 481,737 2 0232 -- quotedblright
+oe 907,485,15 0 0233 -- oe
+/l 352,737 2 0234 -- lslash
+Bq 481,169,189 0 0235 -- quotedblbase
+OE 1000,722 2 0236 -- OE
+/L 722,722 2 0237 -- Lslash
+r! 296,547,205 1 0241 -- exclamdown
+char161 "
+ct 574,566,108 0 0242 -- cent
+char162 "
+Po 574,705,15 2 0243 -- sterling
+char163 "
+Cs 574,591 0 0244 -- currency
+char164 "
+Ye 574,705 2 0245 -- yen
+char165 "
+bb 606,737 2 0246 -- brokenbar
+char166 "
+sc 500,737,86 2 0247 -- section
+char167 "
+ad 333,693 2 0250 -- dieresis
+char168 "
+co 747,737,15 2 0251 -- copyright
+char169 "
+Of 367,737 2 0252 -- ordfeminine
+char170 "
+fo 333,405 0 0253 -- guilsinglleft
+no 606,399 0 0254 -- logicalnot
+char172 "
+\- 606,302 0 0255 -- minus
+rg 747,737,15 2 0256 -- registered
+char174 "
+a- 333,663 0 0257 -- macron
+char175 "
+de 400,705 2 0260 -- degree
+char176 "
+char177 606,514 0 0261 -- plusminus
+S2 344,705 2 0262 -- twosuperior
+char178 "
+S3 344,705 2 0263 -- threesuperior
+char179 "
+aa 333,737 2 0264 -- acute
+char180 "
+char181 685,475,205 1 0265 -- mu
+ps 747,722 2 0266 -- paragraph
+char182 "
+char183 278,338 0 0267 -- periodcentered
+ac 333,0,221 1 0270 -- cedilla
+char184 "
+S1 344,705 2 0271 -- onesuperior
+char185 "
+Om 367,737 2 0272 -- ordmasculine
+char186 "
+fc 333,408 0 0273 -- guilsinglright
+14 861,705 2 0274 -- onequarter
+char188 "
+12 861,705,2 2 0275 -- onehalf
+char189 "
+34 861,705 2 0276 -- threequarters
+char190 "
+r? 500,547,205 1 0277 -- questiondown
+char191 "
+`A 759,981 2 0300 -- Agrave
+char192 "
+'A 759,984 2 0301 -- Aacute
+char193 "
+^A 759,970 2 0302 -- Acircumflex
+char194 "
+~A 759,951 2 0303 -- Atilde
+char195 "
+:A 759,940 2 0304 -- Adieresis
+char196 "
+oA 759,1007 2 0305 -- Aring
+char197 "
+AE 981,722 2 0306 -- AE
+char198 "
+,C 778,737,221 3 0307 -- Ccedilla
+char199 "
+`E 759,981 2 0310 -- Egrave
+char200 "
+'E 759,984 2 0311 -- Eacute
+char201 "
+^E 759,970 2 0312 -- Ecircumflex
+char202 "
+:E 759,940 2 0313 -- Edieresis
+char203 "
+`I 444,981 2 0314 -- Igrave
+char204 "
+'I 444,984 2 0315 -- Iacute
+char205 "
+^I 444,970 2 0316 -- Icircumflex
+char206 "
+:I 444,940 2 0317 -- Idieresis
+char207 "
+-D 833,722 2 0320 -- Eth
+char208 "
+~N 833,951,8 2 0321 -- Ntilde
+char209 "
+`O 833,981,15 2 0322 -- Ograve
+char210 "
+'O 833,984,15 2 0323 -- Oacute
+char211 "
+^O 833,970,15 2 0324 -- Ocircumflex
+char212 "
+~O 833,951,15 2 0325 -- Otilde
+char213 "
+:O 833,940,15 2 0326 -- Odieresis
+char214 "
+char215 606,504 0 0327 -- multiply
+/O 833,768,60 2 0330 -- Oslash
+char216 "
+`U 833,981,15 2 0331 -- Ugrave
+char217 "
+'U 833,984,15 2 0332 -- Uacute
+char218 "
+^U 833,970,15 2 0333 -- Ucircumflex
+char219 "
+:U 833,940,15 2 0334 -- Udieresis
+char220 "
+'Y 722,984 2 0335 -- Yacute
+char221 "
+TP 759,722 2 0336 -- Thorn
+char222 "
+ss 611,737,15 2 0337 -- germandbls
+char223 "
+`a 611,734,15 2 0340 -- agrave
+char224 "
+'a 611,737,15 2 0341 -- aacute
+char225 "
+^a 611,723,15 2 0342 -- acircumflex
+char226 "
+~a 611,704,15 2 0343 -- atilde
+char227 "
+:a 611,693,15 2 0344 -- adieresis
+char228 "
+oa 611,760,15 2 0345 -- aring
+char229 "
+ae 870,485,15 0 0346 -- ae
+char230 "
+,c 556,485,221 1 0347 -- ccedilla
+char231 "
+`e 574,734,15 2 0350 -- egrave
+char232 "
+'e 574,737,15 2 0351 -- eacute
+char233 "
+^e 574,723,15 2 0352 -- ecircumflex
+char234 "
+:e 574,693,15 2 0353 -- edieresis
+char235 "
+`i 370,734 2 0354 -- igrave
+char236 "
+'i 370,737 2 0355 -- iacute
+char237 "
+^i 370,723 2 0356 -- icircumflex
+char238 "
+:i 370,693 2 0357 -- idieresis
+char239 "
+Sd 611,737,15 2 0360 -- eth
+char240 "
+~n 685,704 2 0361 -- ntilde
+char241 "
+`o 611,734,15 2 0362 -- ograve
+char242 "
+'o 611,737,15 2 0363 -- oacute
+char243 "
+^o 611,723,15 2 0364 -- ocircumflex
+char244 "
+~o 611,704,15 2 0365 -- otilde
+char245 "
+:o 611,693,15 2 0366 -- odieresis
+char246 "
+char247 606,514 0 0367 -- divide
+/o 611,565,111 0 0370 -- oslash
+char248 "
+`u 685,734,15 2 0371 -- ugrave
+char249 "
+'u 685,737,15 2 0372 -- uacute
+char250 "
+^u 685,723,15 2 0373 -- ucircumflex
+char251 "
+:u 685,693,15 2 0374 -- udieresis
+char252 "
+'y 611,737,207 3 0375 -- yacute
+char253 "
+Tp 667,675,205 3 0376 -- thorn
+char254 "
+:y 611,693,207 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/NBI b/font/devps/NBI
new file mode 100644
index 00000000..f27fe1d5
--- /dev/null
+++ b/font/devps/NBI
@@ -0,0 +1,447 @@
+name NBI
+internalname NewCenturySchlbk-BoldItalic
+slant 16
+spacewidth 287
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -50
+A w -20
+A v -20
+A ' -74
+A Y -74
+A W -92
+A V -111
+A T -74
+F . -129
+F f -18
+F , -129
+F A -74
+L y -55
+L ' -55
+L Y -55
+L W -55
+L V -74
+L T -55
+P . -129
+P , -129
+P A -92
+R y -50
+R Y -20
+R W -20
+R V -20
+R T -20
+T y -89
+T w -89
+T u -89
+T ; -72
+T s -89
+T r -89
+T . -111
+T o -109
+T i -71
+T - -129
+T hy -129
+T char173 -129
+T e -109
+T , -111
+T : -62
+T c -89
+T a -74
+T A -50
+V y -89
+V u -89
+V ; -74
+V r -109
+V . -111
+V o -129
+V i -72
+V - -74
+V hy -74
+V char173 -74
+V e -129
+V , -111
+V : -74
+V a -129
+V A -129
+W y -74
+W u -74
+W ; -37
+W r -74
+W . -55
+W o -74
+W i -74
+W - -37
+W hy -37
+W char173 -37
+W e -74
+W , -55
+W : -37
+W a -74
+W A -89
+Y v -129
+Y u -129
+Y ; -111
+Y q -129
+Y . -129
+Y p -129
+Y o -129
+Y i -90
+Y - -129
+Y hy -129
+Y char173 -129
+Y e -129
+Y , -129
+Y : -111
+Y a -129
+Y A -111
+f ' 74
+1 1 -74
+` ` -18
+` oq -18
+oq ` -18
+oq oq -18
+' t -37
+' s -37
+' ' -18
+r ' 55
+r . -129
+r , -129
+v . -37
+v , -37
+w . -37
+w , -37
+y . -55
+y , -55
+charset
+ha 606,722,0,0,-2 2 0000 -- asciicircum
+ti 606,353,0,0,-1 0 0001 -- asciitilde
+vS 685,954,15,31,49,31 2 0002 -- Scaron
+vZ 704,954,0,61,79,61 2 0003 -- Zcaron
+vs 481,709,15,46,48,46 2 0004 -- scaron
+vz 519,709,15,27,69,27 2 0005 -- zcaron
+:Y 704,930,0,123,35,109 2 0006 -- Ydieresis
+tm 950,722,0,82,8,82 2 0007 -- trademark
+aq 287,736,0,32,-50,32 2 0010 -- quotesingle
+space 287 0 0040
+! 333,737,15,53,47,53 2 0041 -- exclam
+" 400,737,0,157,-50,109 2 0042 -- quotedbl
+# 574,705,0,9,9,9 2 0043 -- numbersign
+sh "
+$ 574,799,143,35,47,35 2 0044 -- dollar
+Do "
+% 889,721,34,0,-1 2 0045 -- percent
+& 889,737,15,0,19 2 0046 -- ampersand
+' 259,739,0,92,-20,92 2 0047 -- quoteright
+( 407,740,123,95,-21,95 2 0050 -- parenleft
+) 407,740,123,0,120 2 0051 -- parenright
+* 500,704,0,22,18,22 2 0052 -- asterisk
++ 606,505,0,0,9 0 0053 -- plus
+, 287,159,190,0,98 0 0054 -- comma
+- 333,297,0,0,40 0 0055 -- hyphen
+hy "
+char173 "
+. 287,159,15,0,38 0 0056 -- period
+/ 278,737,15,83,75,83 2 0057 -- slash
+sl "
+0 574,705,15,29,29,29 2 0060 -- zero
+1 574,705,0,0,25 2 0061 -- one
+2 574,705,0,14,90,14 2 0062 -- two
+3 574,705,15,14,55,14 2 0063 -- three
+4 574,705,0,20,63,20 2 0064 -- four
+5 574,705,15,49,50,49 2 0065 -- five
+6 574,705,15,49,20,49 2 0066 -- six
+7 574,705,15,69,-14,69 2 0067 -- seven
+8 574,705,15,27,50,27 2 0070 -- eight
+9 574,705,15,20,49,20 2 0071 -- nine
+: 287,477,15,20,52,20 0 0072 -- colon
+; 287,477,190,20,89,20 0 0073 -- semicolon
+< 606,524,14,0,36 0 0074 -- less
+= 606,402,0,0,9 0 0075 -- equal
+> 606,524,14,0,12 0 0076 -- greater
+? 481,737,15,21,-29,21 2 0077 -- question
+@ 747,737,15,25,28,25 2 0100 -- at
+at "
+A 741,737,0,25,125,25 2 0101 -- A
+B 759,722,0,11,100,11 2 0102 -- B
+C 759,737,15,50,15,50 2 0103 -- C
+D 833,722,0,13,99,13 2 0104 -- D
+E 741,722,0,37,91,37 2 0105 -- E
+F 704,722,0,72,91,72 2 0106 -- F
+G 815,737,15,37,16,37 2 0107 -- G
+H 870,722,0,92,91,92 2 0110 -- H
+I 444,722,0,92,91,92 2 0111 -- I
+J 667,722,15,101,59,101 2 0112 -- J
+K 778,722,0,104,91,104 2 0113 -- K
+L 704,722,0,16,91,16 2 0114 -- L
+M 944,722,0,94,74,94 2 0115 -- M
+N 852,722,16,110,107,109 2 0116 -- N
+O 833,737,15,14,14,14 2 0117 -- O
+P 741,722,0,40,88,40 2 0120 -- P
+Q 833,737,186,13,15,13 2 0121 -- Q
+R 796,722,15,5,91,5 2 0122 -- R
+S 685,737,15,31,49,31 2 0123 -- S
+T 722,722,0,90,6,90 2 0124 -- T
+U 833,722,15,112,-38,109 2 0125 -- U
+V 741,722,15,111,18,109 2 0126 -- V
+W 944,722,15,100,10,100 2 0127 -- W
+X 741,722,0,120,122,109 2 0130 -- X
+Y 704,722,0,123,35,109 2 0131 -- Y
+Z 704,722,0,61,79,61 2 0132 -- Z
+[ 407,737,110,75,81,75 2 0133 -- bracketleft
+lB "
+\ 606,737,0,0,-31 2 0134 -- backslash
+rs "
+] 407,737,110,57,99,57 2 0135 -- bracketright
+rB "
+a^ 333,709,0,82,27,82 2 0136 -- circumflex
+^ "
+_ 500,0,129,50,50,50 0 0137 -- underscore
+` 259,747,0,61,11,61 2 0140 -- quoteleft
+oq "
+a 667,477,15,29,35,29 0 0141 -- a
+b 611,737,15,0,22 2 0142 -- b
+c 537,477,15,0,47 0 0143 -- c
+d 667,737,15,46,50,46 2 0144 -- d
+e 519,477,15,9,52,9 0 0145 -- e
+f 389,737,205,211,98,109 3 0146 -- f
+g 611,529,205,41,116,41 1 0147 -- g
+h 685,737,15,2,50,2 2 0150 -- h
+i 389,737,15,4,22,4 2 0151 -- i
+j 370,737,205,61,220,61 3 0152 -- j
+k 648,737,15,0,55 2 0153 -- k
+l 389,737,15,31,24,31 2 0154 -- l
+m 944,477,15,26,41,26 0 0155 -- m
+n 685,477,15,7,47,7 0 0156 -- n
+o 574,477,15,16,40,16 0 0157 -- o
+p 648,477,205,0,168 1 0160 -- p
+q 630,477,205,7,50,7 1 0161 -- q
+r 519,486,0,55,47,55 0 0162 -- r
+s 481,477,15,6,48,6 0 0163 -- s
+t 407,650,15,47,26,47 2 0164 -- t
+u 685,477,15,4,12,4 0 0165 -- u
+v 556,477,15,0,18 0 0166 -- v
+w 833,477,15,5,28,5 0 0167 -- w
+x 574,477,15,47,99,47 0 0170 -- x
+y 519,477,205,23,116,23 1 0171 -- y
+z 519,477,15,2,69,2 0 0172 -- z
+lC 407,738,115,45,-2,45 2 0173 -- braceleft
+{ "
+ba 606,737,0,0,-212 2 0174 -- bar
+| "
+rC 407,738,115,0,80 2 0175 -- braceright
+} "
+a~ 333,683,0,121,16,109 2 0176 -- tilde
+~ "
+bq 259,159,191,0,93 0 0200 -- quotesinglbase
+Fo 481,409,0,0,85 0 0201 -- guillemotleft
+char171 "
+Fc 481,408,0,25,56,25 0 0202 -- guillemotright
+char187 "
+bu 606,537,0,0,-59 0 0203 -- bullet
+Fn 574,737,205,64,77,64 3 0204 -- florin
+f/ 167,705,15,216,216,109 2 0205 -- fraction
+%0 1167,721,34,34,24,34 2 0206 -- perthousand
+dg 500,737,146,60,0,60 2 0207 -- dagger
+dd 500,737,147,64,98,64 2 0210 -- daggerdbl
+en 500,286,0,68,68,68 0 0211 -- endash
+em 1000,286,0,68,68,68 0 0212 -- emdash
+fi 685,737,205,11,120,11 3 0214 -- fi
+fl 685,737,205,46,120,46 3 0215 -- fl
+.i 389,477,15,14,12,14 0 0220 -- dotlessi
+ga 333,719,0,11,-24,11 2 0222 -- grave
+a" 333,719,0,189,27,109 2 0223 -- hungarumlaut
+a. 333,685,0,5,-95,5 2 0224 -- dotaccent
+ab 333,698,0,107,-17,107 2 0225 -- breve
+ah 333,709,0,120,-10,109 2 0226 -- caron
+ao 333,745,0,149,-167,109 2 0227 -- ring
+ho 333,0,155,0,-18 0 0230 -- ogonek
+lq 481,747,0,91,-2,91 2 0231 -- quotedblleft
+rq 481,739,0,102,-11,102 2 0232 -- quotedblright
+oe 852,477,15,8,55,8 0 0233 -- oe
+/l 389,737,15,58,24,58 2 0234 -- lslash
+Bq 481,159,191,0,120 0 0235 -- quotedblbase
+OE 963,722,0,67,31,67 2 0236 -- OE
+/L 704,722,0,16,91,16 2 0237 -- Lslash
+r! 333,544,205,6,89,6 1 0241 -- exclamdown
+char161 "
+ct 574,600,124,0,20 0 0242 -- cent
+char162 "
+Po 574,705,15,42,68,42 2 0243 -- sterling
+char163 "
+Cs 574,612,0,22,10,22 0 0244 -- currency
+char164 "
+Ye 574,705,0,111,27,109 2 0245 -- yen
+char165 "
+bb 606,737,0,0,-212 2 0246 -- brokenbar
+char166 "
+sc 500,737,145,55,90,55 2 0247 -- section
+char167 "
+ad 333,685,0,109,16,109 2 0250 -- dieresis
+char168 "
+co 747,737,15,26,27,26 2 0251 -- copyright
+char169 "
+Of 412,737,0,87,21,87 2 0252 -- ordfeminine
+char170 "
+fo 278,409,0,0,85 0 0253 -- guilsinglleft
+no 606,402,0,0,9 0 0254 -- logicalnot
+char172 "
+\- 606,304,0,0,9 0 0255 -- minus
+rg 747,737,15,26,27,26 2 0256 -- registered
+char174 "
+a- 333,649,0,104,18,104 2 0257 -- macron
+char175 "
+de 400,705,0,20,-20,20 2 0260 -- degree
+char176 "
+char177 606,505,0,0,9 0 0261 -- plusminus
+S2 344,705,0,66,66,66 2 0262 -- twosuperior
+char178 "
+S3 344,705,0,54,54,54 2 0263 -- threesuperior
+char179 "
+aa 333,719,0,88,-73,88 2 0264 -- acute
+char180 "
+char181 685,477,205,4,140,4 1 0265 -- mu
+ps 650,737,0,61,-17,61 2 0266 -- paragraph
+char182 "
+char183 287,342,0,0,9 0 0267 -- periodcentered
+ac 333,3,220,0,137 1 0270 -- cedilla
+char184 "
+S1 344,705,0,29,29,29 2 0271 -- onesuperior
+char185 "
+Om 356,737,0,77,21,77 2 0272 -- ordmasculine
+char186 "
+fc 278,408,0,25,56,25 0 0273 -- guilsinglright
+14 861,705,15,15,29,15 2 0274 -- onequarter
+char188 "
+12 861,705,15,46,29,46 2 0275 -- onehalf
+char189 "
+34 861,705,15,15,54,15 2 0276 -- threequarters
+char190 "
+r? 481,544,205,0,49 1 0277 -- questiondown
+char191 "
+`A 741,964,0,25,125,25 2 0300 -- Agrave
+char192 "
+'A 741,964,0,25,125,25 2 0301 -- Aacute
+char193 "
+^A 741,954,0,25,125,25 2 0302 -- Acircumflex
+char194 "
+~A 741,928,0,25,125,25 2 0303 -- Atilde
+char195 "
+:A 741,930,0,25,125,25 2 0304 -- Adieresis
+char196 "
+oA 741,990,0,25,125,25 2 0305 -- Aring
+char197 "
+AE 889,722,0,64,131,64 2 0306 -- AE
+char198 "
+,C 759,737,220,50,15,50 3 0307 -- Ccedilla
+char199 "
+`E 741,964,0,37,91,37 2 0310 -- Egrave
+char200 "
+'E 741,964,0,37,91,37 2 0311 -- Eacute
+char201 "
+^E 741,954,0,37,91,37 2 0312 -- Ecircumflex
+char202 "
+:E 741,930,0,37,91,37 2 0313 -- Edieresis
+char203 "
+`I 444,964,0,92,91,92 2 0314 -- Igrave
+char204 "
+'I 444,964,0,92,91,92 2 0315 -- Iacute
+char205 "
+^I 444,954,0,92,91,92 2 0316 -- Icircumflex
+char206 "
+:I 444,930,0,104,91,104 2 0317 -- Idieresis
+char207 "
+-D 833,722,0,13,99,13 2 0320 -- Eth
+char208 "
+~N 852,928,16,110,107,109 2 0321 -- Ntilde
+char209 "
+`O 833,964,15,14,14,14 2 0322 -- Ograve
+char210 "
+'O 833,964,15,14,14,14 2 0323 -- Oacute
+char211 "
+^O 833,954,15,14,14,14 2 0324 -- Ocircumflex
+char212 "
+~O 833,928,15,14,14,14 2 0325 -- Otilde
+char213 "
+:O 833,930,15,14,14,14 2 0326 -- Odieresis
+char214 "
+char215 606,507,0,0,9 0 0327 -- multiply
+/O 833,775,82,14,33,14 2 0330 -- Oslash
+char216 "
+`U 833,964,15,112,-38,109 2 0331 -- Ugrave
+char217 "
+'U 833,964,15,112,-38,109 2 0332 -- Uacute
+char218 "
+^U 833,954,15,112,-38,109 2 0333 -- Ucircumflex
+char219 "
+:U 833,930,15,112,-38,109 2 0334 -- Udieresis
+char220 "
+'Y 704,964,0,123,35,109 2 0335 -- Yacute
+char221 "
+TP 741,722,0,0,88 2 0336 -- Thorn
+char222 "
+ss 574,737,205,0,116 3 0337 -- germandbls
+char223 "
+`a 667,719,15,29,35,29 2 0340 -- agrave
+char224 "
+'a 667,719,15,29,35,29 2 0341 -- aacute
+char225 "
+^a 667,709,15,29,35,29 2 0342 -- acircumflex
+char226 "
+~a 667,683,15,29,35,29 2 0343 -- atilde
+char227 "
+:a 667,685,15,29,35,29 2 0344 -- adieresis
+char228 "
+oa 667,745,15,29,35,29 2 0345 -- aring
+char229 "
+ae 815,477,15,9,69,9 0 0346 -- ae
+char230 "
+,c 537,477,220,0,47 1 0347 -- ccedilla
+char231 "
+`e 519,719,15,9,52,9 2 0350 -- egrave
+char232 "
+'e 519,719,15,9,52,9 2 0351 -- eacute
+char233 "
+^e 519,709,15,9,52,9 2 0352 -- ecircumflex
+char234 "
+:e 519,685,15,26,52,26 2 0353 -- edieresis
+char235 "
+`i 389,719,15,14,12,14 2 0354 -- igrave
+char236 "
+'i 389,719,15,60,12,60 2 0355 -- iacute
+char237 "
+^i 389,709,15,44,12,44 2 0356 -- icircumflex
+char238 "
+:i 389,685,15,71,12,71 2 0357 -- idieresis
+char239 "
+Sd 574,737,15,16,40,16 2 0360 -- eth
+char240 "
+~n 685,683,15,7,47,7 2 0361 -- ntilde
+char241 "
+`o 574,719,15,16,40,16 2 0362 -- ograve
+char242 "
+'o 574,719,15,16,40,16 2 0363 -- oacute
+char243 "
+^o 574,709,15,16,40,16 2 0364 -- ocircumflex
+char244 "
+~o 574,683,15,16,40,16 2 0365 -- otilde
+char245 "
+:o 574,685,15,16,40,16 2 0366 -- odieresis
+char246 "
+char247 606,505,0,0,9 0 0367 -- divide
+/o 574,578,126,16,40,16 0 0370 -- oslash
+char248 "
+`u 685,719,15,4,12,4 2 0371 -- ugrave
+char249 "
+'u 685,719,15,4,12,4 2 0372 -- uacute
+char250 "
+^u 685,709,15,4,12,4 2 0373 -- ucircumflex
+char251 "
+:u 685,685,15,4,12,4 2 0374 -- udieresis
+char252 "
+'y 519,719,205,23,116,23 3 0375 -- yacute
+char253 "
+Tp 648,650,205,0,168 3 0376 -- thorn
+char254 "
+:y 519,685,205,23,116,23 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/NI b/font/devps/NI
new file mode 100644
index 00000000..75f7fc44
--- /dev/null
+++ b/font/devps/NI
@@ -0,0 +1,447 @@
+name NI
+internalname NewCenturySchlbk-Italic
+slant 16
+spacewidth 278
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -54
+A w -20
+A v -20
+A ' -74
+A Y -74
+A W -92
+A V -111
+A T -74
+F . -129
+F f -18
+F , -129
+F A -74
+L y -55
+L ' -55
+L Y -55
+L W -55
+L V -74
+L T -55
+P . -129
+P , -129
+P A -92
+R y -54
+R Y -74
+R W -55
+R V -20
+R T -20
+T y -89
+T w -89
+T u -89
+T ; -92
+T s -89
+T r -89
+T . -111
+T o -89
+T i -71
+T - -129
+T hy -129
+T char173 -129
+T e -89
+T , -111
+T : -92
+T c -89
+T a -74
+T A -18
+V y -109
+V u -109
+V ; -74
+V r -109
+V . -111
+V o -129
+V i -62
+V - -74
+V hy -74
+V char173 -74
+V e -129
+V , -140
+V : -74
+V a -129
+V A -111
+W y -74
+W u -74
+W ; -37
+W r -74
+W . -55
+W o -74
+W i -74
+W - -37
+W hy -37
+W char173 -37
+W e -74
+W , -55
+W : -37
+W a -74
+W A -74
+Y v -99
+Y u -99
+Y ; -111
+Y q -129
+Y . -129
+Y p -129
+Y o -129
+Y i -70
+Y - -129
+Y hy -129
+Y char173 -129
+Y e -129
+Y , -129
+Y : -111
+Y a -129
+Y A -74
+f ' 94
+1 1 -74
+` ` -18
+` oq -18
+oq ` -18
+oq oq -18
+' t -37
+' s -37
+' ' -18
+r ' 55
+r . -129
+r , -129
+v . -37
+v , -37
+w . -37
+w , -37
+y . -55
+y , -55
+charset
+ha 606,722,0,0,-2 2 0000 -- asciicircum
+ti 606,335,0,0,9 0 0001 -- asciitilde
+vS 667,944,15,15,50,15 2 0002 -- Scaron
+vZ 667,944,0,50,75,50 2 0003 -- Zcaron
+vs 444,688,15,40,51,40 2 0004 -- scaron
+vz 463,688,15,30,83,30 2 0005 -- zcaron
+:Y 685,900,0,123,18,107 2 0006 -- Ydieresis
+tm 950,722,0,71,2,71 2 0007 -- trademark
+aq 278,737,0,34,-64,34 2 0010 -- quotesingle
+space 278 0 0040
+! 333,737,15,33,20,33 2 0041 -- exclam
+" 400,737,0,45,-50,45 2 0042 -- quotedbl
+# 556,705,0,18,17,18 2 0043 -- numbersign
+sh "
+$ 556,800,133,30,47,30 2 0044 -- dollar
+Do "
+% 833,705,17,9,4,9 2 0045 -- percent
+& 852,737,15,0,26 2 0046 -- ampersand
+' 204,737,0,76,11,76 2 0047 -- quoteright
+( 333,737,124,116,10,107 2 0050 -- parenleft
+) 333,737,124,0,143 2 0051 -- parenright
+* 500,705,0,2,16,2 2 0052 -- asterisk
++ 606,504,0,0,13 0 0053 -- plus
+, 278,109,165,0,89 0 0054 -- comma
+- 333,273,0,0,18 0 0055 -- hyphen
+hy "
+char173 "
+. 278,109,15,0,33 0 0056 -- period
+/ 606,737,102,0,-90 2 0057 -- slash
+sl "
+0 556,705,15,21,21,21 2 0060 -- zero
+1 556,705 2 0061 -- one
+2 556,705,0,2,85,2 2 0062 -- two
+3 556,705,15,0,52 2 0063 -- three
+4 556,705,0,6,58,6 2 0064 -- four
+5 556,705,15,34,46,34 2 0065 -- five
+6 556,705,15,41,14,41 2 0066 -- six
+7 556,705,15,55,-19,55 2 0067 -- seven
+8 556,705,15,21,42,21 2 0070 -- eight
+9 556,705,15,13,43,13 2 0071 -- nine
+: 278,466,15,26,8,26 0 0072 -- colon
+; 278,466,165,33,64,33 0 0073 -- semicolon
+< 606,518,10,0,16 0 0074 -- less
+= 606,381,0,0,14 0 0075 -- equal
+> 606,518,10,6,-3,6 0 0076 -- greater
+? 444,737,15,23,-52,23 2 0077 -- question
+@ 747,737,15,31,22,31 2 0100 -- at
+at "
+A 704,737,0,14,132,14 2 0101 -- A
+B 722,722,0,0,81 2 0102 -- B
+C 722,737,15,41,10,41 2 0103 -- C
+D 778,722,0,7,88,7 2 0104 -- D
+E 722,722,0,29,87,29 2 0105 -- E
+F 667,722,0,81,84,81 2 0106 -- F
+G 778,737,15,35,11,35 2 0107 -- G
+H 833,722,0,84,88,84 2 0110 -- H
+I 407,722,0,74,83,74 2 0111 -- I
+J 611,722,17,85,63,85 2 0112 -- J
+K 741,722,0,123,90,107 2 0113 -- K
+L 667,722,0,13,87,13 2 0114 -- L
+M 944,722,0,79,76,79 2 0115 -- M
+N 815,722,17,94,98,94 2 0116 -- N
+O 778,737,15,7,10,7 2 0117 -- O
+P 667,722,0,46,83,46 2 0120 -- P
+Q 778,737,190,7,10,7 2 0121 -- Q
+R 741,722,17,0,91 2 0122 -- R
+S 667,737,15,15,50,15 2 0123 -- S
+T 685,722,0,91,10,91 2 0124 -- T
+U 815,722,15,95,-43,95 2 0125 -- U
+V 704,722,15,118,14,107 2 0126 -- V
+W 926,722,15,97,-3,97 2 0127 -- W
+X 704,722,0,116,123,107 2 0130 -- X
+Y 685,722,0,123,18,107 2 0131 -- Y
+Z 667,722,0,50,75,50 2 0132 -- Z
+[ 333,737,109,127,83,107 2 0133 -- bracketleft
+lB "
+\ 606,737,0,0,-39 2 0134 -- backslash
+rs "
+] 333,737,109,76,133,76 2 0135 -- bracketright
+rB "
+a^ 333,688,0,48,13,48 2 0136 -- circumflex
+^ "
+_ 500,0,123,50,50,50 0 0137 -- underscore
+` 204,749,0,98,-11,98 2 0140 -- quoteleft
+oq "
+a 574,466,15,0,49 0 0141 -- a
+b 556,737,15,0,18 2 0142 -- b
+c 444,466,15,7,45,7 0 0143 -- c
+d 611,737,15,25,47,25 2 0144 -- d
+e 444,466,15,0,56 0 0145 -- e
+f 333,737,205,187,118,107 3 0146 -- f
+g 537,499,205,36,129,36 1 0147 -- g
+h 611,737,15,0,50 2 0150 -- h
+i 333,715,15,0,23 2 0151 -- i
+j 315,715,205,52,216,52 3 0152 -- j
+k 556,737,15,0,55 2 0153 -- k
+l 333,737,15,11,34,11 2 0154 -- l
+m 889,466,15,0,35 0 0155 -- m
+n 611,466,15,1,36,1 0 0156 -- n
+o 500,466,15,0,45 0 0157 -- o
+p 574,466,205,0,151 1 0160 -- p
+q 556,466,205,0,50 1 0161 -- q
+r 444,466,0,39,41,39 0 0162 -- r
+s 444,466,15,0,51 0 0163 -- s
+t 352,619,15,27,25,27 2 0164 -- t
+u 611,466,15,0,9 0 0165 -- u
+v 519,466,15,0,16 0 0166 -- v
+w 778,466,15,0,18 0 0167 -- w
+x 500,466,15,21,83,21 0 0170 -- x
+y 500,466,205,4,129,4 1 0171 -- y
+z 463,466,15,4,83,4 0 0172 -- z
+lC 333,737,116,98,-2,98 2 0173 -- braceleft
+{ "
+ba 606,737,0,0,-219 2 0174 -- bar
+| "
+rC 333,737,116,0,148 2 0175 -- braceright
+} "
+a~ 333,650,0,97,-2,97 2 0176 -- tilde
+~ "
+bq 204,109,167,0,129 0 0200 -- quotesinglbase
+Fo 426,399,0,26,65,26 0 0201 -- guillemotleft
+char171 "
+Fc 426,394,0,24,67,24 0 0202 -- guillemotright
+char187 "
+bu 606,537,0,0,-64 0 0203 -- bullet
+Fn 556,737,205,57,107,57 3 0204 -- florin
+f/ 167,705,17,216,154,107 2 0205 -- fraction
+%0 1000,705,15,53,56,53 2 0206 -- perthousand
+dg 500,737,147,68,-14,68 2 0207 -- dagger
+dd 500,737,148,78,80,78 2 0210 -- daggerdbl
+en 500,260,0,68,68,68 0 0211 -- endash
+em 1000,260,0,68,68,68 0 0212 -- emdash
+fi 611,737,205,3,110,3 3 0214 -- fi
+fl 611,737,205,33,110,33 3 0215 -- fl
+.i 333,466,15,0,23 0 0220 -- dotlessi
+ga 333,691,0,0,-23 2 0222 -- grave
+a" 333,689,0,237,-84,107 2 0223 -- hungarumlaut
+a. 333,644,0,0,-68 2 0224 -- dotaccent
+ab 333,677,0,87,-19,87 2 0225 -- breve
+ah 333,688,0,95,-23,95 2 0226 -- caron
+ao 333,712,0,146,-180,107 2 0227 -- ring
+ho 333,0,155,0,-18 0 0230 -- ogonek
+lq 389,749,0,93,-13,93 2 0231 -- quotedblleft
+rq 389,737,0,68,12,68 2 0232 -- quotedblright
+oe 778,466,17,0,50 0 0233 -- oe
+/l 333,737,15,59,34,59 2 0234 -- lslash
+Bq 389,109,167,0,129 0 0235 -- quotedblbase
+OE 981,722,0,32,14,32 2 0236 -- OE
+/L 667,722,0,13,87,13 2 0237 -- Lslash
+r! 333,542,205,0,57 1 0241 -- exclamdown
+char161 "
+ct 556,595,129,0,-11 0 0242 -- cent
+char162 "
+Po 556,705,15,39,58,39 2 0243 -- sterling
+char163 "
+Cs 556,603,0,24,25,24 0 0244 -- currency
+char164 "
+Ye 556,705,0,117,10,107 2 0245 -- yen
+char165 "
+bb 606,737,0,0,-219 2 0246 -- brokenbar
+char166 "
+sc 500,737,147,30,61,30 2 0247 -- section
+char167 "
+ad 333,644,0,76,-9,76 2 0250 -- dieresis
+char168 "
+co 747,737,15,27,26,27 2 0251 -- copyright
+char169 "
+Of 422,737,0,50,-33,50 2 0252 -- ordfeminine
+char170 "
+fo 333,399,0,0,8 0 0253 -- guilsinglleft
+no 606,381,0,0,9 0 0254 -- logicalnot
+char172 "
+\- 606,287,0,0,9 0 0255 -- minus
+rg 747,737,15,26,27,26 2 0256 -- registered
+char174 "
+a- 333,610,0,80,-1,80 0 0257 -- macron
+char175 "
+de 400,705,0,20,-20,20 2 0260 -- degree
+char176 "
+char177 606,504,0,0,13 0 0261 -- plusminus
+S2 333,705,0,70,50,70 2 0262 -- twosuperior
+char178 "
+S3 333,705,0,48,49,48 2 0263 -- threesuperior
+char179 "
+aa 333,689,0,72,-82,72 2 0264 -- acute
+char180 "
+char181 611,466,205,0,120 1 0265 -- mu
+ps 650,737,0,45,-38,45 2 0266 -- paragraph
+char182 "
+char183 278,316,0,0,-27 0 0267 -- periodcentered
+ac 333,0,227,0,47 1 0270 -- cedilla
+char184 "
+S1 333,705,0,26,7,26 2 0271 -- onesuperior
+char185 "
+Om 372,738,0,50,-33,50 2 0272 -- ordmasculine
+char186 "
+fc 333,394,0,0,10 0 0273 -- guilsinglright
+14 834,705,17,49,17,49 2 0274 -- onequarter
+char188 "
+12 834,705,17,60,17,60 2 0275 -- onehalf
+char189 "
+34 834,705,17,49,49,49 2 0276 -- threequarters
+char190 "
+r? 444,542,205,0,43 1 0277 -- questiondown
+char191 "
+`A 704,947,0,14,132,14 2 0300 -- Agrave
+char192 "
+'A 704,945,0,14,132,14 2 0301 -- Aacute
+char193 "
+^A 704,944,0,14,132,14 2 0302 -- Acircumflex
+char194 "
+~A 704,906,0,14,132,14 2 0303 -- Atilde
+char195 "
+:A 704,900,0,14,132,14 2 0304 -- Adieresis
+char196 "
+oA 704,968,0,14,132,14 2 0305 -- Aring
+char197 "
+AE 870,722,0,50,142,50 2 0306 -- AE
+char198 "
+,C 722,737,227,41,10,41 3 0307 -- Ccedilla
+char199 "
+`E 722,947,0,29,87,29 2 0310 -- Egrave
+char200 "
+'E 722,945,0,29,87,29 2 0311 -- Eacute
+char201 "
+^E 722,944,0,29,87,29 2 0312 -- Ecircumflex
+char202 "
+:E 722,900,0,29,87,29 2 0313 -- Edieresis
+char203 "
+`I 407,947,0,74,83,74 2 0314 -- Igrave
+char204 "
+'I 407,945,0,74,83,74 2 0315 -- Iacute
+char205 "
+^I 407,944,0,74,83,74 2 0316 -- Icircumflex
+char206 "
+:I 407,900,0,89,83,89 2 0317 -- Idieresis
+char207 "
+-D 778,722,0,7,88,7 2 0320 -- Eth
+char208 "
+~N 815,906,17,94,98,94 2 0321 -- Ntilde
+char209 "
+`O 778,947,15,7,10,7 2 0322 -- Ograve
+char210 "
+'O 778,945,15,7,10,7 2 0323 -- Oacute
+char211 "
+^O 778,944,15,7,10,7 2 0324 -- Ocircumflex
+char212 "
+~O 778,906,15,7,10,7 2 0325 -- Otilde
+char213 "
+:O 778,900,15,7,10,7 2 0326 -- Odieresis
+char214 "
+char215 606,504,0,0,13 0 0327 -- multiply
+/O 778,755,87,7,49,7 2 0330 -- Oslash
+char216 "
+`U 815,947,15,95,-43,95 2 0331 -- Ugrave
+char217 "
+'U 815,945,15,95,-43,95 2 0332 -- Uacute
+char218 "
+^U 815,944,15,95,-43,95 2 0333 -- Ucircumflex
+char219 "
+:U 815,900,15,95,-43,95 2 0334 -- Udieresis
+char220 "
+'Y 685,945,0,123,18,107 2 0335 -- Yacute
+char221 "
+TP 667,722,0,7,83,7 2 0336 -- Thorn
+char222 "
+ss 556,737,205,19,126,19 3 0337 -- germandbls
+char223 "
+`a 574,691,15,0,49 2 0340 -- agrave
+char224 "
+'a 574,689,15,0,49 2 0341 -- aacute
+char225 "
+^a 574,688,15,0,49 2 0342 -- acircumflex
+char226 "
+~a 574,650,15,0,49 2 0343 -- atilde
+char227 "
+:a 574,644,15,0,49 2 0344 -- adieresis
+char228 "
+oa 574,712,15,0,49 2 0345 -- aring
+char229 "
+ae 722,466,15,0,68 0 0346 -- ae
+char230 "
+,c 444,466,227,7,45,7 1 0347 -- ccedilla
+char231 "
+`e 444,691,15,0,56 2 0350 -- egrave
+char232 "
+'e 444,689,15,17,56,17 2 0351 -- eacute
+char233 "
+^e 444,688,15,0,56 2 0352 -- ecircumflex
+char234 "
+:e 444,644,15,11,56,11 2 0353 -- edieresis
+char235 "
+`i 333,691,15,0,23 2 0354 -- igrave
+char236 "
+'i 333,689,15,72,23,72 2 0355 -- iacute
+char237 "
+^i 333,688,15,8,53,8 2 0356 -- icircumflex
+char238 "
+:i 333,644,15,66,23,66 2 0357 -- idieresis
+char239 "
+Sd 500,737,15,0,45 2 0360 -- eth
+char240 "
+~n 611,650,15,1,36,1 2 0361 -- ntilde
+char241 "
+`o 500,691,15,0,45 2 0362 -- ograve
+char242 "
+'o 500,689,15,0,45 2 0363 -- oacute
+char243 "
+^o 500,688,15,0,45 2 0364 -- ocircumflex
+char244 "
+~o 500,650,15,4,45,4 2 0365 -- otilde
+char245 "
+:o 500,644,15,0,45 2 0366 -- odieresis
+char246 "
+char247 606,504,0,0,13 0 0367 -- divide
+/o 500,549,121,0,55 0 0370 -- oslash
+char248 "
+`u 611,691,15,0,9 2 0371 -- ugrave
+char249 "
+'u 611,689,15,0,9 2 0372 -- uacute
+char250 "
+^u 611,688,15,0,9 2 0373 -- ucircumflex
+char251 "
+:u 611,644,15,0,9 2 0374 -- udieresis
+char252 "
+'y 500,689,205,4,129,4 3 0375 -- yacute
+char253 "
+Tp 574,656,205,0,151 3 0376 -- thorn
+char254 "
+:y 500,644,205,4,129,4 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/NR b/font/devps/NR
new file mode 100644
index 00000000..8d29bd12
--- /dev/null
+++ b/font/devps/NR
@@ -0,0 +1,447 @@
+name NR
+internalname NewCenturySchlbk-Roman
+spacewidth 278
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -74
+A w -74
+A v -74
+A ' -74
+A Y -92
+A W -92
+A V -111
+A T -55
+F . -111
+F , -111
+F A -74
+L y -55
+L ' -55
+L Y -92
+L W -74
+L V -92
+L T -55
+P . -129
+P , -129
+P A -74
+R y -18
+R Y -37
+R W -37
+R V -37
+T y -52
+T w -71
+T u -71
+T ; -55
+T s -62
+T r -62
+T . -92
+T o -92
+T i -25
+T - -92
+T hy -92
+T char173 -92
+T e -92
+T , -92
+T : -55
+T c -81
+T a -62
+T A -55
+V y -92
+V u -74
+V ; -74
+V r -74
+V . -129
+V o -92
+V i -44
+V - -92
+V hy -92
+V char173 -92
+V e -92
+V , -129
+V : -74
+V a -92
+V A -111
+W y -74
+W u -55
+W ; -37
+W r -55
+W . -111
+W o -55
+W i -37
+W - -37
+W hy -37
+W char173 -37
+W e -55
+W , -111
+W : -37
+W a -74
+W A -92
+Y v -111
+Y u -92
+Y ; -92
+Y q -111
+Y . -111
+Y p -111
+Y o -111
+Y i -44
+Y - -111
+Y hy -111
+Y char173 -111
+Y e -111
+Y , -111
+Y : -92
+Y a -111
+Y A -92
+f ' 114
+1 1 -55
+` ` -18
+` oq -18
+oq ` -18
+oq oq -18
+' t -18
+' s -37
+' ' -18
+r ' 55
+r . -74
+r - -18
+r hy -18
+r char173 -18
+r , -74
+v . -111
+v , -111
+w . -92
+w , -92
+y . -111
+y , -111
+charset
+ha 606,722 2 0000 -- asciicircum
+ti 606,329 0 0001 -- asciitilde
+vS 630,952,15 2 0002 -- Scaron
+vZ 611,952 2 0003 -- Zcaron
+vs 463,694,15 2 0004 -- scaron
+vz 481,694 2 0005 -- zcaron
+:Y 704,902 2 0006 -- Ydieresis
+tm 1000,737 2 0007 -- trademark
+aq 204,737 2 0010 -- quotesingle
+space 278 0 0040
+! 296,737,15 2 0041 -- exclam
+" 389,737 2 0042 -- quotedbl
+# 556,690 2 0043 -- numbersign
+sh "
+$ 556,804,129 2 0044 -- dollar
+Do "
+% 833,707,18 2 0045 -- percent
+& 815,737,15 2 0046 -- ampersand
+' 204,737 2 0047 -- quoteright
+( 333,737,124 2 0050 -- parenleft
+) 333,737,124 2 0051 -- parenright
+* 500,737 2 0052 -- asterisk
++ 606,492,13 0 0053 -- plus
+, 278,109,184 0 0054 -- comma
+- 333,279 0 0055 -- hyphen
+hy "
+char173 "
+. 278,109,15 0 0056 -- period
+/ 278,737,15 2 0057 -- slash
+sl "
+0 556,705,15 2 0060 -- zero
+1 556,705 2 0061 -- one
+2 556,705,4 2 0062 -- two
+3 556,705,15 2 0063 -- three
+4 556,705 2 0064 -- four
+5 556,705,15 2 0065 -- five
+6 556,705,15 2 0066 -- six
+7 556,705,15 2 0067 -- seven
+8 556,705,15 2 0070 -- eight
+9 556,705,15 2 0071 -- nine
+: 278,475,15 0 0072 -- colon
+; 278,475,189 0 0073 -- semicolon
+< 606,503,25 0 0074 -- less
+= 606,374 0 0075 -- equal
+> 606,503,25 0 0076 -- greater
+? 444,737,15 2 0077 -- question
+@ 737,737,15 2 0100 -- at
+at "
+A 722,737 2 0101 -- A
+B 722,722 2 0102 -- B
+C 722,737,15 2 0103 -- C
+D 778,722 2 0104 -- D
+E 722,722 2 0105 -- E
+F 667,722 2 0106 -- F
+G 778,737,15 2 0107 -- G
+H 833,722 2 0110 -- H
+I 407,722 2 0111 -- I
+J 556,722,15 2 0112 -- J
+K 778,722 2 0113 -- K
+L 667,722 2 0114 -- L
+M 944,722 2 0115 -- M
+N 815,722,15 2 0116 -- N
+O 778,737,15 2 0117 -- O
+P 667,722 2 0120 -- P
+Q 778,737,189 2 0121 -- Q
+R 722,722,15 2 0122 -- R
+S 630,737,15 2 0123 -- S
+T 667,722 2 0124 -- T
+U 815,722,15 2 0125 -- U
+V 722,722,15 2 0126 -- V
+W 981,722,15 2 0127 -- W
+X 704,722 2 0130 -- X
+Y 704,722 2 0131 -- Y
+Z 611,722 2 0132 -- Z
+[ 333,722,109 2 0133 -- bracketleft
+lB "
+\ 606,737 2 0134 -- backslash
+rs "
+] 333,723,108 2 0135 -- bracketright
+rB "
+a^ 333,694 2 0136 -- circumflex
+^ "
+_ 500,0,134 0 0137 -- underscore
+` 204,737 2 0140 -- quoteleft
+oq "
+a 556,479,15 0 0141 -- a
+b 556,737,15 2 0142 -- b
+c 444,479,15 0 0143 -- c
+d 574,737,15 2 0144 -- d
+e 500,479,15 0 0145 -- e
+f 333,737 2 0146 -- f
+g 537,494,205 1 0147 -- g
+h 611,737 2 0150 -- h
+i 315,716 2 0151 -- i
+j 296,716,205 3 0152 -- j
+k 593,737 2 0153 -- k
+l 315,737 2 0154 -- l
+m 889,479 0 0155 -- m
+n 611,479 0 0156 -- n
+o 500,479,15 0 0157 -- o
+p 574,479,205 1 0160 -- p
+q 556,479,205 1 0161 -- q
+r 444,479 0 0162 -- r
+s 463,479,15 0 0163 -- s
+t 389,666,15 2 0164 -- t
+u 611,464,15 0 0165 -- u
+v 537,464,15 0 0166 -- v
+w 778,464,15 0 0167 -- w
+x 537,464 0 0170 -- x
+y 537,464,205 1 0171 -- y
+z 481,464 0 0172 -- z
+lC 333,722,109 2 0173 -- braceleft
+{ "
+ba 606,737 2 0174 -- bar
+| "
+rC 333,722,109 2 0175 -- braceright
+} "
+a~ 333,659 0 0176 -- tilde
+~ "
+bq 204,104,189 0 0200 -- quotesinglbase
+Fo 426,397 0 0201 -- guillemotleft
+char171 "
+Fc 426,399 0 0202 -- guillemotright
+char187 "
+bu 606,554 0 0203 -- bullet
+Fn 556,737,205 3 0204 -- florin
+f/ 167,705 2 0205 -- fraction
+%0 1000,699,1 2 0206 -- perthousand
+dg 500,737,147 2 0207 -- dagger
+dd 500,737,151 2 0210 -- daggerdbl
+en 556,269 0 0211 -- endash
+em 1000,269 0 0212 -- emdash
+fi 611,737 2 0214 -- fi
+fl 611,737 2 0215 -- fl
+.i 315,464 0 0220 -- dotlessi
+ga 333,699 2 0222 -- grave
+a" 333,714 2 0223 -- hungarumlaut
+a. 333,644 0 0224 -- dotaccent
+ab 333,685 2 0225 -- breve
+ah 333,694 2 0226 -- caron
+ao 333,722 2 0227 -- ring
+ho 333,0,163 0 0230 -- ogonek
+lq 389,737 2 0231 -- quotedblleft
+rq 389,737 2 0232 -- quotedblright
+oe 833,479,15 0 0233 -- oe
+/l 315,737 2 0234 -- lslash
+Bq 389,104,189 0 0235 -- quotedblbase
+OE 1000,722 2 0236 -- OE
+/L 667,722 2 0237 -- Lslash
+r! 296,547,205 1 0241 -- exclamdown
+char161 "
+ct 556,584,141 0 0242 -- cent
+char162 "
+Po 556,705,15 2 0243 -- sterling
+char163 "
+Cs 556,603 0 0244 -- currency
+char164 "
+Ye 556,705 2 0245 -- yen
+char165 "
+bb 606,737 2 0246 -- brokenbar
+char166 "
+sc 500,737,147 2 0247 -- section
+char167 "
+ad 333,644 0 0250 -- dieresis
+char168 "
+co 737,737,15 2 0251 -- copyright
+char169 "
+Of 334,722 2 0252 -- ordfeminine
+char170 "
+fo 259,397 0 0253 -- guilsinglleft
+no 606,374 0 0254 -- logicalnot
+char172 "
+\- 606,277 0 0255 -- minus
+rg 737,737,15 2 0256 -- registered
+char174 "
+a- 333,622 0 0257 -- macron
+char175 "
+de 400,705 2 0260 -- degree
+char176 "
+char177 606,492 0 0261 -- plusminus
+S2 333,705 2 0262 -- twosuperior
+char178 "
+S3 333,705 2 0263 -- threesuperior
+char179 "
+aa 333,699 2 0264 -- acute
+char180 "
+char181 611,464,205 1 0265 -- mu
+ps 606,722,147 2 0266 -- paragraph
+char182 "
+char183 278,302 0 0267 -- periodcentered
+ac 333,0,215 1 0270 -- cedilla
+char184 "
+S1 333,705 2 0271 -- onesuperior
+char185 "
+Om 300,722 2 0272 -- ordmasculine
+char186 "
+fc 259,399 0 0273 -- guilsinglright
+14 834,705 2 0274 -- onequarter
+char188 "
+12 834,705,2 2 0275 -- onehalf
+char189 "
+34 834,705 2 0276 -- threequarters
+char190 "
+r? 444,547,205 1 0277 -- questiondown
+char191 "
+`A 722,957 2 0300 -- Agrave
+char192 "
+'A 722,957 2 0301 -- Aacute
+char193 "
+^A 722,952 2 0302 -- Acircumflex
+char194 "
+~A 722,917 2 0303 -- Atilde
+char195 "
+:A 722,902 2 0304 -- Adieresis
+char196 "
+oA 722,980 2 0305 -- Aring
+char197 "
+AE 1000,722 2 0306 -- AE
+char198 "
+,C 722,737,215 3 0307 -- Ccedilla
+char199 "
+`E 722,957 2 0310 -- Egrave
+char200 "
+'E 722,957 2 0311 -- Eacute
+char201 "
+^E 722,952 2 0312 -- Ecircumflex
+char202 "
+:E 722,902 2 0313 -- Edieresis
+char203 "
+`I 407,957 2 0314 -- Igrave
+char204 "
+'I 407,957 2 0315 -- Iacute
+char205 "
+^I 407,952 2 0316 -- Icircumflex
+char206 "
+:I 407,902 2 0317 -- Idieresis
+char207 "
+-D 778,722 2 0320 -- Eth
+char208 "
+~N 815,917,15 2 0321 -- Ntilde
+char209 "
+`O 778,957,15 2 0322 -- Ograve
+char210 "
+'O 778,957,15 2 0323 -- Oacute
+char211 "
+^O 778,952,15 2 0324 -- Ocircumflex
+char212 "
+~O 778,917,15 2 0325 -- Otilde
+char213 "
+:O 778,902,15 2 0326 -- Odieresis
+char214 "
+char215 606,491,13 0 0327 -- multiply
+/O 778,760,74 2 0330 -- Oslash
+char216 "
+`U 815,957,15 2 0331 -- Ugrave
+char217 "
+'U 815,957,15 2 0332 -- Uacute
+char218 "
+^U 815,952,15 2 0333 -- Ucircumflex
+char219 "
+:U 815,902,15 2 0334 -- Udieresis
+char220 "
+'Y 704,957 2 0335 -- Yacute
+char221 "
+TP 667,722 2 0336 -- Thorn
+char222 "
+ss 574,737,15 2 0337 -- germandbls
+char223 "
+`a 556,699,15 2 0340 -- agrave
+char224 "
+'a 556,699,15 2 0341 -- aacute
+char225 "
+^a 556,694,15 2 0342 -- acircumflex
+char226 "
+~a 556,659,15 0 0343 -- atilde
+char227 "
+:a 556,644,15 0 0344 -- adieresis
+char228 "
+oa 556,722,15 2 0345 -- aring
+char229 "
+ae 796,479,15 0 0346 -- ae
+char230 "
+,c 444,479,215 1 0347 -- ccedilla
+char231 "
+`e 500,699,15 2 0350 -- egrave
+char232 "
+'e 500,699,15 2 0351 -- eacute
+char233 "
+^e 500,694,15 2 0352 -- ecircumflex
+char234 "
+:e 500,644,15 0 0353 -- edieresis
+char235 "
+`i 315,699 2 0354 -- igrave
+char236 "
+'i 315,699 2 0355 -- iacute
+char237 "
+^i 315,694 2 0356 -- icircumflex
+char238 "
+:i 315,644 0 0357 -- idieresis
+char239 "
+Sd 500,740,15 2 0360 -- eth
+char240 "
+~n 611,659 0 0361 -- ntilde
+char241 "
+`o 500,699,15 2 0362 -- ograve
+char242 "
+'o 500,699,15 2 0363 -- oacute
+char243 "
+^o 500,694,15 2 0364 -- ocircumflex
+char244 "
+~o 500,659,15 0 0365 -- otilde
+char245 "
+:o 500,644,15 0 0366 -- odieresis
+char246 "
+char247 606,493,11 0 0367 -- divide
+/o 500,556,102 0 0370 -- oslash
+char248 "
+`u 611,699,15 2 0371 -- ugrave
+char249 "
+'u 611,699,15 2 0372 -- uacute
+char250 "
+^u 611,694,15 2 0373 -- ucircumflex
+char251 "
+:u 611,644,15 0 0374 -- udieresis
+char252 "
+'y 537,699,205 3 0375 -- yacute
+char253 "
+Tp 574,737,205 3 0376 -- thorn
+char254 "
+:y 537,644,205 1 0377 -- ydieresis
+char255 "
diff --git a/font/devps/PB b/font/devps/PB
new file mode 100644
index 00000000..ad3c7040
--- /dev/null
+++ b/font/devps/PB
@@ -0,0 +1,449 @@
+name PB
+internalname Palatino-Bold
+spacewidth 250
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -70
+A w -70
+A v -70
+A ' -92
+A Y -111
+A W -90
+A V -129
+A T -92
+F . -111
+F , -111
+F A -55
+L y -74
+L ' -74
+L Y -92
+L W -92
+L V -92
+L T -74
+P . -129
+P , -129
+P A -74
+R y -30
+R Y -55
+R W -37
+R V -74
+R T -55
+T y -90
+T w -90
+T u -129
+T ; -74
+T s -111
+T r -111
+T . -92
+T o -111
+T i -55
+T - -92
+T hy -92
+T char173 -92
+T e -111
+T , -92
+T : -74
+T c -129
+T a -111
+T A -92
+V y -90
+V u -92
+V ; -74
+V r -111
+V . -129
+V o -111
+V i -55
+V - -92
+V hy -92
+V char173 -92
+V e -111
+V , -129
+V : -74
+V a -111
+V A -129
+W y -74
+W u -74
+W ; -37
+W r -74
+W . -37
+W o -74
+W i -37
+W - -37
+W hy -37
+W char173 -37
+W e -74
+W , -92
+W : -37
+W a -74
+W A -90
+Y v -74
+Y u -74
+Y ; -55
+Y q -92
+Y . -74
+Y p -74
+Y o -74
+Y i -55
+Y - -74
+Y hy -74
+Y char173 -74
+Y e -74
+Y , -74
+Y : -55
+Y a -74
+Y A -55
+f ' 37
+f f -18
+1 1 -37
+` ` -55
+` oq -55
+oq ` -55
+oq oq -55
+' t -18
+' s -55
+' ' -55
+r ' 55
+r . -55
+r - -18
+r hy -18
+r char173 -18
+r , -55
+v . -111
+v , -111
+w . -92
+w , -92
+y . -92
+y , -92
+charset
+ha 606,678 2 0000 -- asciicircum
+ti 606,342 0 0001 -- asciitilde
+vS 611,909,17 2 0002 -- Scaron
+vZ 667,909,3 2 0003 -- Zcaron
+vs 444,693,17 2 0004 -- scaron
+vz 500,693,3 2 0005 -- zcaron
+:Y 667,895,3 2 0006 -- Ydieresis
+tm 998,678 2 0007 -- trademark
+aq 227,695 2 0010 -- quotesingle
+space 250 0 0040
+! 278,688,12 2 0041 -- exclam
+" 402,695 2 0042 -- quotedbl
+# 500,673 2 0043 -- numbersign
+sh "
+$ 500,721,114 2 0044 -- dollar
+Do "
+% 889,714,9 2 0045 -- percent
+& 833,684,17 2 0046 -- ampersand
+' 278,695 2 0047 -- quoteright
+( 333,723,104 2 0050 -- parenleft
+) 333,723,104 2 0051 -- parenright
+* 444,695 2 0052 -- asterisk
++ 606,505 0 0053 -- plus
+, 250,141,166 0 0054 -- comma
+- 333,305 0 0055 -- hyphen
+hy "
+char173 "
+. 250,144,12 0 0056 -- period
+/ 296,720,17 2 0057 -- slash
+sl "
+0 500,660,17 2 0060 -- zero
+1 500,670,3 2 0061 -- one
+2 500,660,3 2 0062 -- two
+3 500,660,17 2 0063 -- three
+4 500,672,3 2 0064 -- four
+5 500,656,17 2 0065 -- five
+6 500,660,17 2 0066 -- six
+7 500,656,3 2 0067 -- seven
+8 500,660,17 2 0070 -- eight
+9 500,660,17 2 0071 -- nine
+: 250,454,12 0 0072 -- colon
+; 250,454,166 0 0073 -- semicolon
+< 606,519,15 0 0074 -- less
+= 606,396 0 0075 -- equal
+> 606,519,15 0 0076 -- greater
+? 444,687,12 2 0077 -- question
+@ 747,681,12 2 0100 -- at
+at "
+A 778,686,3 2 0101 -- A
+B 667,681,3 2 0102 -- B
+C 722,695,17 2 0103 -- C
+D 833,681,3 2 0104 -- D
+E 611,681,4 2 0105 -- E
+F 556,681,3 2 0106 -- F
+G 833,695,17 2 0107 -- G
+H 833,681,3 2 0110 -- H
+I 389,681,3 2 0111 -- I
+J 389,681,213 2 0112 -- J
+K 778,681,3 2 0113 -- K
+L 611,681,4 2 0114 -- L
+M 1000,681,10 2 0115 -- M
+N 833,681,16 2 0116 -- N
+O 833,695,17 2 0117 -- O
+P 611,681,3 2 0120 -- P
+Q 833,695,184 2 0121 -- Q
+R 722,681,3 2 0122 -- R
+S 611,695,17 2 0123 -- S
+T 667,681,3 2 0124 -- T
+U 778,681,17 2 0125 -- U
+V 778,681,3 2 0126 -- V
+W 1000,686,3 2 0127 -- W
+X 667,695,3 2 0130 -- X
+Y 667,695,3 2 0131 -- Y
+Z 667,681,3 2 0132 -- Z
+[ 333,720,104 2 0133 -- bracketleft
+lB "
+\ 606,720 2 0134 -- backslash
+rs "
+] 333,720,104 2 0135 -- bracketright
+rB "
+a^ 333,681 2 0136 -- circumflex
+^ "
+_ 500,0,125 0 0137 -- underscore
+` 278,695 2 0140 -- quoteleft
+oq "
+a 500,471,17 0 0141 -- a
+b 611,720,17 2 0142 -- b
+c 444,471,17 0 0143 -- c
+d 611,720,17 2 0144 -- d
+e 500,471,17 0 0145 -- e
+f 389,720,3 2 0146 -- f
+g 556,471,266 1 0147 -- g
+h 611,720,3 2 0150 -- h
+i 333,706,3 2 0151 -- i
+j 333,706,266 3 0152 -- j
+k 611,720,3 2 0153 -- k
+l 333,720,3 2 0154 -- l
+m 889,471,3 0 0155 -- m
+n 611,471,3 0 0156 -- n
+o 556,471,17 0 0157 -- o
+p 611,471,258 1 0160 -- p
+q 611,471,258 1 0161 -- q
+r 389,471,3 0 0162 -- r
+s 444,471,17 0 0163 -- s
+t 333,632,17 2 0164 -- t
+u 611,471,17 0 0165 -- u
+v 556,459,3 0 0166 -- v
+w 833,471,3 0 0167 -- w
+x 500,471,3 0 0170 -- x
+y 556,459,266 1 0171 -- y
+z 500,459,3 0 0172 -- z
+lC 310,725,117 2 0173 -- braceleft
+{ "
+ba 606,720 2 0174 -- bar
+| "
+rC 310,725,117 2 0175 -- braceright
+} "
+a~ 333,661 2 0176 -- tilde
+~ "
+bq 333,130,160 0 0200 -- quotesinglbase
+Fo 500,438 0 0201 -- guillemotleft
+char171 "
+Fc 500,438 0 0202 -- guillemotright
+char187 "
+bu 606,516 0 0203 -- bullet
+Fn 500,703,242 2 0204 -- florin
+f/ 167,660 2 0205 -- fraction
+%0 1000,724,9 2 0206 -- perthousand
+dg 500,682,6 2 0207 -- dagger
+dd 500,682,245 2 0210 -- daggerdbl
+en 500,291 0 0211 -- endash
+em 1000,291 0 0212 -- emdash
+fi 611,720,3 2 0214 -- fi
+fl 611,720,3 2 0215 -- fl
+.i 333,471,3 0 0220 -- dotlessi
+ga 333,691 2 0222 -- grave
+a" 333,691 2 0223 -- hungarumlaut
+a. 333,671 2 0224 -- dotaccent
+ab 333,669 2 0225 -- breve
+ah 333,685 2 0226 -- caron
+ao 333,700 2 0227 -- ring
+ho 333,0,246 0 0230 -- ogonek
+lq 500,695 2 0231 -- quotedblleft
+rq 500,695 2 0232 -- quotedblright
+oe 833,471,17 0 0233 -- oe
+/l 333,720,3 2 0234 -- lslash
+Bq 500,130,160 0 0235 -- quotedblbase
+OE 1000,695,17 2 0236 -- OE
+/L 611,681,4 2 0237 -- Lslash
+r! 278,471,227 0 0241 -- exclamdown
+char161 "
+ct 500,554,106 0 0242 -- cent
+char162 "
+Po 500,676,19 2 0243 -- sterling
+char163 "
+Cs 500,533 0 0244 -- currency
+char164 "
+Ye 500,695,3 2 0245 -- yen
+char165 "
+bb 606,720 2 0246 -- brokenbar
+char166 "
+sc 500,695,217 2 0247 -- section
+char167 "
+ad 333,671 2 0250 -- dieresis
+char168 "
+co 747,695,17 2 0251 -- copyright
+char169 "
+Of 438,660 2 0252 -- ordfeminine
+char170 "
+fo 389,438 0 0253 -- guilsinglleft
+no 606,396 0 0254 -- logicalnot
+char172 "
+\- 606,298 0 0255 -- minus
+rg 747,695,17 2 0256 -- registered
+char174 "
+a- 333,609 0 0257 -- macron
+char175 "
+de 400,660 2 0260 -- degree
+char176 "
+char177 606,505 0 0261 -- plusminus
+S2 300,660 2 0262 -- twosuperior
+char178 "
+S3 300,667 2 0263 -- threesuperior
+char179 "
+aa 333,691 2 0264 -- acute
+char180 "
+char181 611,471,225 0 0265 -- mu
+ps 641,683,161 2 0266 -- paragraph
+char182 "
+char183 250,335 0 0267 -- periodcentered
+ac 333,0,225 0 0270 -- cedilla
+char184 "
+S1 300,665 2 0271 -- onesuperior
+char185 "
+Om 488,660 2 0272 -- ordmasculine
+char186 "
+fc 389,438 0 0273 -- guilsinglright
+14 750,665,2 2 0274 -- onequarter
+char188 "
+12 750,665,2 2 0275 -- onehalf
+char189 "
+34 750,667,2 2 0276 -- threequarters
+char190 "
+r? 444,471,231 0 0277 -- questiondown
+char191 "
+`A 778,915,3 2 0300 -- Agrave
+char192 "
+'A 778,915,3 2 0301 -- Aacute
+char193 "
+^A 778,905,3 2 0302 -- Acircumflex
+char194 "
+~A 778,885,3 2 0303 -- Atilde
+char195 "
+:A 778,895,3 2 0304 -- Adieresis
+char196 "
+oA 778,924,3 2 0305 -- Aring
+char197 "
+AE 1000,681,4 2 0306 -- AE
+char198 "
+,C 722,695,225 2 0307 -- Ccedilla
+char199 "
+`E 611,915,4 2 0310 -- Egrave
+char200 "
+'E 611,915,4 2 0311 -- Eacute
+char201 "
+^E 611,905,4 2 0312 -- Ecircumflex
+char202 "
+:E 611,895,4 2 0313 -- Edieresis
+char203 "
+`I 389,915,3 2 0314 -- Igrave
+char204 "
+'I 389,915,3 2 0315 -- Iacute
+char205 "
+^I 389,905,3 2 0316 -- Icircumflex
+char206 "
+:I 389,895,3 2 0317 -- Idieresis
+char207 "
+-D 833,681,3 2 0320 -- Eth
+char208 "
+~N 833,885,16 2 0321 -- Ntilde
+char209 "
+`O 833,915,17 2 0322 -- Ograve
+char210 "
+'O 833,915,17 2 0323 -- Oacute
+char211 "
+^O 833,905,17 2 0324 -- Ocircumflex
+char212 "
+~O 833,885,17 2 0325 -- Otilde
+char213 "
+:O 833,895,17 2 0326 -- Odieresis
+char214 "
+char215 606,483 0 0327 -- multiply
+/O 833,698,20 2 0330 -- Oslash
+char216 "
+`U 778,915,17 2 0331 -- Ugrave
+char217 "
+'U 778,915,17 2 0332 -- Uacute
+char218 "
+^U 778,905,17 2 0333 -- Ucircumflex
+char219 "
+:U 778,895,17 2 0334 -- Udieresis
+char220 "
+'Y 667,915,3 2 0335 -- Yacute
+char221 "
+TP 611,681,3 2 0336 -- Thorn
+char222 "
+ss 611,720,17 2 0337 -- germandbls
+char223 "
+`a 500,711,17 2 0340 -- agrave
+char224 "
+'a 500,711,17 2 0341 -- aacute
+char225 "
+^a 500,701,17 2 0342 -- acircumflex
+char226 "
+~a 500,673,17 2 0343 -- atilde
+char227 "
+:a 500,691,17 2 0344 -- adieresis
+char228 "
+oa 500,700,17 2 0345 -- aring
+char229 "
+ae 778,471,17 0 0346 -- ae
+char230 "
+,c 444,471,225 0 0347 -- ccedilla
+char231 "
+`e 500,711,17 2 0350 -- egrave
+char232 "
+'e 500,711,17 2 0351 -- eacute
+char233 "
+^e 500,701,17 2 0352 -- ecircumflex
+char234 "
+:e 500,691,17 2 0353 -- edieresis
+char235 "
+`i 333,711,3 2 0354 -- igrave
+char236 "
+'i 333,711,3 2 0355 -- iacute
+char237 "
+^i 333,701,3 2 0356 -- icircumflex
+char238 "
+:i 333,691,3 2 0357 -- idieresis
+char239 "
+Sd 556,720,17 2 0360 -- eth
+char240 "
+~n 611,673,3 2 0361 -- ntilde
+char241 "
+`o 556,711,17 2 0362 -- ograve
+char242 "
+'o 556,711,17 2 0363 -- oacute
+char243 "
+^o 556,701,17 2 0364 -- ocircumflex
+char244 "
+~o 556,673,17 2 0365 -- otilde
+char245 "
+:o 556,691,17 2 0366 -- odieresis
+char246 "
+char247 606,510 0 0367 -- divide
+/o 556,471,18 0 0370 -- oslash
+char248 "
+`u 611,711,17 2 0371 -- ugrave
+char249 "
+'u 611,711,17 2 0372 -- uacute
+char250 "
+^u 611,701,17 2 0373 -- ucircumflex
+char251 "
+:u 611,691,17 2 0374 -- udieresis
+char252 "
+'y 556,711,266 3 0375 -- yacute
+char253 "
+Tp 611,720,258 3 0376 -- thorn
+char254 "
+:y 556,691,266 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/PBI b/font/devps/PBI
new file mode 100644
index 00000000..f17c1042
--- /dev/null
+++ b/font/devps/PBI
@@ -0,0 +1,451 @@
+name PBI
+internalname Palatino-BoldItalic
+slant 10
+spacewidth 250
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -55
+A w -37
+A v -55
+A ' -55
+A Y -74
+A W -74
+A V -74
+A T -55
+F . -111
+F , -111
+F A -74
+L y -37
+L ' -55
+L Y -74
+L W -74
+L V -74
+L T -74
+P . -129
+P , -129
+P A -92
+R y -20
+R Y -37
+R W -55
+R V -55
+R T -37
+T y -80
+T w -50
+T u -92
+T ; -55
+T s -92
+T r -92
+T . -55
+T o -111
+T i -74
+T - -92
+T hy -92
+T char173 -92
+T e -111
+T , -55
+T : -55
+T c -92
+T a -111
+T O -18
+T A -55
+V y -50
+V u -50
+V ; -37
+V r -74
+V . -111
+V o -74
+V i -50
+V - -37
+V hy -37
+V char173 -37
+V e -74
+V , -111
+V : -37
+V a -92
+V A -74
+W y -30
+W u -30
+W ; -18
+W r -30
+W . -55
+W o -55
+W i -30
+W e -55
+W , -55
+W : -28
+W a -74
+W A -74
+Y v -30
+Y u -50
+Y ; -55
+Y q -92
+Y . -55
+Y p -74
+Y o -111
+Y i -54
+Y - -55
+Y hy -55
+Y char173 -55
+Y e -92
+Y , -55
+Y : -55
+Y a -111
+Y A -55
+f ' 37
+f f -37
+1 1 -55
+` ` -55
+` oq -55
+oq ` -55
+oq oq -55
+' t -18
+' s -37
+' ' -55
+r ' 55
+r q -18
+r . -55
+r o -18
+r h -18
+r g -18
+r e -18
+r , -55
+r c -18
+v . -55
+v , -55
+w . -55
+w , -55
+y . -37
+y , -37
+charset
+ha 606,678,0,0,-13 2 0000 -- asciicircum
+ti 606,346,0,0,-1 0 0001 -- asciitilde
+vS 556,896,17,51,0,51 2 0002 -- Scaron
+vZ 667,896,3,59,49,59 2 0003 -- Zcaron
+vs 444,692,17,95,25,66 2 0004 -- scaron
+vz 500,692,17,67,19,66 2 0005 -- zcaron
+:Y 611,880,3,114,-4,66 2 0006 -- Ydieresis
+tm 1000,678,0,11,12,11 2 0007 -- trademark
+aq 250,720,0,93,-77,66 2 0010 -- quotesingle
+space 250 0 0040
+! 333,695,17,39,-8,39 2 0041 -- exclam
+" 500,720,0,43,-87,43 2 0042 -- quotedbl
+# 500,673,0,46,46,46 2 0043 -- numbersign
+sh "
+$ 500,737,108,27,30,27 2 0044 -- dollar
+Do "
+% 889,697,17,0,-6 2 0045 -- percent
+& 833,695,17,28,-24,28 2 0046 -- ampersand
+' 278,720,0,74,-26,66 2 0047 -- quoteright
+( 333,723,129,85,-8,66 2 0050 -- parenleft
+) 333,723,129,15,62,15 2 0051 -- parenright
+* 444,695,0,45,-34,45 2 0052 -- asterisk
++ 606,501,5 0 0053 -- plus
+, 250,147,164,8,83,8 0 0054 -- comma
+- 389,300,0,23,13,23 0 0055 -- hyphen
+hy "
+char173 "
+. 250,135,17,0,2 0 0056 -- period
+/ 315,720,17,50,49,50 2 0057 -- slash
+sl "
+0 500,683,17,40,8,40 2 0060 -- zero
+1 500,678,3,0,9 2 0061 -- one
+2 500,683,3,4,49,4 2 0062 -- two
+3 500,683,17,0,42 2 0063 -- three
+4 500,683,3,37,47,37 2 0064 -- four
+5 500,675,17,31,36,31 2 0065 -- five
+6 500,683,17,38,11,38 2 0066 -- six
+7 500,674,3,94,-19,66 2 0067 -- seven
+8 500,683,17,34,24,34 2 0070 -- eight
+9 500,683,17,41,23,41 2 0071 -- nine
+: 250,452,17,36,12,36 0 0072 -- colon
+; 250,452,164,47,83,47 0 0073 -- semicolon
+< 606,517,21,2,1,2 0 0074 -- less
+= 606,390,0,0,-1 0 0075 -- equal
+> 606,517,21,1,2,1 0 0076 -- greater
+? 444,695,17,56,-41,56 2 0077 -- question
+@ 833,681,12,0,-32 2 0100 -- at
+at "
+A 722,683,3,13,85,13 2 0101 -- A
+B 667,681,3,12,42,12 2 0102 -- B
+C 685,695,17,60,-19,60 2 0103 -- C
+D 778,682,3,19,50,19 2 0104 -- D
+E 611,681,3,45,39,45 2 0105 -- E
+F 556,681,3,87,56,66 2 0106 -- F
+G 778,695,17,22,-22,22 2 0107 -- G
+H 778,681,3,98,62,66 2 0110 -- H
+I 389,681,3,73,51,66 2 0111 -- I
+J 389,681,207,78,79,66 2 0112 -- J
+K 722,681,3,74,60,66 2 0113 -- K
+L 611,681,3,17,24,17 2 0114 -- L
+M 944,681,17,91,73,66 2 0115 -- M
+N 778,681,3,101,52,66 2 0116 -- N
+O 833,695,17,11,-26,11 2 0117 -- O
+P 667,681,3,56,39,56 2 0120 -- P
+Q 833,695,222,11,-26,11 2 0121 -- Q
+R 722,681,3,25,46,25 2 0122 -- R
+S 556,695,17,11,0,11 2 0123 -- S
+T 611,681,3,113,-6,66 2 0124 -- T
+U 778,681,17,97,-33,66 2 0125 -- U
+V 667,681,3,128,-17,66 2 0126 -- V
+W 1000,689,3,123,-17,66 2 0127 -- W
+X 722,681,3,100,59,66 2 0130 -- X
+Y 611,695,3,114,-4,66 2 0131 -- Y
+Z 667,681,3,59,49,59 2 0132 -- Z
+[ 333,723,102,98,5,66 2 0133 -- bracketleft
+lB "
+\ 606,720,0,0,-22 2 0134 -- backslash
+rs "
+] 333,723,102,32,71,32 2 0135 -- bracketright
+rB "
+a^ 333,684,0,132,-38,66 2 0136 -- circumflex
+^ "
+_ 500,0,125,50,50,50 0 0137 -- underscore
+` 278,720,0,63,-15,63 2 0140 -- quoteleft
+oq "
+a 556,470,17,13,6,13 0 0141 -- a
+b 537,726,17,7,6,7 2 0142 -- b
+c 444,469,17,42,18,42 0 0143 -- c
+d 556,726,17,44,12,44 2 0144 -- d
+e 444,469,17,24,22,24 0 0145 -- e
+f 333,726,271,166,180,66 3 0146 -- f
+g 500,469,271,79,100,66 1 0147 -- g
+h 556,726,17,16,28,16 2 0150 -- h
+i 333,695,17,29,24,29 2 0151 -- i
+j 333,695,271,40,114,40 3 0152 -- j
+k 556,726,17,22,16,22 2 0153 -- k
+l 333,726,17,35,-14,35 2 0154 -- l
+m 833,469,17,20,31,20 0 0155 -- m
+n 556,469,17,15,33,15 0 0156 -- n
+o 556,469,17,0,2 0 0157 -- o
+p 556,469,271,10,71,10 1 0160 -- p
+q 537,469,271,26,18,26 1 0161 -- q
+r 389,469,17,72,30,66 0 0162 -- r
+s 444,469,17,12,25,12 0 0163 -- s
+t 389,636,17,70,8,66 2 0164 -- t
+u 556,469,17,15,28,15 0 0165 -- u
+v 556,469,17,7,31,7 0 0166 -- v
+w 833,469,17,19,23,19 0 0167 -- w
+x 500,469,17,50,58,50 0 0170 -- x
+y 556,469,271,35,37,35 1 0171 -- y
+z 500,469,17,20,19,20 0 0172 -- z
+lC 333,720,105,51,32,51 2 0173 -- braceleft
+{ "
+ba 606,720,0,0,-209 2 0174 -- bar
+| "
+rC 333,720,105,32,51,32 2 0175 -- braceright
+} "
+a~ 333,654,0,158,-32,66 2 0176 -- tilde
+~ "
+bq 250,145,144,20,53,20 0 0200 -- quotesinglbase
+Fo 500,446,0,8,15,8 0 0201 -- guillemotleft
+char171 "
+Fc 500,443,0,8,15,8 0 0202 -- guillemotright
+char187 "
+bu 606,516,0,0,-81 0 0203 -- bullet
+Fn 500,690,242,29,42,29 2 0204 -- florin
+f/ 167,683,0,221,220,66 2 0205 -- fraction
+%0 1000,691,17,0,-15 2 0206 -- perthousand
+dg 556,685,3,0,-17 2 0207 -- dagger
+dd 556,693,153,31,17,31 2 0210 -- daggerdbl
+en 500,282,0,62,62,62 0 0211 -- endash
+em 1000,282,0,62,62,62 0 0212 -- emdash
+fi 611,726,271,27,180,27 3 0214 -- fi
+fl 611,726,271,70,180,66 3 0215 -- fl
+.i 333,469,17,10,24,10 0 0220 -- dotlessi
+ga 333,699,0,39,-60,39 2 0222 -- grave
+a" 333,699,0,126,78,66 2 0223 -- hungarumlaut
+a. 333,668,0,42,-152,42 2 0224 -- dotaccent
+ab 333,680,0,129,-46,66 2 0225 -- breve
+ah 333,684,0,162,-63,66 2 0226 -- caron
+ao 556,714,0,0,-227 2 0227 -- ring
+ho 333,0,206,0,18 0 0230 -- ogonek
+lq 500,720,0,61,-15,61 2 0231 -- quotedblleft
+rq 500,720,0,69,-23,66 2 0232 -- quotedblright
+oe 778,469,17,27,2,27 0 0233 -- oe
+/l 333,726,17,82,37,66 2 0234 -- lslash
+Bq 500,145,144,0,68 0 0235 -- quotedblbase
+OE 944,695,17,67,11,66 2 0236 -- OE
+/L 611,681,3,17,44,17 2 0237 -- Lslash
+r! 333,479,225,0,48 0 0241 -- exclamdown
+char161 "
+ct 500,547,105,6,-2,6 0 0242 -- cent
+char162 "
+Po 500,683,5,51,29,51 2 0243 -- sterling
+char163 "
+Cs 500,533,0,18,18,18 0 0244 -- currency
+char164 "
+Ye 500,695,3,88,39,66 2 0245 -- yen
+char165 "
+bb 606,720,0,0,-209 2 0246 -- brokenbar
+char166 "
+sc 556,695,151,0,3 2 0247 -- section
+char167 "
+ad 333,668,0,143,-40,66 2 0250 -- dieresis
+char168 "
+co 747,695,17,23,24,23 2 0251 -- copyright
+char169 "
+Of 333,684,0,72,3,66 2 0252 -- ordfeminine
+char170 "
+fo 333,446,0,9,-10,9 0 0253 -- guilsinglleft
+no 606,390,0,0,-1 0 0254 -- logicalnot
+char172 "
+\- 606,292,0,0,-1 0 0255 -- minus
+rg 747,695,17,23,24,23 2 0256 -- registered
+char174 "
+a- 333,608,0,135,-26,66 0 0257 -- macron
+char175 "
+de 400,683 2 0260 -- degree
+char176 "
+char177 606,501 0 0261 -- plusminus
+S2 300,683,0,71,24,66 2 0262 -- twosuperior
+char178 "
+S3 300,683,0,60,27,60 2 0263 -- threesuperior
+char179 "
+aa 333,699,0,109,-103,66 2 0264 -- acute
+char180 "
+char181 556,469,232,15,65,15 0 0265 -- mu
+ps 556,681,204,123,36,66 2 0266 -- paragraph
+char182 "
+char183 250,324,0,6,-17,6 0 0267 -- periodcentered
+ac 333,5,218,0,38 0 0270 -- cedilla
+char184 "
+S1 300,680,0,48,9,48 2 0271 -- onesuperior
+char185 "
+Om 333,683,0,63,-1,63 2 0272 -- ordmasculine
+char186 "
+fc 333,443,0,0,15 0 0273 -- guilsinglright
+14 750,683,2,32,32,32 2 0274 -- onequarter
+char188 "
+12 750,683,2,36,36,36 2 0275 -- onehalf
+char189 "
+34 750,683,2,32,32,32 2 0276 -- threequarters
+char190 "
+r? 444,479,226,0,62 0 0277 -- questiondown
+char191 "
+`A 722,911,3,13,85,13 2 0300 -- Agrave
+char192 "
+'A 722,911,3,13,85,13 2 0301 -- Aacute
+char193 "
+^A 722,896,3,13,85,13 2 0302 -- Acircumflex
+char194 "
+~A 722,866,3,13,85,13 2 0303 -- Atilde
+char195 "
+:A 722,880,3,13,85,13 2 0304 -- Adieresis
+char196 "
+oA 722,926,3,13,85,13 2 0305 -- Aring
+char197 "
+AE 944,681,3,33,79,33 2 0306 -- AE
+char198 "
+,C 685,695,218,60,-19,60 2 0307 -- Ccedilla
+char199 "
+`E 611,911,3,45,39,45 2 0310 -- Egrave
+char200 "
+'E 611,911,3,45,39,45 2 0311 -- Eacute
+char201 "
+^E 611,896,3,45,39,45 2 0312 -- Ecircumflex
+char202 "
+:E 611,880,3,45,39,45 2 0313 -- Edieresis
+char203 "
+`I 389,911,3,73,51,66 2 0314 -- Igrave
+char204 "
+'I 389,911,3,81,51,66 2 0315 -- Iacute
+char205 "
+^I 389,896,3,104,51,66 2 0316 -- Icircumflex
+char206 "
+:I 389,880,3,115,51,66 2 0317 -- Idieresis
+char207 "
+-D 778,682,3,19,50,19 2 0320 -- Eth
+char208 "
+~N 778,866,3,101,52,66 2 0321 -- Ntilde
+char209 "
+`O 833,911,17,11,-26,11 2 0322 -- Ograve
+char210 "
+'O 833,911,17,11,-26,11 2 0323 -- Oacute
+char211 "
+^O 833,896,17,11,-26,11 2 0324 -- Ocircumflex
+char212 "
+~O 833,866,17,11,-26,11 2 0325 -- Otilde
+char213 "
+:O 833,880,17,11,-26,11 2 0326 -- Odieresis
+char214 "
+char215 606,479,0,0,-22 0 0327 -- multiply
+/O 833,730,54,14,-7,14 2 0330 -- Oslash
+char216 "
+`U 778,911,17,97,-33,66 2 0331 -- Ugrave
+char217 "
+'U 778,911,17,97,-33,66 2 0332 -- Uacute
+char218 "
+^U 778,896,17,97,-33,66 2 0333 -- Ucircumflex
+char219 "
+:U 778,880,17,97,-33,66 2 0334 -- Udieresis
+char220 "
+'Y 611,911,3,114,-4,66 2 0335 -- Yacute
+char221 "
+TP 667,681,3,27,39,27 2 0336 -- Thorn
+char222 "
+ss 556,726,271,43,181,43 3 0337 -- germandbls
+char223 "
+`a 556,719,17,13,6,13 2 0340 -- agrave
+char224 "
+'a 556,719,17,13,6,13 2 0341 -- aacute
+char225 "
+^a 556,704,17,21,6,21 2 0342 -- acircumflex
+char226 "
+~a 556,666,17,47,6,47 2 0343 -- atilde
+char227 "
+:a 556,688,17,32,6,32 2 0344 -- adieresis
+char228 "
+oa 556,714,17,13,6,13 2 0345 -- aring
+char229 "
+ae 738,469,17,23,6,23 0 0346 -- ae
+char230 "
+,c 444,469,218,42,18,42 0 0347 -- ccedilla
+char231 "
+`e 444,719,17,24,22,24 2 0350 -- egrave
+char232 "
+'e 444,719,17,54,22,54 2 0351 -- eacute
+char233 "
+^e 444,704,17,77,22,66 2 0352 -- ecircumflex
+char234 "
+:e 444,688,17,88,22,66 2 0353 -- edieresis
+char235 "
+`i 333,719,17,39,24,39 2 0354 -- igrave
+char236 "
+'i 333,719,17,109,24,66 2 0355 -- iacute
+char237 "
+^i 333,704,17,120,24,66 2 0356 -- icircumflex
+char238 "
+:i 333,688,17,143,24,66 2 0357 -- idieresis
+char239 "
+Sd 556,726,17,40,2,40 2 0360 -- eth
+char240 "
+~n 556,666,17,47,33,47 2 0361 -- ntilde
+char241 "
+`o 556,719,17,0,2 2 0362 -- ograve
+char242 "
+'o 556,719,17,0,2 2 0363 -- oacute
+char243 "
+^o 556,704,17,9,2,9 2 0364 -- ocircumflex
+char244 "
+~o 556,666,17,47,2,47 2 0365 -- otilde
+char245 "
+:o 556,688,17,32,2,32 2 0366 -- odieresis
+char246 "
+char247 606,501,5 0 0367 -- divide
+/o 556,506,50,16,36,16 0 0370 -- oslash
+char248 "
+`u 556,719,17,15,28,15 2 0371 -- ugrave
+char249 "
+'u 556,719,17,15,28,15 2 0372 -- uacute
+char250 "
+^u 556,704,17,15,28,15 2 0373 -- ucircumflex
+char251 "
+:u 556,688,17,32,28,32 2 0374 -- udieresis
+char252 "
+'y 556,719,271,35,37,35 3 0375 -- yacute
+char253 "
+Tp 556,726,271,10,71,10 3 0376 -- thorn
+char254 "
+:y 556,688,271,35,37,35 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/PI b/font/devps/PI
new file mode 100644
index 00000000..3b703b1a
--- /dev/null
+++ b/font/devps/PI
@@ -0,0 +1,453 @@
+name PI
+internalname Palatino-Italic
+slant 10
+spacewidth 250
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -55
+A w -37
+A v -37
+A ' -55
+A Y -55
+A W -55
+A V -74
+A T -55
+F . -111
+F , -111
+F A -111
+L y -37
+L ' -37
+L Y -74
+L W -74
+L V -74
+L T -74
+P . -129
+P , -129
+P A -129
+R y -37
+R Y -55
+R W -55
+R V -74
+R T -55
+T y -92
+T w -92
+T u -111
+T ; -74
+T s -111
+T r -111
+T . -74
+T o -111
+T i -55
+T - -55
+T hy -55
+T char173 -55
+T e -111
+T , -74
+T : -74
+T c -111
+T a -111
+T O -18
+T A -92
+V y -74
+V u -74
+V ; -37
+V r -92
+V . -129
+V o -74
+V i -74
+V - -55
+V hy -55
+V char173 -55
+V e -92
+V , -129
+V : -37
+V a -74
+V A -210
+W y -20
+W u -20
+W ; -18
+W r -20
+W . -55
+W o -20
+W i -20
+W - -18
+W hy -18
+W char173 -18
+W e -20
+W , -55
+W : -18
+W a -20
+W A -92
+Y v -74
+Y u -92
+Y ; -74
+Y q -92
+Y . -92
+Y p -74
+Y o -111
+Y i -55
+Y - -74
+Y hy -74
+Y char173 -74
+Y e -111
+Y , -92
+Y : -74
+Y a -92
+Y A -92
+f ' 55
+1 1 -55
+` ` -74
+` oq -74
+oq ` -74
+oq oq -74
+' t -37
+' s -55
+' ' -74
+r ' 37
+r q -18
+r . -74
+r o -18
+r h -18
+r g -18
+r e -18
+r , -74
+r c -18
+v . -55
+v , -55
+w . -55
+w , -55
+y . -37
+y , -37
+charset
+ha 606,689,0,0,-1 2 0000 -- asciicircum
+ti 606,339,0,0,-1 0 0001 -- asciitilde
+vS 556,907,18,33,8,33 2 0002 -- Scaron
+vZ 667,907,3,20,30,20 2 0003 -- Zcaron
+vs 389,687,11,80,41,68 2 0004 -- scaron
+vz 444,687,11,53,51,53 2 0005 -- zcaron
+:Y 667,847,3,58,-2,58 2 0006 -- Ydieresis
+tm 1000,689,0,1,-2,1 2 0007 -- trademark
+aq 333,733,0,5,-90,5 2 0010 -- quotesingle
+space 250 0 0040
+! 333,733,8,9,-26,9 2 0041 -- exclam
+" 500,733,0,5,-90,5 2 0042 -- quotedbl
+# 500,692,0,45,46,45 2 0043 -- numbersign
+sh "
+$ 500,733,113,2,35,2 2 0044 -- dollar
+Do "
+% 889,710,7,0,-24 2 0045 -- percent
+& 778,692,18,38,3,38 2 0046 -- ampersand
+' 278,733,0,30,-28,30 2 0047 -- quoteright
+( 333,733,106,48,-4,48 2 0050 -- parenleft
+) 333,733,106,0,48 2 0051 -- parenright
+* 389,706,0,61,-26,61 2 0052 -- asterisk
++ 606,504,0,0,-1 0 0053 -- plus
+, 250,123,143,3,42,3 0 0054 -- comma
+- 333,281,0,21,31,21 0 0055 -- hyphen
+hy "
+char173 "
+. 250,112,5,0,-3 0 0056 -- period
+/ 296,733,119,146,90,68 2 0057 -- slash
+sl "
+0 500,699,11,30,14,30 2 0060 -- zero
+1 500,699,3,0,-4 2 0061 -- one
+2 500,699,3,0,38 2 0062 -- two
+3 500,699,11,0,28 2 0063 -- three
+4 500,699,3,28,35,28 2 0064 -- four
+5 500,693,11,41,36,41 2 0065 -- five
+6 500,699,11,19,1,19 2 0066 -- six
+7 500,692,3,52,-3,52 2 0067 -- seven
+8 500,699,11,19,14,19 2 0070 -- eight
+9 500,699,11,18,18,18 2 0071 -- nine
+: 250,458,5,7,6,7 0 0072 -- colon
+; 250,456,146,19,59,19 0 0073 -- semicolon
+< 606,516,6,0,-3 0 0074 -- less
+= 606,378,0,0,-1 0 0075 -- equal
+> 606,516,6,0,-3 0 0076 -- greater
+? 500,706,8,0,-64 2 0077 -- question
+@ 747,706,18,21,23,21 2 0100 -- at
+at "
+A 722,705,3,5,69,5 2 0101 -- A
+B 611,692,6,0,24 2 0102 -- B
+C 667,706,18,34,5,34 2 0103 -- C
+D 778,692,3,13,22,13 2 0104 -- D
+E 611,692,3,9,20,9 2 0105 -- E
+F 556,692,3,42,50,42 2 0106 -- F
+G 722,706,18,22,0,22 2 0107 -- G
+H 778,692,3,72,53,68 2 0110 -- H
+I 333,692,3,71,43,68 2 0111 -- I
+J 333,692,206,75,85,68 2 0112 -- J
+K 667,692,3,66,37,66 2 0113 -- K
+L 556,692,3,17,34,17 2 0114 -- L
+M 944,692,18,46,69,46 2 0115 -- M
+N 778,692,11,76,48,68 2 0116 -- N
+O 778,706,18,20,-3,20 2 0117 -- O
+P 611,692,3,33,41,33 2 0120 -- P
+Q 778,706,201,20,-3,20 2 0121 -- Q
+R 667,692,3,22,41,22 2 0122 -- R
+S 556,706,18,0,8 2 0123 -- S
+T 611,692,3,74,-3,68 2 0124 -- T
+U 778,692,18,70,-38,68 2 0125 -- U
+V 722,692,8,82,-25,68 2 0126 -- V
+W 944,700,8,86,-21,68 2 0127 -- W
+X 722,692,3,62,30,62 2 0130 -- X
+Y 667,705,3,58,-2,58 2 0131 -- Y
+Z 667,692,3,20,30,20 2 0132 -- Z
+[ 333,733,100,43,32,43 2 0133 -- bracketleft
+lB "
+\ 606,733,0,0,-31 2 0134 -- backslash
+rs "
+] 333,733,100,32,43,32 2 0135 -- bracketright
+rB "
+a^ 333,679,0,67,-6,67 2 0136 -- circumflex
+^ "
+_ 500,0,125,50,50,50 0 0137 -- underscore
+` 278,733,0,30,-28,30 2 0140 -- quoteleft
+oq "
+a 444,482,11,12,46,12 0 0141 -- a
+b 463,733,11,20,13,20 2 0142 -- b
+c 407,482,11,32,25,32 0 0143 -- c
+d 500,733,11,33,33,33 2 0144 -- d
+e 389,482,11,35,35,35 0 0145 -- e
+f 278,733,276,185,212,68 3 0146 -- f
+g 500,482,276,48,87,48 1 0147 -- g
+h 500,733,9,21,40,21 2 0150 -- h
+i 278,712,9,36,16,36 2 0151 -- i
+j 278,712,276,37,120,37 3 0152 -- j
+k 444,733,9,55,42,55 2 0153 -- k
+l 278,733,9,23,14,23 2 0154 -- l
+m 778,482,9,12,26,12 0 0155 -- m
+n 556,482,9,8,26,8 0 0156 -- n
+o 444,482,11,17,33,17 0 0157 -- o
+p 500,482,276,15,57,15 1 0160 -- p
+q 463,482,276,19,26,19 1 0161 -- q
+r 389,482,9,45,24,45 0 0162 -- r
+s 389,482,11,6,41,6 0 0163 -- s
+t 333,646,9,27,9,27 2 0164 -- t
+u 556,482,11,6,18,6 0 0165 -- u
+v 500,482,11,27,29,27 0 0166 -- v
+w 722,482,11,27,29,27 0 0167 -- w
+x 500,482,11,34,41,34 0 0170 -- x
+y 500,482,276,40,58,40 1 0171 -- y
+z 444,482,11,22,51,22 0 0172 -- z
+lC 333,733,100,36,35,36 2 0173 -- braceleft
+{ "
+ba 606,733,0,0,-225 2 0174 -- bar
+| "
+rC 333,733,100,35,36,35 2 0175 -- braceright
+} "
+a~ 333,638,0,107,-13,68 0 0176 -- tilde
+~ "
+bq 278,120,122,0,23 0 0200 -- quotesinglbase
+Fo 500,440,0,0,-7 0 0201 -- guillemotleft
+char171 "
+Fc 500,440,0,0,-13 0 0202 -- guillemotright
+char187 "
+bu 500,526,0,0,-36 0 0203 -- bullet
+Fn 500,708,276,20,45,20 3 0204 -- florin
+f/ 167,699,0,220,220,68 2 0205 -- fraction
+%0 1000,717,6,0,-22 2 0206 -- perthousand
+dg 500,692,0,19,2,19 2 0207 -- dagger
+dd 500,692,162,44,40,44 2 0210 -- daggerdbl
+en 500,278,0,60,60,60 0 0211 -- endash
+em 1000,278,0,60,60,60 0 0212 -- emdash
+fi 528,733,276,24,212,24 3 0214 -- fi
+fl 545,733,276,25,212,25 3 0215 -- fl
+.i 278,482,9,13,16,13 0 0220 -- dotlessi
+ga 333,687,0,27,-36,27 2 0222 -- grave
+a" 333,730,0,102,4,68 2 0223 -- hungarumlaut
+a. 333,645,0,0,-125 2 0224 -- dotaccent
+ab 333,677,0,110,-42,68 2 0225 -- breve
+ah 333,679,0,126,-54,68 2 0226 -- caron
+ao 333,708,0,76,-109,68 2 0227 -- ring
+ho 333,0,207,0,12 0 0230 -- ogonek
+lq 500,733,0,25,-48,25 2 0231 -- quotedblleft
+rq 500,733,0,25,-48,25 2 0232 -- quotedblright
+oe 669,482,11,35,33,35 0 0233 -- oe
+/l 278,733,9,74,60,68 2 0234 -- lslash
+Bq 500,120,122,0,7 0 0235 -- quotedblbase
+OE 1028,706,18,11,-6,11 2 0236 -- OE
+/L 556,692,3,17,66,17 2 0237 -- Lslash
+r! 333,467,276,0,35 1 0241 -- exclamdown
+char161 "
+ct 500,551,96,0,-6 0 0242 -- cent
+char162 "
+Po 500,708,18,29,48,29 2 0243 -- sterling
+char163 "
+Cs 500,577,0,36,36,36 0 0244 -- currency
+char164 "
+Ye 500,699,3,62,15,62 2 0245 -- yen
+char165 "
+bb 606,733,0,0,-225 2 0246 -- brokenbar
+char166 "
+sc 500,706,220,13,36,13 2 0247 -- section
+char167 "
+ad 333,637,0,95,-28,68 0 0250 -- dieresis
+char168 "
+co 747,706,18,39,39,39 2 0251 -- copyright
+char169 "
+Of 333,699,0,38,-10,38 2 0252 -- ordfeminine
+char170 "
+fo 333,440,0,0,-7 0 0253 -- guilsinglleft
+no 606,378,0,0,-1 0 0254 -- logicalnot
+char172 "
+\- 606,280,0,0,-1 0 0255 -- minus
+rg 747,706,18,39,39,39 2 0256 -- registered
+char174 "
+a- 333,589,0,103,-24,68 0 0257 -- macron
+char175 "
+de 400,689,0,40,-40,40 2 0260 -- degree
+char176 "
+char177 606,504,0,0,-1 0 0261 -- plusminus
+S2 300,699,0,40,37,40 2 0262 -- twosuperior
+char178 "
+S3 300,699,0,54,22,54 2 0263 -- threesuperior
+char179 "
+aa 333,687,0,63,-72,63 2 0264 -- acute
+char180 "
+char181 556,482,226,6,35,6 0 0265 -- mu
+ps 500,692,224,161,17,68 2 0266 -- paragraph
+char182 "
+char183 250,312,0,0,-3 0 0267 -- periodcentered
+ac 333,0,216,0,59 0 0270 -- cedilla
+char184 "
+S1 300,699,0,35,-11,35 2 0271 -- onesuperior
+char185 "
+Om 333,699,0,39,-16,39 2 0272 -- ordmasculine
+char186 "
+fc 333,440,0,0,-13 0 0273 -- guilsinglright
+14 750,699,2,15,19,15 2 0274 -- onequarter
+char188 "
+12 750,699,2,21,19,21 2 0275 -- onehalf
+char189 "
+34 750,699,2,15,15,15 2 0276 -- threequarters
+char190 "
+r? 500,467,246,0,-7 0 0277 -- questiondown
+char191 "
+`A 722,897,3,5,69,5 2 0300 -- Agrave
+char192 "
+'A 722,897,3,5,69,5 2 0301 -- Aacute
+char193 "
+^A 722,889,3,5,69,5 2 0302 -- Acircumflex
+char194 "
+~A 722,866,3,5,69,5 2 0303 -- Atilde
+char195 "
+:A 722,847,3,5,69,5 2 0304 -- Adieresis
+char196 "
+oA 722,918,3,5,69,5 2 0305 -- Aring
+char197 "
+AE 941,692,3,11,54,11 2 0306 -- AE
+char198 "
+,C 667,706,216,34,5,34 2 0307 -- Ccedilla
+char199 "
+`E 611,897,3,9,20,9 2 0310 -- Egrave
+char200 "
+'E 611,897,3,9,20,9 2 0311 -- Eacute
+char201 "
+^E 611,889,3,9,20,9 2 0312 -- Ecircumflex
+char202 "
+:E 611,847,3,9,20,9 2 0313 -- Edieresis
+char203 "
+`I 333,897,3,71,43,68 2 0314 -- Igrave
+char204 "
+'I 333,897,3,123,43,68 2 0315 -- Iacute
+char205 "
+^I 333,889,3,107,43,68 2 0316 -- Icircumflex
+char206 "
+:I 333,847,3,135,43,68 2 0317 -- Idieresis
+char207 "
+-D 778,692,3,13,31,13 2 0320 -- Eth
+char208 "
+~N 778,866,11,76,48,68 2 0321 -- Ntilde
+char209 "
+`O 778,897,18,20,-3,20 2 0322 -- Ograve
+char210 "
+'O 778,897,18,20,-3,20 2 0323 -- Oacute
+char211 "
+^O 778,889,18,20,-3,20 2 0324 -- Ocircumflex
+char212 "
+~O 778,866,18,20,-3,20 2 0325 -- Otilde
+char213 "
+:O 778,847,18,20,-3,20 2 0326 -- Odieresis
+char214 "
+char215 606,474,0,0,-33 0 0327 -- multiply
+/O 778,721,39,34,18,34 2 0330 -- Oslash
+char216 "
+`U 778,897,18,70,-38,68 2 0331 -- Ugrave
+char217 "
+'U 778,897,18,70,-38,68 2 0332 -- Uacute
+char218 "
+^U 778,889,18,70,-38,68 2 0333 -- Ucircumflex
+char219 "
+:U 778,847,18,70,-38,68 2 0334 -- Udieresis
+char220 "
+'Y 667,897,3,58,-2,58 2 0335 -- Yacute
+char221 "
+TP 611,692,3,9,41,9 2 0336 -- Thorn
+char222 "
+ss 500,733,276,38,210,38 3 0337 -- germandbls
+char223 "
+`a 444,707,11,12,46,12 2 0340 -- agrave
+char224 "
+'a 444,707,11,20,46,20 2 0341 -- aacute
+char225 "
+^a 444,699,11,12,46,12 2 0342 -- acircumflex
+char226 "
+~a 444,650,11,52,46,52 2 0343 -- atilde
+char227 "
+:a 444,657,11,40,46,40 2 0344 -- adieresis
+char228 "
+oa 444,728,11,12,46,12 2 0345 -- aring
+char229 "
+ae 638,482,11,35,49,35 0 0346 -- ae
+char230 "
+,c 407,482,216,32,25,32 0 0347 -- ccedilla
+char231 "
+`e 389,707,11,35,35,35 2 0350 -- egrave
+char232 "
+'e 389,707,11,55,35,55 2 0351 -- eacute
+char233 "
+^e 389,699,11,59,35,59 2 0352 -- ecircumflex
+char234 "
+:e 389,657,11,67,35,67 2 0353 -- edieresis
+char235 "
+`i 278,707,9,43,16,43 2 0354 -- igrave
+char236 "
+'i 278,707,9,103,16,68 2 0355 -- iacute
+char237 "
+^i 278,699,9,95,21,68 2 0356 -- icircumflex
+char238 "
+:i 278,657,9,123,16,68 2 0357 -- idieresis
+char239 "
+Sd 444,733,11,84,33,68 2 0360 -- eth
+char240 "
+~n 556,650,9,8,26,8 2 0361 -- ntilde
+char241 "
+`o 444,707,11,17,33,17 2 0362 -- ograve
+char242 "
+'o 444,707,11,20,33,20 2 0363 -- oacute
+char243 "
+^o 444,699,11,17,33,17 2 0364 -- ocircumflex
+char244 "
+~o 444,650,11,52,33,52 2 0365 -- otilde
+char245 "
+:o 444,657,11,40,33,40 2 0366 -- odieresis
+char246 "
+char247 606,504,0,0,-1 0 0367 -- divide
+/o 444,510,24,66,68,66 0 0370 -- oslash
+char248 "
+`u 556,707,11,6,18,6 2 0371 -- ugrave
+char249 "
+'u 556,707,11,6,18,6 2 0372 -- uacute
+char250 "
+^u 556,699,11,6,18,6 2 0373 -- ucircumflex
+char251 "
+:u 556,657,11,6,18,6 2 0374 -- udieresis
+char252 "
+'y 500,707,276,40,58,40 3 0375 -- yacute
+char253 "
+Tp 500,733,276,0,89 3 0376 -- thorn
+char254 "
+:y 500,657,276,40,58,40 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/PR b/font/devps/PR
new file mode 100644
index 00000000..6442b09a
--- /dev/null
+++ b/font/devps/PR
@@ -0,0 +1,456 @@
+name PR
+internalname Palatino-Roman
+spacewidth 250
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -74
+A w -74
+A v -92
+A ' -74
+A Y -111
+A W -74
+A V -111
+A T -74
+F . -92
+F , -92
+F A -74
+L y -55
+L ' -74
+L Y -92
+L W -74
+L V -92
+L T -74
+P . -129
+P , -129
+P A -92
+R y -37
+R Y -37
+R W -37
+R V -55
+R T -37
+T y -90
+T w -90
+T u -90
+T ; -55
+T s -90
+T r -90
+T . -74
+T o -92
+T i -55
+T - -55
+T hy -55
+T char173 -55
+T e -92
+T , -74
+T : -55
+T c -111
+T a -92
+T O -18
+T A -74
+V y -92
+V u -92
+V ; -55
+V r -92
+V . -129
+V o -111
+V i -55
+V - -74
+V hy -74
+V char173 -74
+V e -111
+V , -129
+V : -55
+V a -92
+V A -111
+W y -50
+W u -50
+W ; -18
+W r -74
+W . -92
+W o -92
+W i -55
+W - -55
+W hy -55
+W char173 -55
+W e -92
+W , -92
+W : -18
+W a -92
+W A -92
+Y v -90
+Y u -90
+Y ; -74
+Y q -90
+Y . -111
+Y p -111
+Y o -92
+Y i -55
+Y - -92
+Y hy -92
+Y char173 -92
+Y e -92
+Y , -111
+Y : -74
+Y a -92
+Y A -92
+f ' 55
+f f -18
+1 1 -55
+` ` -37
+` oq -37
+oq ` -37
+oq oq -37
+' ' -37
+r u -8
+r ' 74
+r q -18
+r . -74
+r o -18
+r - -18
+r hy -18
+r char173 -18
+r h -18
+r g -18
+r e -18
+r d -18
+r , -74
+r c -18
+v . -111
+v , -111
+w . -92
+w , -92
+y . -111
+y , -111
+charset
+ha 606,689 2 0000 -- asciicircum
+ti 606,347 0 0001 -- asciitilde
+vS 525,908,20 2 0002 -- Scaron
+vZ 667,908,3 2 0003 -- Zcaron
+vs 424,685,20 2 0004 -- scaron
+vz 500,685,3 2 0005 -- zcaron
+:Y 667,868,3 2 0006 -- Ydieresis
+tm 979,689 2 0007 -- trademark
+aq 208,709 2 0010 -- quotesingle
+space 250 0 0040
+! 278,694,5 2 0041 -- exclam
+" 371,709 2 0042 -- quotedbl
+# 500,684 2 0043 -- numbersign
+sh "
+$ 500,731,116 2 0044 -- dollar
+Do "
+% 840,709,20 2 0045 -- percent
+& 778,689,20 2 0046 -- ampersand
+' 278,709 2 0047 -- quoteright
+( 333,726,215 2 0050 -- parenleft
+) 333,726,215 2 0051 -- parenright
+* 389,689 2 0052 -- asterisk
++ 606,512 0 0053 -- plus
+, 250,123,155 0 0054 -- comma
+- 333,287 0 0055 -- hyphen
+hy "
+char173 "
+. 250,111,5 0 0056 -- period
+/ 606,726,119 2 0057 -- slash
+sl "
+0 500,689,20 2 0060 -- zero
+1 500,694,3 2 0061 -- one
+2 500,689,3 2 0062 -- two
+3 500,689,20 2 0063 -- three
+4 500,694,3 2 0064 -- four
+5 500,689,20 2 0065 -- five
+6 500,689,20 2 0066 -- six
+7 500,689,3 2 0067 -- seven
+8 500,689,20 2 0070 -- eight
+9 500,689,20 2 0071 -- nine
+: 250,456,5 0 0072 -- colon
+; 250,456,153 0 0073 -- semicolon
+< 606,522 0 0074 -- less
+= 606,386 0 0075 -- equal
+> 606,522 0 0076 -- greater
+? 444,694,5 2 0077 -- question
+@ 747,694,20 2 0100 -- at
+at "
+A 778,700,3 2 0101 -- A
+B 611,692,3 2 0102 -- B
+C 709,709,20 2 0103 -- C
+D 774,692,3 2 0104 -- D
+E 611,692,3 2 0105 -- E
+F 556,692,3 2 0106 -- F
+G 763,709,20 2 0107 -- G
+H 832,692,3 2 0110 -- H
+I 337,692,3 2 0111 -- I
+J 333,692,194 2 0112 -- J
+K 726,692,3 2 0113 -- K
+L 611,692,3 2 0114 -- L
+M 946,692,13 2 0115 -- M
+N 831,692,20 2 0116 -- N
+O 786,709,20 2 0117 -- O
+P 604,692,3 2 0120 -- P
+Q 786,709,176 2 0121 -- Q
+R 668,692,3 2 0122 -- R
+S 525,709,20 2 0123 -- S
+T 613,692,3 2 0124 -- T
+U 778,692,20 2 0125 -- U
+V 722,692,9 2 0126 -- V
+W 1000,700,9 2 0127 -- W
+X 667,700,3 2 0130 -- X
+Y 667,704,3 2 0131 -- Y
+Z 667,692,3 2 0132 -- Z
+[ 333,726,184 2 0133 -- bracketleft
+lB "
+\ 606,726 2 0134 -- backslash
+rs "
+] 333,726,184 2 0135 -- bracketright
+rB "
+a^ 333,677 2 0136 -- circumflex
+^ "
+_ 500,0,125 0 0137 -- underscore
+` 278,709 2 0140 -- quoteleft
+oq "
+a 500,469,12 0 0141 -- a
+b 553,726,12 2 0142 -- b
+c 444,469,20 0 0143 -- c
+d 611,726,12 2 0144 -- d
+e 479,469,20 0 0145 -- e
+f 333,728,3 2 0146 -- f
+g 556,469,283 1 0147 -- g
+h 582,726,3 2 0150 -- h
+i 291,687,3 2 0151 -- i
+j 234,688,283 3 0152 -- j
+k 556,726,12 2 0153 -- k
+l 291,726,3 2 0154 -- l
+m 883,469,3 0 0155 -- m
+n 582,469,3 0 0156 -- n
+o 546,469,20 0 0157 -- o
+p 601,469,281 1 0160 -- p
+q 560,469,281 1 0161 -- q
+r 395,469,3 0 0162 -- r
+s 424,469,20 0 0163 -- s
+t 326,621,12 2 0164 -- t
+u 603,469,12 0 0165 -- u
+v 565,459,7 0 0166 -- v
+w 834,469,7 0 0167 -- w
+x 516,469,3 0 0170 -- x
+y 556,459,283 1 0171 -- y
+z 500,462,3 0 0172 -- z
+lC 333,726,175 2 0173 -- braceleft
+{ "
+ba 606,726 2 0174 -- bar
+| "
+rC 333,726,175 2 0175 -- braceright
+} "
+a~ 333,640 2 0176 -- tilde
+~ "
+bq 278,110,153 0 0200 -- quotesinglbase
+Fo 500,428 0 0201 -- guillemotleft
+char171 "
+Fc 500,428 0 0202 -- guillemotright
+char187 "
+bu 606,516 0 0203 -- bullet
+Fn 500,706,262 2 0204 -- florin
+f/ 167,689 2 0205 -- fraction
+%0 1144,709,20 2 0206 -- perthousand
+dg 500,694,5 2 0207 -- dagger
+dd 500,694,249 2 0210 -- daggerdbl
+en 500,277 0 0211 -- endash
+em 1000,277 0 0212 -- emdash
+fi 605,728,3 2 0214 -- fi
+fl 608,728,3 2 0215 -- fl
+.i 287,469,3 0 0220 -- dotlessi
+ga 333,677 2 0222 -- grave
+a" 380,687 2 0223 -- hungarumlaut
+a. 250,637 2 0224 -- dotaccent
+ab 333,664 2 0225 -- breve
+ah 333,677 2 0226 -- caron
+ao 333,696 2 0227 -- ring
+ho 313,0,165 0 0230 -- ogonek
+lq 500,709 2 0231 -- quotedblleft
+rq 500,709 2 0232 -- quotedblright
+oe 827,469,20 0 0233 -- oe
+/l 291,726,3 2 0234 -- lslash
+Bq 500,110,153 0 0235 -- quotedblbase
+OE 998,709,20 2 0236 -- OE
+/L 611,692,3 2 0237 -- Lslash
+r! 278,469,225 0 0241 -- exclamdown
+char161 "
+ct 500,562,101 0 0242 -- cent
+char162 "
+Po 500,694,13 2 0243 -- sterling
+char163 "
+Cs 500,531 0 0244 -- currency
+char164 "
+Ye 500,701,3 2 0245 -- yen
+char165 "
+bb 606,726 2 0246 -- brokenbar
+char166 "
+sc 500,709,219 2 0247 -- section
+char167 "
+ad 333,637 2 0250 -- dieresis
+char168 "
+co 747,706,18 2 0251 -- copyright
+char169 "
+Of 333,709 2 0252 -- ordfeminine
+char170 "
+fo 331,428 0 0253 -- guilsinglleft
+no 606,386 0 0254 -- logicalnot
+char172 "
+\- 606,289 0 0255 -- minus
+rg 747,706,18 2 0256 -- registered
+char174 "
+a- 333,591 0 0257 -- macron
+char175 "
+de 400,689 2 0260 -- degree
+char176 "
+char177 606,512 0 0261 -- plusminus
+S2 300,689 2 0262 -- twosuperior
+char178 "
+S3 300,689 2 0263 -- threesuperior
+char179 "
+aa 333,677 2 0264 -- acute
+char180 "
+char181 603,469,236 0 0265 -- mu
+ps 628,694,150 2 0266 -- paragraph
+char182 "
+char183 250,319 0 0267 -- periodcentered
+ac 333,0,225 0 0270 -- cedilla
+char184 "
+S1 300,692 2 0271 -- onesuperior
+char185 "
+Om 333,709 2 0272 -- ordmasculine
+char186 "
+fc 331,428 0 0273 -- guilsinglright
+14 750,692,3 2 0274 -- onequarter
+char188 "
+12 750,692,3 2 0275 -- onehalf
+char189 "
+34 750,689,3 2 0276 -- threequarters
+char190 "
+r? 444,469,231 0 0277 -- questiondown
+char191 "
+`A 778,908,3 2 0300 -- Agrave
+char192 "
+'A 778,908,3 2 0301 -- Aacute
+char193 "
+^A 778,908,3 2 0302 -- Acircumflex
+char194 "
+~A 778,871,3 2 0303 -- Atilde
+char195 "
+:A 778,868,3 2 0304 -- Adieresis
+char196 "
+oA 778,927,3 2 0305 -- Aring
+char197 "
+AE 944,692,3 2 0306 -- AE
+char198 "
+,C 709,709,225 2 0307 -- Ccedilla
+char199 "
+`E 611,908,3 2 0310 -- Egrave
+char200 "
+'E 611,908,3 2 0311 -- Eacute
+char201 "
+^E 611,908,3 2 0312 -- Ecircumflex
+char202 "
+:E 611,868,3 2 0313 -- Edieresis
+char203 "
+`I 337,908,3 2 0314 -- Igrave
+char204 "
+'I 337,908,3 2 0315 -- Iacute
+char205 "
+^I 337,908,3 2 0316 -- Icircumflex
+char206 "
+:I 337,868,3 2 0317 -- Idieresis
+char207 "
+-D 774,692,3 2 0320 -- Eth
+char208 "
+~N 831,871,20 2 0321 -- Ntilde
+char209 "
+`O 786,908,20 2 0322 -- Ograve
+char210 "
+'O 786,908,20 2 0323 -- Oacute
+char211 "
+^O 786,908,20 2 0324 -- Ocircumflex
+char212 "
+~O 786,883,20 2 0325 -- Otilde
+char213 "
+:O 786,868,20 2 0326 -- Odieresis
+char214 "
+char215 606,474 0 0327 -- multiply
+/O 833,709,20 2 0330 -- Oslash
+char216 "
+`U 778,908,20 2 0331 -- Ugrave
+char217 "
+'U 778,908,20 2 0332 -- Uacute
+char218 "
+^U 778,908,20 2 0333 -- Ucircumflex
+char219 "
+:U 778,868,20 2 0334 -- Udieresis
+char220 "
+'Y 667,908,3 2 0335 -- Yacute
+char221 "
+TP 604,692,3 2 0336 -- Thorn
+char222 "
+ss 556,731,9 2 0337 -- germandbls
+char223 "
+`a 500,697,12 2 0340 -- agrave
+char224 "
+'a 500,697,12 2 0341 -- aacute
+char225 "
+^a 500,697,12 2 0342 -- acircumflex
+char226 "
+~a 500,652,12 2 0343 -- atilde
+char227 "
+:a 500,657,12 2 0344 -- adieresis
+char228 "
+oa 500,716,12 2 0345 -- aring
+char229 "
+ae 758,469,20 0 0346 -- ae
+char230 "
+,c 444,469,225 0 0347 -- ccedilla
+char231 "
+`e 479,697,20 2 0350 -- egrave
+char232 "
+'e 479,697,20 2 0351 -- eacute
+char233 "
+^e 479,697,20 2 0352 -- ecircumflex
+char234 "
+:e 479,657,20 2 0353 -- edieresis
+char235 "
+`i 287,697,3 2 0354 -- igrave
+char236 "
+'i 287,697,3 2 0355 -- iacute
+char237 "
+^i 287,697,3 2 0356 -- icircumflex
+char238 "
+:i 287,657,3 2 0357 -- idieresis
+char239 "
+Sd 546,728,20 2 0360 -- eth
+char240 "
+~n 582,652,3 2 0361 -- ntilde
+char241 "
+`o 546,697,20 2 0362 -- ograve
+char242 "
+'o 546,697,20 2 0363 -- oacute
+char243 "
+^o 546,697,20 2 0364 -- ocircumflex
+char244 "
+~o 546,652,20 2 0365 -- otilde
+char245 "
+:o 546,657,20 2 0366 -- odieresis
+char246 "
+char247 606,512 0 0367 -- divide
+/o 556,474,23 0 0370 -- oslash
+char248 "
+`u 603,697,12 2 0371 -- ugrave
+char249 "
+'u 603,697,12 2 0372 -- uacute
+char250 "
+^u 603,697,12 2 0373 -- ucircumflex
+char251 "
+:u 603,657,12 2 0374 -- udieresis
+char252 "
+'y 556,697,283 3 0375 -- yacute
+char253 "
+Tp 601,726,281 3 0376 -- thorn
+char254 "
+:y 556,657,283 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/S b/font/devps/S
new file mode 100644
index 00000000..3cf77d9d
--- /dev/null
+++ b/font/devps/S
@@ -0,0 +1,227 @@
+name S
+internalname Symbol
+special
+spacewidth 250
+charset
+space 250 0 0040
+! 333,672,17 3 0041 -- exclam
+fa 713,705 3 0042 -- universal
+# 500,673,16 3 0043 -- numbersign
+sh "
+te 549,707 3 0044 -- existential
+% 833,655,36 3 0045 -- percent
+& 778,661,18 3 0046 -- ampersand
+st 439,500,17 3 0047 -- suchthat
+( 333,673,191 3 0050 -- parenleft
+) 333,673,191 3 0051 -- parenright
+** 500,551 3 0052 -- asteriskmath
++ 549,533 3 0053 -- plus
+pl "
+, 250,104,152 3 0054 -- comma
+\- 549,288 3 0055 -- minus
+mi "
+. 250,95,17 3 0056 -- period
+/ 278,646,18 3 0057 -- slash
+sl "
+0 500,685,17 3 0060 -- zero
+1 500,673 3 0061 -- one
+2 500,686 3 0062 -- two
+3 500,685,17 3 0063 -- three
+4 500,685 3 0064 -- four
+5 500,685,17 3 0065 -- five
+6 500,685,17 3 0066 -- six
+7 500,673,16 3 0067 -- seven
+8 500,685,18 3 0070 -- eight
+9 500,685,18 3 0071 -- nine
+: 278,460,17 3 0072 -- colon
+; 278,460,152 3 0073 -- semicolon
+< 549,522 3 0074 -- less
+= 549,390 3 0075 -- equal
+eq "
+> 549,522 3 0076 -- greater
+? 444,686,17 3 0077 -- question
+=~ 549,475 3 0100 -- congruent
+*A 722,673 3 0101 -- Alpha
+*B 667,673 3 0102 -- Beta
+*X 722,673 3 0103 -- Chi
+*D 612,688 3 0104 -- Delta
+*E 611,673 3 0105 -- Epsilon
+*F 763,673 3 0106 -- Phi
+*G 603,673 3 0107 -- Gamma
+*Y 722,673 3 0110 -- Eta
+*I 333,673 3 0111 -- Iota
++h 631,689,18 3 0112 -- theta1
+*K 722,673 3 0113 -- Kappa
+*L 686,688 3 0114 -- Lambda
+*M 889,673 3 0115 -- Mu
+*N 722,673,8 3 0116 -- Nu
+*O 722,685,17 3 0117 -- Omicron
+*P 768,673 3 0120 -- Pi
+*H 741,685,17 3 0121 -- Theta
+*R 556,673 3 0122 -- Rho
+*S 592,673 3 0123 -- Sigma
+*T 611,673 3 0124 -- Tau
+--- 690,673 3 0125 -- Upsilon
+ts 439,500,233 3 0126 -- sigma1
+*W 768,688 3 0127 -- Omega
+*C 645,673 3 0130 -- Xi
+*Q 795,684 3 0131 -- Psi
+*Z 611,673 3 0132 -- Zeta
+[ 333,674,155 3 0133 -- bracketleft
+lB "
+3d 863,478 3 0134 -- therefore
+tf "
+] 333,674,155 3 0135 -- bracketright
+rB "
+pp 658,674 3 0136 -- perpendicular
+_ 500,0,252 3 0137 -- underscore
+radicalex 500,917 3 0140 -- radicalex
+*a 631,500,18 3 0141 -- alpha
+*b 549,741,223 3 0142 -- beta
+*x 549,499,231 3 0143 -- chi
+*d 494,740,19 3 0144 -- delta
+*e 439,502,19 3 0145 -- epsilon
+*f 521,671,224 3 0146 -- phi
+*g 411,499,225 3 0147 -- gamma
+*y 603,514,202 3 0150 -- eta
+*i 329,503,17 3 0151 -- iota
++f 603,499,224 3 0152 -- phi1
+*k 549,501 3 0153 -- kappa
+*l 549,739,17 3 0154 -- lambda
+char181 576,500,223 3 0155 -- mu
+*m "
+*n 521,507,16 3 0156 -- nu
+*o 549,499,19 3 0157 -- omicron
+*p 549,487,19 3 0160 -- pi
+*h 521,690,17 3 0161 -- theta
+*r 549,499,230 3 0162 -- rho
+*s 603,500,21 3 0163 -- sigma
+*t 439,500,19 3 0164 -- tau
+*u 576,507,18 3 0165 -- upsilon
++p 713,583,18 3 0166 -- omega1
+*w 686,500,17 3 0167 -- omega
+*c 493,766,224 3 0170 -- xi
+*q 686,500,228 3 0171 -- psi
+*z 494,756,225 3 0172 -- zeta
+lC 480,673,183 3 0173 -- braceleft
+{ "
+ba 200,673,177 3 0174 -- bar
+| "
+rC 480,673,183 3 0175 -- braceright
+} "
+ap 549,307 3 0176 -- similar
+*U 620,685 3 0241 -- Upsilon1
+fm 247,735 3 0242 -- minute
+<= 549,639 3 0243 -- lessequal
+f/ 167,677,12 3 0244 -- fraction
+if 713,404 3 0245 -- infinity
+Fn 500,686,193 3 0246 -- florin
+CL 753,533,26 3 0247 -- club
+DI 753,550,36 3 0250 -- diamond
+HE 753,532,33 3 0251 -- heart
+SP 753,548,36 3 0252 -- spade
+<> 1042,511,15 3 0253 -- arrowboth
+<- 987,511,15 3 0254 -- arrowleft
+ua 603,910 3 0255 -- arrowup
+arrowverttp "
+-> 987,511,15 3 0256 -- arrowright
+da 603,888,22 3 0257 -- arrowdown
+arrowvertbt "
+de 400,685 3 0260 -- degree
+char176 "
+char177 549,645 3 0261 -- plusminus
++- "
+sd 411,737 3 0262 -- second
+>= 549,639 3 0263 -- greaterequal
+char215 549,524 3 0264 -- multiply
+mu "
+pt 713,404 3 0265 -- proportional
+pd 494,746,20 3 0266 -- partialdiff
+bu 460,473 3 0267 -- bullet
+char247 549,456 3 0270 -- divide
+di "
+!= 549,549,25 3 0271 -- notequal
+== 549,443 3 0272 -- equivalence
+~~ 549,394 3 0273 -- approxequal
+~= "
+--- 1000,95,17 3 0274 -- ellipsis
+arrowvertex 603,1010,120 3 0275 -- arrowvertex
+an 1000,276 3 0276 -- arrowhorizex
+CR 658,629,16 3 0277 -- carriagereturn
+Ah 823,658,18 3 0300 -- aleph
+Im 686,740,53 3 0301 -- Ifraktur
+Re 795,734,15 3 0302 -- Rfraktur
+wp 987,573,211 3 0303 -- weierstrass
+c* 768,673,17 3 0304 -- circlemultiply
+c+ 768,675,15 3 0305 -- circleplus
+es 823,719,24 3 0306 -- emptyset
+ca 768,509 3 0307 -- intersection
+cu 768,492,17 3 0310 -- union
+sp 713,470 3 0311 -- propersuperset
+ip 713,470,125 3 0312 -- reflexsuperset
+nb 713,540,70 3 0313 -- notsubset
+sb 713,470 3 0314 -- propersubset
+ib 713,470,125 3 0315 -- reflexsubset
+mo 713,468 3 0316 -- element
+nm 713,555,58 3 0317 -- notelement
+/_ 768,673 3 0320 -- angle
+gr 713,718,19 3 0321 -- gradient
+--- 790,673,17 3 0322 -- registerserif
+--- 790,675,15 3 0323 -- copyrightserif
+--- 890,673 3 0324 -- trademarkserif
+product 823,751,101 3 0325 -- product
+sr 549,917,38 3 0326 -- radical
+md 250,310 3 0327 -- dotmath
+no 713,288 3 0330 -- logicalnot
+char172 "
+AN 603,454 3 0331 -- logicaland
+OR 603,477 3 0332 -- logicalor
+hA 1042,510,20 3 0333 -- arrowdblboth
+lA 987,513,15 3 0334 -- arrowdblleft
+uA 603,911 3 0335 -- arrowdblup
+rA 987,508,20 3 0336 -- arrowdblright
+dA 603,890,19 3 0337 -- arrowdbldown
+lz 494,745 3 0340 -- lozenge
+la 329,746,198 3 0341 -- angleleft
+--- 790,670,20 3 0342 -- registersans
+--- 790,675,15 3 0343 -- copyrightsans
+--- 786,673 3 0344 -- trademarksans
+sum 713,752,108 3 0345 -- summation
+parenlefttp 384,926,293 3 0346 -- parenlefttp
+parenleftex 384,920,80 3 0347 -- parenleftex
+parenleftbt 384,920,293 3 0350 -- parenleftbt
+bracketlefttp 384,925,75 3 0351 -- bracketlefttp
+lc "
+bracketleftex 384,925,75 3 0352 -- bracketleftex
+bracketleftbt 384,925,75 3 0353 -- bracketleftbt
+lf "
+bracelefttp 494,925,75 3 0354 -- bracelefttp
+lt "
+braceleftmid 494,925,75 3 0355 -- braceleftmid
+lk "
+braceleftbt 494,925,75 3 0356 -- braceleftbt
+lb "
+braceex 494,925,75 3 0357 -- braceex
+bracerightex "
+braceleftex "
+barex "
+bv "
+ra 329,746,198 3 0361 -- angleright
+is 274,916,107,67,52,-10 3 0362 -- integral
+--- 686,921,83 3 0363 -- integraltp
+--- 686,975,88 3 0364 -- integralex
+--- 686,921,81 3 0365 -- integralbt
+parenrighttp 384,926,293 3 0366 -- parenrighttp
+parenrightex 384,920,80 3 0367 -- parenrightex
+parenrightbt 384,920,293 3 0370 -- parenrightbt
+bracketrighttp 384,925,75 3 0371 -- bracketrighttp
+rc "
+bracketrightex 384,925,75 3 0372 -- bracketrightex
+bracketrightbt 384,925,75 3 0373 -- bracketrightbt
+rf "
+bracerighttp 494,925,75 3 0374 -- bracerighttp
+rt "
+bracerightmid 494,925,75 3 0375 -- bracerightmid
+rk "
+bracerightbt 494,925,75 3 0376 -- bracerightbt
+rb "
diff --git a/font/devps/SS b/font/devps/SS
new file mode 100644
index 00000000..933eb1c1
--- /dev/null
+++ b/font/devps/SS
@@ -0,0 +1,194 @@
+name SS
+internalname Symbol-Slanted
+special
+slant 15.5
+spacewidth 223
+charset
+space 223 0 0040
+--- 296,599,15,137,-72,99 3 0041 -- exclam
+--- 635,627,0,216,-173,99 3 0042 -- universal
+--- 445,599,15,162,-21,99 3 0043 -- numbersign
+--- 489,629,0,183,28,99 3 0044 -- existential
+--- 741,583,32,75,-97,75 3 0045 -- percent
+--- 692,589,16,103,-18,99 3 0046 -- ampersand
+--- 391,444,15,109,6,99 3 0047 -- suchthat
+--- 296,599,170,203,-39,99 3 0050 -- parenleft
+--- 296,600,170,93,72,93 3 0051 -- parenright
+--- 445,490,0,105,-76,99 3 0052 -- asteriskmath
+--- 489,474,0,123,-26,99 3 0053 -- plus
+--- 223,93,136,10,41,10 3 0054 -- comma
+--- 489,256,0,117,-24,99 3 0055 -- minus
+--- 223,85,15,1,-20,1 3 0056 -- period
+--- 247,575,15,208,55,99 3 0057 -- slash
+--- 445,610,15,142,-40,99 3 0060 -- zero
+--- 445,599,0,56,-57,56 3 0061 -- one
+--- 445,611,0,129,28,99 3 0062 -- two
+--- 445,611,16,115,-6,99 3 0063 -- three
+--- 445,610,0,135,-8,99 3 0064 -- four
+--- 445,610,15,188,14,99 3 0065 -- five
+--- 445,610,16,193,-37,99 3 0066 -- six
+--- 445,599,15,190,-101,99 3 0067 -- seven
+--- 445,611,16,141,-32,99 3 0070 -- eight
+--- 445,609,15,140,-2,99 3 0071 -- nine
+--- 247,409,15,89,-31,89 3 0072 -- colon
+--- 247,409,136,99,17,99 3 0073 -- semicolon
+--- 489,464,0,171,-37,99 3 0074 -- less
+--- 489,347,0,147,1,99 3 0075 -- equal
+--- 489,464,0,108,27,99 3 0076 -- greater
+--- 395,610,15,172,-113,99 3 0077 -- question
+--- 489,423,0,158,40,99 3 0100 -- congruent
+--- 643,599,0,21,47,21 3 0101 -- Alpha
+--- 594,598,0,101,24,99 3 0102 -- Beta
+--- 643,599,0,205,58,99 3 0103 -- Chi
+--- 545,612,0,46,45,46 3 0104 -- Delta
+--- 544,599,0,194,22,99 3 0105 -- Epsilon
+--- 679,598,0,132,-55,99 3 0106 -- Phi
+--- 537,599,0,227,19,99 3 0107 -- Gamma
+--- 643,599,0,243,15,99 3 0110 -- Eta
+--- 296,599,0,222,22,99 3 0111 -- Iota
++h 562,614,15,133,-58,99 3 0112 -- theta1
+--- 643,598,0,185,19,99 3 0113 -- Kappa
+--- 611,612,0,49,45,49 3 0114 -- Lambda
+--- 791,599,0,233,22,99 3 0115 -- Mu
+--- 643,599,7,234,24,99 3 0116 -- Nu
+--- 643,610,15,154,-62,99 3 0117 -- Omicron
+--- 684,599,0,213,28,99 3 0120 -- Pi
+--- 659,610,15,138,-62,99 3 0121 -- Theta
+--- 495,599,0,200,25,99 3 0122 -- Rho
+--- 527,599,0,186,45,99 3 0123 -- Sigma
+--- 544,599,0,229,-109,99 3 0124 -- Tau
+--- 614,599,0,240,-125,99 3 0125 -- Upsilon
+ts 391,445,208,151,-28,99 3 0126 -- sigma1
+--- 684,612,0,126,20,99 3 0127 -- Omega
+--- 574,598,0,176,14,99 3 0130 -- Xi
+--- 708,608,0,227,-138,99 3 0131 -- Psi
+--- 544,599,0,231,11,99 3 0132 -- Zeta
+--- 296,599,138,207,16,99 3 0133 -- bracketleft
+--- 768,426,0,0,-110 3 0134 -- therefore
+--- 296,599,138,159,64,99 3 0135 -- bracketright
+--- 586,600,0,60,37,60 3 0136 -- perpendicular
+--- 445,0,224,0,122 3 0137 -- underscore
+--- 445,816,0,829,-622,99 3 0140 -- radicalex
+*a 562,445,15,146,-34,99 3 0141 -- alpha
+*b 489,659,198,139,57,99 3 0142 -- beta
+*x 489,445,206,134,98,99 3 0143 -- chi
+*d 440,658,16,181,-33,99 3 0144 -- delta
+*e 391,447,17,127,1,99 3 0145 -- epsilon
+*f 464,596,200,103,-28,99 3 0146 -- phi
+*g 366,444,200,252,-42,99 3 0147 -- gamma
+*y 537,457,180,68,-50,68 3 0150 -- eta
+*i 293,448,16,53,-47,53 3 0151 -- iota
++f 537,444,199,117,-42,99 3 0152 -- phi1
+*k 489,447,0,182,-56,99 3 0153 -- kappa
+*l 489,658,16,91,29,91 3 0154 -- lambda
+*m 513,445,198,70,68,70 3 0155 -- mu
+*n 464,451,15,134,-69,99 3 0156 -- nu
+*o 489,444,17,87,-36,87 3 0157 -- omicron
+*p 489,433,18,160,-8,99 3 0160 -- pi
+*h 464,614,16,140,-53,99 3 0161 -- theta
+*r 489,444,205,82,69,82 3 0162 -- rho
+*s 537,445,19,175,-37,99 3 0163 -- sigma
+*t 391,445,16,170,-45,99 3 0164 -- tau
+*u 513,451,15,95,-55,95 3 0165 -- upsilon
++p 635,519,15,173,-28,99 3 0166 -- omega1
+*w 611,445,16,126,-35,99 3 0167 -- omega
+*c 439,681,200,126,-20,99 3 0170 -- xi
+*q 611,445,203,198,-91,99 3 0171 -- psi
+*z 440,673,200,190,-50,99 3 0172 -- zeta
+--- 427,599,163,163,-66,99 3 0173 -- braceleft
+--- 178,599,158,179,41,99 3 0174 -- bar
+--- 427,599,163,67,31,67 3 0175 -- braceright
+--- 489,273,0,110,-28,99 3 0176 -- similar
+--- 552,609,0,208,-84,99 3 0241 -- Upsilon1
+--- 220,654,0,223,-106,99 3 0242 -- minute
+--- 489,569,0,206,24,99 3 0243 -- lessequal
+--- 149,603,11,391,214,99 3 0244 -- fraction
+--- 635,360,0,107,-41,99 3 0245 -- infinity
+--- 445,612,172,219,86,99 3 0246 -- florin
+--- 670,474,23,25,-69,25 3 0247 -- club
+--- 670,490,32,0,-148 3 0250 -- diamond
+--- 670,473,29,59,-155,59 3 0251 -- heart
+--- 670,488,32,0,-82 3 0252 -- spade
+--- 927,455,13,103,-40,99 3 0253 -- arrowboth
+--- 878,455,13,87,-47,87 3 0254 -- arrowleft
+--- 537,810,0,204,-173,99 3 0255 -- arrowup
+--- 878,455,13,94,-55,94 3 0256 -- arrowright
+--- 537,790,20,85,-54,85 3 0257 -- arrowdown
+--- 356,609,0,160,-137,99 3 0260 -- degree
+--- 489,574,0,154,41,99 3 0261 -- plusminus
+--- 366,656,0,244,-100,99 3 0262 -- second
+--- 489,569,0,143,24,99 3 0263 -- greaterequal
+--- 489,466,0,170,22,99 3 0264 -- multiply
+--- 635,360,0,82,-40,82 3 0265 -- proportional
+--- 440,664,18,152,-12,99 3 0266 -- partialdiff
+--- 409,421,0,95,-68,95 3 0267 -- bullet
+--- 489,406,0,119,-24,99 3 0270 -- divide
+--- 489,489,22,148,-1,99 3 0271 -- notequal
+--- 489,394,0,163,15,99 3 0272 -- equivalence
+--- 489,351,0,133,-7,99 3 0273 -- approxequal
+--- 890,85,15,0,-57 3 0274 -- ellipsis
+--- 537,899,107,92,-166,92 3 0275 -- arrowvertex
+--- 890,246,0,171,42,99 3 0276 -- arrowhorizex
+--- 586,560,14,174,10,99 3 0277 -- carriagereturn
+--- 732,586,16,58,-109,58 3 0300 -- aleph
+--- 611,659,47,123,24,99 3 0301 -- Ifraktur
+--- 708,653,13,175,-21,99 3 0302 -- Rfraktur
+--- 878,510,188,50,-62,50 3 0303 -- weierstrass
+--- 684,599,15,124,-64,99 3 0304 -- circlemultiply
+--- 684,601,13,125,-65,99 3 0305 -- circleplus
+--- 732,640,21,202,12,99 3 0306 -- emptyset
+--- 684,453,0,80,14,80 3 0307 -- intersection
+--- 684,438,15,154,-60,99 3 0310 -- union
+--- 635,418,0,90,32,90 3 0311 -- propersuperset
+--- 635,418,111,89,67,89 3 0312 -- reflexsuperset
+--- 635,481,62,159,-37,99 3 0313 -- notsubset
+--- 635,418,0,159,-37,99 3 0314 -- propersubset
+--- 635,418,111,159,34,99 3 0315 -- reflexsubset
+--- 635,417,0,0,-43 3 0316 -- element
+--- 635,494,52,0,-24 3 0317 -- notelement
+--- 684,599,0,199,27,99 3 0320 -- angle
+--- 635,639,17,220,-181,99 3 0321 -- gradient
+--- 703,596,18,110,-70,99 3 0322 -- registerserif
+--- 703,601,13,113,-72,99 3 0323 -- copyrightserif
+--- 792,599,0,205,-119,99 3 0324 -- trademarkserif
+--- 732,668,90,238,56,99 3 0325 -- product
+--- 489,816,34,272,-84,99 3 0326 -- radical
+--- 223,276,0,52,-81,52 3 0327 -- dotmath
+--- 635,256,0,100,-28,99 3 0330 -- logicalnot
+--- 537,404,0,32,29,32 3 0331 -- logicaland
+--- 537,424,0,152,-101,99 3 0332 -- logicalor
+--- 927,454,18,101,-42,99 3 0333 -- arrowdblboth
+--- 878,457,13,114,-46,99 3 0334 -- arrowdblleft
+--- 537,811,0,201,-102,99 3 0335 -- arrowdblup
+--- 878,452,18,89,-21,89 3 0336 -- arrowdblright
+--- 537,792,17,152,-53,99 3 0337 -- arrowdbldown
+--- 440,663,0,129,-71,99 3 0340 -- lozenge
+--- 293,664,176,229,-48,99 3 0341 -- angleleft
+--- 703,596,18,110,-70,99 3 0342 -- registersans
+--- 703,601,13,111,-70,99 3 0343 -- copyrightsans
+--- 700,599,0,182,-129,99 3 0344 -- trademarksans
+--- 635,669,96,171,65,99 3 0345 -- summation
+--- 342,824,261,350,96,99 3 0346 -- parenlefttp
+--- 342,823,76,46,38,46 3 0347 -- parenleftex
+--- 342,824,261,47,-63,47 3 0350 -- parenleftbt
+--- 342,824,71,268,72,99 3 0351 -- bracketlefttp
+--- 342,823,70,13,72,13 3 0352 -- bracketleftex
+--- 342,824,71,14,72,14 3 0353 -- bracketleftbt
+--- 440,824,67,258,-108,99 3 0354 -- bracelefttp
+--- 440,832,76,96,-76,96 3 0355 -- braceleftmid
+--- 440,824,62,94,-169,94 3 0356 -- braceleftbt
+--- 440,832,71,96,-107,96 3 0357 -- braceex
+--- 293,664,176,102,79,99 3 0361 -- angleright
+--- 244,815,95,305,63,99 3 0362 -- integral
+--- 611,820,74,312,-222,99 3 0363 -- integraltp
+--- 611,868,78,79,-221,79 3 0364 -- integralex
+--- 611,820,72,64,20,64 3 0365 -- integralbt
+--- 342,824,261,206,-223,99 3 0366 -- parenrighttp
+--- 342,823,76,365,-281,99 3 0367 -- parenrightex
+--- 342,824,261,365,80,99 3 0370 -- parenrightbt
+--- 342,824,71,285,-199,99 3 0371 -- bracketrighttp
+--- 342,823,70,285,-200,99 3 0372 -- bracketrightex
+--- 342,824,71,285,54,99 3 0373 -- bracketrightbt
+--- 440,824,67,35,-108,35 3 0374 -- bracerighttp
+--- 440,832,76,127,-105,99 3 0375 -- bracerightmid
+--- 440,824,62,94,54,94 3 0376 -- bracerightbt
diff --git a/font/devps/TB b/font/devps/TB
new file mode 100644
index 00000000..e4fb5384
--- /dev/null
+++ b/font/devps/TB
@@ -0,0 +1,533 @@
+name TB
+internalname Times-Bold
+spacewidth 250
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -74
+A w -90
+A v -100
+A u -50
+A ' -74
+A p -25
+A Y -100
+A W -130
+A V -145
+A U -50
+A T -95
+A Q -45
+A O -45
+A G -55
+A C -55
+B U -10
+B A -30
+D . -20
+D Y -40
+D W -40
+D V -40
+D A -35
+F . -110
+F o -25
+F e -25
+F , -92
+F a -25
+F A -90
+J u -15
+J . -20
+J o -15
+J e -15
+J a -15
+J A -30
+K y -45
+K u -15
+K o -25
+K e -25
+K O -30
+L y -55
+L ' -110
+L rq -20
+L Y -92
+L W -92
+L V -92
+L T -92
+N A -20
+O Y -50
+O X -40
+O W -50
+O V -50
+O T -40
+O A -40
+P . -110
+P o -20
+P e -20
+P , -92
+P a -10
+P A -74
+Q . -20
+Q U -10
+R Y -35
+R W -35
+R V -55
+R U -30
+R T -40
+R O -30
+T y -74
+T w -74
+T u -92
+T ; -74
+T r -74
+T . -90
+T o -92
+T i -18
+T - -92
+T hy -92
+T char173 -92
+T e -92
+T , -74
+T : -74
+T a -92
+T O -18
+T A -90
+U . -50
+U , -50
+U A -60
+V u -92
+V ; -92
+V . -145
+V o -100
+V i -37
+V - -74
+V hy -74
+V char173 -74
+V e -100
+V , -129
+V : -92
+V a -92
+V O -45
+V G -30
+V A -135
+W y -60
+W u -50
+W ; -55
+W . -92
+W o -75
+W i -18
+W - -37
+W hy -37
+W char173 -37
+W e -65
+W , -92
+W : -55
+W a -65
+W O -10
+W A -120
+Y u -92
+Y ; -92
+Y . -92
+Y o -111
+Y i -37
+Y - -92
+Y hy -92
+Y char173 -92
+Y e -111
+Y , -92
+Y : -92
+Y a -85
+Y O -35
+Y A -110
+a v -25
+b v -15
+b u -20
+b . -40
+b b -10
+, ' -55
+, rq -45
+d w -15
+e v -15
+f ' 55
+f rq 50
+f . -15
+f o -25
+f i -25
+f .i -35
+f , -15
+g . -15
+h y -15
+i v -10
+k y -15
+k o -15
+k e -10
+n v -40
+o w -10
+o v -10
+. ' -55
+. rq -55
+lq A -10
+` ` -63
+` oq -63
+oq ` -63
+oq oq -63
+` A -10
+oq A -10
+' v -20
+' s -37
+' r -20
+' ' -63
+' d -20
+r v -10
+r q -18
+r . -100
+r p -10
+r o -18
+r n -15
+r - -37
+r hy -37
+r char173 -37
+r g -10
+r e -18
+r , -92
+r c -18
+v . -70
+v o -10
+v e -10
+v , -55
+v a -10
+w . -70
+w o -10
+w , -55
+y . -70
+y o -25
+y e -10
+y , -55
+charset
+ha 581,676 2 0000 -- asciicircum
+ti 520,333 0 0001 -- asciitilde
+vS 556,914,19 2 0002 -- Scaron
+vZ 667,914 2 0003 -- Zcaron
+vs 389,704,14 2 0004 -- scaron
+vz 444,704 2 0005 -- zcaron
+:Y 722,877 2 0006 -- Ydieresis
+tm 1000,676 2 0007 -- trademark
+aq 278,691 2 0010 -- quotesingle
+space 250 0 0040
+! 333,691,13 2 0041 -- exclam
+" 555,691 2 0042 -- quotedbl
+# 500,700 2 0043 -- numbersign
+sh "
+$ 500,750,99 2 0044 -- dollar
+Do "
+% 1000,692,14 2 0045 -- percent
+& 833,691,16 2 0046 -- ampersand
+' 333,691 2 0047 -- quoteright
+( 333,694,168 2 0050 -- parenleft
+) 333,694,168 2 0051 -- parenright
+* 500,691 2 0052 -- asterisk
++ 570,506 0 0053 -- plus
+, 250,155,180 0 0054 -- comma
+- 333,287 0 0055 -- hyphen
+hy "
+char173 "
+. 250,156,13 0 0056 -- period
+/ 278,691,19 2 0057 -- slash
+sl "
+0 500,688,13 2 0060 -- zero
+1 500,688 2 0061 -- one
+2 500,688 2 0062 -- two
+3 500,688,14 2 0063 -- three
+4 500,688 2 0064 -- four
+5 500,676,8 2 0065 -- five
+6 500,688,13 2 0066 -- six
+7 500,676 2 0067 -- seven
+8 500,688,13 2 0070 -- eight
+9 500,688,13 2 0071 -- nine
+: 333,472,13 0 0072 -- colon
+; 333,472,180 0 0073 -- semicolon
+< 570,514,8 0 0074 -- less
+= 570,399 0 0075 -- equal
+> 570,514,8 0 0076 -- greater
+? 500,689,13 2 0077 -- question
+@ 930,691,19 2 0100 -- at
+at "
+A 722,690 2 0101 -- A
+B 667,676 2 0102 -- B
+C 722,691,19 2 0103 -- C
+D 722,676 2 0104 -- D
+E 667,676 2 0105 -- E
+F 611,676 2 0106 -- F
+G 778,691,19 2 0107 -- G
+H 778,676 2 0110 -- H
+I 389,676 2 0111 -- I
+J 500,676,96 2 0112 -- J
+K 778,676 2 0113 -- K
+L 667,676 2 0114 -- L
+M 944,676 2 0115 -- M
+N 722,676,18 2 0116 -- N
+O 778,691,19 2 0117 -- O
+P 611,676 2 0120 -- P
+Q 778,691,176 2 0121 -- Q
+R 722,676 2 0122 -- R
+S 556,692,19 2 0123 -- S
+T 667,676 2 0124 -- T
+U 722,676,19 2 0125 -- U
+V 722,676,18 2 0126 -- V
+W 1000,676,15 2 0127 -- W
+X 722,676 2 0130 -- X
+Y 722,676 2 0131 -- Y
+Z 667,676 2 0132 -- Z
+[ 333,678,149 2 0133 -- bracketleft
+lB "
+\ 278,691,19 2 0134 -- backslash
+rs "
+] 333,678,149 2 0135 -- bracketright
+rB "
+a^ 333,704 2 0136 -- circumflex
+^ "
+_ 500,0,125 0 0137 -- underscore
+` 333,691 2 0140 -- quoteleft
+oq "
+a 500,473,14 0 0141 -- a
+b 556,676,14 2 0142 -- b
+c 444,473,14 0 0143 -- c
+d 556,676,14 2 0144 -- d
+e 444,473,14 0 0145 -- e
+f 333,691 2 0146 -- f
+g 500,473,206 1 0147 -- g
+h 556,676 2 0150 -- h
+i 278,691 2 0151 -- i
+j 333,691,203 3 0152 -- j
+k 556,676 2 0153 -- k
+l 278,676 2 0154 -- l
+m 833,473 0 0155 -- m
+n 556,473 0 0156 -- n
+o 500,473,14 0 0157 -- o
+p 556,473,205 1 0160 -- p
+q 556,473,205 1 0161 -- q
+r 444,473 0 0162 -- r
+s 389,473,14 0 0163 -- s
+t 333,630,12 2 0164 -- t
+u 556,461,14 0 0165 -- u
+v 500,461,14 0 0166 -- v
+w 722,461,14 0 0167 -- w
+x 500,461 0 0170 -- x
+y 500,461,205 1 0171 -- y
+z 444,461 0 0172 -- z
+lC 394,698,175 2 0173 -- braceleft
+{ "
+ba 220,691,19 2 0174 -- bar
+| "
+rC 394,698,175 2 0175 -- braceright
+} "
+a~ 333,674 2 0176 -- tilde
+~ "
+bq 333,155,180 0 0200 -- quotesinglbase
+Fo 500,415 0 0201 -- guillemotleft
+char171 "
+Fc 500,415 0 0202 -- guillemotright
+char187 "
+bu 350,478 0 0203 -- bullet
+Fn 500,706,155 2 0204 -- florin
+f/ 167,688,12 2 0205 -- fraction
+%0 1000,706,29 2 0206 -- perthousand
+dg 500,691,134 2 0207 -- dagger
+dd 500,691,132 2 0210 -- daggerdbl
+en 500,271 0 0211 -- endash
+em 1000,271 0 0212 -- emdash
+fi 556,691 2 0214 -- fi
+fl 556,691 2 0215 -- fl
+.i 278,461 0 0220 -- dotlessi
+ga 333,713 2 0222 -- grave
+a" 333,713 2 0223 -- hungarumlaut
+a. 333,667 2 0224 -- dotaccent
+ab 333,691 2 0225 -- breve
+ah 333,704 2 0226 -- caron
+ao 333,740 2 0227 -- ring
+ho 333,44,173 0 0230 -- ogonek
+lq 500,691 2 0231 -- quotedblleft
+rq 500,691 2 0232 -- quotedblright
+oe 722,473,14 0 0233 -- oe
+/l 278,676 2 0234 -- lslash
+Bq 500,155,180 0 0235 -- quotedblbase
+OE 1000,684,5 2 0236 -- OE
+/L 667,676 2 0237 -- Lslash
+r! 333,501,203 1 0241 -- exclamdown
+char161 "
+ct 500,588,140 0 0242 -- cent
+char162 "
+Po 500,684,14 2 0243 -- sterling
+char163 "
+Cs 500,613 0 0244 -- currency
+char164 "
+Ye 500,676 2 0245 -- yen
+char165 "
+bb 220,691,19 2 0246 -- brokenbar
+char166 "
+sc 500,691,132 2 0247 -- section
+char167 "
+ad 333,667 2 0250 -- dieresis
+char168 "
+co 747,691,19 2 0251 -- copyright
+char169 "
+Of 300,688 2 0252 -- ordfeminine
+char170 "
+fo 333,415 0 0253 -- guilsinglleft
+no 570,399 0 0254 -- logicalnot
+char172 "
+\- 570,297 0 0255 -- minus
+rg 747,691,19 2 0256 -- registered
+char174 "
+a- 333,637 2 0257 -- macron
+char175 "
+de 400,688 2 0260 -- degree
+char176 "
+char177 570,506 0 0261 -- plusminus
+S2 300,688 2 0262 -- twosuperior
+char178 "
+S3 300,688 2 0263 -- threesuperior
+char179 "
+aa 333,713 2 0264 -- acute
+char180 "
+char181 556,461,206 1 0265 -- mu
+ps 540,676,186 2 0266 -- paragraph
+char182 "
+char183 250,417 0 0267 -- periodcentered
+ac 333,0,218 1 0270 -- cedilla
+char184 "
+S1 300,688 2 0271 -- onesuperior
+char185 "
+Om 330,688 2 0272 -- ordmasculine
+char186 "
+fc 333,415 0 0273 -- guilsinglright
+14 750,688,12 2 0274 -- onequarter
+char188 "
+12 750,688,12 2 0275 -- onehalf
+char189 "
+34 750,688,12 2 0276 -- threequarters
+char190 "
+r? 500,501,201 0 0277 -- questiondown
+char191 "
+`A 722,923 2 0300 -- Agrave
+char192 "
+'A 722,923 2 0301 -- Aacute
+char193 "
+^A 722,914 2 0302 -- Acircumflex
+char194 "
+~A 722,884 2 0303 -- Atilde
+char195 "
+:A 722,877 2 0304 -- Adieresis
+char196 "
+oA 722,935 2 0305 -- Aring
+char197 "
+AE 1000,676 2 0306 -- AE
+char198 "
+,C 722,691,218 3 0307 -- Ccedilla
+char199 "
+`E 667,923 2 0310 -- Egrave
+char200 "
+'E 667,923 2 0311 -- Eacute
+char201 "
+^E 667,914 2 0312 -- Ecircumflex
+char202 "
+:E 667,877 2 0313 -- Edieresis
+char203 "
+`I 389,923 2 0314 -- Igrave
+char204 "
+'I 389,923 2 0315 -- Iacute
+char205 "
+^I 389,914 2 0316 -- Icircumflex
+char206 "
+:I 389,877 2 0317 -- Idieresis
+char207 "
+-D 722,676 2 0320 -- Eth
+char208 "
+~N 722,884,18 2 0321 -- Ntilde
+char209 "
+`O 778,923,19 2 0322 -- Ograve
+char210 "
+'O 778,923,19 2 0323 -- Oacute
+char211 "
+^O 778,914,19 2 0324 -- Ocircumflex
+char212 "
+~O 778,884,19 2 0325 -- Otilde
+char213 "
+:O 778,877,19 2 0326 -- Odieresis
+char214 "
+char215 570,490 0 0327 -- multiply
+/O 778,737,74 2 0330 -- Oslash
+char216 "
+`U 722,923,19 2 0331 -- Ugrave
+char217 "
+'U 722,923,19 2 0332 -- Uacute
+char218 "
+^U 722,914,19 2 0333 -- Ucircumflex
+char219 "
+:U 722,877,19 2 0334 -- Udieresis
+char220 "
+'Y 722,928 2 0335 -- Yacute
+char221 "
+TP 611,676 2 0336 -- Thorn
+char222 "
+ss 556,691,12 2 0337 -- germandbls
+char223 "
+`a 500,713,14 2 0340 -- agrave
+char224 "
+'a 500,713,14 2 0341 -- aacute
+char225 "
+^a 500,704,14 2 0342 -- acircumflex
+char226 "
+~a 500,674,14 2 0343 -- atilde
+char227 "
+:a 500,667,14 2 0344 -- adieresis
+char228 "
+oa 500,740,14 2 0345 -- aring
+char229 "
+ae 722,473,14 0 0346 -- ae
+char230 "
+,c 444,473,218 1 0347 -- ccedilla
+char231 "
+`e 444,713,14 2 0350 -- egrave
+char232 "
+'e 444,713,14 2 0351 -- eacute
+char233 "
+^e 444,704,14 2 0352 -- ecircumflex
+char234 "
+:e 444,667,14 2 0353 -- edieresis
+char235 "
+`i 278,713 2 0354 -- igrave
+char236 "
+'i 278,713 2 0355 -- iacute
+char237 "
+^i 278,704 2 0356 -- icircumflex
+char238 "
+:i 278,667 2 0357 -- idieresis
+char239 "
+Sd 500,691,14 2 0360 -- eth
+char240 "
+~n 556,674 2 0361 -- ntilde
+char241 "
+`o 500,713,14 2 0362 -- ograve
+char242 "
+'o 500,713,14 2 0363 -- oacute
+char243 "
+^o 500,704,14 2 0364 -- ocircumflex
+char244 "
+~o 500,674,14 2 0365 -- otilde
+char245 "
+:o 500,667,14 2 0366 -- odieresis
+char246 "
+char247 570,537,31 0 0367 -- divide
+/o 500,549,92 0 0370 -- oslash
+char248 "
+`u 556,713,14 2 0371 -- ugrave
+char249 "
+'u 556,713,14 2 0372 -- uacute
+char250 "
+^u 556,704,14 2 0373 -- ucircumflex
+char251 "
+:u 556,667,14 2 0374 -- udieresis
+char252 "
+'y 500,713,205 3 0375 -- yacute
+char253 "
+Tp 556,676,205 3 0376 -- thorn
+char254 "
+:y 500,667,205 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/TBI b/font/devps/TBI
new file mode 100644
index 00000000..d2efe7d5
--- /dev/null
+++ b/font/devps/TBI
@@ -0,0 +1,515 @@
+name TBI
+internalname Times-BoldItalic
+slant 15
+spacewidth 250
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -74
+A w -74
+A v -74
+A u -30
+A ' -74
+A Y -70
+A W -100
+A V -95
+A U -50
+A T -55
+A Q -55
+A O -50
+A G -60
+A C -65
+B U -10
+B A -25
+D Y -50
+D W -40
+D V -50
+D A -25
+F r -50
+F . -129
+F o -70
+F i -40
+F e -100
+F , -129
+F a -95
+F A -100
+J u -40
+J . -10
+J o -40
+J e -40
+J , -10
+J a -40
+J A -25
+K y -20
+K u -20
+K o -25
+K e -25
+K O -30
+L y -37
+L ' -55
+L Y -37
+L W -37
+L V -37
+L T -18
+N A -30
+O Y -50
+O X -40
+O W -50
+O V -50
+O T -40
+O A -40
+P . -129
+P o -55
+P e -50
+P , -129
+P a -40
+P A -85
+Q U -10
+R Y -18
+R W -18
+R V -18
+R U -40
+R T -30
+R O -40
+T y -37
+T w -37
+T u -37
+T ; -74
+T r -37
+T . -92
+T o -95
+T i -37
+T - -92
+T hy -92
+T char173 -92
+T e -92
+T , -92
+T : -74
+T a -92
+T O -18
+T A -55
+U A -45
+V u -55
+V ; -74
+V . -129
+V o -111
+V i -55
+V - -70
+V hy -70
+V char173 -70
+V e -111
+V , -129
+V : -74
+V a -111
+V O -30
+V G -10
+V A -85
+W y -55
+W u -55
+W ; -55
+W . -74
+W o -80
+W i -37
+W - -50
+W hy -50
+W char173 -50
+W e -90
+W , -74
+W : -55
+W a -85
+W O -15
+W A -74
+Y u -92
+Y ; -92
+Y . -74
+Y o -111
+Y i -55
+Y - -92
+Y hy -92
+Y char173 -92
+Y e -111
+Y , -92
+Y : -92
+Y a -92
+Y O -25
+Y A -74
+b u -20
+b . -40
+b b -10
+c k -10
+c h -10
+, ' -95
+, rq -95
+e b -10
+f ' 55
+f . -10
+f o -10
+f f -18
+f e -10
+f .i -30
+f , -10
+k o -10
+k e -30
+n v -40
+o y -10
+o x -10
+o w -25
+o v -15
+. ' -95
+. rq -95
+` ` -74
+` oq -74
+oq ` -74
+oq oq -74
+' v -15
+' t -37
+' s -74
+' r -15
+' ' -74
+' d -15
+r . -65
+r , -65
+v . -37
+v o -15
+v e -15
+v , -37
+w . -37
+w o -15
+w e -10
+w , -37
+w a -10
+x e -10
+y . -37
+y , -37
+charset
+ha 570,669,0,0,-17 2 0000 -- asciicircum
+ti 570,333,0,0,-4 0 0001 -- asciitilde
+vS 556,897,18,20,48,20 2 0002 -- Scaron
+vZ 611,897,0,29,61,29 2 0003 -- Zcaron
+vs 389,690,13,100,69,99 2 0004 -- scaron
+vz 389,690,78,85,93,85 2 0005 -- zcaron
+:Y 611,862,0,98,-23,98 2 0006 -- Ydieresis
+tm 1000,669,0,18,18,18 2 0007 -- trademark
+aq 278,685,0,40,-78,40 2 0010 -- quotesingle
+space 250 0 0040
+! 389,684,13,31,-17,31 2 0041 -- exclam
+" 555,685,0,31,-86,31 2 0042 -- quotedbl
+# 500,700,0,83,83,83 2 0043 -- numbersign
+sh "
+$ 500,733,100,47,70,47 2 0044 -- dollar
+Do "
+% 833,692,10,10,11,10 2 0045 -- percent
+& 778,682,19,0,45 2 0046 -- ampersand
+' 333,685,0,19,-48,19 2 0047 -- quoteright
+( 333,685,179,61,22,61 2 0050 -- parenleft
+) 333,685,179,0,94 2 0051 -- parenright
+* 500,685,0,6,-15,6 2 0052 -- asterisk
++ 570,506,0,17,17,17 0 0053 -- plus
+, 250,134,182,0,110 0 0054 -- comma
+- 333,282,0,0,48 0 0055 -- hyphen
+hy "
+char173 "
+. 250,135,13,0,59 0 0056 -- period
+/ 278,685,18,114,114,99 2 0057 -- slash
+sl "
+0 500,683,14,27,33,27 2 0060 -- zero
+1 500,683,0,0,45 2 0061 -- one
+2 500,683,0,0,77 2 0062 -- two
+3 500,683,13,0,65 2 0063 -- three
+4 500,683,0,53,65,53 2 0064 -- four
+5 500,669,13,37,61,37 2 0065 -- five
+6 500,679,15,59,27,59 2 0066 -- six
+7 500,669,0,75,-2,75 2 0067 -- seven
+8 500,683,13,26,47,26 2 0070 -- eight
+9 500,683,10,25,62,25 2 0071 -- nine
+: 333,459,13,0,27 0 0072 -- colon
+; 333,459,183,0,75 0 0073 -- semicolon
+< 570,514,8,19,19,19 0 0074 -- less
+= 570,399,0,17,17,17 0 0075 -- equal
+> 570,514,8,19,19,19 0 0076 -- greater
+? 500,684,13,20,-29,20 2 0077 -- question
+@ 832,685,18,0,-13 2 0100 -- at
+at "
+A 667,683,0,0,117 2 0101 -- A
+B 667,669,0,7,74,7 2 0102 -- B
+C 667,685,18,60,18,60 2 0103 -- C
+D 722,669,0,13,96,13 2 0104 -- D
+E 667,669,0,36,77,36 2 0105 -- E
+F 667,669,0,43,63,43 2 0106 -- F
+G 722,685,18,34,29,34 2 0107 -- G
+H 778,669,0,71,74,71 2 0110 -- H
+I 389,669,0,67,82,67 2 0111 -- I
+J 500,669,99,74,96,74 2 0112 -- J
+K 667,669,0,85,71,85 2 0113 -- K
+L 611,669,0,29,72,29 2 0114 -- L
+M 889,669,12,78,79,78 2 0115 -- M
+N 722,669,15,76,77,76 2 0116 -- N
+O 722,685,18,19,23,19 2 0117 -- O
+P 611,669,0,52,77,52 2 0120 -- P
+Q 722,685,208,19,23,19 3 0121 -- Q
+R 667,669,0,6,79,6 2 0122 -- R
+S 556,685,18,20,48,20 2 0123 -- S
+T 611,669,0,89,0,89 2 0124 -- T
+U 722,669,18,72,-17,72 2 0125 -- U
+V 667,669,18,98,-15,98 2 0126 -- V
+W 889,669,18,101,-15,99 2 0127 -- W
+X 667,669,0,77,74,77 2 0130 -- X
+Y 611,669,0,98,-23,98 2 0131 -- Y
+Z 611,669,0,29,61,29 2 0132 -- Z
+[ 333,674,159,79,87,79 2 0133 -- bracketleft
+lB "
+\ 278,685,18,51,51,51 2 0134 -- backslash
+rs "
+] 333,674,157,60,106,60 2 0135 -- bracketright
+rB "
+a^ 333,690,0,84,10,84 2 0136 -- circumflex
+^ "
+_ 500,0,125,50,50,50 0 0137 -- underscore
+` 333,685,0,49,-78,49 2 0140 -- quoteleft
+oq "
+a 500,462,14,5,71,5 0 0141 -- a
+b 500,699,13,0,64 2 0142 -- b
+c 444,462,13,0,55 0 0143 -- c
+d 500,699,13,67,71,67 2 0144 -- d
+e 444,462,13,4,45,4 0 0145 -- e
+f 333,698,205,163,219,99 3 0146 -- f
+g 500,462,203,28,102,28 1 0147 -- g
+h 556,699,9,0,63 2 0150 -- h
+i 278,684,9,35,48,35 2 0151 -- i
+j 278,684,207,51,239,51 3 0152 -- j
+k 500,699,8,33,73,33 2 0153 -- k
+l 278,699,9,62,48,62 2 0154 -- l
+m 778,462,9,0,64 0 0155 -- m
+n 556,462,9,0,56 0 0156 -- n
+o 500,462,13,0,53 0 0157 -- o
+p 500,462,205,0,170 1 0160 -- p
+q 500,462,205,21,49,21 1 0161 -- q
+r 389,462,0,50,71,50 0 0162 -- r
+s 389,462,13,0,69 0 0163 -- s
+t 278,594,9,53,61,53 2 0164 -- t
+u 556,462,9,0,35 0 0165 -- u
+v 444,462,13,7,34,7 0 0166 -- v
+w 667,462,13,0,34 0 0167 -- w
+x 500,462,13,19,96,19 0 0170 -- x
+y 444,462,205,0,144 1 0171 -- y
+z 389,449,78,29,93,29 0 0172 -- z
+lC 348,686,187,138,45,99 2 0173 -- braceleft
+{ "
+ba 220,685,18,0,-16 2 0174 -- bar
+| "
+rC 348,686,187,4,179,4 2 0175 -- braceright
+} "
+a~ 333,655,0,124,2,99 2 0176 -- tilde
+~ "
+bq 333,134,182,0,55 0 0200 -- quotesinglbase
+Fo 500,415,0,18,38,18 0 0201 -- guillemotleft
+char171 "
+Fc 500,415,0,18,38,18 0 0202 -- guillemotright
+char187 "
+bu 350,525,0,50,50,50 0 0203 -- bullet
+Fn 500,707,156,87,137,87 2 0204 -- florin
+f/ 167,683,14,207,219,99 2 0205 -- fraction
+%0 1000,706,29,46,43,46 2 0206 -- perthousand
+dg 500,685,145,44,-41,44 2 0207 -- dagger
+dd 500,685,139,43,40,43 2 0210 -- daggerdbl
+en 500,269,0,27,90,27 0 0211 -- endash
+em 1000,269,0,27,90,27 0 0212 -- emdash
+fi 556,703,205,8,238,8 3 0214 -- fi
+fl 556,704,205,47,236,47 3 0215 -- fl
+.i 278,462,9,10,48,10 0 0220 -- dotlessi
+ga 333,697,0,14,-35,14 2 0222 -- grave
+a" 333,697,0,215,-19,99 2 0223 -- hungarumlaut
+a. 333,655,0,10,-113,10 2 0224 -- dotaccent
+ab 333,678,0,104,-21,99 2 0225 -- breve
+ah 333,690,0,128,-29,99 2 0226 -- caron
+ao 333,729,0,57,-77,57 2 0227 -- ring
+ho 333,44,173,0,90 0 0230 -- ogonek
+lq 500,685,0,63,-3,63 2 0231 -- quotedblleft
+rq 500,685,0,63,-3,63 2 0232 -- quotedblright
+oe 722,462,13,2,44,2 0 0233 -- oe
+/l 278,699,9,73,63,73 2 0234 -- lslash
+Bq 500,134,182,0,107 0 0235 -- quotedblbase
+OE 944,677,8,52,27,52 2 0236 -- OE
+/L 611,669,0,29,72,29 2 0237 -- Lslash
+r! 389,492,205,0,31 1 0241 -- exclamdown
+char161 "
+ct 500,576,143,0,8 0 0242 -- cent
+char162 "
+Po 500,683,12,60,82,60 2 0243 -- sterling
+char163 "
+Cs 500,586,0,76,76,76 0 0244 -- currency
+char164 "
+Ye 500,669,0,178,17,99 2 0245 -- yen
+char165 "
+bb 220,685,18,0,-16 2 0246 -- brokenbar
+char166 "
+sc 500,685,143,9,14,9 2 0247 -- section
+char167 "
+ad 333,655,0,114,-5,99 2 0250 -- dieresis
+char168 "
+co 747,685,18,21,20,21 2 0251 -- copyright
+char169 "
+Of 266,685,0,114,34,99 2 0252 -- ordfeminine
+char170 "
+fo 333,415,0,20,18,20 0 0253 -- guilsinglleft
+no 606,399,0,0,-1 0 0254 -- logicalnot
+char172 "
+\- 606,297,0,0,-1 0 0255 -- minus
+rg 747,685,18,21,20,21 2 0256 -- registered
+char174 "
+a- 333,623,0,110,-1,99 2 0257 -- macron
+char175 "
+de 400,683,0,19,-33,19 2 0260 -- degree
+char176 "
+char177 570,506,0,17,17,17 0 0261 -- plusminus
+S2 300,683,0,63,48,63 2 0262 -- twosuperior
+char178 "
+S3 300,683,0,71,33,71 2 0263 -- threesuperior
+char179 "
+aa 333,697,0,96,-89,96 2 0264 -- acute
+char180 "
+char181 576,449,207,0,110 1 0265 -- mu
+ps 500,669,193,112,107,99 2 0266 -- paragraph
+char182 "
+char183 250,405,0,0,-1 0 0267 -- periodcentered
+ac 333,5,218,0,130 1 0270 -- cedilla
+char184 "
+S1 300,683,0,51,20,51 2 0271 -- onesuperior
+char185 "
+Om 300,685,0,97,-6,97 2 0272 -- ordmasculine
+char186 "
+fc 333,415,0,0,40 0 0273 -- guilsinglright
+14 750,683,14,21,43,21 2 0274 -- onequarter
+char188 "
+12 750,683,14,23,59,23 2 0275 -- onehalf
+char189 "
+34 750,683,14,26,43,26 2 0276 -- threequarters
+char190 "
+r? 500,492,205,0,20 1 0277 -- questiondown
+char191 "
+`A 667,904,0,0,117 2 0300 -- Agrave
+char192 "
+'A 667,904,0,0,117 2 0301 -- Aacute
+char193 "
+^A 667,897,0,0,117 2 0302 -- Acircumflex
+char194 "
+~A 667,862,0,0,117 2 0303 -- Atilde
+char195 "
+:A 667,862,0,0,117 2 0304 -- Adieresis
+char196 "
+oA 667,921,0,0,117 2 0305 -- Aring
+char197 "
+AE 944,669,0,24,114,24 2 0306 -- AE
+char198 "
+,C 667,685,218,60,18,60 3 0307 -- Ccedilla
+char199 "
+`E 667,904,0,36,77,36 2 0310 -- Egrave
+char200 "
+'E 667,904,0,36,77,36 2 0311 -- Eacute
+char201 "
+^E 667,897,0,36,77,36 2 0312 -- Ecircumflex
+char202 "
+:E 667,862,0,36,77,36 2 0313 -- Edieresis
+char203 "
+`I 389,904,0,67,82,67 2 0314 -- Igrave
+char204 "
+'I 389,904,0,73,82,73 2 0315 -- Iacute
+char205 "
+^I 389,897,0,81,82,81 2 0316 -- Icircumflex
+char206 "
+:I 389,862,0,106,82,99 2 0317 -- Idieresis
+char207 "
+-D 722,669,0,28,81,28 2 0320 -- Eth
+char208 "
+~N 722,862,15,76,77,76 2 0321 -- Ntilde
+char209 "
+`O 722,904,18,19,23,19 2 0322 -- Ograve
+char210 "
+'O 722,904,18,19,23,19 2 0323 -- Oacute
+char211 "
+^O 722,897,18,19,23,19 2 0324 -- Ocircumflex
+char212 "
+~O 722,862,18,19,23,19 2 0325 -- Otilde
+char213 "
+:O 722,862,18,19,23,19 2 0326 -- Odieresis
+char214 "
+char215 570,490,0,2,2,2 0 0327 -- multiply
+/O 722,764,125,19,23,19 2 0330 -- Oslash
+char216 "
+`U 722,904,18,72,-17,72 2 0331 -- Ugrave
+char217 "
+'U 722,904,18,72,-17,72 2 0332 -- Uacute
+char218 "
+^U 722,897,18,72,-17,72 2 0333 -- Ucircumflex
+char219 "
+:U 722,862,18,72,-17,72 2 0334 -- Udieresis
+char220 "
+'Y 611,904,0,98,-23,98 2 0335 -- Yacute
+char221 "
+TP 611,669,0,12,77,12 2 0336 -- Thorn
+char222 "
+ss 500,705,200,23,250,23 2 0337 -- germandbls
+char223 "
+`a 500,697,14,5,71,5 2 0340 -- agrave
+char224 "
+'a 500,697,14,13,71,13 2 0341 -- aacute
+char225 "
+^a 500,690,14,5,71,5 2 0342 -- acircumflex
+char226 "
+~a 500,655,14,41,71,41 2 0343 -- atilde
+char227 "
+:a 500,655,14,21,71,21 2 0344 -- adieresis
+char228 "
+oa 500,729,14,5,71,5 2 0345 -- aring
+char229 "
+ae 722,462,13,1,55,1 0 0346 -- ae
+char230 "
+,c 444,462,218,0,74 1 0347 -- ccedilla
+char231 "
+`e 444,697,13,4,45,4 2 0350 -- egrave
+char232 "
+'e 444,697,13,41,45,41 2 0351 -- eacute
+char233 "
+^e 444,690,13,29,45,29 2 0352 -- ecircumflex
+char234 "
+:e 444,655,13,49,45,49 2 0353 -- edieresis
+char235 "
+`i 278,697,9,32,48,32 2 0354 -- igrave
+char236 "
+'i 278,697,9,124,48,99 2 0355 -- iacute
+char237 "
+^i 278,690,9,97,52,97 2 0356 -- icircumflex
+char238 "
+:i 278,655,9,132,48,99 2 0357 -- idieresis
+char239 "
+Sd 500,699,13,4,53,4 2 0360 -- eth
+char240 "
+~n 556,655,9,0,56 2 0361 -- ntilde
+char241 "
+`o 500,697,13,0,53 2 0362 -- ograve
+char242 "
+'o 500,697,13,13,53,13 2 0363 -- oacute
+char243 "
+^o 500,690,13,1,53,1 2 0364 -- ocircumflex
+char244 "
+~o 500,655,13,41,53,41 2 0365 -- otilde
+char245 "
+:o 500,655,13,16,53,16 2 0366 -- odieresis
+char246 "
+char247 570,535,29,17,17,17 0 0367 -- divide
+/o 500,560,119,0,53 0 0370 -- oslash
+char248 "
+`u 556,697,9,0,35 2 0371 -- ugrave
+char249 "
+'u 556,697,9,0,35 2 0372 -- uacute
+char250 "
+^u 556,690,9,0,35 2 0373 -- ucircumflex
+char251 "
+:u 556,655,9,0,35 2 0374 -- udieresis
+char252 "
+'y 444,697,205,41,144,41 3 0375 -- yacute
+char253 "
+Tp 500,699,205,0,170 3 0376 -- thorn
+char254 "
+:y 444,655,205,44,144,44 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/TI b/font/devps/TI
new file mode 100644
index 00000000..9ec7eeed
--- /dev/null
+++ b/font/devps/TI
@@ -0,0 +1,528 @@
+name TI
+internalname Times-Italic
+slant 7
+spacewidth 250
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -55
+A w -55
+A v -55
+A u -20
+A ' -37
+A Y -55
+A W -95
+A V -105
+A U -50
+A T -37
+A Q -40
+A O -40
+A G -35
+A C -30
+B U -10
+B A -25
+D Y -40
+D W -40
+D V -40
+D A -35
+F r -55
+F . -135
+F o -105
+F i -45
+F e -75
+F , -135
+F a -75
+F A -115
+J u -35
+J . -25
+J o -25
+J e -25
+J , -25
+J a -35
+J A -40
+K y -40
+K u -40
+K o -40
+K e -35
+K O -50
+L y -30
+L ' -37
+L Y -20
+L W -55
+L V -55
+L T -20
+N A -27
+O Y -50
+O X -40
+O W -50
+O V -50
+O T -40
+O A -55
+P . -135
+P o -80
+P e -80
+P , -135
+P a -80
+P A -90
+Q U -10
+R Y -18
+R W -18
+R V -18
+R U -40
+R O -40
+T y -74
+T w -74
+T u -55
+T ; -65
+T r -55
+T . -74
+T o -92
+T i -55
+T - -74
+T hy -74
+T char173 -74
+T e -92
+T , -74
+T : -55
+T a -92
+T O -18
+T A -50
+U . -25
+U , -25
+U A -40
+V u -74
+V ; -74
+V . -129
+V o -111
+V i -74
+V - -55
+V hy -55
+V char173 -55
+V e -111
+V , -129
+V : -65
+V a -111
+V O -30
+V A -60
+W y -70
+W u -55
+W ; -65
+W . -92
+W o -92
+W i -55
+W - -37
+W hy -37
+W char173 -37
+W e -92
+W , -92
+W : -65
+W a -92
+W O -25
+W A -60
+Y u -92
+Y ; -65
+Y . -92
+Y o -92
+Y i -74
+Y - -74
+Y hy -74
+Y char173 -74
+Y e -92
+Y , -92
+Y : -65
+Y a -92
+Y O -15
+Y A -50
+a g -10
+b u -20
+b . -40
+c k -20
+c h -15
+, ' -140
+, rq -140
+e y -30
+e x -20
+e w -15
+e v -15
+e . -15
+e g -40
+e , -10
+f ' 92
+f . -15
+f i -20
+f f -18
+f .i -60
+f , -10
+g . -15
+g g -10
+g e -10
+g , -10
+k y -10
+k o -10
+k e -10
+n v -40
+o v -10
+o g -10
+. ' -140
+. rq -140
+` ` -111
+` oq -111
+oq ` -111
+oq oq -111
+' v -10
+' t -30
+' s -40
+' r -25
+' ' -111
+' d -25
+r s -10
+r q -37
+r . -111
+r o -45
+r - -20
+r hy -20
+r char173 -20
+r g -37
+r e -37
+r d -37
+r , -111
+r c -37
+r a -15
+v . -74
+v , -74
+w . -74
+w , -74
+y . -55
+y , -55
+charset
+ha 422,666,0,50,50,43 2 0000 -- asciicircum
+ti 541,323,0,11,10,11 0 0001 -- asciitilde
+vS 500,873,18,70,33,43 2 0002 -- Scaron
+vZ 556,873,0,100,56,43 2 0003 -- Zcaron
+vs 389,661,13,115,34,43 2 0004 -- scaron
+vz 389,661,81,95,52,43 2 0005 -- zcaron
+:Y 556,818,0,127,-28,43 2 0006 -- Ydieresis
+tm 980,653,0,27,20,27 2 0007 -- trademark
+aq 214,666,0,77,-82,43 2 0010 -- quotesingle
+space 250 0 0040
+! 333,667,11,19,11,19 2 0041 -- exclam
+" 420,666,0,62,-94,43 2 0042 -- quotedbl
+# 500,676,0,90,48,43 2 0043 -- numbersign
+sh "
+$ 500,731,89,47,19,43 2 0044 -- dollar
+Do "
+% 833,676,13,7,-29,7 2 0045 -- percent
+& 778,666,18,0,-26 2 0046 -- ampersand
+' 333,666,0,7,-101,7 2 0047 -- quoteright
+( 333,669,181,32,8,32 2 0050 -- parenleft
+) 333,669,180,6,34,6 2 0051 -- parenright
+* 500,666,0,42,-78,42 2 0052 -- asterisk
++ 675,506,0,0,-36 0 0053 -- plus
+, 250,101,129,0,54 0 0054 -- comma
+- 333,255,0,0,1 0 0055 -- hyphen
+hy "
+char173 "
+. 250,100,11,0,23 0 0056 -- period
+/ 278,666,18,158,115,43 2 0057 -- slash
+sl "
+0 500,676,7,47,18,43 2 0060 -- zero
+1 500,676,0,0,1 2 0061 -- one
+2 500,676,0,2,38,2 2 0062 -- two
+3 500,676,7,15,35,15 2 0063 -- three
+4 500,676,0,29,49,29 2 0064 -- four
+5 500,666,7,41,35,41 2 0065 -- five
+6 500,686,7,71,20,43 2 0066 -- six
+7 500,666,8,87,-25,43 2 0067 -- seven
+8 500,676,7,43,20,43 2 0070 -- eight
+9 500,676,17,42,27,42 2 0071 -- nine
+: 333,441,11 0 0072 -- colon
+; 333,441,129,0,23 0 0073 -- semicolon
+< 675,514,8,0,-34 0 0074 -- less
+= 675,386,0,0,-36 0 0075 -- equal
+> 675,514,8,0,-34 0 0076 -- greater
+? 500,664,12,22,-82,22 2 0077 -- question
+@ 920,666,18,0,-68 2 0100 -- at
+at "
+A 611,668,0,3,101,3 2 0101 -- A
+B 611,653,0,27,58,27 2 0102 -- B
+C 667,666,18,72,-16,43 2 0103 -- C
+D 722,653,0,28,58,28 2 0104 -- D
+E 611,653,0,73,51,43 2 0105 -- E
+F 611,653,0,84,42,43 2 0106 -- F
+G 722,666,18,50,-2,43 2 0107 -- G
+H 722,653,0,95,58,43 2 0110 -- H
+I 333,653,0,101,58,43 2 0111 -- I
+J 444,653,18,97,56,43 2 0112 -- J
+K 667,653,0,105,43,43 2 0113 -- K
+L 556,653,0,53,58,43 2 0114 -- L
+M 833,653,0,90,68,43 2 0115 -- M
+N 667,653,15,110,70,43 2 0116 -- N
+O 722,666,18,27,-10,27 2 0117 -- O
+P 611,653,0,44,50,43 2 0120 -- P
+Q 722,666,182,27,-9,27 2 0121 -- Q
+R 611,653,0,27,63,27 2 0122 -- R
+S 500,667,18,58,33,43 2 0123 -- S
+T 556,653,0,127,-9,43 2 0124 -- T
+U 722,653,18,93,-52,43 2 0125 -- U
+V 611,653,18,127,-26,43 2 0126 -- V
+W 833,653,18,123,-21,43 2 0127 -- W
+X 611,653,0,94,79,43 2 0130 -- X
+Y 556,653,0,127,-28,43 2 0131 -- Y
+Z 556,653,0,100,56,43 2 0132 -- Z
+[ 389,663,153,52,29,43 2 0133 -- bracketleft
+lB "
+\ 278,666,18,91,91,43 2 0134 -- backslash
+rs "
+] 389,663,153,43,38,43 2 0135 -- bracketright
+rB "
+a^ 333,661,0,102,-41,43 2 0136 -- circumflex
+^ "
+_ 500,0,125,50,50,43 0 0137 -- underscore
+` 333,666,0,27,-121,27 2 0140 -- quoteleft
+oq "
+a 500,441,11,26,33,26 0 0141 -- a
+b 500,683,11,23,27,23 2 0142 -- b
+c 444,441,11,31,20,31 0 0143 -- c
+d 500,683,13,77,35,43 2 0144 -- d
+e 444,441,11,18,19,18 0 0145 -- e
+f 278,678,207,196,197,43 3 0146 -- f
+g 500,441,206,22,42,22 1 0147 -- g
+h 500,683,9,28,31,28 2 0150 -- h
+i 278,654,11,36,1,36 2 0151 -- i
+j 278,654,207,48,174,43 3 0152 -- j
+k 444,683,11,67,36,43 2 0153 -- k
+l 278,683,11,51,9,43 2 0154 -- l
+m 722,441,9,32,38,32 0 0155 -- m
+n 500,441,9,24,36,24 0 0156 -- n
+o 500,441,11,18,23,18 0 0157 -- o
+p 500,441,205,19,125,19 1 0160 -- p
+q 500,441,209,33,25,33 1 0161 -- q
+r 389,441,0,73,5,43 0 0162 -- r
+s 389,442,13,27,34,27 0 0163 -- s
+t 278,546,11,68,13,43 2 0164 -- t
+u 500,441,11,25,8,25 0 0165 -- u
+v 444,441,18,32,29,32 0 0166 -- v
+w 667,441,18,31,34,31 0 0167 -- w
+x 444,441,11,53,77,43 0 0170 -- x
+y 444,441,206,32,74,32 1 0171 -- y
+z 389,428,81,41,52,41 0 0172 -- z
+lC 400,687,177,57,-1,43 2 0173 -- braceleft
+{ "
+ba 275,666,18,0,-55 2 0174 -- bar
+| "
+rC 400,687,177,0,57 2 0175 -- braceright
+} "
+a~ 333,624,0,144,-50,43 2 0176 -- tilde
+~ "
+bq 333,101,129,0,6 0 0200 -- quotesinglbase
+Fo 500,403,0,0,-3 0 0201 -- guillemotleft
+char171 "
+Fc 500,403,0,0,-5 0 0202 -- guillemotright
+char187 "
+bu 350,461,0,10,10,10 0 0203 -- bullet
+Fn 500,682,182,57,25,43 2 0204 -- florin
+f/ 167,676,10,220,219,43 2 0205 -- fraction
+%0 1000,706,19,60,25,43 2 0206 -- perthousand
+dg 500,666,159,38,-51,38 2 0207 -- dagger
+dd 500,666,143,41,28,41 2 0210 -- daggerdbl
+en 500,243,0,55,56,43 0 0211 -- endash
+em 889,243,0,55,56,43 0 0212 -- emdash
+fi 500,681,207,31,191,31 3 0214 -- fi
+fl 500,682,204,68,191,43 3 0215 -- fl
+.i 278,441,11,7,1,7 0 0220 -- dotlessi
+ga 333,664,0,28,-71,28 2 0222 -- grave
+a" 333,664,0,203,-43,43 2 0223 -- hungarumlaut
+a. 333,606,0,22,-157,22 2 0224 -- dotaccent
+ab 333,650,0,135,-67,43 2 0225 -- breve
+ah 333,661,0,143,-71,43 2 0226 -- caron
+ao 333,691,0,72,-105,43 2 0227 -- ring
+ho 333,40,169,0,70 0 0230 -- ogonek
+lq 556,666,0,8,-116,8 2 0231 -- quotedblleft
+rq 556,666,0,0,-101 2 0232 -- quotedblright
+oe 667,441,12,29,30,29 0 0233 -- oe
+/l 278,683,11,79,13,43 2 0234 -- lslash
+Bq 556,101,129,0,-7 0 0235 -- quotedblbase
+OE 944,666,8,70,1,43 2 0236 -- OE
+/L 556,653,0,53,58,43 2 0237 -- Lslash
+r! 389,473,205,0,-9 1 0241 -- exclamdown
+char161 "
+ct 500,560,143,22,-27,22 2 0242 -- cent
+char162 "
+Po 500,670,6,67,40,43 2 0243 -- sterling
+char163 "
+Cs 500,597,0,72,72,43 2 0244 -- currency
+char164 "
+Ye 500,653,0,153,23,43 2 0245 -- yen
+char165 "
+bb 275,666,18,0,-55 2 0246 -- brokenbar
+char166 "
+sc 500,666,162,11,-3,11 2 0247 -- section
+char167 "
+ad 333,606,0,122,-57,43 2 0250 -- dieresis
+char168 "
+co 760,666,18,9,9,9 2 0251 -- copyright
+char169 "
+Of 276,676,0,126,8,43 2 0252 -- ordfeminine
+char170 "
+fo 333,403,0,0,-1 0 0253 -- guilsinglleft
+no 675,386,0,0,-36 0 0254 -- logicalnot
+char172 "
+\- 675,286,0,0,-36 0 0255 -- minus
+rg 760,666,18,9,9,9 2 0256 -- registered
+char174 "
+a- 333,583,0,128,-49,43 2 0257 -- macron
+char175 "
+de 400,676,0,37,-51,37 2 0260 -- degree
+char176 "
+char177 675,506,0,0,-36 0 0261 -- plusminus
+S2 300,676,0,74,17,43 2 0262 -- twosuperior
+char178 "
+S3 300,676,0,89,7,43 2 0263 -- threesuperior
+char179 "
+aa 333,664,0,120,-130,43 2 0264 -- acute
+char180 "
+char181 500,428,209,47,80,43 1 0265 -- mu
+ps 523,653,123,143,-5,43 2 0266 -- paragraph
+char182 "
+char183 250,310,0,0,-20 0 0267 -- periodcentered
+ac 333,0,217,0,80 1 0270 -- cedilla
+char184 "
+S1 300,676,0,34,7,34 2 0271 -- onesuperior
+char185 "
+Om 310,676,0,102,-17,43 2 0272 -- ordmasculine
+char186 "
+fc 333,403,0,0,-2 0 0273 -- guilsinglright
+14 750,676,10,36,17,36 2 0274 -- onequarter
+char188 "
+12 750,676,10,49,16,43 2 0275 -- onehalf
+char189 "
+34 750,676,10,36,27,36 2 0276 -- threequarters
+char190 "
+r? 500,471,205,0,22 1 0277 -- questiondown
+char191 "
+`A 611,876,0,3,101,3 2 0300 -- Agrave
+char192 "
+'A 611,876,0,3,101,3 2 0301 -- Aacute
+char193 "
+^A 611,873,0,3,101,3 2 0302 -- Acircumflex
+char194 "
+~A 611,836,0,5,101,5 2 0303 -- Atilde
+char195 "
+:A 611,818,0,3,101,3 2 0304 -- Adieresis
+char196 "
+oA 611,883,0,3,101,3 2 0305 -- Aring
+char197 "
+AE 889,653,0,72,77,43 2 0306 -- AE
+char198 "
+,C 667,666,217,72,-16,43 3 0307 -- Ccedilla
+char199 "
+`E 611,876,0,73,51,43 2 0310 -- Egrave
+char200 "
+'E 611,876,0,73,51,43 2 0311 -- Eacute
+char201 "
+^E 611,873,0,73,51,43 2 0312 -- Ecircumflex
+char202 "
+:E 611,818,0,73,51,43 2 0313 -- Edieresis
+char203 "
+`I 333,876,0,101,58,43 2 0314 -- Igrave
+char204 "
+'I 333,876,0,130,58,43 2 0315 -- Iacute
+char205 "
+^I 333,873,0,142,58,43 2 0316 -- Icircumflex
+char206 "
+:I 333,818,0,152,58,43 2 0317 -- Idieresis
+char207 "
+-D 722,653,0,28,58,28 2 0320 -- Eth
+char208 "
+~N 667,836,15,110,70,43 2 0321 -- Ntilde
+char209 "
+`O 722,876,18,27,-10,27 2 0322 -- Ograve
+char210 "
+'O 722,876,18,27,-10,27 2 0323 -- Oacute
+char211 "
+^O 722,873,18,27,-10,27 2 0324 -- Ocircumflex
+char212 "
+~O 722,836,18,27,-10,27 2 0325 -- Otilde
+char213 "
+:O 722,818,18,27,-10,27 2 0326 -- Odieresis
+char214 "
+char215 675,497,0,0,-43 0 0327 -- multiply
+/O 722,722,105,27,-10,27 2 0330 -- Oslash
+char216 "
+`U 722,876,18,93,-52,43 2 0331 -- Ugrave
+char217 "
+'U 722,876,18,93,-52,43 2 0332 -- Uacute
+char218 "
+^U 722,873,18,93,-52,43 2 0333 -- Ucircumflex
+char219 "
+:U 722,818,18,93,-52,43 2 0334 -- Udieresis
+char220 "
+'Y 556,876,0,127,-28,43 2 0335 -- Yacute
+char221 "
+TP 611,653,0,8,50,8 2 0336 -- Thorn
+char222 "
+ss 500,679,207,43,218,43 3 0337 -- germandbls
+char223 "
+`a 500,664,11,26,33,26 2 0340 -- agrave
+char224 "
+'a 500,664,11,37,33,37 2 0341 -- aacute
+char225 "
+^a 500,661,11,26,33,26 2 0342 -- acircumflex
+char226 "
+~a 500,624,11,61,33,43 2 0343 -- atilde
+char227 "
+:a 500,606,11,39,33,39 2 0344 -- adieresis
+char228 "
+oa 500,691,11,26,33,26 2 0345 -- aring
+char229 "
+ae 667,441,11,23,27,23 0 0346 -- ae
+char230 "
+,c 444,441,217,31,24,31 1 0347 -- ccedilla
+char231 "
+`e 444,664,11,18,19,18 2 0350 -- egrave
+char232 "
+'e 444,664,11,65,19,43 2 0351 -- eacute
+char233 "
+^e 444,661,11,47,19,43 2 0352 -- ecircumflex
+char234 "
+:e 444,606,11,57,19,43 2 0353 -- edieresis
+char235 "
+`i 278,664,11,56,1,43 2 0354 -- igrave
+char236 "
+'i 278,664,11,128,1,43 2 0355 -- iacute
+char237 "
+^i 278,661,11,100,16,43 2 0356 -- icircumflex
+char238 "
+:i 278,606,11,125,1,43 2 0357 -- idieresis
+char239 "
+Sd 500,683,11,32,23,32 2 0360 -- eth
+char240 "
+~n 500,624,9,26,36,26 2 0361 -- ntilde
+char241 "
+`o 500,664,11,18,23,18 2 0362 -- ograve
+char242 "
+'o 500,664,11,37,23,37 2 0363 -- oacute
+char243 "
+^o 500,661,11,18,23,18 2 0364 -- ocircumflex
+char244 "
+~o 500,624,11,46,23,43 2 0365 -- otilde
+char245 "
+:o 500,606,11,39,23,39 2 0366 -- odieresis
+char246 "
+char247 675,517,11,0,-36 0 0367 -- divide
+/o 500,554,135,19,22,19 2 0370 -- oslash
+char248 "
+`u 500,664,11,25,8,25 2 0371 -- ugrave
+char249 "
+'u 500,664,11,27,8,27 2 0372 -- uacute
+char250 "
+^u 500,661,11,25,8,25 2 0373 -- ucircumflex
+char251 "
+:u 500,606,11,29,8,29 2 0374 -- udieresis
+char252 "
+'y 444,664,206,65,74,43 3 0375 -- yacute
+char253 "
+Tp 500,683,205,19,125,19 3 0376 -- thorn
+char254 "
+:y 444,606,206,47,74,43 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/TR b/font/devps/TR
new file mode 100644
index 00000000..7c332754
--- /dev/null
+++ b/font/devps/TR
@@ -0,0 +1,519 @@
+name TR
+internalname Times-Roman
+spacewidth 250
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -92
+A w -92
+A v -74
+A ' -111
+A Y -105
+A W -90
+A V -135
+A U -55
+A T -111
+A Q -55
+A O -55
+A G -40
+A C -40
+B U -10
+B A -35
+D Y -55
+D W -30
+D V -40
+D A -40
+F . -80
+F o -15
+F , -80
+F a -15
+F A -74
+J A -60
+K y -25
+K u -15
+K o -35
+K e -25
+K O -30
+L y -55
+L ' -92
+L Y -100
+L W -74
+L V -100
+L T -92
+N A -35
+O Y -50
+O X -40
+O W -35
+O V -50
+O T -40
+O A -35
+P . -111
+P , -111
+P a -15
+P A -92
+Q U -10
+R Y -65
+R W -55
+R V -80
+R U -40
+R T -60
+R O -40
+T y -80
+T w -80
+T u -45
+T ; -55
+T r -35
+T . -74
+T o -80
+T i -35
+T - -92
+T hy -92
+T char173 -92
+T e -70
+T , -74
+T : -50
+T a -80
+T O -18
+T A -93
+U A -40
+V u -75
+V ; -74
+V . -129
+V o -129
+V i -60
+V - -100
+V hy -100
+V char173 -100
+V e -111
+V , -129
+V : -74
+V a -111
+V O -40
+V G -15
+V A -135
+W y -73
+W u -50
+W ; -37
+W . -92
+W o -80
+W i -40
+W - -65
+W hy -65
+W char173 -65
+W e -80
+W , -92
+W : -37
+W a -80
+W O -10
+W A -120
+Y u -111
+Y ; -92
+Y . -129
+Y o -110
+Y i -55
+Y - -111
+Y hy -111
+Y char173 -111
+Y e -100
+Y , -129
+Y : -92
+Y a -100
+Y O -30
+Y A -120
+a w -15
+a v -20
+b v -15
+b u -20
+b . -40
+c y -15
+, ' -70
+, rq -70
+e y -15
+e x -15
+e w -25
+e v -25
+e g -15
+f ' 55
+f i -20
+f f -25
+f .i -50
+f a -10
+g a -5
+h y -5
+i v -25
+k y -15
+k o -10
+k e -10
+l w -10
+n y -15
+n v -40
+o y -10
+o w -25
+o v -15
+p y -10
+. ' -70
+. rq -70
+lq A -80
+` ` -74
+` oq -74
+oq ` -74
+oq oq -74
+` A -80
+oq A -80
+' v -50
+' t -18
+' s -55
+' r -50
+' ' -74
+' l -10
+' d -50
+r . -55
+r - -20
+r hy -20
+r char173 -20
+r g -18
+r , -40
+v . -65
+v o -20
+v e -15
+v , -65
+v a -25
+w . -65
+w o -10
+w , -65
+w a -10
+x e -15
+y . -65
+y , -65
+charset
+ha 469,662 2 0000 -- asciicircum
+ti 541,323 0 0001 -- asciitilde
+vS 556,886,14 2 0002 -- Scaron
+vZ 611,886 2 0003 -- Zcaron
+vs 389,674,10 2 0004 -- scaron
+vz 444,674 2 0005 -- zcaron
+:Y 722,835 2 0006 -- Ydieresis
+tm 980,662 2 0007 -- trademark
+aq 180,676 2 0010 -- quotesingle
+space 250 0 0040
+! 333,676,9 2 0041 -- exclam
+" 408,676 2 0042 -- quotedbl
+# 500,662 2 0043 -- numbersign
+sh "
+$ 500,727,87 2 0044 -- dollar
+Do "
+% 833,676,13 2 0045 -- percent
+& 778,676,13 2 0046 -- ampersand
+' 333,676 2 0047 -- quoteright
+( 333,676,177 2 0050 -- parenleft
+) 333,676,177 2 0051 -- parenright
+* 500,676 2 0052 -- asterisk
++ 564,506 0 0053 -- plus
+, 250,102,141 0 0054 -- comma
+- 333,257 0 0055 -- hyphen
+hy "
+char173 "
+. 250,100,11 0 0056 -- period
+/ 278,676,14 2 0057 -- slash
+sl "
+0 500,676,14 2 0060 -- zero
+1 500,676 2 0061 -- one
+2 500,676 2 0062 -- two
+3 500,676,14 2 0063 -- three
+4 500,676 2 0064 -- four
+5 500,688,14 2 0065 -- five
+6 500,684,14 2 0066 -- six
+7 500,662,8 2 0067 -- seven
+8 500,676,14 2 0070 -- eight
+9 500,676,22 2 0071 -- nine
+: 278,459,11 0 0072 -- colon
+; 278,459,141 0 0073 -- semicolon
+< 564,514,8 0 0074 -- less
+= 564,386 0 0075 -- equal
+> 564,514,8 0 0076 -- greater
+? 444,676,8 2 0077 -- question
+@ 921,676,14 2 0100 -- at
+at "
+A 722,674 2 0101 -- A
+B 667,662 2 0102 -- B
+C 667,676,14 2 0103 -- C
+D 722,662 2 0104 -- D
+E 611,662 2 0105 -- E
+F 556,662 2 0106 -- F
+G 722,676,14 2 0107 -- G
+H 722,662 2 0110 -- H
+I 333,662 2 0111 -- I
+J 389,662,14 2 0112 -- J
+K 722,662 2 0113 -- K
+L 611,662 2 0114 -- L
+M 889,662 2 0115 -- M
+N 722,662,11 2 0116 -- N
+O 722,676,14 2 0117 -- O
+P 556,662 2 0120 -- P
+Q 722,676,178 2 0121 -- Q
+R 667,662 2 0122 -- R
+S 556,676,14 2 0123 -- S
+T 611,662 2 0124 -- T
+U 722,662,14 2 0125 -- U
+V 722,662,11 2 0126 -- V
+W 944,662,11 2 0127 -- W
+X 722,662 2 0130 -- X
+Y 722,662 2 0131 -- Y
+Z 611,662 2 0132 -- Z
+[ 333,662,156 2 0133 -- bracketleft
+lB "
+\ 278,676,14 2 0134 -- backslash
+rs "
+] 333,662,156 2 0135 -- bracketright
+rB "
+a^ 333,674 2 0136 -- circumflex
+^ "
+_ 500,0,125 0 0137 -- underscore
+` 333,676 2 0140 -- quoteleft
+oq "
+a 444,460,10 0 0141 -- a
+b 500,683,10 2 0142 -- b
+c 444,460,10 0 0143 -- c
+d 500,683,10 2 0144 -- d
+e 444,460,10 0 0145 -- e
+f 333,683 2 0146 -- f
+g 500,460,218 1 0147 -- g
+h 500,683 2 0150 -- h
+i 278,683 2 0151 -- i
+j 278,683,218 3 0152 -- j
+k 500,683 2 0153 -- k
+l 278,683 2 0154 -- l
+m 778,460 0 0155 -- m
+n 500,460 0 0156 -- n
+o 500,460,10 0 0157 -- o
+p 500,460,217 1 0160 -- p
+q 500,460,217 1 0161 -- q
+r 333,460 0 0162 -- r
+s 389,460,10 0 0163 -- s
+t 278,579,10 2 0164 -- t
+u 500,450,10 0 0165 -- u
+v 500,450,14 0 0166 -- v
+w 722,450,14 0 0167 -- w
+x 500,450 0 0170 -- x
+y 500,450,218 1 0171 -- y
+z 444,450 0 0172 -- z
+lC 480,680,181 2 0173 -- braceleft
+{ "
+ba 200,676,14 2 0174 -- bar
+| "
+rC 480,680,181 2 0175 -- braceright
+} "
+a~ 333,638 2 0176 -- tilde
+~ "
+bq 333,102,141 0 0200 -- quotesinglbase
+Fo 500,416 0 0201 -- guillemotleft
+char171 "
+Fc 500,416 0 0202 -- guillemotright
+char187 "
+bu 350,466 0 0203 -- bullet
+Fn 500,676,189 2 0204 -- florin
+f/ 167,676,14 2 0205 -- fraction
+%0 1000,706,19 2 0206 -- perthousand
+dg 500,676,149 2 0207 -- dagger
+dd 500,676,153 2 0210 -- daggerdbl
+en 500,250 0 0211 -- endash
+em 1000,250 0 0212 -- emdash
+fi 556,683 2 0214 -- fi
+fl 556,683 2 0215 -- fl
+.i 278,460 0 0220 -- dotlessi
+ga 333,678 2 0222 -- grave
+a" 333,678 2 0223 -- hungarumlaut
+a. 333,623 2 0224 -- dotaccent
+ab 333,664 2 0225 -- breve
+ah 333,674 2 0226 -- caron
+ao 333,711 2 0227 -- ring
+ho 333,0,165 0 0230 -- ogonek
+lq 444,676 2 0231 -- quotedblleft
+rq 444,676 2 0232 -- quotedblright
+oe 722,460,10 0 0233 -- oe
+/l 278,683 2 0234 -- lslash
+Bq 444,102,141 0 0235 -- quotedblbase
+OE 889,668,6 2 0236 -- OE
+/L 611,662 2 0237 -- Lslash
+r! 333,467,218 1 0241 -- exclamdown
+char161 "
+ct 500,579,138 2 0242 -- cent
+char162 "
+Po 500,676,8 2 0243 -- -- sterling
+char163 "
+Cs 500,602 2 0244 -- currency
+char164 "
+Ye 500,662 2 0245 -- yen
+char165 "
+bb 200,676,14 2 0246 -- brokenbar
+char166 "
+sc 500,676,148 2 0247 -- section
+char167 "
+ad 333,623 2 0250 -- dieresis
+char168 "
+co 760,676,14 2 0251 -- copyright
+char169 "
+Of 276,676 2 0252 -- ordfeminine
+char170 "
+fo 333,416 0 0253 -- guilsinglleft
+no 564,386 0 0254 -- logicalnot
+char172 "
+\- 564,286 0 0255 -- minus
+rg 760,676,14 2 0256 -- registered
+char174 "
+a- 333,601 2 0257 -- macron
+char175 "
+de 400,676 2 0260 -- degree
+char176 "
+char177 564,506 0 0261 -- plusminus
+S2 300,676 2 0262 -- twosuperior
+char178 "
+S3 300,676 2 0263 -- threesuperior
+char179 "
+aa 333,678 2 0264 -- acute
+char180 "
+char181 500,450,218 1 0265 -- mu
+ps 453,662,154 2 0266 -- paragraph
+char182 "
+char183 250,310 0 0267 -- periodcentered
+ac 333,0,215 0 0270 -- cedilla
+char184 "
+S1 300,676 2 0271 -- onesuperior
+char185 "
+Om 310,676 2 0272 -- ordmasculine
+char186 "
+fc 333,416 0 0273 -- guilsinglright
+14 750,676,14 2 0274 -- onequarter
+char188 "
+12 750,676,14 2 0275 -- onehalf
+char189 "
+34 750,676,14 2 0276 -- threequarters
+char190 "
+r? 444,466,218 1 0277 -- questiondown
+char191 "
+`A 722,890 2 0300 -- Agrave
+char192 "
+'A 722,890 2 0301 -- Aacute
+char193 "
+^A 722,886 2 0302 -- Acircumflex
+char194 "
+~A 722,850 2 0303 -- Atilde
+char195 "
+:A 722,835 2 0304 -- Adieresis
+char196 "
+oA 722,898 2 0305 -- Aring
+char197 "
+AE 889,662 2 0306 -- AE
+char198 "
+,C 667,676,215 2 0307 -- Ccedilla
+char199 "
+`E 611,890 2 0310 -- Egrave
+char200 "
+'E 611,890 2 0311 -- Eacute
+char201 "
+^E 611,886 2 0312 -- Ecircumflex
+char202 "
+:E 611,835 2 0313 -- Edieresis
+char203 "
+`I 333,890 2 0314 -- Igrave
+char204 "
+'I 333,890 2 0315 -- Iacute
+char205 "
+^I 333,886 2 0316 -- Icircumflex
+char206 "
+:I 333,835 2 0317 -- Idieresis
+char207 "
+-D 722,662 2 0320 -- Eth
+char208 "
+~N 722,850,11 2 0321 -- Ntilde
+char209 "
+`O 722,890,14 2 0322 -- Ograve
+char210 "
+'O 722,890,14 2 0323 -- Oacute
+char211 "
+^O 722,886,14 2 0324 -- Ocircumflex
+char212 "
+~O 722,850,14 2 0325 -- Otilde
+char213 "
+:O 722,835,14 2 0326 -- Odieresis
+char214 "
+char215 564,497 0 0327 -- multiply
+/O 722,734,80 2 0330 -- Oslash
+char216 "
+`U 722,890,14 2 0331 -- Ugrave
+char217 "
+'U 722,890,14 2 0332 -- Uacute
+char218 "
+^U 722,886,14 2 0333 -- Ucircumflex
+char219 "
+:U 722,835,14 2 0334 -- Udieresis
+char220 "
+'Y 722,890 2 0335 -- Yacute
+char221 "
+TP 556,662 2 0336 -- Thorn
+char222 "
+ss 500,683,9 2 0337 -- germandbls
+char223 "
+`a 444,678,10 2 0340 -- agrave
+char224 "
+'a 444,678,10 2 0341 -- aacute
+char225 "
+^a 444,674,10 2 0342 -- acircumflex
+char226 "
+~a 444,638,10 2 0343 -- atilde
+char227 "
+:a 444,623,10 2 0344 -- adieresis
+char228 "
+oa 444,711,10 2 0345 -- aring
+char229 "
+ae 667,460,10 0 0346 -- ae
+char230 "
+,c 444,460,215 0 0347 -- ccedilla
+char231 "
+`e 444,678,10 2 0350 -- egrave
+char232 "
+'e 444,678,10 2 0351 -- eacute
+char233 "
+^e 444,674,10 2 0352 -- ecircumflex
+char234 "
+:e 444,623,10 2 0353 -- edieresis
+char235 "
+`i 278,678 2 0354 -- igrave
+char236 "
+'i 278,678 2 0355 -- iacute
+char237 "
+^i 278,674 2 0356 -- icircumflex
+char238 "
+:i 278,623 2 0357 -- idieresis
+char239 "
+Sd 500,686,10 2 0360 -- eth
+char240 "
+~n 500,638 2 0361 -- ntilde
+char241 "
+`o 500,678,10 2 0362 -- ograve
+char242 "
+'o 500,678,10 2 0363 -- oacute
+char243 "
+^o 500,674,10 2 0364 -- ocircumflex
+char244 "
+~o 500,638,10 2 0365 -- otilde
+char245 "
+:o 500,623,10 2 0366 -- odieresis
+char246 "
+char247 564,516,10 0 0367 -- divide
+/o 500,551,112 0 0370 -- oslash
+char248 "
+`u 500,678,10 2 0371 -- ugrave
+char249 "
+'u 500,678,10 2 0372 -- uacute
+char250 "
+^u 500,674,10 2 0373 -- ucircumflex
+char251 "
+:u 500,623,10 2 0374 -- udieresis
+char252 "
+'y 500,678,218 3 0375 -- yacute
+char253 "
+Tp 500,683,217 3 0376 -- thorn
+char254 "
+:y 500,623,218 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/ZCMI b/font/devps/ZCMI
new file mode 100644
index 00000000..bd3de645
--- /dev/null
+++ b/font/devps/ZCMI
@@ -0,0 +1,477 @@
+name ZCMI
+internalname ZapfChancery-MediumItalic
+slant 14
+spacewidth 220
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A ' -40
+A rq -40
+A U -10
+A T 10
+A Q 10
+A O 10
+A G -30
+A C 20
+D . -30
+D , -20
+D Y 10
+D A -10
+F . -40
+F i 10
+F , -30
+G . -20
+G , -10
+J . -20
+J , -10
+K u -20
+K o -20
+K e -20
+L y -10
+L ' -25
+L rq -25
+L W -10
+L V -20
+O . -20
+O , -10
+O Y 10
+O T 20
+O A -20
+P . -50
+P o -10
+P e -10
+P , -40
+P a -20
+P A -10
+Q U -10
+R Y 10
+R W 10
+R T 20
+T o -20
+T i 20
+T - -20
+T hy -20
+T char173 -20
+T h 20
+T e -20
+T a -20
+T O 30
+T A 10
+V . -100
+V o -20
+V e -20
+V , -90
+V a -20
+V O 10
+V G -20
+W . -50
+W o -20
+W i 10
+W h 10
+W e -20
+W , -40
+W a -20
+W O 10
+Y u -20
+Y . -50
+Y o -50
+Y i 10
+Y e -40
+Y , -40
+Y a -60
+b . -30
+b l -20
+b , -20
+b b -20
+c k -10
+, ' -70
+, rq -70
+d w -20
+d v -10
+d d -40
+e y 10
+f ' 30
+f rq 30
+f . -50
+f f -50
+f e -10
+f , -40
+f a -20
+g y 10
+g . -30
+g i 10
+g e 10
+g , -20
+g a 10
+k y 10
+k o -10
+k e -20
+m y 10
+m u 10
+n y 20
+o . -30
+o , -20
+p . -30
+p p -10
+p , -20
+. ' -80
+. rq -80
+lq ` 20
+lq oq 20
+lq A 10
+` ` -115
+` oq -115
+oq ` -115
+oq oq -115
+` A 10
+oq A 10
+' v 30
+' t 20
+' s -25
+' r 30
+' ' -115
+' rq 20
+' l 20
+r . -50
+r i 10
+r , -40
+s . -20
+s , -10
+v . -30
+v , -20
+w . -30
+w o 10
+w h 20
+w , -20
+charset
+ha 520,594,0,62,-82,62 2 0000 -- asciicircum
+ti 520,320,0,69,-73,69 0 0001 -- asciitilde
+vS 460,831,81,184,5,87 2 0002 -- Scaron
+vZ 620,831,19,99,8,87 2 0003 -- Zcaron
+vs 320,659,14,194,4,87 2 0004 -- scaron
+vz 440,659,14,124,24,87 2 0005 -- zcaron
+:Y 560,762,168,264,9,87 2 0006 -- Ydieresis
+tm 1000,594,0,96,-77,87 2 0007 -- trademark
+aq 160,610,0,105,-95,87 2 0010 -- quotesingle
+space 220 0 0040
+! 280,610,14,123,-69,87 2 0041 -- exclam
+" 220,610,0,163,-70,87 2 0042 -- quotedbl
+# 440,594,0,131,-33,87 2 0043 -- numbersign
+sh "
+$ 440,709,144,118,-10,87 2 0044 -- dollar
+Do "
+% 680,700,160,80,-82,80 2 0045 -- percent
+& 780,610,16,185,-76,87 2 0046 -- ampersand
+' 240,610,0,148,-118,87 2 0047 -- quoteright
+( 260,664,216,201,-46,87 2 0050 -- parenleft
+) 220,664,216,132,63,87 2 0051 -- parenright
+* 420,610,0,109,-89,87 2 0052 -- asterisk
++ 520,426,0,73,-67,73 0 0053 -- plus
+, 220,148,140,43,25,43 0 0054 -- comma
+- 280,248,0,104,-19,87 0 0055 -- hyphen
+hy "
+char173 "
+. 220,128,14,58,-52,58 0 0056 -- period
+/ 340,610,16,168,-24,87 2 0057 -- slash
+sl "
+0 440,610,16,148,-29,87 2 0060 -- zero
+1 440,610,0,38,9,38 2 0061 -- one
+2 440,610,16,95,33,87 2 0062 -- two
+3 440,610,16,95,49,87 2 0063 -- three
+4 440,610,35,109,-27,87 2 0064 -- four
+5 440,679,16,205,-10,87 2 0065 -- five
+6 440,610,16,166,-40,87 2 0066 -- six
+7 440,645,33,171,-107,87 2 0067 -- seven
+8 440,610,16,139,-15,87 2 0070 -- eight
+9 440,610,16,127,18,87 2 0071 -- nine
+: 260,438,14,86,-48,86 0 0072 -- colon
+; 240,438,140,109,21,87 0 0073 -- semicolon
+< 520,468,0,57,-89,57 0 0074 -- less
+= 520,340,0,73,-67,73 0 0075 -- equal
+> 520,468,0,57,-89,57 0 0076 -- greater
+? 380,610,14,125,-100,87 2 0077 -- question
+@ 700,610,16,103,-77,87 2 0100 -- at
+at "
+A 620,632,16,127,37,87 2 0101 -- A
+B 600,640,6,124,-35,87 2 0102 -- B
+C 520,610,16,161,-43,87 2 0103 -- C
+D 700,640,6,118,-36,87 2 0104 -- D
+E 620,618,12,139,-41,87 2 0105 -- E
+F 580,629,118,263,-70,87 2 0106 -- F
+G 620,610,242,139,-98,87 2 0107 -- G
+H 680,708,16,248,32,87 2 0110 -- H
+I 380,594,0,174,-49,87 2 0111 -- I
+J 400,594,147,188,64,87 2 0112 -- J
+K 660,610,153,234,-3,87 2 0113 -- K
+L 580,610,16,127,-3,87 2 0114 -- L
+M 840,722,16,230,-8,87 2 0115 -- M
+N 700,708,168,265,-35,87 2 0116 -- N
+O 600,610,16,110,-44,87 2 0117 -- O
+P 540,628,0,168,8,87 2 0120 -- P
+Q 600,610,177,225,-34,87 2 0121 -- Q
+R 600,640,168,255,-8,87 2 0122 -- R
+S 460,610,81,148,5,87 2 0123 -- S
+T 500,667,0,294,-13,87 2 0124 -- T
+U 740,617,16,102,-76,87 2 0125 -- U
+V 640,714,16,220,-74,87 2 0126 -- V
+W 880,723,16,216,-44,87 2 0127 -- W
+X 560,610,16,189,80,87 2 0130 -- X
+Y 560,647,168,264,9,87 2 0131 -- Y
+Z 620,624,19,99,8,87 2 0132 -- Z
+[ 240,655,207,215,63,87 2 0133 -- bracketleft
+lB "
+\ 480,610,16,94,-90,87 2 0134 -- backslash
+rs "
+] 320,655,207,121,77,87 2 0135 -- bracketright
+rB "
+a^ 340,649,0,153,-173,87 2 0136 -- circumflex
+^ "
+_ 500,0,125,50,50,50 0 0137 -- underscore
+` 240,610,0,149,-119,87 2 0140 -- quoteleft
+oq "
+a 420,438,15,115,-42,87 0 0141 -- a
+b 420,714,23,122,-32,87 2 0142 -- b
+c 340,438,14,116,-37,87 0 0143 -- c
+d 440,714,14,261,-52,87 2 0144 -- d
+e 340,438,14,113,-37,87 0 0145 -- e
+f 320,714,314,277,169,87 3 0146 -- f
+g 400,438,314,153,158,87 1 0147 -- g
+h 440,714,14,134,-5,87 2 0150 -- h
+i 240,635,14,151,-50,87 2 0151 -- i
+j 220,635,314,162,162,87 3 0152 -- j
+k 440,714,184,238,-37,87 2 0153 -- k
+l 240,714,14,290,-52,87 2 0154 -- l
+m 620,438,14,134,-36,87 0 0155 -- m
+n 460,438,14,134,-51,87 0 0156 -- n
+o 400,438,14,99,-37,87 0 0157 -- o
+p 440,432,314,94,73,87 1 0160 -- p
+q 400,510,300,140,-37,87 1 0161 -- q
+r 300,438,14,174,-51,87 0 0162 -- r
+s 320,438,14,133,4,87 0 0163 -- s
+t 320,539,14,156,-56,87 2 0164 -- t
+u 460,438,14,118,-52,87 0 0165 -- u
+v 440,488,14,143,-37,87 0 0166 -- v
+w 680,488,14,152,-37,87 0 0167 -- w
+x 420,438,195,219,-20,87 0 0170 -- x
+y 400,438,314,133,74,87 1 0171 -- y
+z 440,445,14,118,24,87 0 0172 -- z
+lC 240,655,207,193,-5,87 2 0173 -- braceleft
+{ "
+ba 520,714,16,0,-270 2 0174 -- bar
+| "
+rC 240,655,207,128,60,87 2 0175 -- braceright
+} "
+a~ 440,619,0,132,-193,87 2 0176 -- tilde
+~ "
+bq 180,146,121,61,29,61 0 0200 -- quotesinglbase
+Fo 340,414,0,66,-48,66 0 0201 -- guillemotleft
+char171 "
+Fc 380,414,0,45,-67,45 0 0202 -- guillemotright
+char187 "
+bu 600,445,0,0,-178 0 0203 -- bullet
+Fn 440,610,314,192,114,87 3 0204 -- florin
+f/ 60,610,16,310,231,87 2 0205 -- fraction
+%0 960,700,160,95,-62,87 2 0206 -- perthousand
+dg 460,610,37,158,-88,87 2 0207 -- dagger
+dd 480,610,59,103,-88,87 2 0210 -- daggerdbl
+en 500,239,0,115,-1,87 0 0211 -- endash
+em 1000,239,0,115,-1,87 0 0212 -- emdash
+fi 520,714,314,135,174,87 3 0214 -- fi
+fl 520,714,314,200,174,87 3 0215 -- fl
+.i 240,438,14,116,-50,87 0 0220 -- dotlessi
+ga 220,659,0,169,-143,87 2 0222 -- grave
+a" 400,659,0,145,-158,87 2 0223 -- hungarumlaut
+a. 220,610,0,158,-186,87 2 0224 -- dotaccent
+ab 440,631,0,111,-203,87 2 0225 -- breve
+ah 340,659,0,184,-204,87 2 0226 -- caron
+ao 300,659,0,166,-190,87 2 0227 -- ring
+ho 280,6,191,3,12,3 0 0230 -- ogonek
+lq 340,610,0,174,-119,87 2 0231 -- quotedblleft
+rq 360,610,0,143,-108,87 2 0232 -- quotedblright
+oe 560,438,14,118,-28,87 0 0233 -- oe
+/l 300,714,14,265,-71,87 2 0234 -- lslash
+Bq 280,146,121,51,64,51 0 0235 -- quotedblbase
+OE 820,610,16,139,-13,87 2 0236 -- OE
+/L 580,610,16,127,1,87 2 0237 -- Lslash
+r! 280,438,186,76,-22,76 0 0241 -- exclamdown
+char161 "
+ct 440,543,134,86,-72,86 2 0242 -- cent
+char162 "
+Po 440,610,52,116,66,87 2 0243 -- sterling
+char163 "
+Cs 440,509,0,84,0,84 0 0244 -- currency
+char164 "
+Ye 440,647,168,223,51,87 2 0245 -- yen
+char165 "
+bb 520,714,16,0,-270 2 0246 -- brokenbar
+char166 "
+sc 420,610,215,144,-3,87 2 0247 -- section
+char167 "
+ad 360,610,0,159,-193,87 2 0250 -- dieresis
+char168 "
+co 740,610,16,73,-87,73 2 0251 -- copyright
+char169 "
+Of 260,610,0,176,-61,87 2 0252 -- ordfeminine
+char170 "
+fo 240,414,0,68,-48,68 0 0253 -- guilsinglleft
+no 520,340,0,73,-67,73 0 0254 -- logicalnot
+char172 "
+\- 520,242,0,73,-67,73 0 0255 -- minus
+rg 740,610,16,73,-87,73 2 0256 -- registered
+char174 "
+a- 440,578,0,75,-172,75 2 0257 -- macron
+char175 "
+de 400,610,0,107,-121,87 2 0260 -- degree
+char176 "
+char177 520,436,0,73,-67,73 0 0261 -- plusminus
+S2 264,610,0,140,-22,87 2 0262 -- twosuperior
+char178 "
+S3 264,610,0,134,-9,87 2 0263 -- threesuperior
+char179 "
+aa 300,659,0,172,-215,87 2 0264 -- acute
+char180 "
+char181 460,438,314,113,43,87 1 0265 -- mu
+ps 500,594,199,188,-55,87 2 0266 -- paragraph
+char182 "
+char183 220,310,0,71,-89,71 0 0267 -- periodcentered
+ac 300,6,191,0,38 0 0270 -- cedilla
+char184 "
+S1 264,610,0,97,-33,87 2 0271 -- onesuperior
+char185 "
+Om 260,610,0,163,-78,87 2 0272 -- ordmasculine
+char186 "
+fc 260,414,0,56,-56,56 0 0273 -- guilsinglright
+14 660,610,16,92,-6,87 2 0274 -- onequarter
+char188 "
+12 660,610,16,92,-6,87 2 0275 -- onehalf
+char189 "
+34 660,610,16,96,11,87 2 0276 -- threequarters
+char190 "
+r? 400,438,186,37,-32,37 0 0277 -- questiondown
+char191 "
+`A 620,821,16,127,37,87 2 0300 -- Agrave
+char192 "
+'A 620,821,16,132,37,87 2 0301 -- Aacute
+char193 "
+^A 620,821,16,127,37,87 2 0302 -- Acircumflex
+char194 "
+~A 620,771,16,132,37,87 2 0303 -- Atilde
+char195 "
+:A 620,762,16,139,37,87 2 0304 -- Adieresis
+char196 "
+oA 620,831,16,127,37,87 2 0305 -- Aring
+char197 "
+AE 740,594,16,109,71,87 2 0306 -- AE
+char198 "
+,C 520,610,191,161,-43,87 2 0307 -- Ccedilla
+char199 "
+`E 620,821,12,139,-41,87 2 0310 -- Egrave
+char200 "
+'E 620,821,12,139,-41,87 2 0311 -- Eacute
+char201 "
+^E 620,821,12,139,-41,87 2 0312 -- Ecircumflex
+char202 "
+:E 620,762,12,139,-41,87 2 0313 -- Edieresis
+char203 "
+`I 380,821,0,174,-49,87 2 0314 -- Igrave
+char204 "
+'I 380,821,0,202,-49,87 2 0315 -- Iacute
+char205 "
+^I 380,821,0,174,-49,87 2 0316 -- Icircumflex
+char206 "
+:I 380,762,0,189,-49,87 2 0317 -- Idieresis
+char207 "
+-D 700,640,6,118,-36,87 2 0320 -- Eth
+char208 "
+~N 700,761,168,265,-35,87 2 0321 -- Ntilde
+char209 "
+`O 600,821,16,110,-44,87 2 0322 -- Ograve
+char210 "
+'O 600,821,16,110,-44,87 2 0323 -- Oacute
+char211 "
+^O 600,821,16,110,-44,87 2 0324 -- Ocircumflex
+char212 "
+~O 600,761,16,110,-44,87 2 0325 -- Otilde
+char213 "
+:O 600,762,16,110,-44,87 2 0326 -- Odieresis
+char214 "
+char215 520,410,0,57,-83,57 0 0327 -- multiply
+/O 660,672,78,141,-33,87 2 0330 -- Oslash
+char216 "
+`U 740,821,16,102,-76,87 2 0331 -- Ugrave
+char217 "
+'U 740,821,16,102,-76,87 2 0332 -- Uacute
+char218 "
+^U 740,821,16,102,-76,87 2 0333 -- Ucircumflex
+char219 "
+:U 740,762,16,102,-76,87 2 0334 -- Udieresis
+char220 "
+'Y 560,821,168,264,9,87 2 0335 -- Yacute
+char221 "
+TP 540,623,0,157,-2,87 2 0336 -- Thorn
+char222 "
+ss 420,714,314,172,177,87 3 0337 -- germandbls
+char223 "
+`a 420,659,15,115,-42,87 2 0340 -- agrave
+char224 "
+'a 420,659,15,122,-42,87 2 0341 -- aacute
+char225 "
+^a 420,649,15,115,-42,87 2 0342 -- acircumflex
+char226 "
+~a 420,619,15,152,-42,87 2 0343 -- atilde
+char227 "
+:a 420,610,15,115,-42,87 2 0344 -- adieresis
+char228 "
+oa 420,659,15,115,-42,87 2 0345 -- aring
+char229 "
+ae 540,468,14,134,-17,87 0 0346 -- ae
+char230 "
+,c 340,438,191,116,-12,87 0 0347 -- ccedilla
+char231 "
+`e 340,659,14,113,-37,87 2 0350 -- egrave
+char232 "
+'e 340,659,14,172,-37,87 2 0351 -- eacute
+char233 "
+^e 340,649,14,143,-37,87 2 0352 -- ecircumflex
+char234 "
+:e 340,610,14,159,-37,87 2 0353 -- edieresis
+char235 "
+`i 240,659,14,116,-50,87 2 0354 -- igrave
+char236 "
+'i 240,659,14,202,-50,87 2 0355 -- iacute
+char237 "
+^i 240,649,14,173,-50,87 2 0356 -- icircumflex
+char238 "
+:i 240,610,14,179,-50,87 2 0357 -- idieresis
+char239 "
+Sd 400,714,14,172,-37,87 2 0360 -- eth
+char240 "
+~n 460,619,14,134,-51,87 2 0361 -- ntilde
+char241 "
+`o 400,659,14,99,-37,87 2 0362 -- ograve
+char242 "
+'o 400,659,14,132,-37,87 2 0363 -- oacute
+char243 "
+^o 400,649,14,103,-37,87 2 0364 -- ocircumflex
+char244 "
+~o 400,619,14,152,-37,87 2 0365 -- otilde
+char245 "
+:o 400,610,14,129,-37,87 2 0366 -- odieresis
+char246 "
+char247 520,440,14,73,-67,73 0 0367 -- divide
+/o 440,488,64,150,4,87 0 0370 -- oslash
+char248 "
+`u 460,659,14,118,-52,87 2 0371 -- ugrave
+char249 "
+'u 460,659,14,118,-52,87 2 0372 -- uacute
+char250 "
+^u 460,649,14,118,-52,87 2 0373 -- ucircumflex
+char251 "
+:u 460,610,14,118,-52,87 2 0374 -- udieresis
+char252 "
+'y 400,659,314,133,74,87 3 0375 -- yacute
+char253 "
+Tp 440,714,314,115,88,87 3 0376 -- thorn
+char254 "
+:y 400,610,314,133,74,87 3 0377 -- ydieresis
+char255 "
diff --git a/font/devps/ZD b/font/devps/ZD
new file mode 100644
index 00000000..3066c39b
--- /dev/null
+++ b/font/devps/ZD
@@ -0,0 +1,193 @@
+name ZD
+internalname ZapfDingbats
+special
+spacewidth 278
+charset
+space 278 0 0040
+--- 974,621 3 0041 -- a1
+--- 961,611 3 0042 -- a2
+--- 974,621 3 0043 -- a202
+--- 980,692 3 0044 -- a3
+--- 719,566 3 0045 -- a4
+--- 789,705,14 3 0046 -- a5
+--- 790,705,14 3 0047 -- a119
+--- 791,705,13 3 0050 -- a118
+--- 690,553 3 0051 -- a117
+--- 960,568 3 0052 -- a11
+rh 939,559 3 0053 -- a12
+--- 549,705,11 3 0054 -- a13
+--- 855,632 3 0055 -- a14
+--- 911,642 3 0056 -- a15
+--- 933,550 3 0057 -- a16
+--- 911,642 3 0060 -- a105
+--- 945,553 3 0061 -- a17
+--- 974,587 3 0062 -- a18
+OK 755,705,13 3 0063 -- a19
+--- 846,705,14 3 0064 -- a20
+--- 762,692 3 0065 -- a21
+--- 761,692 3 0066 -- a22
+--- 571,661,68 3 0067 -- a23
+--- 677,705,13 3 0070 -- a24
+--- 763,692 3 0071 -- a25
+--- 760,692 3 0072 -- a26
+--- 759,692 3 0073 -- a27
+--- 754,692 3 0074 -- a28
+--- 494,692 3 0075 -- a6
+--- 552,692 3 0076 -- a7
+--- 537,692 3 0077 -- a8
+--- 577,596 3 0100 -- a9
+--- 692,705,14 3 0101 -- a10
+--- 786,705,14 3 0102 -- a29
+--- 788,705,14 3 0103 -- a30
+--- 788,705,14 3 0104 -- a31
+--- 790,705,14 3 0105 -- a32
+--- 793,705,13 3 0106 -- a33
+--- 794,705,13 3 0107 -- a34
+--- 816,705,14 3 0110 -- a35
+--- 823,705,14 3 0111 -- a36
+--- 789,705,14 3 0112 -- a37
+--- 841,705,14 3 0113 -- a38
+--- 823,705,14 3 0114 -- a39
+--- 833,705,14 3 0115 -- a40
+--- 816,705,13 3 0116 -- a41
+--- 831,705,14 3 0117 -- a42
+--- 923,705,14 3 0120 -- a43
+--- 744,692 3 0121 -- a44
+--- 723,692 3 0122 -- a45
+--- 749,692 3 0123 -- a46
+--- 790,705,14 3 0124 -- a47
+--- 792,705,14 3 0125 -- a48
+--- 695,706,14 3 0126 -- a49
+--- 776,699,6 3 0127 -- a50
+--- 768,699,7 3 0130 -- a51
+--- 792,705,14 3 0131 -- a52
+--- 759,692 3 0132 -- a53
+--- 707,704,13 3 0133 -- a54
+--- 708,705,14 3 0134 -- a55
+--- 682,705,14 3 0135 -- a56
+--- 701,705,14 3 0136 -- a57
+--- 826,705,14 3 0137 -- a58
+--- 815,705,14 3 0140 -- a59
+--- 789,705,14 3 0141 -- a60
+--- 789,705,14 3 0142 -- a61
+--- 707,705,14 3 0143 -- a62
+--- 687,692 3 0144 -- a63
+--- 696,691 3 0145 -- a64
+--- 689,692 3 0146 -- a65
+--- 786,705,14 3 0147 -- a66
+--- 787,705,14 3 0150 -- a67
+--- 713,705,14 3 0151 -- a68
+--- 791,705,14 3 0152 -- a69
+--- 785,705,14 3 0153 -- a70
+--- 791,705,14 3 0154 -- a71
+--- 873,705,14 3 0155 -- a72
+--- 761,692 3 0156 -- a73
+--- 762,692 3 0157 -- a74
+--- 762,692 3 0160 -- a203
+--- 759,692 3 0161 -- a75
+--- 759,692 3 0162 -- a204
+--- 892,705 3 0163 -- a76
+--- 892,692,14 3 0164 -- a77
+--- 788,705,14 3 0165 -- a78
+--- 784,705,14 3 0166 -- a79
+--- 438,705,14 3 0167 -- a81
+--- 138,692 3 0170 -- a82
+--- 277,692 3 0171 -- a83
+--- 415,692 3 0172 -- a84
+--- 392,705 3 0173 -- a97
+--- 392,705 3 0174 -- a98
+--- 668,705 3 0175 -- a99
+--- 668,705 3 0176 -- a100
+--- 732,806,143 3 0241 -- a101
+--- 544,706,14 3 0242 -- a102
+--- 544,705,14 3 0243 -- a103
+--- 910,651 3 0244 -- a104
+--- 667,705,14 3 0245 -- a106
+--- 760,705,14 3 0246 -- a107
+--- 760,569 3 0247 -- a108
+--- 776,705 3 0250 -- a112
+--- 595,705,14 3 0251 -- a111
+--- 694,705,14 3 0252 -- a110
+--- 626,705 3 0253 -- a109
+--- 788,705,14 3 0254 -- a120
+--- 788,705,14 3 0255 -- a121
+--- 788,705,14 3 0256 -- a122
+--- 788,705,14 3 0257 -- a123
+--- 788,705,14 3 0260 -- a124
+--- 788,705,14 3 0261 -- a125
+--- 788,705,14 3 0262 -- a126
+--- 788,705,14 3 0263 -- a127
+--- 788,705,14 3 0264 -- a128
+--- 788,705,14 3 0265 -- a129
+--- 788,705,14 3 0266 -- a130
+--- 788,705,14 3 0267 -- a131
+--- 788,705,14 3 0270 -- a132
+--- 788,705,14 3 0271 -- a133
+--- 788,705,14 3 0272 -- a134
+--- 788,705,14 3 0273 -- a135
+--- 788,705,14 3 0274 -- a136
+--- 788,705,14 3 0275 -- a137
+--- 788,705,14 3 0276 -- a138
+--- 788,705,14 3 0277 -- a139
+--- 788,705,14 3 0300 -- a140
+--- 788,705,14 3 0301 -- a141
+--- 788,705,14 3 0302 -- a142
+--- 788,705,14 3 0303 -- a143
+--- 788,705,14 3 0304 -- a144
+--- 788,705,14 3 0305 -- a145
+--- 788,705,14 3 0306 -- a146
+--- 788,705,14 3 0307 -- a147
+--- 788,705,14 3 0310 -- a148
+--- 788,705,14 3 0311 -- a149
+--- 788,705,14 3 0312 -- a150
+--- 788,705,14 3 0313 -- a151
+--- 788,705,14 3 0314 -- a152
+--- 788,705,14 3 0315 -- a153
+--- 788,705,14 3 0316 -- a154
+--- 788,705,14 3 0317 -- a155
+--- 788,705,14 3 0320 -- a156
+--- 788,705,14 3 0321 -- a157
+--- 788,705,14 3 0322 -- a158
+--- 788,705,14 3 0323 -- a159
+--- 894,634 3 0324 -- a160
+--- 838,540 3 0325 -- a161
+--- 1016,540 3 0326 -- a163
+--- 458,820,127 3 0327 -- a164
+--- 748,597 3 0330 -- a196
+--- 924,552 3 0331 -- a165
+--- 748,597 3 0332 -- a192
+--- 918,526 3 0333 -- a166
+--- 927,660 3 0334 -- a167
+--- 928,562 3 0335 -- a168
+--- 928,563 3 0336 -- a169
+--- 834,537 3 0337 -- a170
+--- 873,599 3 0340 -- a171
+--- 828,588 3 0341 -- a172
+--- 924,594 3 0342 -- a173
+--- 924,594 3 0343 -- a162
+--- 917,692 3 0344 -- a174
+--- 930,608 3 0345 -- a175
+--- 931,608 3 0346 -- a176
+--- 463,791,99 3 0347 -- a177
+--- 883,623 3 0350 -- a178
+--- 836,648 3 0351 -- a179
+--- 836,648 3 0352 -- a193
+--- 867,591 3 0353 -- a180
+--- 867,591 3 0354 -- a199
+--- 696,648 3 0355 -- a181
+--- 696,648 3 0356 -- a200
+--- 874,619 3 0357 -- a182
+--- 874,615 3 0361 -- a201
+--- 760,692 3 0362 -- a183
+--- 946,533 3 0363 -- a184
+--- 771,655 3 0364 -- a197
+--- 865,481 3 0365 -- a185
+--- 771,655 3 0366 -- a194
+--- 888,712,19 3 0367 -- a198
+--- 967,568 3 0370 -- a186
+--- 888,712,19 3 0371 -- a195
+--- 831,579 3 0372 -- a187
+--- 873,578 3 0373 -- a188
+--- 927,542 3 0374 -- a189
+--- 970,616 3 0375 -- a190
+--- 918,593 3 0376 -- a191
diff --git a/font/devps/ZDR b/font/devps/ZDR
new file mode 100644
index 00000000..ab5b54f7
--- /dev/null
+++ b/font/devps/ZDR
@@ -0,0 +1,193 @@
+name ZDR
+internalname ZapfDingbats-Reverse
+special
+spacewidth 278
+charset
+space 278 0 0040
+--- 974,621 3 0041 -- a1
+--- 961,611 3 0042 -- a2
+--- 974,621 3 0043 -- a202
+--- 980,692 3 0044 -- a3
+--- 719,566 3 0045 -- a4
+--- 789,705,14 3 0046 -- a5
+--- 790,705,14 3 0047 -- a119
+--- 791,705,13 3 0050 -- a118
+--- 690,553 3 0051 -- a117
+--- 960,568 3 0052 -- a11
+lh 939,559 3 0053 -- a12
+--- 549,705,11 3 0054 -- a13
+--- 855,632 3 0055 -- a14
+--- 911,642 3 0056 -- a15
+--- 933,550 3 0057 -- a16
+--- 911,642 3 0060 -- a105
+--- 945,553 3 0061 -- a17
+--- 974,587 3 0062 -- a18
+--- 755,705,13 3 0063 -- a19
+--- 846,705,14 3 0064 -- a20
+--- 762,692 3 0065 -- a21
+--- 761,692 3 0066 -- a22
+--- 571,661,68 3 0067 -- a23
+--- 677,705,13 3 0070 -- a24
+--- 763,692 3 0071 -- a25
+--- 760,692 3 0072 -- a26
+--- 759,692 3 0073 -- a27
+--- 754,692 3 0074 -- a28
+--- 494,692 3 0075 -- a6
+--- 552,692 3 0076 -- a7
+--- 537,692 3 0077 -- a8
+--- 577,596 3 0100 -- a9
+--- 692,705,14 3 0101 -- a10
+--- 786,705,14 3 0102 -- a29
+--- 788,705,14 3 0103 -- a30
+--- 788,705,14 3 0104 -- a31
+--- 790,705,14 3 0105 -- a32
+--- 793,705,13 3 0106 -- a33
+--- 794,705,13 3 0107 -- a34
+--- 816,705,14 3 0110 -- a35
+--- 823,705,14 3 0111 -- a36
+--- 789,705,14 3 0112 -- a37
+--- 841,705,14 3 0113 -- a38
+--- 823,705,14 3 0114 -- a39
+--- 833,705,14 3 0115 -- a40
+--- 816,705,13 3 0116 -- a41
+--- 831,705,14 3 0117 -- a42
+--- 923,705,14 3 0120 -- a43
+--- 744,692 3 0121 -- a44
+--- 723,692 3 0122 -- a45
+--- 749,692 3 0123 -- a46
+--- 790,705,14 3 0124 -- a47
+--- 792,705,14 3 0125 -- a48
+--- 695,706,14 3 0126 -- a49
+--- 776,699,6 3 0127 -- a50
+--- 768,699,7 3 0130 -- a51
+--- 792,705,14 3 0131 -- a52
+--- 759,692 3 0132 -- a53
+--- 707,704,13 3 0133 -- a54
+--- 708,705,14 3 0134 -- a55
+--- 682,705,14 3 0135 -- a56
+--- 701,705,14 3 0136 -- a57
+--- 826,705,14 3 0137 -- a58
+--- 815,705,14 3 0140 -- a59
+--- 789,705,14 3 0141 -- a60
+--- 789,705,14 3 0142 -- a61
+--- 707,705,14 3 0143 -- a62
+--- 687,692 3 0144 -- a63
+--- 696,691 3 0145 -- a64
+--- 689,692 3 0146 -- a65
+--- 786,705,14 3 0147 -- a66
+--- 787,705,14 3 0150 -- a67
+--- 713,705,14 3 0151 -- a68
+--- 791,705,14 3 0152 -- a69
+--- 785,705,14 3 0153 -- a70
+--- 791,705,14 3 0154 -- a71
+--- 873,705,14 3 0155 -- a72
+--- 761,692 3 0156 -- a73
+--- 762,692 3 0157 -- a74
+--- 762,692 3 0160 -- a203
+--- 759,692 3 0161 -- a75
+--- 759,692 3 0162 -- a204
+--- 892,705 3 0163 -- a76
+--- 892,692,14 3 0164 -- a77
+--- 788,705,14 3 0165 -- a78
+--- 784,705,14 3 0166 -- a79
+--- 438,705,14 3 0167 -- a81
+--- 138,692 3 0170 -- a82
+--- 277,692 3 0171 -- a83
+--- 415,692 3 0172 -- a84
+--- 392,705 3 0173 -- a97
+--- 392,705 3 0174 -- a98
+--- 668,705 3 0175 -- a99
+--- 668,705 3 0176 -- a100
+--- 732,806,143 3 0241 -- a101
+--- 544,706,14 3 0242 -- a102
+--- 544,705,14 3 0243 -- a103
+--- 910,651 3 0244 -- a104
+--- 667,705,14 3 0245 -- a106
+--- 760,705,14 3 0246 -- a107
+--- 760,569 3 0247 -- a108
+--- 776,705 3 0250 -- a112
+--- 595,705,14 3 0251 -- a111
+--- 694,705,14 3 0252 -- a110
+--- 626,705 3 0253 -- a109
+--- 788,705,14 3 0254 -- a120
+--- 788,705,14 3 0255 -- a121
+--- 788,705,14 3 0256 -- a122
+--- 788,705,14 3 0257 -- a123
+--- 788,705,14 3 0260 -- a124
+--- 788,705,14 3 0261 -- a125
+--- 788,705,14 3 0262 -- a126
+--- 788,705,14 3 0263 -- a127
+--- 788,705,14 3 0264 -- a128
+--- 788,705,14 3 0265 -- a129
+--- 788,705,14 3 0266 -- a130
+--- 788,705,14 3 0267 -- a131
+--- 788,705,14 3 0270 -- a132
+--- 788,705,14 3 0271 -- a133
+--- 788,705,14 3 0272 -- a134
+--- 788,705,14 3 0273 -- a135
+--- 788,705,14 3 0274 -- a136
+--- 788,705,14 3 0275 -- a137
+--- 788,705,14 3 0276 -- a138
+--- 788,705,14 3 0277 -- a139
+--- 788,705,14 3 0300 -- a140
+--- 788,705,14 3 0301 -- a141
+--- 788,705,14 3 0302 -- a142
+--- 788,705,14 3 0303 -- a143
+--- 788,705,14 3 0304 -- a144
+--- 788,705,14 3 0305 -- a145
+--- 788,705,14 3 0306 -- a146
+--- 788,705,14 3 0307 -- a147
+--- 788,705,14 3 0310 -- a148
+--- 788,705,14 3 0311 -- a149
+--- 788,705,14 3 0312 -- a150
+--- 788,705,14 3 0313 -- a151
+--- 788,705,14 3 0314 -- a152
+--- 788,705,14 3 0315 -- a153
+--- 788,705,14 3 0316 -- a154
+--- 788,705,14 3 0317 -- a155
+--- 788,705,14 3 0320 -- a156
+--- 788,705,14 3 0321 -- a157
+--- 788,705,14 3 0322 -- a158
+--- 788,705,14 3 0323 -- a159
+--- 894,634 3 0324 -- a160
+--- 838,540 3 0325 -- a161
+--- 1016,540 3 0326 -- a163
+--- 458,820,127 3 0327 -- a164
+--- 748,597 3 0330 -- a196
+--- 924,552 3 0331 -- a165
+--- 748,597 3 0332 -- a192
+--- 918,526 3 0333 -- a166
+--- 927,660 3 0334 -- a167
+--- 928,562 3 0335 -- a168
+--- 928,563 3 0336 -- a169
+--- 834,537 3 0337 -- a170
+--- 873,599 3 0340 -- a171
+--- 828,588 3 0341 -- a172
+--- 924,594 3 0342 -- a173
+--- 924,594 3 0343 -- a162
+--- 917,692 3 0344 -- a174
+--- 930,608 3 0345 -- a175
+--- 931,608 3 0346 -- a176
+--- 463,791,99 3 0347 -- a177
+--- 883,623 3 0350 -- a178
+--- 836,648 3 0351 -- a179
+--- 836,648 3 0352 -- a193
+--- 867,591 3 0353 -- a180
+--- 867,591 3 0354 -- a199
+--- 696,648 3 0355 -- a181
+--- 696,648 3 0356 -- a200
+--- 874,619 3 0357 -- a182
+--- 874,615 3 0361 -- a201
+--- 760,692 3 0362 -- a183
+--- 946,533 3 0363 -- a184
+--- 771,655 3 0364 -- a197
+--- 865,481 3 0365 -- a185
+--- 771,655 3 0366 -- a194
+--- 888,712,19 3 0367 -- a198
+--- 967,568 3 0370 -- a186
+--- 888,712,19 3 0371 -- a195
+--- 831,579 3 0372 -- a187
+--- 873,578 3 0373 -- a188
+--- 927,542 3 0374 -- a189
+--- 970,616 3 0375 -- a190
+--- 918,593 3 0376 -- a191
diff --git a/font/devps/download b/font/devps/download
new file mode 100644
index 00000000..b98885cd
--- /dev/null
+++ b/font/devps/download
@@ -0,0 +1,5 @@
+# List of downloadable fonts
+# PostScript-name Filename
+
+Symbol-Slanted symbolsl.pfa
+ZapfDingbats-Reverse zapfdr.pfa
diff --git a/font/devps/generate/Makefile b/font/devps/generate/Makefile
new file mode 100644
index 00000000..f62c2929
--- /dev/null
+++ b/font/devps/generate/Makefile
@@ -0,0 +1,224 @@
+#Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+# Written by James Clark (jjc@jclark.com)
+#
+#This file is part of groff.
+#
+#groff 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.
+#
+#groff 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 groff; see the file COPYING. If not, write to the Free Software
+#Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# This is set up so you can do
+# make -f generate/Makefile
+# in the parent directory of this directory.
+
+# Directory containing AFM files. Must not be current directory.
+# Either long names (eg Times-Roman.afm) or short names (eg timesr.afm)
+# may be used. See the afmname script.
+afmdir=/usr/local/afm
+srcdir=generate
+
+SPECIALFONTS=S
+DINGBATSFONTS=ZD ZDR
+GREEKFONTS=SS
+TEXTFONTS=AB ABI AI AR BMB BMBI BMI BMR CB CBI CI CR HB HBI HI HR HNB HNBI \
+ HNI HNR NB NBI NI NR PB PBI PI PR TB TBI TI TR ZCMI
+
+FONTS=$(TEXTFONTS) $(SPECIALFONTS) $(GREEKFONTS) $(DINGBATSFONTS)
+
+DESC=$(srcdir)/../DESC
+AFMTODIT=afmtodit -d$(DESC)
+IFLAG=-i 50
+NOLIGFLAG=-n
+TEXTENC=$(srcdir)/../text.enc
+EFLAG=-e $(TEXTENC)
+TEXTMAP=$(srcdir)/textmap
+SHELL=/bin/sh
+AFMNAME=$(SHELL) $(srcdir)/afmname
+
+all: $(FONTS)
+
+TR:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Times-Roman.afm` $(TEXTMAP) $@
+
+TB:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Times-Bold.afm` $(TEXTMAP) $@
+
+TI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) -a 7 \
+ `$(AFMNAME) $(afmdir)/Times-Italic.afm` $(TEXTMAP) $@
+
+TBI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Times-BoldItalic.afm` $(TEXTMAP) $@
+
+HR:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Helvetica.afm` $(TEXTMAP) $@
+
+HB:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Helvetica-Bold.afm` $(TEXTMAP) $@
+
+HI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Helvetica-Oblique.afm` $(TEXTMAP) $@
+
+HBI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Helvetica-BoldOblique.afm` $(TEXTMAP) $@
+
+CR:
+ $(AFMTODIT) $(NOLIGFLAG) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Courier.afm` $(TEXTMAP) $@
+
+CB:
+ $(AFMTODIT) $(NOLIGFLAG) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Courier-Bold.afm` $(TEXTMAP) $@
+
+CI:
+ $(AFMTODIT) $(NOLIGFLAG) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Courier-Oblique.afm` $(TEXTMAP) $@
+
+CBI:
+ $(AFMTODIT) $(NOLIGFLAG) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Courier-BoldOblique.afm` $(TEXTMAP) $@
+
+PR:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Palatino-Roman.afm` $(TEXTMAP) $@
+
+PB:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Palatino-Bold.afm` $(TEXTMAP) $@
+
+PI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Palatino-Italic.afm` $(TEXTMAP) $@
+
+PBI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Palatino-BoldItalic.afm` $(TEXTMAP) $@
+
+NR:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/NewCenturySchlbk-Roman.afm` $(TEXTMAP) $@
+
+NB:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/NewCenturySchlbk-Bold.afm` $(TEXTMAP) $@
+
+NI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/NewCenturySchlbk-Italic.afm` $(TEXTMAP) $@
+
+NBI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/NewCenturySchlbk-BoldItalic.afm` $(TEXTMAP) $@
+
+BMR:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Bookman-Light.afm` $(TEXTMAP) $@
+
+BMB:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Bookman-Demi.afm` $(TEXTMAP) $@
+
+BMI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Bookman-LightItalic.afm` $(TEXTMAP) $@
+
+BMBI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Bookman-DemiItalic.afm` $(TEXTMAP) $@
+
+AR:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/AvantGarde-Book.afm` $(TEXTMAP) $@
+
+AB:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/AvantGarde-Demi.afm` $(TEXTMAP) $@
+
+AI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/AvantGarde-BookOblique.afm` $(TEXTMAP) $@
+
+ABI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/AvantGarde-DemiOblique.afm` $(TEXTMAP) $@
+
+HNR:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Helvetica-Narrow.afm` $(TEXTMAP) $@
+
+HNB:
+ $(AFMTODIT) $(EFLAG) \
+ `$(AFMNAME) $(afmdir)/Helvetica-Narrow-Bold.afm` $(TEXTMAP) $@
+
+HNI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Helvetica-Narrow-Oblique.afm` $(TEXTMAP) $@
+
+HNBI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/Helvetica-Narrow-BoldOblique.afm` $(TEXTMAP) $@
+
+ZCMI:
+ $(AFMTODIT) $(EFLAG) $(IFLAG) \
+ `$(AFMNAME) $(afmdir)/ZapfChancery-MediumItalic.afm` $(TEXTMAP) $@
+
+ZD:
+ $(AFMTODIT) -s \
+ `$(AFMNAME) $(afmdir)/ZapfDingbats.afm` $(srcdir)/dingbatsmap $@
+
+SS: $(srcdir)/symbolsl.afm
+ $(AFMTODIT) -s $(IFLAG) $(srcdir)/symbolsl.afm $(srcdir)/lgreekmap $@
+
+S: symbol.afm
+ $(AFMTODIT) -s symbol.afm symbolmap $@
+
+ZDR: zapfdr.afm
+ $(AFMTODIT) -s zapfdr.afm $(srcdir)/dingbatsrmap $@
+
+symbol.afm: $(srcdir)/symbol.sed
+ -rm -f $@
+ sed -f $(srcdir)/symbol.sed `$(AFMNAME) $(afmdir)/Symbol.afm` >$@
+
+zapfdr.afm:
+ -rm -f $@
+ sed -e '/^FontName /s/ZapfDingbats/ZapfDingbats-Reverse/' \
+ `$(AFMNAME) $(afmdir)/ZapfDingbats.afm` >$@
+
+ZD: $(srcdir)/dingbatsmap
+ZDR: $(srcdir)/dingbatsrmap
+$(TEXTFONTS): $(TEXTMAP) $(TEXTENC)
+$(SPECIALFONTS): symbolmap
+$(GREEKFONTS): $(srcdir)/lgreekmap
+$(FONTS): $(DESC)
+
+symbolmap: $(TEXTMAP) $(srcdir)/symbolchars
+ cat $(TEXTMAP) $(srcdir)/symbolchars >$@
+
+clean:
+ -rm -f symbolmap symbol.afm zapfdr.afm
+
+realclean: clean
+ -rm -f $(FONTS)
+
+extraclean: realclean
+ -rm -f core *~ \#*
+
+.PHONY: all clean realclean extraclean
+
diff --git a/font/devps/generate/afmname b/font/devps/generate/afmname
new file mode 100755
index 00000000..8503d46d
--- /dev/null
+++ b/font/devps/generate/afmname
@@ -0,0 +1,44 @@
+#!/bin/sh
+# Fix the path name of an AFM file.
+if test -f "$1"
+then
+ echo "$1"
+else
+ echo `dirname $1`/`basename $1 .afm | awk -e '
+/^AvantGarde-Book$/ { print "avangbk" }
+/^AvantGarde-BookOblique$/ { print "avangbko" }
+/^AvantGarde-Demi$/ { print "avangd" }
+/^AvantGarde-DemiOblique$/ { print "avangdo" }
+/^Bookman-Demi$/ { print "bookmd" }
+/^Bookman-DemiItalic$/ { print "bookmdi" }
+/^Bookman-Light$/ { print "bookml" }
+/^Bookman-LightItalic$/ { print "bookmli" }
+/^Courier$/ { print "couri" }
+/^Courier-Bold$/ { print "courib" }
+/^Courier-BoldOblique$/ { print "couribo" }
+/^Courier-Oblique$/ { print "courio" }
+/^Helvetica$/ { print "helve" }
+/^Helvetica-Bold$/ { print "helveb" }
+/^Helvetica-BoldOblique$/ { print "helvebo" }
+/^Helvetica-Narrow$/ { print "helven" }
+/^Helvetica-Narrow-Bold$/ { print "helvenb" }
+/^Helvetica-Narrow-BoldOblique$/ { print "helvenbo" }
+/^Helvetica-Narrow-Oblique$/ { print "helveno" }
+/^Helvetica-Oblique$/ { print "helveo" }
+/^NewCenturySchlbk-Bold$/ { print "newcsb" }
+/^NewCenturySchlbk-BoldItalic$/ { print "newcsbi" }
+/^NewCenturySchlbk-Italic$/ { print "newcsi" }
+/^NewCenturySchlbk-Roman$/ { print "newcsr" }
+/^Palatino-Bold$/ { print "palatb" }
+/^Palatino-BoldItalic$/ { print "palatbi" }
+/^Palatino-Italic$/ { print "palati" }
+/^Palatino-Roman$/ { print "palatr" }
+/^Symbol$/ { print "symbol" }
+/^Times-Bold$/ { print "timesb" }
+/^Times-BoldItalic$/ { print "timesbi" }
+/^Times-Italic$/ { print "timesi" }
+/^Times-Roman$/ { print "timesr" }
+/^ZapfChancery-MediumItalic$/ { print "zapfcmi" }
+/^ZapfDingbats$/ { print "zapfd" }
+' `.afm
+fi
diff --git a/font/devps/generate/dingbatsmap b/font/devps/generate/dingbatsmap
new file mode 100755
index 00000000..3a97fa99
--- /dev/null
+++ b/font/devps/generate/dingbatsmap
@@ -0,0 +1,2 @@
+a19 OK
+a12 rh
diff --git a/font/devps/generate/dingbatsrmap b/font/devps/generate/dingbatsrmap
new file mode 100755
index 00000000..ccc14cb2
--- /dev/null
+++ b/font/devps/generate/dingbatsrmap
@@ -0,0 +1 @@
+a12 lh
diff --git a/font/devps/generate/lgreekmap b/font/devps/generate/lgreekmap
new file mode 100644
index 00000000..0b0c1978
--- /dev/null
+++ b/font/devps/generate/lgreekmap
@@ -0,0 +1,28 @@
+alpha *a
+beta *b
+chi *x
+delta *d
+epsilon *e
+eta *y
+gamma *g
+iota *i
+kappa *k
+lambda *l
+mu *m
+nu *n
+omega *w
+omega1 +p
+omicron *o
+phi *f
+phi1 +f
+pi *p
+psi *q
+rho *r
+sigma *s
+tau *t
+theta *h
+theta1 +h
+upsilon *u
+xi *c
+zeta *z
+sigma1 ts
diff --git a/font/devps/generate/symbol.sed b/font/devps/generate/symbol.sed
new file mode 100644
index 00000000..b4b02aba
--- /dev/null
+++ b/font/devps/generate/symbol.sed
@@ -0,0 +1,33 @@
+#! /bin/sed -f
+# Tweak the AFM file for the Symbol font.
+/^C .*[ ;]N bracketlefttp[ ;]/bx
+/^C .*[ ;]N bracketleftex[ ;]/bx
+/^C .*[ ;]N bracketleftbt[ ;]/bx
+/^C .*[ ;]N bracketrighttp[ ;]/bx
+/^C .*[ ;]N bracketrightex[ ;]/bx
+/^C .*[ ;]N bracketrightbt[ ;]/bx
+/^C .*[ ;]N bracelefttp[ ;]/bx
+/^C .*[ ;]N braceleftmid[ ;]/bx
+/^C .*[ ;]N braceleftbt[ ;]/bx
+/^C .*[ ;]N bracerighttp[ ;]/bx
+/^C .*[ ;]N bracerightmid[ ;]/bx
+/^C .*[ ;]N bracerightbt[ ;]/bx
+/^C .*[ ;]N braceex[ ;]/bx
+/^C .*[ ;]N parenleftex[ ;]/by
+/^C .*[ ;]N parenrightex[ ;]/by
+/^C .*[ ;]N parenleftbt[ ;]/bz
+/^C .*[ ;]N parenrightbt[ ;]/bz
+/^EndCharMetrics/a\
+italicCorrection integral 67\
+leftItalicCorrection integral 52\
+subscriptCorrection integral -10
+b
+:x
+s/B \([-0-9][0-9]*\) [-0-9][0-9]* \([-0-9][0-9]*\) [-0-9][0-9]*/B \1 -75 \2 925/
+b
+:y
+s/B \([-0-9][0-9]*\) [-0-9][0-9]* \([-0-9][0-9]*\) [-0-9][0-9]*/B \1 -80 \2 920/
+b
+:z
+s/B \([-0-9][0-9]*\) \([-0-9][0-9]*\) \([-0-9][0-9]*\) [-0-9][0-9]*/B \1 \2 \3 920/
+b
diff --git a/font/devps/generate/symbolchars b/font/devps/generate/symbolchars
new file mode 100644
index 00000000..41ec3e46
--- /dev/null
+++ b/font/devps/generate/symbolchars
@@ -0,0 +1,60 @@
+plus pl
+minus mi
+plusminus +-
+equal eq
+divide di
+multiply mu
+arrowup arrowverttp
+arrowdown arrowvertbt
+Alpha *A
+Beta *B
+Chi *X
+Delta *D
+Epsilon *E
+Eta *Y
+Gamma *G
+Iota *I
+Kappa *K
+Lambda *L
+Mu *M
+Nu *N
+Omega *W
+Omicron *O
+Phi *F
+Pi *P
+Psi *Q
+Rho *R
+Sigma *S
+Tau *T
+Theta *H
+Upsilon1 *U
+Xi *C
+Zeta *Z
+alpha *a
+beta *b
+chi *x
+delta *d
+epsilon *e
+eta *y
+gamma *g
+iota *i
+kappa *k
+lambda *l
+mu *m
+nu *n
+omega *w
+omega1 +p
+omicron *o
+phi *f
+phi1 +f
+pi *p
+psi *q
+rho *r
+sigma *s
+sigma1 ts
+tau *t
+theta *h
+theta1 +h
+upsilon *u
+xi *c
+zeta *z
diff --git a/font/devps/generate/symbolsl.afm b/font/devps/generate/symbolsl.afm
new file mode 100644
index 00000000..90939ada
--- /dev/null
+++ b/font/devps/generate/symbolsl.afm
@@ -0,0 +1,203 @@
+StartFontMetrics 2.0
+FontName Symbol-Slanted
+Version 001.001
+FamilyName Symbol
+ItalicAngle -15.5
+IsFixedPitch false
+UnderlineThickness 54
+Weight Medium
+UnderlinePosition -98
+FullName Symbol
+FontBBox -241 -261 1250 899
+StartCharMetrics 189
+C 32 ; WX 223 ; N space ; B 223 0 223 0 ;
+C 33 ; WX 296 ; N exclam ; B 122 -15 383 599 ;
+C 34 ; WX 635 ; N universal ; B 223 0 801 627 ;
+C 35 ; WX 445 ; N numbersign ; B 71 -15 557 599 ;
+C 36 ; WX 489 ; N existential ; B 22 0 622 629 ;
+C 37 ; WX 741 ; N percent ; B 147 -32 766 583 ;
+C 38 ; WX 692 ; N ampersand ; B 68 -16 745 589 ;
+C 39 ; WX 391 ; N suchthat ; B 44 -15 450 444 ;
+C 40 ; WX 296 ; N parenleft ; B 89 -170 449 599 ;
+C 41 ; WX 296 ; N parenright ; B -22 -170 339 600 ;
+C 42 ; WX 445 ; N asteriskmath ; B 126 119 500 490 ;
+C 43 ; WX 489 ; N plus ; B 76 0 562 474 ;
+C 44 ; WX 223 ; N comma ; B 9 -136 183 93 ;
+C 45 ; WX 489 ; N minus ; B 74 207 556 256 ;
+C 46 ; WX 223 ; N period ; B 70 -15 174 85 ;
+C 47 ; WX 247 ; N slash ; B -5 -15 405 575 ;
+C 48 ; WX 445 ; N zero ; B 90 -15 537 610 ;
+C 49 ; WX 445 ; N one ; B 107 0 451 599 ;
+C 50 ; WX 445 ; N two ; B 22 0 524 611 ;
+C 51 ; WX 445 ; N three ; B 56 -16 510 611 ;
+C 52 ; WX 445 ; N four ; B 58 0 530 610 ;
+C 53 ; WX 445 ; N five ; B 36 -15 583 610 ;
+C 54 ; WX 445 ; N six ; B 87 -16 588 610 ;
+C 55 ; WX 445 ; N seven ; B 151 -15 585 599 ;
+C 56 ; WX 445 ; N eight ; B 82 -16 536 611 ;
+C 57 ; WX 445 ; N nine ; B 52 -15 535 609 ;
+C 58 ; WX 247 ; N colon ; B 81 -15 286 409 ;
+C 59 ; WX 247 ; N semicolon ; B 33 -136 296 409 ;
+C 60 ; WX 489 ; N less ; B 87 0 610 464 ;
+C 61 ; WX 489 ; N equal ; B 49 126 586 347 ;
+C 62 ; WX 489 ; N greater ; B 23 0 547 464 ;
+C 63 ; WX 395 ; N question ; B 163 -15 517 610 ;
+C 64 ; WX 489 ; N congruent ; B 10 0 597 423 ;
+C 65 ; WX 643 ; N Alpha ; B 3 0 614 599 ;
+C 66 ; WX 594 ; N Beta ; B 26 0 645 598 ;
+C 67 ; WX 643 ; N Chi ; B -8 0 798 599 ;
+C 68 ; WX 545 ; N Delta ; B 5 0 541 612 ;
+C 69 ; WX 544 ; N Epsilon ; B 28 0 688 599 ;
+C 70 ; WX 679 ; N Phi ; B 105 0 761 598 ;
+C 71 ; WX 537 ; N Gamma ; B 31 0 714 599 ;
+C 72 ; WX 643 ; N Eta ; B 35 0 836 599 ;
+C 73 ; WX 296 ; N Iota ; B 28 0 468 599 ;
+C 74 ; WX 562 ; N theta1 ; B 108 -15 645 614 ;
+C 75 ; WX 643 ; N Kappa ; B 31 0 778 598 ;
+C 76 ; WX 611 ; N Lambda ; B 5 0 610 612 ;
+C 77 ; WX 791 ; N Mu ; B 28 0 974 599 ;
+C 78 ; WX 643 ; N Nu ; B 26 -7 827 599 ;
+C 79 ; WX 643 ; N Omicron ; B 112 -15 747 610 ;
+C 80 ; WX 684 ; N Pi ; B 22 0 847 599 ;
+C 81 ; WX 659 ; N Theta ; B 112 -15 747 610 ;
+C 82 ; WX 495 ; N Rho ; B 25 0 645 599 ;
+C 83 ; WX 527 ; N Sigma ; B 5 0 663 599 ;
+C 84 ; WX 544 ; N Tau ; B 159 0 723 599 ;
+C 85 ; WX 614 ; N Upsilon ; B 175 0 804 599 ;
+C 86 ; WX 391 ; N sigma1 ; B 78 -208 492 445 ;
+C 87 ; WX 684 ; N Omega ; B 30 0 760 612 ;
+C 88 ; WX 574 ; N Xi ; B 36 0 700 598 ;
+C 89 ; WX 708 ; N Psi ; B 188 0 885 608 ;
+C 90 ; WX 544 ; N Zeta ; B 39 0 725 599 ;
+C 91 ; WX 296 ; N bracketleft ; B 34 -138 453 599 ;
+C 92 ; WX 768 ; N therefore ; B 160 0 645 426 ;
+C 93 ; WX 296 ; N bracketright ; B -14 -138 405 599 ;
+C 94 ; WX 586 ; N perpendicular ; B 13 0 596 600 ;
+C 95 ; WX 445 ; N underscore ; B -72 -224 390 -183 ;
+C 96 ; WX 445 ; N radicalex ; B 672 784 1224 816 ;
+C 97 ; WX 562 ; N alpha ; B 84 -15 658 445 ;
+C 98 ; WX 489 ; N beta ; B -7 -198 578 659 ;
+C 99 ; WX 489 ; N chi ; B -48 -206 573 445 ;
+C 100 ; WX 440 ; N delta ; B 83 -16 571 658 ;
+C 101 ; WX 391 ; N epsilon ; B 49 -17 468 447 ;
+C 102 ; WX 464 ; N phi ; B 78 -200 517 596 ;
+C 103 ; WX 366 ; N gamma ; B 92 -200 568 444 ;
+C 104 ; WX 537 ; N eta ; B 100 -180 555 457 ;
+C 105 ; WX 293 ; N iota ; B 97 -16 296 448 ;
+C 106 ; WX 537 ; N phi1 ; B 92 -199 604 444 ;
+C 107 ; WX 489 ; N kappa ; B 106 0 621 447 ;
+C 108 ; WX 489 ; N lambda ; B 21 -16 530 658 ;
+C 109 ; WX 513 ; N mu ; B -18 -198 533 445 ;
+C 110 ; WX 464 ; N nu ; B 119 -15 548 451 ;
+C 111 ; WX 489 ; N omicron ; B 86 -17 526 444 ;
+C 112 ; WX 489 ; N pi ; B 58 -18 599 433 ;
+C 113 ; WX 464 ; N theta ; B 103 -16 554 614 ;
+C 114 ; WX 489 ; N rho ; B -19 -205 521 444 ;
+C 115 ; WX 537 ; N sigma ; B 87 -19 662 445 ;
+C 116 ; WX 391 ; N tau ; B 95 -16 511 445 ;
+C 117 ; WX 513 ; N upsilon ; B 105 -15 558 451 ;
+C 118 ; WX 635 ; N omega1 ; B 78 -15 758 519 ;
+C 119 ; WX 611 ; N omega ; B 85 -16 687 445 ;
+C 120 ; WX 439 ; N xi ; B 70 -200 515 681 ;
+C 121 ; WX 611 ; N psi ; B 141 -203 759 445 ;
+C 122 ; WX 440 ; N zeta ; B 100 -200 580 673 ;
+C 123 ; WX 427 ; N braceleft ; B 116 -163 540 599 ;
+C 124 ; WX 178 ; N bar ; B 9 -158 307 599 ;
+C 125 ; WX 427 ; N braceright ; B 19 -163 444 599 ;
+C 126 ; WX 489 ; N similar ; B 78 181 549 273 ;
+C 161 ; WX 552 ; N Upsilon1 ; B 134 0 710 609 ;
+C 162 ; WX 220 ; N minute ; B 156 408 393 654 ;
+C 163 ; WX 489 ; N lessequal ; B 26 0 645 569 ;
+C 164 ; WX 149 ; N fraction ; B -164 -11 490 603 ;
+C 165 ; WX 635 ; N infinity ; B 91 111 692 360 ;
+C 166 ; WX 445 ; N florin ; B -36 -172 614 612 ;
+C 167 ; WX 670 ; N club ; B 119 -23 645 474 ;
+C 168 ; WX 670 ; N diamond ; B 198 -32 605 490 ;
+C 169 ; WX 670 ; N heart ; B 205 -29 679 473 ;
+C 170 ; WX 670 ; N spade ; B 132 -32 604 488 ;
+C 171 ; WX 927 ; N arrowboth ; B 90 -13 980 455 ;
+C 172 ; WX 878 ; N arrowleft ; B 97 -13 915 455 ;
+C 173 ; WX 537 ; N arrowup ; B 223 0 691 810 ;
+C 174 ; WX 878 ; N arrowright ; B 105 -13 922 455 ;
+C 175 ; WX 537 ; N arrowdown ; B 104 -20 572 790 ;
+C 176 ; WX 356 ; N degree ; B 187 343 466 609 ;
+C 177 ; WX 489 ; N plusminus ; B 9 0 593 574 ;
+C 178 ; WX 366 ; N second ; B 150 408 560 656 ;
+C 179 ; WX 489 ; N greaterequal ; B 26 0 582 569 ;
+C 180 ; WX 489 ; N multiply ; B 28 7 609 466 ;
+C 181 ; WX 635 ; N proportional ; B 90 110 667 360 ;
+C 182 ; WX 440 ; N partialdiff ; B 62 -18 542 664 ;
+C 183 ; WX 409 ; N bullet ; B 118 101 454 421 ;
+C 184 ; WX 489 ; N divide ; B 74 63 558 406 ;
+C 185 ; WX 489 ; N notequal ; B 51 -22 587 489 ;
+C 186 ; WX 489 ; N equivalence ; B 35 73 602 394 ;
+C 187 ; WX 489 ; N approxequal ; B 57 120 572 351 ;
+C 188 ; WX 890 ; N ellipsis ; B 107 -15 804 85 ;
+C 189 ; WX 537 ; N arrowvertex ; B 216 -107 579 899 ;
+C 190 ; WX 890 ; N arrowhorizex ; B 8 196 1011 246 ;
+C 191 ; WX 586 ; N carriagereturn ; B 40 -14 710 560 ;
+C 192 ; WX 732 ; N aleph ; B 159 -16 740 586 ;
+C 193 ; WX 611 ; N Ifraktur ; B 26 -47 684 659 ;
+C 194 ; WX 708 ; N Rfraktur ; B 71 -13 833 653 ;
+C 195 ; WX 878 ; N weierstrass ; B 112 -188 878 510 ;
+C 196 ; WX 684 ; N circlemultiply ; B 114 -15 758 599 ;
+C 197 ; WX 684 ; N circleplus ; B 115 -13 759 601 ;
+C 198 ; WX 732 ; N emptyset ; B 38 -21 884 640 ;
+C 199 ; WX 684 ; N intersection ; B 36 0 714 453 ;
+C 200 ; WX 684 ; N union ; B 110 -15 788 438 ;
+C 201 ; WX 635 ; N propersuperset ; B 18 0 675 418 ;
+C 202 ; WX 635 ; N reflexsuperset ; B -17 -111 674 418 ;
+C 203 ; WX 635 ; N notsubset ; B 87 -62 744 481 ;
+C 204 ; WX 635 ; N propersubset ; B 87 0 744 418 ;
+C 205 ; WX 635 ; N reflexsubset ; B 16 -111 744 418 ;
+C 206 ; WX 635 ; N element ; B 93 0 579 417 ;
+C 207 ; WX 635 ; N notelement ; B 74 -52 579 494 ;
+C 208 ; WX 684 ; N angle ; B 23 0 833 599 ;
+C 209 ; WX 635 ; N gradient ; B 231 -17 805 639 ;
+C 210 ; WX 703 ; N registerserif ; B 120 -18 763 596 ;
+C 211 ; WX 703 ; N copyrightserif ; B 122 -13 766 601 ;
+C 212 ; WX 792 ; N trademarkserif ; B 169 261 947 599 ;
+C 213 ; WX 732 ; N product ; B -6 -90 920 668 ;
+C 214 ; WX 489 ; N radical ; B 134 -34 711 816 ;
+C 215 ; WX 223 ; N dotmath ; B 131 187 225 276 ;
+C 216 ; WX 635 ; N logicalnot ; B 78 0 685 256 ;
+C 217 ; WX 537 ; N logicaland ; B 21 0 519 404 ;
+C 218 ; WX 537 ; N logicalor ; B 151 0 639 424 ;
+C 219 ; WX 927 ; N arrowdblboth ; B 92 -18 978 454 ;
+C 220 ; WX 878 ; N arrowdblleft ; B 96 -13 942 457 ;
+C 221 ; WX 537 ; N arrowdblup ; B 152 2 688 811 ;
+C 222 ; WX 878 ; N arrowdblright ; B 71 -18 917 452 ;
+C 223 ; WX 537 ; N arrowdbldown ; B 103 -17 639 792 ;
+C 224 ; WX 440 ; N lozenge ; B 121 0 519 663 ;
+C 225 ; WX 293 ; N angleleft ; B 98 -176 472 664 ;
+C 226 ; WX 703 ; N registersans ; B 120 -18 763 596 ;
+C 227 ; WX 703 ; N copyrightsans ; B 120 -13 764 601 ;
+C 228 ; WX 700 ; N trademarksans ; B 179 261 832 599 ;
+C 229 ; WX 635 ; N summation ; B -15 -96 756 669 ;
+C 230 ; WX 342 ; N parenlefttp ; B -46 -261 642 824 ;
+C 231 ; WX 342 ; N parenleftex ; B 12 -76 338 823 ;
+C 232 ; WX 342 ; N parenleftbt ; B 113 -261 339 824 ;
+C 233 ; WX 342 ; N bracketlefttp ; B -22 -71 560 824 ;
+C 234 ; WX 342 ; N bracketleftex ; B -22 -70 305 823 ;
+C 235 ; WX 342 ; N bracketleftbt ; B -22 -71 306 824 ;
+C 236 ; WX 440 ; N bracelefttp ; B 158 -67 648 824 ;
+C 237 ; WX 440 ; N braceleftmid ; B 126 -76 486 832 ;
+C 238 ; WX 440 ; N braceleftbt ; B 219 -62 484 824 ;
+C 239 ; WX 440 ; N braceex ; B 157 -71 486 832 ;
+C 241 ; WX 293 ; N angleright ; B -29 -176 345 664 ;
+C 242 ; WX 244 ; N integral ; B -13 -95 499 815 ;
+C 243 ; WX 611 ; N integraltp ; B 272 -74 873 820 ;
+C 244 ; WX 611 ; N integralex ; B 271 -78 640 868 ;
+C 245 ; WX 611 ; N integralbt ; B 30 -72 625 820 ;
+C 246 ; WX 342 ; N parenrighttp ; B 273 -261 498 824 ;
+C 247 ; WX 342 ; N parenrightex ; B 331 -76 657 823 ;
+C 248 ; WX 342 ; N parenrightbt ; B -30 -261 657 824 ;
+C 249 ; WX 342 ; N bracketrighttp ; B 249 -71 577 824 ;
+C 250 ; WX 342 ; N bracketrightex ; B 250 -70 577 823 ;
+C 251 ; WX 342 ; N bracketrightbt ; B -4 -71 577 824 ;
+C 252 ; WX 440 ; N bracerighttp ; B 158 -67 425 824 ;
+C 253 ; WX 440 ; N bracerightmid ; B 155 -76 517 832 ;
+C 254 ; WX 440 ; N bracerightbt ; B -4 -62 484 824 ;
+C -1 ; WX 703 ; N apple ; B 136 -2 784 719 ;
+EndCharMetrics
+EndFontMetrics
diff --git a/font/devps/generate/textmap b/font/devps/generate/textmap
new file mode 100644
index 00000000..bcf3ad7b
--- /dev/null
+++ b/font/devps/generate/textmap
@@ -0,0 +1,450 @@
+a a
+b b
+c c
+d d
+e e
+f f
+g g
+h h
+i i
+j j
+k k
+l l
+m m
+n n
+o o
+p p
+q q
+r r
+s s
+t t
+u u
+v v
+w w
+x x
+y y
+z z
+A A
+B B
+C C
+D D
+E E
+F F
+G G
+H H
+I I
+J J
+K K
+L L
+M M
+N N
+O O
+P P
+Q Q
+R R
+S S
+T T
+U U
+V V
+W W
+X X
+Y Y
+Z Z
+AE AE
+Aacute 'A
+Acircumflex ^A
+Adieresis :A
+Agrave `A
+Aring oA
+Atilde ~A
+Cacute 'C
+Ccedilla ,C
+Eacute 'E
+Ecircumflex ^E
+Edieresis :E
+Egrave `E
+Eth -D
+IJ IJ
+Iacute 'I
+Icircumflex ^I
+Idieresis :I
+Ifraktur Im
+Igrave `I
+Lslash /L
+Ntilde ~N
+OE OE
+Oacute 'O
+Ocircumflex ^O
+Odieresis :O
+Ograve `O
+Oslash /O
+Otilde ~O
+Rfraktur Re
+Scaron vS
+Thorn TP
+Uacute 'U
+Ucircumflex ^U
+Udieresis :U
+Ugrave `U
+Yacute 'Y
+Ydieresis :Y
+Zcaron vZ
+aacute 'a
+acircumflex ^a
+acute aa
+adieresis :a
+ae ae
+agrave `a
+angle /_
+angleleft la
+angleright ra
+aleph Ah
+ampersand &
+approxequal ~~
+aring oa
+arrowboth <>
+arrowdblboth hA
+arrowdbldown dA
+arrowdblleft lA
+arrowdblright rA
+arrowdblup uA
+arrowdown da
+arrowleft <-
+arrowright ->
+arrowup ua
+asciicircum ha
+asciitilde ti
+asterisk *
+asteriskmath **
+at @
+at at
+atilde ~a
+backslash \
+backslash rs
+bar ba
+bar |
+bell bs
+braceleft lC
+braceleft {
+braceright rC
+braceright }
+bracketleft [
+bracketleft lB
+bracketright ]
+bracketright rB
+breve ab
+brokenbar bb
+bullet bu
+cacute 'c
+caron ah
+ccedilla ,c
+cedilla ac
+cent ct
+checkmark OK
+circle ci
+circlemultiply c*
+circleplus c+
+circumflex a^
+circumflex ^
+colon :
+comma ,
+congruent =~
+copyright co
+currency Cs
+dagger dg
+daggerdbl dd
+degree de
+dieresis ad
+dollar $
+dollar Do
+dotaccent a.
+dotlessi .i
+dotlessj .j
+dotmath md
+eacute 'e
+ecircumflex ^e
+edieresis :e
+egrave `e
+eight 8
+element mo
+emdash em
+emptyset es
+endash en
+equal =
+equalmath eq
+equivalence ==
+eth Sd
+exclam !
+exclamdown r!
+existential te
+ff ff
+ffi Fi
+ffl Fl
+fi fi
+five 5
+fl fl
+florin Fn
+four 4
+germandbls ss
+gradient gr
+grave ga
+greater >
+greaterequal >=
+guillemotleft Fo
+guillemotright Fc
+guilsinglleft fo
+guilsinglright fc
+handleft lh
+handright rh
+hbar -h
+hungarumlaut a"
+hyphen -
+hyphen hy
+iacute 'i
+icircumflex ^i
+idieresis :i
+igrave `i
+ij ij
+infinity if
+integral is
+intersection ca
+less <
+lessequal <=
+logicaland AN
+logicalnot no
+logicalor OR
+lozenge lz
+lslash /l
+macron a-
+minus \-
+minusplus -+
+minute fm
+nine 9
+notelement nm
+notequal !=
+notequivalence ne
+notpropersuperset nc
+notsubset nb
+ntilde ~n
+numbersign #
+numbersign sh
+oacute 'o
+ocircumflex ^o
+odieresis :o
+oe oe
+ogonek ho
+ograve `o
+one 1
+onehalf 12
+onequarter 14
+onesuperior S1
+ordfeminine Of
+ordmasculine Om
+oslash /o
+otilde ~o
+paragraph ps
+parenleft (
+parenright )
+partialdiff pd
+percent %
+period .
+perthousand %0
+perpendicular pp
+plus +
+plusmath pl
+propersubset sb
+propersuperset sp
+proportional pt
+question ?
+questiondown r?
+quotedbl "
+quotedblbase Bq
+quotedblleft lq
+quotedblright rq
+quoteleft `
+quoteleft oq
+quoteright '
+quotesingle aq
+quotesinglbase bq
+reflexsubset ib
+reflexsuperset ip
+registered rg
+ring ao
+scaron vs
+second sd
+section sc
+semicolon ;
+seven 7
+similar ap
+similarequal ~=
+six 6
+slash /
+slash sl
+square sq
+sterling Po
+therefore 3d
+therefore tf
+thorn Tp
+three 3
+threequarters 34
+threesuperior S3
+tilde a~
+tilde ~
+trademark tm
+two 2
+twosuperior S2
+uacute 'u
+ucircumflex ^u
+udieresis :u
+ugrave `u
+underscore _
+union cu
+universal fa
+weierstrass wp
+yacute 'y
+ydieresis :y
+yen Ye
+zcaron vz
+zero 0
+exclamdown char161
+cent char162
+sterling char163
+currency char164
+yen char165
+brokenbar char166
+section char167
+dieresis char168
+copyright char169
+ordfeminine char170
+guillemotleft char171
+logicalnot char172
+hyphen char173
+registered char174
+macron char175
+degree char176
+plusminus char177
+twosuperior char178
+threesuperior char179
+acute char180
+mu char181
+paragraph char182
+periodcentered char183
+cedilla char184
+onesuperior char185
+ordmasculine char186
+guillemotright char187
+onequarter char188
+onehalf char189
+threequarters char190
+questiondown char191
+Agrave char192
+Aacute char193
+Acircumflex char194
+Atilde char195
+Adieresis char196
+Aring char197
+AE char198
+Ccedilla char199
+Egrave char200
+Eacute char201
+Ecircumflex char202
+Edieresis char203
+Igrave char204
+Iacute char205
+Icircumflex char206
+Idieresis char207
+Eth char208
+Ntilde char209
+Ograve char210
+Oacute char211
+Ocircumflex char212
+Otilde char213
+Odieresis char214
+multiply char215
+Oslash char216
+Ugrave char217
+Uacute char218
+Ucircumflex char219
+Udieresis char220
+Yacute char221
+Thorn char222
+germandbls char223
+agrave char224
+aacute char225
+acircumflex char226
+atilde char227
+adieresis char228
+aring char229
+ae char230
+ccedilla char231
+egrave char232
+eacute char233
+ecircumflex char234
+edieresis char235
+igrave char236
+iacute char237
+icircumflex char238
+idieresis char239
+eth char240
+ntilde char241
+ograve char242
+oacute char243
+ocircumflex char244
+otilde char245
+odieresis char246
+divide char247
+oslash char248
+ugrave char249
+uacute char250
+ucircumflex char251
+udieresis char252
+yacute char253
+thorn char254
+ydieresis char255
+fraction f/
+club CL
+diamond DI
+heart HE
+spade SP
+carriagereturn CR
+suchthat st
+bracelefttp bracelefttp
+braceleftmid braceleftmid
+braceleftbt braceleftbt
+braceex braceex
+braceex bracerightex
+braceex braceleftex
+braceex barex
+bracerighttp bracerighttp
+bracerightmid bracerightmid
+bracerightbt bracerightbt
+parenlefttp parenlefttp
+parenleftbt parenleftbt
+parenleftex parenleftex
+parenrighttp parenrighttp
+parenrightbt parenrightbt
+parenrightex parenrightex
+bracketlefttp bracketlefttp
+bracketleftbt bracketleftbt
+bracketleftex bracketleftex
+bracketrighttp bracketrighttp
+bracketrightbt bracketrightbt
+bracketrightex bracketrightex
+radical sr
+radicalex radicalex
+approxequal ~=
+bracketlefttp lc
+bracketleftbt lf
+bracketrighttp rc
+bracketrightbt rf
+bracelefttp lt
+braceleftmid lk
+braceleftbt lb
+braceex bv
+bracerighttp rt
+bracerightmid rk
+bracerightbt rb
+summation sum
+product product
+arrowvertex arrowvertex
+arrowhorizex an
diff --git a/font/devps/prologue.ps b/font/devps/prologue.ps
new file mode 100644
index 00000000..b7bad1c5
--- /dev/null
+++ b/font/devps/prologue.ps
@@ -0,0 +1,228 @@
+%!PS-Adobe-3.0 Resource-ProcSet
+
+/setpacking where {
+ pop
+ currentpacking
+ true setpacking
+} if
+
+/grops 120 dict dup begin
+
+% The ASCII code of the space character.
+/SC 32 def
+
+/A /show load def
+/B { 0 SC 3 -1 roll widthshow } bind def
+/C { 0 exch ashow } bind def
+/D { 0 exch 0 SC 5 2 roll awidthshow } bind def
+/E { 0 rmoveto show } bind def
+/F { 0 rmoveto 0 SC 3 -1 roll widthshow } bind def
+/G { 0 rmoveto 0 exch ashow } bind def
+/H { 0 rmoveto 0 exch 0 SC 5 2 roll awidthshow } bind def
+/I { 0 exch rmoveto show } bind def
+/J { 0 exch rmoveto 0 SC 3 -1 roll widthshow } bind def
+/K { 0 exch rmoveto 0 exch ashow } bind def
+/L { 0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow } bind def
+/M { rmoveto show } bind def
+/N { rmoveto 0 SC 3 -1 roll widthshow } bind def
+/O { rmoveto 0 exch ashow } bind def
+/P { rmoveto 0 exch 0 SC 5 2 roll awidthshow } bind def
+/Q { moveto show } bind def
+/R { moveto 0 SC 3 -1 roll widthshow } bind def
+/S { moveto 0 exch ashow } bind def
+/T { moveto 0 exch 0 SC 5 2 roll awidthshow } bind def
+
+% name size font SF -
+
+/SF {
+ findfont exch
+ [ exch dup 0 exch 0 exch neg 0 0 ] makefont
+ dup setfont
+ [ exch /setfont cvx ] cvx bind def
+} bind def
+
+% name a c d font MF -
+
+/MF {
+ findfont
+ [ 5 2 roll
+ 0 3 1 roll % b
+ neg 0 0 ] makefont
+ dup setfont
+ [ exch /setfont cvx ] cvx bind def
+} bind def
+
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+
+% Enable manual feed.
+% MANUAL -
+
+/MANUAL {
+ statusdict begin /manualfeed true store end
+} bind def
+
+% Guess the page length.
+% This assumes that the imageable area is vertically centered on the page.
+% PLG - length
+
+/PLG {
+ gsave newpath clippath pathbbox grestore
+ exch pop add exch pop
+} bind def
+
+% BP -
+
+/BP {
+ /level0 save def
+ 1 setlinecap
+ 1 setlinejoin
+ 72 RES div dup scale
+ LS {
+ 90 rotate
+ } {
+ 0 PL translate
+ } ifelse
+ 1 -1 scale
+} bind def
+
+/EP {
+ level0 restore
+ showpage
+} bind def
+
+
+% centerx centery radius startangle endangle DA -
+
+/DA {
+ newpath arcn stroke
+} bind def
+
+% x y SN - x' y'
+% round a position to nearest (pixel + (.25,.25))
+
+/SN {
+ transform
+ .25 sub exch .25 sub exch
+ round .25 add exch round .25 add exch
+ itransform
+} bind def
+
+% endx endy startx starty DL -
+% we round the endpoints of the line, so that parallel horizontal
+% and vertical lines will appear even
+
+/DL {
+ SN
+ moveto
+ SN
+ lineto stroke
+} bind def
+
+% centerx centery radius DC -
+
+/DC {
+ newpath 0 360 arc closepath
+} bind def
+
+
+/TM matrix def
+
+% width height centerx centery DE -
+
+/DE {
+ TM currentmatrix pop
+ translate scale newpath 0 0 .5 0 360 arc closepath
+ TM setmatrix
+} bind def
+
+% these are for splines
+
+/RC /rcurveto load def
+/RL /rlineto load def
+/ST /stroke load def
+/MT /moveto load def
+/CL /closepath load def
+
+% fill the last path
+
+% amount FL -
+
+/FL {
+ currentgray exch setgray fill setgray
+} bind def
+
+% fill with the ``current color''
+
+/BL /fill load def
+
+/LW /setlinewidth load def
+% new_font_name encoding_vector old_font_name RE -
+
+/RE {
+ findfont
+ dup maxlength 1 index /FontName known not { 1 add } if dict begin
+ {
+ 1 index /FID ne { def } { pop pop } ifelse
+ } forall
+ /Encoding exch def
+ dup /FontName exch def
+ currentdict end definefont pop
+} bind def
+
+/DEFS 0 def
+
+% hpos vpos EBEGIN -
+
+/EBEGIN {
+ moveto
+ DEFS begin
+} bind def
+
+/EEND /end load def
+
+/CNT 0 def
+/level1 0 def
+
+% llx lly newwid wid newht ht newllx newlly PBEGIN -
+
+/PBEGIN {
+ /level1 save def
+ translate
+ div 3 1 roll div exch scale
+ neg exch neg exch translate
+ % set the graphics state to default values
+ 0 setgray
+ 0 setlinecap
+ 1 setlinewidth
+ 0 setlinejoin
+ 10 setmiterlimit
+ [] 0 setdash
+ /setstrokeadjust where {
+ pop
+ false setstrokeadjust
+ } if
+ /setoverprint where {
+ pop
+ false setoverprint
+ } if
+ newpath
+ /CNT countdictstack def
+ userdict begin
+ /showpage {} def
+} bind def
+
+/PEND {
+ clear
+ countdictstack CNT sub { end } repeat
+ level1 restore
+} bind def
+
+end def
+
+/setpacking where {
+ pop
+ setpacking
+} if
diff --git a/font/devps/psstrip.sed b/font/devps/psstrip.sed
new file mode 100644
index 00000000..3e61775a
--- /dev/null
+++ b/font/devps/psstrip.sed
@@ -0,0 +1,7 @@
+/^%[%!]/b
+s/%.*//
+s/^[ ][ ]*//
+s/[ ][ ]*$//
+/^$/d
+s|[ ]*\([][}{/]\)|\1|g
+s|\([][}{/]\)[ ]*|\1|g
diff --git a/font/devps/symbol.afm b/font/devps/symbol.afm
new file mode 100644
index 00000000..eccf6c2a
--- /dev/null
+++ b/font/devps/symbol.afm
@@ -0,0 +1,215 @@
+(c) 1987, 1988, 1989, 1990, 1991 Adobe Systems Incorporated.
+All rights reserved.
+
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All rights reserved.
+Comment Creation Date: Wed Jan 17 21:48:26 1990
+Comment UniqueID 27004
+Comment VMusage 28489 37622
+FontName Symbol
+FullName Symbol
+FamilyName Symbol
+Weight Medium
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -180 -293 1090 1010
+UnderlinePosition -98
+UnderlineThickness 54
+Version 001.007
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All rights reserved.
+EncodingScheme FontSpecific
+StartCharMetrics 189
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 128 -17 240 672 ;
+C 34 ; WX 713 ; N universal ; B 31 0 681 705 ;
+C 35 ; WX 500 ; N numbersign ; B 20 -16 481 673 ;
+C 36 ; WX 549 ; N existential ; B 25 0 478 707 ;
+C 37 ; WX 833 ; N percent ; B 63 -36 771 655 ;
+C 38 ; WX 778 ; N ampersand ; B 41 -18 750 661 ;
+C 39 ; WX 439 ; N suchthat ; B 48 -17 414 500 ;
+C 40 ; WX 333 ; N parenleft ; B 53 -191 300 673 ;
+C 41 ; WX 333 ; N parenright ; B 30 -191 277 673 ;
+C 42 ; WX 500 ; N asteriskmath ; B 65 134 427 551 ;
+C 43 ; WX 549 ; N plus ; B 10 0 539 533 ;
+C 44 ; WX 250 ; N comma ; B 56 -152 194 104 ;
+C 45 ; WX 549 ; N minus ; B 11 233 535 288 ;
+C 46 ; WX 250 ; N period ; B 69 -17 181 95 ;
+C 47 ; WX 278 ; N slash ; B 0 -18 254 646 ;
+C 48 ; WX 500 ; N zero ; B 23 -17 471 685 ;
+C 49 ; WX 500 ; N one ; B 117 0 390 673 ;
+C 50 ; WX 500 ; N two ; B 25 0 475 686 ;
+C 51 ; WX 500 ; N three ; B 39 -17 435 685 ;
+C 52 ; WX 500 ; N four ; B 16 0 469 685 ;
+C 53 ; WX 500 ; N five ; B 29 -17 443 685 ;
+C 54 ; WX 500 ; N six ; B 36 -17 467 685 ;
+C 55 ; WX 500 ; N seven ; B 24 -16 448 673 ;
+C 56 ; WX 500 ; N eight ; B 54 -18 440 685 ;
+C 57 ; WX 500 ; N nine ; B 31 -18 460 685 ;
+C 58 ; WX 278 ; N colon ; B 81 -17 193 460 ;
+C 59 ; WX 278 ; N semicolon ; B 83 -152 221 460 ;
+C 60 ; WX 549 ; N less ; B 26 0 523 522 ;
+C 61 ; WX 549 ; N equal ; B 11 141 537 390 ;
+C 62 ; WX 549 ; N greater ; B 26 0 523 522 ;
+C 63 ; WX 444 ; N question ; B 70 -17 412 686 ;
+C 64 ; WX 549 ; N congruent ; B 11 0 537 475 ;
+C 65 ; WX 722 ; N Alpha ; B 4 0 684 673 ;
+C 66 ; WX 667 ; N Beta ; B 29 0 592 673 ;
+C 67 ; WX 722 ; N Chi ; B -9 0 704 673 ;
+C 68 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C 69 ; WX 611 ; N Epsilon ; B 32 0 617 673 ;
+C 70 ; WX 763 ; N Phi ; B 26 0 741 673 ;
+C 71 ; WX 603 ; N Gamma ; B 24 0 609 673 ;
+C 72 ; WX 722 ; N Eta ; B 39 0 729 673 ;
+C 73 ; WX 333 ; N Iota ; B 32 0 316 673 ;
+C 74 ; WX 631 ; N theta1 ; B 18 -18 623 689 ;
+C 75 ; WX 722 ; N Kappa ; B 35 0 722 673 ;
+C 76 ; WX 686 ; N Lambda ; B 6 0 680 688 ;
+C 77 ; WX 889 ; N Mu ; B 28 0 887 673 ;
+C 78 ; WX 722 ; N Nu ; B 29 -8 720 673 ;
+C 79 ; WX 722 ; N Omicron ; B 41 -17 715 685 ;
+C 80 ; WX 768 ; N Pi ; B 25 0 745 673 ;
+C 81 ; WX 741 ; N Theta ; B 41 -17 715 685 ;
+C 82 ; WX 556 ; N Rho ; B 28 0 563 673 ;
+C 83 ; WX 592 ; N Sigma ; B 5 0 589 673 ;
+C 84 ; WX 611 ; N Tau ; B 33 0 607 673 ;
+C 85 ; WX 690 ; N Upsilon ; B -8 0 694 673 ;
+C 86 ; WX 439 ; N sigma1 ; B 40 -233 436 500 ;
+C 87 ; WX 768 ; N Omega ; B 34 0 736 688 ;
+C 88 ; WX 645 ; N Xi ; B 40 0 599 673 ;
+C 89 ; WX 795 ; N Psi ; B 15 0 781 684 ;
+C 90 ; WX 611 ; N Zeta ; B 44 0 636 673 ;
+C 91 ; WX 333 ; N bracketleft ; B 86 -155 299 674 ;
+C 92 ; WX 863 ; N therefore ; B 163 0 701 478 ;
+C 93 ; WX 333 ; N bracketright ; B 33 -155 246 674 ;
+C 94 ; WX 658 ; N perpendicular ; B 15 0 652 674 ;
+C 95 ; WX 500 ; N underscore ; B -2 -252 502 -206 ;
+C 96 ; WX 500 ; N radicalex ; B 480 881 1090 917 ;
+C 97 ; WX 631 ; N alpha ; B 41 -18 622 500 ;
+C 98 ; WX 549 ; N beta ; B 61 -223 515 741 ;
+C 99 ; WX 549 ; N chi ; B 12 -231 522 499 ;
+C 100 ; WX 494 ; N delta ; B 40 -19 481 740 ;
+C 101 ; WX 439 ; N epsilon ; B 22 -19 427 502 ;
+C 102 ; WX 521 ; N phi ; B 27 -224 490 671 ;
+C 103 ; WX 411 ; N gamma ; B 5 -225 484 499 ;
+C 104 ; WX 603 ; N eta ; B 0 -202 527 514 ;
+C 105 ; WX 329 ; N iota ; B 0 -17 301 503 ;
+C 106 ; WX 603 ; N phi1 ; B 36 -224 587 499 ;
+C 107 ; WX 549 ; N kappa ; B 33 0 558 501 ;
+C 108 ; WX 549 ; N lambda ; B 24 -17 548 739 ;
+C 109 ; WX 576 ; N mu ; B 33 -223 567 500 ;
+C 110 ; WX 521 ; N nu ; B -9 -16 475 507 ;
+C 111 ; WX 549 ; N omicron ; B 35 -19 501 499 ;
+C 112 ; WX 549 ; N pi ; B 10 -19 530 487 ;
+C 113 ; WX 521 ; N theta ; B 43 -17 485 690 ;
+C 114 ; WX 549 ; N rho ; B 50 -230 490 499 ;
+C 115 ; WX 603 ; N sigma ; B 30 -21 588 500 ;
+C 116 ; WX 439 ; N tau ; B 10 -19 418 500 ;
+C 117 ; WX 576 ; N upsilon ; B 7 -18 535 507 ;
+C 118 ; WX 713 ; N omega1 ; B 12 -18 671 583 ;
+C 119 ; WX 686 ; N omega ; B 42 -17 684 500 ;
+C 120 ; WX 493 ; N xi ; B 27 -224 469 766 ;
+C 121 ; WX 686 ; N psi ; B 12 -228 701 500 ;
+C 122 ; WX 494 ; N zeta ; B 60 -225 467 756 ;
+C 123 ; WX 480 ; N braceleft ; B 58 -183 397 673 ;
+C 124 ; WX 200 ; N bar ; B 65 -177 135 673 ;
+C 125 ; WX 480 ; N braceright ; B 79 -183 418 673 ;
+C 126 ; WX 549 ; N similar ; B 17 203 529 307 ;
+C 161 ; WX 620 ; N Upsilon1 ; B -2 0 610 685 ;
+C 162 ; WX 247 ; N minute ; B 27 459 228 735 ;
+C 163 ; WX 549 ; N lessequal ; B 29 0 526 639 ;
+C 164 ; WX 167 ; N fraction ; B -180 -12 340 677 ;
+C 165 ; WX 713 ; N infinity ; B 26 124 688 404 ;
+C 166 ; WX 500 ; N florin ; B 2 -193 494 686 ;
+C 167 ; WX 753 ; N club ; B 86 -26 660 533 ;
+C 168 ; WX 753 ; N diamond ; B 142 -36 600 550 ;
+C 169 ; WX 753 ; N heart ; B 117 -33 631 532 ;
+C 170 ; WX 753 ; N spade ; B 113 -36 629 548 ;
+C 171 ; WX 1042 ; N arrowboth ; B 24 -15 1024 511 ;
+C 172 ; WX 987 ; N arrowleft ; B 32 -15 942 511 ;
+C 173 ; WX 603 ; N arrowup ; B 45 0 571 910 ;
+C 174 ; WX 987 ; N arrowright ; B 49 -15 959 511 ;
+C 175 ; WX 603 ; N arrowdown ; B 45 -22 571 888 ;
+C 176 ; WX 400 ; N degree ; B 50 385 350 685 ;
+C 177 ; WX 549 ; N plusminus ; B 10 0 539 645 ;
+C 178 ; WX 411 ; N second ; B 20 459 413 737 ;
+C 179 ; WX 549 ; N greaterequal ; B 29 0 526 639 ;
+C 180 ; WX 549 ; N multiply ; B 17 8 533 524 ;
+C 181 ; WX 713 ; N proportional ; B 27 123 639 404 ;
+C 182 ; WX 494 ; N partialdiff ; B 26 -20 462 746 ;
+C 183 ; WX 460 ; N bullet ; B 50 113 410 473 ;
+C 184 ; WX 549 ; N divide ; B 10 71 536 456 ;
+C 185 ; WX 549 ; N notequal ; B 15 -25 540 549 ;
+C 186 ; WX 549 ; N equivalence ; B 14 82 538 443 ;
+C 187 ; WX 549 ; N approxequal ; B 14 135 527 394 ;
+C 188 ; WX 1000 ; N ellipsis ; B 111 -17 889 95 ;
+C 189 ; WX 603 ; N arrowvertex ; B 280 -120 336 1010 ;
+C 190 ; WX 1000 ; N arrowhorizex ; B -60 220 1050 276 ;
+C 191 ; WX 658 ; N carriagereturn ; B 15 -16 602 629 ;
+C 192 ; WX 823 ; N aleph ; B 175 -18 661 658 ;
+C 193 ; WX 686 ; N Ifraktur ; B 10 -53 578 740 ;
+C 194 ; WX 795 ; N Rfraktur ; B 26 -15 759 734 ;
+C 195 ; WX 987 ; N weierstrass ; B 159 -211 870 573 ;
+C 196 ; WX 768 ; N circlemultiply ; B 43 -17 733 673 ;
+C 197 ; WX 768 ; N circleplus ; B 43 -15 733 675 ;
+C 198 ; WX 823 ; N emptyset ; B 39 -24 781 719 ;
+C 199 ; WX 768 ; N intersection ; B 40 0 732 509 ;
+C 200 ; WX 768 ; N union ; B 40 -17 732 492 ;
+C 201 ; WX 713 ; N propersuperset ; B 20 0 673 470 ;
+C 202 ; WX 713 ; N reflexsuperset ; B 20 -125 673 470 ;
+C 203 ; WX 713 ; N notsubset ; B 36 -70 690 540 ;
+C 204 ; WX 713 ; N propersubset ; B 37 0 690 470 ;
+C 205 ; WX 713 ; N reflexsubset ; B 37 -125 690 470 ;
+C 206 ; WX 713 ; N element ; B 45 0 505 468 ;
+C 207 ; WX 713 ; N notelement ; B 45 -58 505 555 ;
+C 208 ; WX 768 ; N angle ; B 26 0 738 673 ;
+C 209 ; WX 713 ; N gradient ; B 36 -19 681 718 ;
+C 210 ; WX 790 ; N registerserif ; B 50 -17 740 673 ;
+C 211 ; WX 790 ; N copyrightserif ; B 51 -15 741 675 ;
+C 212 ; WX 890 ; N trademarkserif ; B 18 293 855 673 ;
+C 213 ; WX 823 ; N product ; B 25 -101 803 751 ;
+C 214 ; WX 549 ; N radical ; B 10 -38 515 917 ;
+C 215 ; WX 250 ; N dotmath ; B 69 210 169 310 ;
+C 216 ; WX 713 ; N logicalnot ; B 15 0 680 288 ;
+C 217 ; WX 603 ; N logicaland ; B 23 0 583 454 ;
+C 218 ; WX 603 ; N logicalor ; B 30 0 578 477 ;
+C 219 ; WX 1042 ; N arrowdblboth ; B 27 -20 1023 510 ;
+C 220 ; WX 987 ; N arrowdblleft ; B 30 -15 939 513 ;
+C 221 ; WX 603 ; N arrowdblup ; B 39 2 567 911 ;
+C 222 ; WX 987 ; N arrowdblright ; B 45 -20 954 508 ;
+C 223 ; WX 603 ; N arrowdbldown ; B 44 -19 572 890 ;
+C 224 ; WX 494 ; N lozenge ; B 18 0 466 745 ;
+C 225 ; WX 329 ; N angleleft ; B 25 -198 306 746 ;
+C 226 ; WX 790 ; N registersans ; B 50 -20 740 670 ;
+C 227 ; WX 790 ; N copyrightsans ; B 49 -15 739 675 ;
+C 228 ; WX 786 ; N trademarksans ; B 5 293 725 673 ;
+C 229 ; WX 713 ; N summation ; B 14 -108 695 752 ;
+C 230 ; WX 384 ; N parenlefttp ; B 40 -293 436 926 ;
+C 231 ; WX 384 ; N parenleftex ; B 40 -80 92 920 ;
+C 232 ; WX 384 ; N parenleftbt ; B 40 -293 436 920 ;
+C 233 ; WX 384 ; N bracketlefttp ; B 0 -75 341 925 ;
+C 234 ; WX 384 ; N bracketleftex ; B 0 -75 55 925 ;
+C 235 ; WX 384 ; N bracketleftbt ; B 0 -75 340 925 ;
+C 236 ; WX 494 ; N bracelefttp ; B 201 -75 439 925 ;
+C 237 ; WX 494 ; N braceleftmid ; B 14 -75 255 925 ;
+C 238 ; WX 494 ; N braceleftbt ; B 201 -75 439 925 ;
+C 239 ; WX 494 ; N braceex ; B 201 -75 255 925 ;
+C 241 ; WX 329 ; N angleright ; B 21 -198 302 746 ;
+C 242 ; WX 274 ; N integral ; B 2 -107 291 916 ;
+C 243 ; WX 686 ; N integraltp ; B 332 -83 715 921 ;
+C 244 ; WX 686 ; N integralex ; B 332 -88 415 975 ;
+C 245 ; WX 686 ; N integralbt ; B 39 -81 415 921 ;
+C 246 ; WX 384 ; N parenrighttp ; B 54 -293 450 926 ;
+C 247 ; WX 384 ; N parenrightex ; B 398 -80 450 920 ;
+C 248 ; WX 384 ; N parenrightbt ; B 54 -293 450 920 ;
+C 249 ; WX 384 ; N bracketrighttp ; B 22 -75 360 925 ;
+C 250 ; WX 384 ; N bracketrightex ; B 305 -75 360 925 ;
+C 251 ; WX 384 ; N bracketrightbt ; B 20 -75 360 925 ;
+C 252 ; WX 494 ; N bracerighttp ; B 17 -75 255 925 ;
+C 253 ; WX 494 ; N bracerightmid ; B 201 -75 442 925 ;
+C 254 ; WX 494 ; N bracerightbt ; B 17 -75 255 925 ;
+C -1 ; WX 790 ; N apple ; B 56 -3 733 808 ;
+EndCharMetrics
+italicCorrection integral 67
+leftItalicCorrection integral 52
+subscriptCorrection integral -10
+EndFontMetrics
diff --git a/font/devps/symbolmap b/font/devps/symbolmap
new file mode 100644
index 00000000..82827c89
--- /dev/null
+++ b/font/devps/symbolmap
@@ -0,0 +1,510 @@
+a a
+b b
+c c
+d d
+e e
+f f
+g g
+h h
+i i
+j j
+k k
+l l
+m m
+n n
+o o
+p p
+q q
+r r
+s s
+t t
+u u
+v v
+w w
+x x
+y y
+z z
+A A
+B B
+C C
+D D
+E E
+F F
+G G
+H H
+I I
+J J
+K K
+L L
+M M
+N N
+O O
+P P
+Q Q
+R R
+S S
+T T
+U U
+V V
+W W
+X X
+Y Y
+Z Z
+AE AE
+Aacute 'A
+Acircumflex ^A
+Adieresis :A
+Agrave `A
+Aring oA
+Atilde ~A
+Cacute 'C
+Ccedilla ,C
+Eacute 'E
+Ecircumflex ^E
+Edieresis :E
+Egrave `E
+Eth -D
+IJ IJ
+Iacute 'I
+Icircumflex ^I
+Idieresis :I
+Ifraktur Im
+Igrave `I
+Lslash /L
+Ntilde ~N
+OE OE
+Oacute 'O
+Ocircumflex ^O
+Odieresis :O
+Ograve `O
+Oslash /O
+Otilde ~O
+Rfraktur Re
+Scaron vS
+Thorn TP
+Uacute 'U
+Ucircumflex ^U
+Udieresis :U
+Ugrave `U
+Yacute 'Y
+Ydieresis :Y
+Zcaron vZ
+aacute 'a
+acircumflex ^a
+acute aa
+adieresis :a
+ae ae
+agrave `a
+angle /_
+angleleft la
+angleright ra
+aleph Ah
+ampersand &
+approxequal ~~
+aring oa
+arrowboth <>
+arrowdblboth hA
+arrowdbldown dA
+arrowdblleft lA
+arrowdblright rA
+arrowdblup uA
+arrowdown da
+arrowleft <-
+arrowright ->
+arrowup ua
+asciicircum ha
+asciitilde ti
+asterisk *
+asteriskmath **
+at @
+at at
+atilde ~a
+backslash \
+backslash rs
+bar ba
+bar |
+bell bs
+braceleft lC
+braceleft {
+braceright rC
+braceright }
+bracketleft [
+bracketleft lB
+bracketright ]
+bracketright rB
+breve ab
+brokenbar bb
+bullet bu
+cacute 'c
+caron ah
+ccedilla ,c
+cedilla ac
+cent ct
+checkmark OK
+circle ci
+circlemultiply c*
+circleplus c+
+circumflex a^
+circumflex ^
+colon :
+comma ,
+congruent =~
+copyright co
+currency Cs
+dagger dg
+daggerdbl dd
+degree de
+dieresis ad
+dollar $
+dollar Do
+dotaccent a.
+dotlessi .i
+dotlessj .j
+dotmath md
+eacute 'e
+ecircumflex ^e
+edieresis :e
+egrave `e
+eight 8
+element mo
+emdash em
+emptyset es
+endash en
+equal =
+equalmath eq
+equivalence ==
+eth Sd
+exclam !
+exclamdown r!
+existential te
+ff ff
+ffi Fi
+ffl Fl
+fi fi
+five 5
+fl fl
+florin Fn
+four 4
+germandbls ss
+gradient gr
+grave ga
+greater >
+greaterequal >=
+guillemotleft Fo
+guillemotright Fc
+guilsinglleft fo
+guilsinglright fc
+handleft lh
+handright rh
+hbar -h
+hungarumlaut a"
+hyphen -
+hyphen hy
+iacute 'i
+icircumflex ^i
+idieresis :i
+igrave `i
+ij ij
+infinity if
+integral is
+intersection ca
+less <
+lessequal <=
+logicaland AN
+logicalnot no
+logicalor OR
+lozenge lz
+lslash /l
+macron a-
+minus \-
+minusplus -+
+minute fm
+nine 9
+notelement nm
+notequal !=
+notequivalence ne
+notpropersuperset nc
+notsubset nb
+ntilde ~n
+numbersign #
+numbersign sh
+oacute 'o
+ocircumflex ^o
+odieresis :o
+oe oe
+ogonek ho
+ograve `o
+one 1
+onehalf 12
+onequarter 14
+onesuperior S1
+ordfeminine Of
+ordmasculine Om
+oslash /o
+otilde ~o
+paragraph ps
+parenleft (
+parenright )
+partialdiff pd
+percent %
+period .
+perthousand %0
+perpendicular pp
+plus +
+plusmath pl
+propersubset sb
+propersuperset sp
+proportional pt
+question ?
+questiondown r?
+quotedbl "
+quotedblbase Bq
+quotedblleft lq
+quotedblright rq
+quoteleft `
+quoteleft oq
+quoteright '
+quotesingle aq
+quotesinglbase bq
+reflexsubset ib
+reflexsuperset ip
+registered rg
+ring ao
+scaron vs
+second sd
+section sc
+semicolon ;
+seven 7
+similar ap
+similarequal ~=
+six 6
+slash /
+slash sl
+square sq
+sterling Po
+therefore 3d
+therefore tf
+thorn Tp
+three 3
+threequarters 34
+threesuperior S3
+tilde a~
+tilde ~
+trademark tm
+two 2
+twosuperior S2
+uacute 'u
+ucircumflex ^u
+udieresis :u
+ugrave `u
+underscore _
+union cu
+universal fa
+weierstrass wp
+yacute 'y
+ydieresis :y
+yen Ye
+zcaron vz
+zero 0
+exclamdown char161
+cent char162
+sterling char163
+currency char164
+yen char165
+brokenbar char166
+section char167
+dieresis char168
+copyright char169
+ordfeminine char170
+guillemotleft char171
+logicalnot char172
+hyphen char173
+registered char174
+macron char175
+degree char176
+plusminus char177
+twosuperior char178
+threesuperior char179
+acute char180
+mu char181
+paragraph char182
+periodcentered char183
+cedilla char184
+onesuperior char185
+ordmasculine char186
+guillemotright char187
+onequarter char188
+onehalf char189
+threequarters char190
+questiondown char191
+Agrave char192
+Aacute char193
+Acircumflex char194
+Atilde char195
+Adieresis char196
+Aring char197
+AE char198
+Ccedilla char199
+Egrave char200
+Eacute char201
+Ecircumflex char202
+Edieresis char203
+Igrave char204
+Iacute char205
+Icircumflex char206
+Idieresis char207
+Eth char208
+Ntilde char209
+Ograve char210
+Oacute char211
+Ocircumflex char212
+Otilde char213
+Odieresis char214
+multiply char215
+Oslash char216
+Ugrave char217
+Uacute char218
+Ucircumflex char219
+Udieresis char220
+Yacute char221
+Thorn char222
+germandbls char223
+agrave char224
+aacute char225
+acircumflex char226
+atilde char227
+adieresis char228
+aring char229
+ae char230
+ccedilla char231
+egrave char232
+eacute char233
+ecircumflex char234
+edieresis char235
+igrave char236
+iacute char237
+icircumflex char238
+idieresis char239
+eth char240
+ntilde char241
+ograve char242
+oacute char243
+ocircumflex char244
+otilde char245
+odieresis char246
+divide char247
+oslash char248
+ugrave char249
+uacute char250
+ucircumflex char251
+udieresis char252
+yacute char253
+thorn char254
+ydieresis char255
+fraction f/
+club CL
+diamond DI
+heart HE
+spade SP
+carriagereturn CR
+suchthat st
+bracelefttp bracelefttp
+braceleftmid braceleftmid
+braceleftbt braceleftbt
+braceex braceex
+braceex bracerightex
+braceex braceleftex
+braceex barex
+bracerighttp bracerighttp
+bracerightmid bracerightmid
+bracerightbt bracerightbt
+parenlefttp parenlefttp
+parenleftbt parenleftbt
+parenleftex parenleftex
+parenrighttp parenrighttp
+parenrightbt parenrightbt
+parenrightex parenrightex
+bracketlefttp bracketlefttp
+bracketleftbt bracketleftbt
+bracketleftex bracketleftex
+bracketrighttp bracketrighttp
+bracketrightbt bracketrightbt
+bracketrightex bracketrightex
+radical sr
+radicalex radicalex
+approxequal ~=
+bracketlefttp lc
+bracketleftbt lf
+bracketrighttp rc
+bracketrightbt rf
+bracelefttp lt
+braceleftmid lk
+braceleftbt lb
+braceex bv
+bracerighttp rt
+bracerightmid rk
+bracerightbt rb
+summation sum
+product product
+arrowvertex arrowvertex
+arrowhorizex an
+plus pl
+minus mi
+plusminus +-
+equal eq
+divide di
+multiply mu
+arrowup arrowverttp
+arrowdown arrowvertbt
+Alpha *A
+Beta *B
+Chi *X
+Delta *D
+Epsilon *E
+Eta *Y
+Gamma *G
+Iota *I
+Kappa *K
+Lambda *L
+Mu *M
+Nu *N
+Omega *W
+Omicron *O
+Phi *F
+Pi *P
+Psi *Q
+Rho *R
+Sigma *S
+Tau *T
+Theta *H
+Upsilon1 *U
+Xi *C
+Zeta *Z
+alpha *a
+beta *b
+chi *x
+delta *d
+epsilon *e
+eta *y
+gamma *g
+iota *i
+kappa *k
+lambda *l
+mu *m
+nu *n
+omega *w
+omega1 +p
+omicron *o
+phi *f
+phi1 +f
+pi *p
+psi *q
+rho *r
+sigma *s
+sigma1 ts
+tau *t
+theta *h
+theta1 +h
+upsilon *u
+xi *c
+zeta *z
diff --git a/font/devps/symbolsl.ps b/font/devps/symbolsl.ps
new file mode 100644
index 00000000..d384203e
--- /dev/null
+++ b/font/devps/symbolsl.ps
@@ -0,0 +1,41 @@
+%!PS-Adobe-3.0 Resource-Font
+%%DocumentNeededResources: font Symbol
+
+% newfontname matrix oldfontname MakeTransformedFont
+
+/MakeTransformedFont {
+ findfont dup maxlength dict begin
+ {
+ exch dup dup /FID ne exch /UniqueID ne and {
+ exch def
+ } {
+ pop pop
+ } ifelse
+ } forall
+ % first copy FontBBox
+ /FontBBox
+ % FontBBox sometimes seems to have the executable
+ % attribute set
+ % so to get the array on the stack, we have to do this
+ currentdict /FontBBox get
+ 4 array copy def
+ % now transform it
+ FontBBox aload pop
+ 4 index transform 4 2 roll
+ 4 index transform 4 2 roll
+ FontBBox astore pop
+ % matrix
+ % now transform FontMatrix
+ FontMatrix exch matrix concatmatrix
+ /FontMatrix exch def
+ dup /FontName exch def
+ currentdict end
+ definefont pop
+} bind def
+
+%%IncludeResource: font Symbol
+
+/Symbol-Slanted
+[.89 0.0 15.5 dup sin exch cos div .89 0.0 0.0]
+/Symbol
+MakeTransformedFont
diff --git a/font/devps/text.enc b/font/devps/text.enc
new file mode 100644
index 00000000..dde5bb7c
--- /dev/null
+++ b/font/devps/text.enc
@@ -0,0 +1,231 @@
+asciicircum 0
+asciitilde 1
+Scaron 2
+Zcaron 3
+scaron 4
+zcaron 5
+Ydieresis 6
+trademark 7
+quotesingle 8
+space 32
+exclam 33
+quotedbl 34
+numbersign 35
+dollar 36
+percent 37
+ampersand 38
+quoteright 39
+parenleft 40
+parenright 41
+asterisk 42
+plus 43
+comma 44
+hyphen 45
+period 46
+slash 47
+zero 48
+one 49
+two 50
+three 51
+four 52
+five 53
+six 54
+seven 55
+eight 56
+nine 57
+colon 58
+semicolon 59
+less 60
+equal 61
+greater 62
+question 63
+at 64
+A 65
+B 66
+C 67
+D 68
+E 69
+F 70
+G 71
+H 72
+I 73
+J 74
+K 75
+L 76
+M 77
+N 78
+O 79
+P 80
+Q 81
+R 82
+S 83
+T 84
+U 85
+V 86
+W 87
+X 88
+Y 89
+Z 90
+bracketleft 91
+backslash 92
+bracketright 93
+circumflex 94
+underscore 95
+quoteleft 96
+a 97
+b 98
+c 99
+d 100
+e 101
+f 102
+g 103
+h 104
+i 105
+j 106
+k 107
+l 108
+m 109
+n 110
+o 111
+p 112
+q 113
+r 114
+s 115
+t 116
+u 117
+v 118
+w 119
+x 120
+y 121
+z 122
+braceleft 123
+bar 124
+braceright 125
+tilde 126
+quotesinglbase 128
+guillemotleft 129
+guillemotright 130
+bullet 131
+florin 132
+fraction 133
+perthousand 134
+dagger 135
+daggerdbl 136
+endash 137
+emdash 138
+ff 139
+fi 140
+fl 141
+ffi 142
+ffl 143
+dotlessi 144
+dotlessj 145
+grave 146
+hungarumlaut 147
+dotaccent 148
+breve 149
+caron 150
+ring 151
+ogonek 152
+quotedblleft 153
+quotedblright 154
+oe 155
+lslash 156
+quotedblbase 157
+OE 158
+Lslash 159
+exclamdown 161
+cent 162
+sterling 163
+currency 164
+yen 165
+brokenbar 166
+section 167
+dieresis 168
+copyright 169
+ordfeminine 170
+guilsinglleft 171
+logicalnot 172
+registered 174
+minus 173
+macron 175
+degree 176
+plusminus 177
+twosuperior 178
+threesuperior 179
+acute 180
+mu 181
+paragraph 182
+periodcentered 183
+cedilla 184
+onesuperior 185
+ordmasculine 186
+guilsinglright 187
+onequarter 188
+onehalf 189
+threequarters 190
+questiondown 191
+Agrave 192
+Aacute 193
+Acircumflex 194
+Atilde 195
+Adieresis 196
+Aring 197
+AE 198
+Ccedilla 199
+Egrave 200
+Eacute 201
+Ecircumflex 202
+Edieresis 203
+Igrave 204
+Iacute 205
+Icircumflex 206
+Idieresis 207
+Eth 208
+Ntilde 209
+Ograve 210
+Oacute 211
+Ocircumflex 212
+Otilde 213
+Odieresis 214
+multiply 215
+Oslash 216
+Ugrave 217
+Uacute 218
+Ucircumflex 219
+Udieresis 220
+Yacute 221
+Thorn 222
+germandbls 223
+agrave 224
+aacute 225
+acircumflex 226
+atilde 227
+adieresis 228
+aring 229
+ae 230
+ccedilla 231
+egrave 232
+eacute 233
+ecircumflex 234
+edieresis 235
+igrave 236
+iacute 237
+icircumflex 238
+idieresis 239
+eth 240
+ntilde 241
+ograve 242
+oacute 243
+ocircumflex 244
+otilde 245
+odieresis 246
+divide 247
+oslash 248
+ugrave 249
+uacute 250
+ucircumflex 251
+udieresis 252
+yacute 253
+thorn 254
+ydieresis 255
diff --git a/font/devps/zapfdr.afm b/font/devps/zapfdr.afm
new file mode 100644
index 00000000..ce216de4
--- /dev/null
+++ b/font/devps/zapfdr.afm
@@ -0,0 +1,222 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1988, 1989 Adobe Systems Incorporated. All rights reserved.
+Comment Creation Date: Fri Dec 1 12:57:42 1989
+Comment UniqueID 26200
+Comment VMusage 39281 49041
+FontName ZapfDingbats-Reverse
+FullName ITC Zapf Dingbats
+FamilyName ITC Zapf Dingbats
+Weight Medium
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -1 -143 981 820
+UnderlinePosition -98
+UnderlineThickness 54
+Version 001.004
+Notice Copyright (c) 1985, 1987, 1988, 1989 Adobe Systems Incorporated. All rights reserved.ITC Zapf Dingbats is a registered trademark of International Typeface Corporation.
+EncodingScheme FontSpecific
+StartCharMetrics 202
+C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 974 ; N a1 ; B 35 72 939 621 ;
+C 34 ; WX 961 ; N a2 ; B 35 81 927 611 ;
+C 35 ; WX 974 ; N a202 ; B 35 72 939 621 ;
+C 36 ; WX 980 ; N a3 ; B 35 0 945 692 ;
+C 37 ; WX 719 ; N a4 ; B 34 139 685 566 ;
+C 38 ; WX 789 ; N a5 ; B 35 -14 755 705 ;
+C 39 ; WX 790 ; N a119 ; B 35 -14 755 705 ;
+C 40 ; WX 791 ; N a118 ; B 35 -13 761 705 ;
+C 41 ; WX 690 ; N a117 ; B 35 138 655 553 ;
+C 42 ; WX 960 ; N a11 ; B 35 123 925 568 ;
+C 43 ; WX 939 ; N a12 ; B 35 134 904 559 ;
+C 44 ; WX 549 ; N a13 ; B 29 -11 516 705 ;
+C 45 ; WX 855 ; N a14 ; B 34 59 820 632 ;
+C 46 ; WX 911 ; N a15 ; B 35 50 876 642 ;
+C 47 ; WX 933 ; N a16 ; B 35 139 899 550 ;
+C 48 ; WX 911 ; N a105 ; B 35 50 876 642 ;
+C 49 ; WX 945 ; N a17 ; B 35 139 909 553 ;
+C 50 ; WX 974 ; N a18 ; B 35 104 938 587 ;
+C 51 ; WX 755 ; N a19 ; B 34 -13 721 705 ;
+C 52 ; WX 846 ; N a20 ; B 36 -14 811 705 ;
+C 53 ; WX 762 ; N a21 ; B 35 0 727 692 ;
+C 54 ; WX 761 ; N a22 ; B 35 0 727 692 ;
+C 55 ; WX 571 ; N a23 ; B -1 -68 571 661 ;
+C 56 ; WX 677 ; N a24 ; B 36 -13 642 705 ;
+C 57 ; WX 763 ; N a25 ; B 35 0 728 692 ;
+C 58 ; WX 760 ; N a26 ; B 35 0 726 692 ;
+C 59 ; WX 759 ; N a27 ; B 35 0 725 692 ;
+C 60 ; WX 754 ; N a28 ; B 35 0 720 692 ;
+C 61 ; WX 494 ; N a6 ; B 35 0 460 692 ;
+C 62 ; WX 552 ; N a7 ; B 35 0 517 692 ;
+C 63 ; WX 537 ; N a8 ; B 35 0 503 692 ;
+C 64 ; WX 577 ; N a9 ; B 35 96 542 596 ;
+C 65 ; WX 692 ; N a10 ; B 35 -14 657 705 ;
+C 66 ; WX 786 ; N a29 ; B 35 -14 751 705 ;
+C 67 ; WX 788 ; N a30 ; B 35 -14 752 705 ;
+C 68 ; WX 788 ; N a31 ; B 35 -14 753 705 ;
+C 69 ; WX 790 ; N a32 ; B 35 -14 756 705 ;
+C 70 ; WX 793 ; N a33 ; B 35 -13 759 705 ;
+C 71 ; WX 794 ; N a34 ; B 35 -13 759 705 ;
+C 72 ; WX 816 ; N a35 ; B 35 -14 782 705 ;
+C 73 ; WX 823 ; N a36 ; B 35 -14 787 705 ;
+C 74 ; WX 789 ; N a37 ; B 35 -14 754 705 ;
+C 75 ; WX 841 ; N a38 ; B 35 -14 807 705 ;
+C 76 ; WX 823 ; N a39 ; B 35 -14 789 705 ;
+C 77 ; WX 833 ; N a40 ; B 35 -14 798 705 ;
+C 78 ; WX 816 ; N a41 ; B 35 -13 782 705 ;
+C 79 ; WX 831 ; N a42 ; B 35 -14 796 705 ;
+C 80 ; WX 923 ; N a43 ; B 35 -14 888 705 ;
+C 81 ; WX 744 ; N a44 ; B 35 0 710 692 ;
+C 82 ; WX 723 ; N a45 ; B 35 0 688 692 ;
+C 83 ; WX 749 ; N a46 ; B 35 0 714 692 ;
+C 84 ; WX 790 ; N a47 ; B 34 -14 756 705 ;
+C 85 ; WX 792 ; N a48 ; B 35 -14 758 705 ;
+C 86 ; WX 695 ; N a49 ; B 35 -14 661 706 ;
+C 87 ; WX 776 ; N a50 ; B 35 -6 741 699 ;
+C 88 ; WX 768 ; N a51 ; B 35 -7 734 699 ;
+C 89 ; WX 792 ; N a52 ; B 35 -14 757 705 ;
+C 90 ; WX 759 ; N a53 ; B 35 0 725 692 ;
+C 91 ; WX 707 ; N a54 ; B 35 -13 672 704 ;
+C 92 ; WX 708 ; N a55 ; B 35 -14 672 705 ;
+C 93 ; WX 682 ; N a56 ; B 35 -14 647 705 ;
+C 94 ; WX 701 ; N a57 ; B 35 -14 666 705 ;
+C 95 ; WX 826 ; N a58 ; B 35 -14 791 705 ;
+C 96 ; WX 815 ; N a59 ; B 35 -14 780 705 ;
+C 97 ; WX 789 ; N a60 ; B 35 -14 754 705 ;
+C 98 ; WX 789 ; N a61 ; B 35 -14 754 705 ;
+C 99 ; WX 707 ; N a62 ; B 34 -14 673 705 ;
+C 100 ; WX 687 ; N a63 ; B 36 0 651 692 ;
+C 101 ; WX 696 ; N a64 ; B 35 0 661 691 ;
+C 102 ; WX 689 ; N a65 ; B 35 0 655 692 ;
+C 103 ; WX 786 ; N a66 ; B 34 -14 751 705 ;
+C 104 ; WX 787 ; N a67 ; B 35 -14 752 705 ;
+C 105 ; WX 713 ; N a68 ; B 35 -14 678 705 ;
+C 106 ; WX 791 ; N a69 ; B 35 -14 756 705 ;
+C 107 ; WX 785 ; N a70 ; B 36 -14 751 705 ;
+C 108 ; WX 791 ; N a71 ; B 35 -14 757 705 ;
+C 109 ; WX 873 ; N a72 ; B 35 -14 838 705 ;
+C 110 ; WX 761 ; N a73 ; B 35 0 726 692 ;
+C 111 ; WX 762 ; N a74 ; B 35 0 727 692 ;
+C 112 ; WX 762 ; N a203 ; B 35 0 727 692 ;
+C 113 ; WX 759 ; N a75 ; B 35 0 725 692 ;
+C 114 ; WX 759 ; N a204 ; B 35 0 725 692 ;
+C 115 ; WX 892 ; N a76 ; B 35 0 858 705 ;
+C 116 ; WX 892 ; N a77 ; B 35 -14 858 692 ;
+C 117 ; WX 788 ; N a78 ; B 35 -14 754 705 ;
+C 118 ; WX 784 ; N a79 ; B 35 -14 749 705 ;
+C 119 ; WX 438 ; N a81 ; B 35 -14 403 705 ;
+C 120 ; WX 138 ; N a82 ; B 35 0 104 692 ;
+C 121 ; WX 277 ; N a83 ; B 35 0 242 692 ;
+C 122 ; WX 415 ; N a84 ; B 35 0 380 692 ;
+C 123 ; WX 392 ; N a97 ; B 35 263 357 705 ;
+C 124 ; WX 392 ; N a98 ; B 34 263 357 705 ;
+C 125 ; WX 668 ; N a99 ; B 35 263 633 705 ;
+C 126 ; WX 668 ; N a100 ; B 36 263 634 705 ;
+C 161 ; WX 732 ; N a101 ; B 35 -143 697 806 ;
+C 162 ; WX 544 ; N a102 ; B 56 -14 488 706 ;
+C 163 ; WX 544 ; N a103 ; B 34 -14 508 705 ;
+C 164 ; WX 910 ; N a104 ; B 35 40 875 651 ;
+C 165 ; WX 667 ; N a106 ; B 35 -14 633 705 ;
+C 166 ; WX 760 ; N a107 ; B 35 -14 726 705 ;
+C 167 ; WX 760 ; N a108 ; B 0 121 758 569 ;
+C 168 ; WX 776 ; N a112 ; B 35 0 741 705 ;
+C 169 ; WX 595 ; N a111 ; B 34 -14 560 705 ;
+C 170 ; WX 694 ; N a110 ; B 35 -14 659 705 ;
+C 171 ; WX 626 ; N a109 ; B 34 0 591 705 ;
+C 172 ; WX 788 ; N a120 ; B 35 -14 754 705 ;
+C 173 ; WX 788 ; N a121 ; B 35 -14 754 705 ;
+C 174 ; WX 788 ; N a122 ; B 35 -14 754 705 ;
+C 175 ; WX 788 ; N a123 ; B 35 -14 754 705 ;
+C 176 ; WX 788 ; N a124 ; B 35 -14 754 705 ;
+C 177 ; WX 788 ; N a125 ; B 35 -14 754 705 ;
+C 178 ; WX 788 ; N a126 ; B 35 -14 754 705 ;
+C 179 ; WX 788 ; N a127 ; B 35 -14 754 705 ;
+C 180 ; WX 788 ; N a128 ; B 35 -14 754 705 ;
+C 181 ; WX 788 ; N a129 ; B 35 -14 754 705 ;
+C 182 ; WX 788 ; N a130 ; B 35 -14 754 705 ;
+C 183 ; WX 788 ; N a131 ; B 35 -14 754 705 ;
+C 184 ; WX 788 ; N a132 ; B 35 -14 754 705 ;
+C 185 ; WX 788 ; N a133 ; B 35 -14 754 705 ;
+C 186 ; WX 788 ; N a134 ; B 35 -14 754 705 ;
+C 187 ; WX 788 ; N a135 ; B 35 -14 754 705 ;
+C 188 ; WX 788 ; N a136 ; B 35 -14 754 705 ;
+C 189 ; WX 788 ; N a137 ; B 35 -14 754 705 ;
+C 190 ; WX 788 ; N a138 ; B 35 -14 754 705 ;
+C 191 ; WX 788 ; N a139 ; B 35 -14 754 705 ;
+C 192 ; WX 788 ; N a140 ; B 35 -14 754 705 ;
+C 193 ; WX 788 ; N a141 ; B 35 -14 754 705 ;
+C 194 ; WX 788 ; N a142 ; B 35 -14 754 705 ;
+C 195 ; WX 788 ; N a143 ; B 35 -14 754 705 ;
+C 196 ; WX 788 ; N a144 ; B 35 -14 754 705 ;
+C 197 ; WX 788 ; N a145 ; B 35 -14 754 705 ;
+C 198 ; WX 788 ; N a146 ; B 35 -14 754 705 ;
+C 199 ; WX 788 ; N a147 ; B 35 -14 754 705 ;
+C 200 ; WX 788 ; N a148 ; B 35 -14 754 705 ;
+C 201 ; WX 788 ; N a149 ; B 35 -14 754 705 ;
+C 202 ; WX 788 ; N a150 ; B 35 -14 754 705 ;
+C 203 ; WX 788 ; N a151 ; B 35 -14 754 705 ;
+C 204 ; WX 788 ; N a152 ; B 35 -14 754 705 ;
+C 205 ; WX 788 ; N a153 ; B 35 -14 754 705 ;
+C 206 ; WX 788 ; N a154 ; B 35 -14 754 705 ;
+C 207 ; WX 788 ; N a155 ; B 35 -14 754 705 ;
+C 208 ; WX 788 ; N a156 ; B 35 -14 754 705 ;
+C 209 ; WX 788 ; N a157 ; B 35 -14 754 705 ;
+C 210 ; WX 788 ; N a158 ; B 35 -14 754 705 ;
+C 211 ; WX 788 ; N a159 ; B 35 -14 754 705 ;
+C 212 ; WX 894 ; N a160 ; B 35 58 860 634 ;
+C 213 ; WX 838 ; N a161 ; B 35 152 803 540 ;
+C 214 ; WX 1016 ; N a163 ; B 34 152 981 540 ;
+C 215 ; WX 458 ; N a164 ; B 35 -127 422 820 ;
+C 216 ; WX 748 ; N a196 ; B 35 94 698 597 ;
+C 217 ; WX 924 ; N a165 ; B 35 140 890 552 ;
+C 218 ; WX 748 ; N a192 ; B 35 94 698 597 ;
+C 219 ; WX 918 ; N a166 ; B 35 166 884 526 ;
+C 220 ; WX 927 ; N a167 ; B 35 32 892 660 ;
+C 221 ; WX 928 ; N a168 ; B 35 129 891 562 ;
+C 222 ; WX 928 ; N a169 ; B 35 128 893 563 ;
+C 223 ; WX 834 ; N a170 ; B 35 155 799 537 ;
+C 224 ; WX 873 ; N a171 ; B 35 93 838 599 ;
+C 225 ; WX 828 ; N a172 ; B 35 104 791 588 ;
+C 226 ; WX 924 ; N a173 ; B 35 98 889 594 ;
+C 227 ; WX 924 ; N a162 ; B 35 98 889 594 ;
+C 228 ; WX 917 ; N a174 ; B 35 0 882 692 ;
+C 229 ; WX 930 ; N a175 ; B 35 84 896 608 ;
+C 230 ; WX 931 ; N a176 ; B 35 84 896 608 ;
+C 231 ; WX 463 ; N a177 ; B 35 -99 429 791 ;
+C 232 ; WX 883 ; N a178 ; B 35 71 848 623 ;
+C 233 ; WX 836 ; N a179 ; B 35 44 802 648 ;
+C 234 ; WX 836 ; N a193 ; B 35 44 802 648 ;
+C 235 ; WX 867 ; N a180 ; B 35 101 832 591 ;
+C 236 ; WX 867 ; N a199 ; B 35 101 832 591 ;
+C 237 ; WX 696 ; N a181 ; B 35 44 661 648 ;
+C 238 ; WX 696 ; N a200 ; B 35 44 661 648 ;
+C 239 ; WX 874 ; N a182 ; B 35 77 840 619 ;
+C 241 ; WX 874 ; N a201 ; B 35 73 840 615 ;
+C 242 ; WX 760 ; N a183 ; B 35 0 725 692 ;
+C 243 ; WX 946 ; N a184 ; B 35 160 911 533 ;
+C 244 ; WX 771 ; N a197 ; B 34 37 736 655 ;
+C 245 ; WX 865 ; N a185 ; B 35 207 830 481 ;
+C 246 ; WX 771 ; N a194 ; B 34 37 736 655 ;
+C 247 ; WX 888 ; N a198 ; B 34 -19 853 712 ;
+C 248 ; WX 967 ; N a186 ; B 35 124 932 568 ;
+C 249 ; WX 888 ; N a195 ; B 34 -19 853 712 ;
+C 250 ; WX 831 ; N a187 ; B 35 113 796 579 ;
+C 251 ; WX 873 ; N a188 ; B 36 118 838 578 ;
+C 252 ; WX 927 ; N a189 ; B 35 150 891 542 ;
+C 253 ; WX 970 ; N a190 ; B 35 76 931 616 ;
+C 254 ; WX 918 ; N a191 ; B 34 99 884 593 ;
+C -1 ; WX 410 ; N a86 ; B 35 0 375 692 ;
+C -1 ; WX 509 ; N a85 ; B 35 0 475 692 ;
+C -1 ; WX 334 ; N a95 ; B 35 0 299 692 ;
+C -1 ; WX 509 ; N a205 ; B 35 0 475 692 ;
+C -1 ; WX 390 ; N a89 ; B 35 -14 356 705 ;
+C -1 ; WX 234 ; N a87 ; B 35 -14 199 705 ;
+C -1 ; WX 276 ; N a91 ; B 35 0 242 692 ;
+C -1 ; WX 390 ; N a90 ; B 35 -14 355 705 ;
+C -1 ; WX 410 ; N a206 ; B 35 0 375 692 ;
+C -1 ; WX 317 ; N a94 ; B 35 0 283 692 ;
+C -1 ; WX 317 ; N a93 ; B 35 0 283 692 ;
+C -1 ; WX 276 ; N a92 ; B 35 0 242 692 ;
+C -1 ; WX 334 ; N a96 ; B 35 0 299 692 ;
+C -1 ; WX 234 ; N a88 ; B 35 -14 199 705 ;
+EndCharMetrics
+EndFontMetrics
diff --git a/font/devps/zapfdr.ps b/font/devps/zapfdr.ps
new file mode 100644
index 00000000..8283be26
--- /dev/null
+++ b/font/devps/zapfdr.ps
@@ -0,0 +1,225 @@
+%!PS-Adobe-3.0 Resource-Font
+%%DocumentNeededResources: font ZapfDingbats
+
+%%IncludeResource: font ZapfDingbats
+
+/ZapfDingbats findfont [-1 0 0 1 0 0] makefont
+
+dup length 1 add dict begin
+{
+ exch dup dup /FID ne exch /UniqueID ne and {
+ exch def
+ } {
+ pop pop
+ } ifelse
+} forall
+
+/FontName /ZapfDingbats-Reverse def
+
+/Metrics 202 dict dup begin
+ /space [0 -278] def
+ /a1 [-939 -974] def
+ /a2 [-926 -961] def
+ /a202 [-939 -974] def
+ /a3 [-945 -980] def
+ /a4 [-685 -719] def
+ /a5 [-754 -789] def
+ /a119 [-755 -790] def
+ /a118 [-756 -791] def
+ /a117 [-655 -690] def
+ /a11 [-925 -960] def
+ /a12 [-904 -939] def
+ /a13 [-520 -549] def
+ /a14 [-821 -855] def
+ /a15 [-876 -911] def
+ /a16 [-898 -933] def
+ /a105 [-876 -911] def
+ /a17 [-910 -945] def
+ /a18 [-939 -974] def
+ /a19 [-721 -755] def
+ /a20 [-811 -846] def
+ /a21 [-727 -762] def
+ /a22 [-726 -761] def
+ /a23 [-572 -571] def
+ /a24 [-641 -677] def
+ /a25 [-728 -763] def
+ /a26 [-725 -760] def
+ /a27 [-724 -759] def
+ /a28 [-719 -754] def
+ /a6 [-459 -494] def
+ /a7 [-517 -552] def
+ /a8 [-502 -537] def
+ /a9 [-542 -577] def
+ /a10 [-657 -692] def
+ /a29 [-751 -786] def
+ /a30 [-753 -788] def
+ /a31 [-753 -788] def
+ /a32 [-755 -790] def
+ /a33 [-758 -793] def
+ /a34 [-759 -794] def
+ /a35 [-781 -816] def
+ /a36 [-788 -823] def
+ /a37 [-754 -789] def
+ /a38 [-806 -841] def
+ /a39 [-788 -823] def
+ /a40 [-798 -833] def
+ /a41 [-781 -816] def
+ /a42 [-796 -831] def
+ /a43 [-888 -923] def
+ /a44 [-709 -744] def
+ /a45 [-688 -723] def
+ /a46 [-714 -749] def
+ /a47 [-756 -790] def
+ /a48 [-757 -792] def
+ /a49 [-660 -695] def
+ /a50 [-741 -776] def
+ /a51 [-733 -768] def
+ /a52 [-757 -792] def
+ /a53 [-724 -759] def
+ /a54 [-672 -707] def
+ /a55 [-673 -708] def
+ /a56 [-647 -682] def
+ /a57 [-666 -701] def
+ /a58 [-791 -826] def
+ /a59 [-780 -815] def
+ /a60 [-754 -789] def
+ /a61 [-754 -789] def
+ /a62 [-673 -707] def
+ /a63 [-651 -687] def
+ /a64 [-661 -696] def
+ /a65 [-654 -689] def
+ /a66 [-752 -786] def
+ /a67 [-752 -787] def
+ /a68 [-678 -713] def
+ /a69 [-756 -791] def
+ /a70 [-749 -785] def
+ /a71 [-756 -791] def
+ /a72 [-838 -873] def
+ /a73 [-726 -761] def
+ /a74 [-727 -762] def
+ /a203 [-727 -762] def
+ /a75 [-724 -759] def
+ /a204 [-724 -759] def
+ /a76 [-857 -892] def
+ /a77 [-857 -892] def
+ /a78 [-753 -788] def
+ /a79 [-749 -784] def
+ /a81 [-403 -438] def
+ /a82 [-103 -138] def
+ /a83 [-242 -277] def
+ /a84 [-380 -415] def
+ /a97 [-357 -392] def
+ /a98 [-358 -392] def
+ /a99 [-633 -668] def
+ /a100 [-632 -668] def
+ /a101 [-697 -732] def
+ /a102 [-488 -544] def
+ /a103 [-510 -544] def
+ /a104 [-875 -910] def
+ /a106 [-632 -667] def
+ /a107 [-725 -760] def
+ /a108 [-760 -760] def
+ /a112 [-741 -776] def
+ /a111 [-561 -595] def
+ /a110 [-659 -694] def
+ /a109 [-592 -626] def
+ /a120 [-753 -788] def
+ /a121 [-753 -788] def
+ /a122 [-753 -788] def
+ /a123 [-753 -788] def
+ /a124 [-753 -788] def
+ /a125 [-753 -788] def
+ /a126 [-753 -788] def
+ /a127 [-753 -788] def
+ /a128 [-753 -788] def
+ /a129 [-753 -788] def
+ /a130 [-753 -788] def
+ /a131 [-753 -788] def
+ /a132 [-753 -788] def
+ /a133 [-753 -788] def
+ /a134 [-753 -788] def
+ /a135 [-753 -788] def
+ /a136 [-753 -788] def
+ /a137 [-753 -788] def
+ /a138 [-753 -788] def
+ /a139 [-753 -788] def
+ /a140 [-753 -788] def
+ /a141 [-753 -788] def
+ /a142 [-753 -788] def
+ /a143 [-753 -788] def
+ /a144 [-753 -788] def
+ /a145 [-753 -788] def
+ /a146 [-753 -788] def
+ /a147 [-753 -788] def
+ /a148 [-753 -788] def
+ /a149 [-753 -788] def
+ /a150 [-753 -788] def
+ /a151 [-753 -788] def
+ /a152 [-753 -788] def
+ /a153 [-753 -788] def
+ /a154 [-753 -788] def
+ /a155 [-753 -788] def
+ /a156 [-753 -788] def
+ /a157 [-753 -788] def
+ /a158 [-753 -788] def
+ /a159 [-753 -788] def
+ /a160 [-859 -894] def
+ /a161 [-803 -838] def
+ /a163 [-982 -1016] def
+ /a164 [-423 -458] def
+ /a196 [-713 -748] def
+ /a165 [-889 -924] def
+ /a192 [-713 -748] def
+ /a166 [-883 -918] def
+ /a167 [-892 -927] def
+ /a168 [-893 -928] def
+ /a169 [-893 -928] def
+ /a170 [-799 -834] def
+ /a171 [-838 -873] def
+ /a172 [-793 -828] def
+ /a173 [-889 -924] def
+ /a162 [-889 -924] def
+ /a174 [-882 -917] def
+ /a175 [-895 -930] def
+ /a176 [-896 -931] def
+ /a177 [-428 -463] def
+ /a178 [-848 -883] def
+ /a179 [-801 -836] def
+ /a193 [-801 -836] def
+ /a180 [-832 -867] def
+ /a199 [-832 -867] def
+ /a181 [-661 -696] def
+ /a200 [-661 -696] def
+ /a182 [-839 -874] def
+ /a201 [-839 -874] def
+ /a183 [-725 -760] def
+ /a184 [-911 -946] def
+ /a197 [-737 -771] def
+ /a185 [-830 -865] def
+ /a194 [-737 -771] def
+ /a198 [-854 -888] def
+ /a186 [-932 -967] def
+ /a195 [-854 -888] def
+ /a187 [-796 -831] def
+ /a188 [-837 -873] def
+ /a189 [-892 -927] def
+ /a190 [-935 -970] def
+ /a191 [-884 -918] def
+ /a205 [-474 -509] def
+ /a206 [-375 -410] def
+ /a85 [-474 -509] def
+ /a86 [-375 -410] def
+ /a87 [-199 -234] def
+ /a88 [-199 -234] def
+ /a89 [-355 -390] def
+ /a90 [-355 -390] def
+ /a91 [-241 -276] def
+ /a92 [-241 -276] def
+ /a93 [-282 -317] def
+ /a94 [-282 -317] def
+ /a95 [-299 -334] def
+ /a96 [-299 -334] def
+
+end def
+
+/ZapfDingbats-Reverse currentdict end definefont pop
diff --git a/font/devutf8/DESC.proto b/font/devutf8/DESC.proto
new file mode 100644
index 00000000..88399ab1
--- /dev/null
+++ b/font/devutf8/DESC.proto
@@ -0,0 +1,8 @@
+res 240
+hor 24
+vert 40
+unitwidth 10
+sizes 10 0
+fonts 4 R I B BI
+tcommand
+postpro grotty
diff --git a/font/devutf8/Makefile.sub b/font/devutf8/Makefile.sub
new file mode 100644
index 00000000..f6ce659c
--- /dev/null
+++ b/font/devutf8/Makefile.sub
@@ -0,0 +1,32 @@
+DEV=utf8
+FONTS=R I B BI
+DEVFILES=$(FONTS) DESC
+CLEANADD=$(FONTS) DESC
+
+RES=240
+CPI=10
+LPI=6
+
+$(FONTS): R.proto
+ @echo Making $@
+ @-rm -f $@
+ @(charwidth=`expr $(RES) / $(CPI)` ; \
+ sed -e "s/^name [A-Z]*$$/name $@/" \
+ -e "s/^\\([^ ]*\\) [0-9]+ /\\1 $$charwidth /" \
+ -e "s/^spacewidth [0-9]+$$/spacewidth $$charwidth/" \
+ -e "s/^internalname .*$$/internalname $@/" \
+ -e "/^internalname/s/BI/3/" \
+ -e "/^internalname/s/B/2/" \
+ -e "/^internalname/s/I/1/" \
+ -e "/^internalname .*[^ 0-9]/d" \
+ $(srcdir)/R.proto >$@)
+
+DESC: DESC.proto
+ @echo Making $@
+ @-rm -f $@
+ @sed -e "s/^res .*$$/res $(RES)/" \
+ -e "s/^hor .*$$/hor `expr $(RES) / $(CPI)`/" \
+ -e "s/^vert .*$$/vert `expr $(RES) / $(LPI)`/" \
+ -e "s/^fonts .*$$/fonts `set $(FONTS); echo $$#` $(FONTS)/" \
+ $(srcdir)/DESC.proto >$@
+
diff --git a/font/devutf8/NOTES b/font/devutf8/NOTES
new file mode 100644
index 00000000..064b7baf
--- /dev/null
+++ b/font/devutf8/NOTES
@@ -0,0 +1,91 @@
+The following from the original troff manual (by Ossanna and Kernighan) is
+unmapped:
+
+ \(bs solid ball
+
+Character 0x002D has not been given a name because its Unicode name
+"HYPHEN-MINUS" is so ambiguous that it's unusable for serious typographic use.
+
+The following are mentioned in the original troff manual but not in
+groff_char.7:
+
+ \(sr square root
+ \(rn overline
+ \(is integral sign
+
+The following, mentioned in the original troff manual, are only approximate:
+
+ \(lk middle part of big left curly brace
+ \(rk middle part of big right curly brace
+
+\(bv has been mapped to 0x2502, not 0x2759, because it appears to mean
+"bar vertical", not "bold vertical".
+
+\(wp has been mapped to 0x2118, because according to unicode.org's
+NamesList-3.0.0.txt, U+2118 "SCRIPT CAPITAL P" is really a Weierstrass p,
+neither SCRIPT not CAPITAL.
+
+The following lines could be added, to define names which are known to
+"devps" but are not documented and not known to "devdvi".
+space 24 0 0x0020
+vS 24 0 0x0160
+vs 24 0 0x0161
+:Y 24 0 0x0178
+vZ 24 0 0x017D
+vz 24 0 0x017E
+3d 24 0 0x2234
+nb 24 0 0x2284
+product 24 0 0x220F
+sum 24 0 0x2211
+SP 24 0 0x2660
+CL 24 0 0x2663
+HE 24 0 0x2665
+DI 24 0 0x2666
+
+"devps" maps \(a~ and ~ to asciitilde, which is equivalent to 0x02DC, but
+this glyph is just too small. We map them to 0x007E instead.
+
+"devps" maps \(a^ and ^ to circumflex, which is equivalent to 0x02C6, but
+this glyph is just too small. We map them to 0x005E instead.
+
+"devps" maps *m to mu, which is equivalent to either 0x00B5 or 0x03BC. We
+map it to 0x03BC.
+
+"devps" maps *U to Upsilon1, which is equivalent to 0x03D2. We map it to
+0x03A5 instead.
+
+"devps" maps *W to Omega, which is equivalent to either 0x2126 or 0x03A9. We
+map it to 0x03A9.
+
+"devps" maps *D to Delta, which is equivalent to either 0x2206 or 0x0394. We
+map it to 0x0394.
+
+"devps" maps CR to carriagereturn, which is equivalent to 0x21B5. We map it
+to 0x240D instead.
+
+"devps" maps md to dotmath, which is equivalent to 0x22C5. We map it to 0x00B7
+instead.
+
+The line
+char173 24 0 0x00AD
+has been removed, because tmac.tty contains the line
+".if c\[char173] .shc \[char173]"
+(i.e. if char173 is defined, then tell the troff engine that it shall use
+char173 as soft hyphen - otherwise it will use hy = HYPHEN), and char173 in
+Markus Kuhn's UCS-fonts looks more like a minus sign than like a hyphen.
+Once Markus Kuhn's fonts are fixed, this line should be added again, because
+ISO-8859-x describes the soft hyphen character as "a graphic character that
+is imaged by a graphic symbol identical with, or similar to, that representing
+HYPHEN, for use when a line break has been established within a word" - which
+is exactly groff's use of 'shc'.
+
+Using unnamed characters:
+Assume you want to use a Unicode character not provided in the list, say
+U+20AC. You need to do two things:
+- Add a line "--- 24 0 0x20AC" (the second column is
+ computed as 24 * wcwidth(0x20AC)) to the file R.proto, or, when groff
+ is already installed, to the four fonts files in
+ $(prefix)/share/groff/font/devutf8/.
+- In your source file, use the notation \N'8364' where 8364 is the decimal
+ representation of 0x20AC.
+
diff --git a/font/devutf8/R.proto b/font/devutf8/R.proto
new file mode 100644
index 00000000..faff6d85
--- /dev/null
+++ b/font/devutf8/R.proto
@@ -0,0 +1,468 @@
+name R
+internalname 0
+spacewidth 24
+charset
+! 24 0 0x0021
+" 24 0 0x0022
+# 24 0 0x0023
+sh "
+$ 24 0 0x0024
+Do "
+% 24 0 0x0025
+& 24 0 0x0026
+aq 24 0 0x0027
+( 24 0 0x0028
+) 24 0 0x0029
+* 24 0 0x002A
++ 24 0 0x002B
+pl "
+, 24 0 0x002C
+--- 24 0 0x002D
+. 24 0 0x002E
+/ 24 0 0x002F
+sl "
+0 24 0 0x0030
+1 24 0 0x0031
+2 24 0 0x0032
+3 24 0 0x0033
+4 24 0 0x0034
+5 24 0 0x0035
+6 24 0 0x0036
+7 24 0 0x0037
+8 24 0 0x0038
+9 24 0 0x0039
+: 24 0 0x003A
+; 24 0 0x003B
+< 24 0 0x003C
+= 24 0 0x003D
+eq "
+> 24 0 0x003E
+? 24 0 0x003F
+@ 24 0 0x0040
+at "
+A 24 0 0x0041
+B 24 0 0x0042
+C 24 0 0x0043
+D 24 0 0x0044
+E 24 0 0x0045
+F 24 0 0x0046
+G 24 0 0x0047
+H 24 0 0x0048
+I 24 0 0x0049
+J 24 0 0x004A
+K 24 0 0x004B
+L 24 0 0x004C
+M 24 0 0x004D
+N 24 0 0x004E
+O 24 0 0x004F
+P 24 0 0x0050
+Q 24 0 0x0051
+R 24 0 0x0052
+S 24 0 0x0053
+T 24 0 0x0054
+U 24 0 0x0055
+V 24 0 0x0056
+W 24 0 0x0057
+X 24 0 0x0058
+Y 24 0 0x0059
+Z 24 0 0x005A
+[ 24 0 0x005B
+lB "
+\ 24 0 0x005C
+rs "
+] 24 0 0x005D
+rB "
+a^ 24 0 0x005E
+^ "
+ha "
+_ 24 0 0x005F
+ru "
+ul "
+\` 24 0 0x0060
+ga "
+a 24 0 0x0061
+b 24 0 0x0062
+c 24 0 0x0063
+d 24 0 0x0064
+e 24 0 0x0065
+f 24 0 0x0066
+g 24 0 0x0067
+h 24 0 0x0068
+i 24 0 0x0069
+j 24 0 0x006A
+k 24 0 0x006B
+l 24 0 0x006C
+m 24 0 0x006D
+n 24 0 0x006E
+o 24 0 0x006F
+p 24 0 0x0070
+q 24 0 0x0071
+r 24 0 0x0072
+s 24 0 0x0073
+t 24 0 0x0074
+u 24 0 0x0075
+v 24 0 0x0076
+w 24 0 0x0077
+x 24 0 0x0078
+y 24 0 0x0079
+z 24 0 0x007A
+lC 24 0 0x007B
+{ "
+ba 24 0 0x007C
+or "
+| "
+rC 24 0 0x007D
+} "
+a~ 24 0 0x007E
+~ "
+ti "
+r! 24 0 0x00A1
+char161 "
+ct 24 0 0x00A2
+char162 "
+Po 24 0 0x00A3
+char163 "
+Cs 24 0 0x00A4
+char164 "
+Ye 24 0 0x00A5
+char165 "
+bb 24 0 0x00A6
+char166 "
+sc 24 0 0x00A7
+char167 "
+ad 24 0 0x00A8
+char168 "
+co 24 0 0x00A9
+char169 "
+Of 24 0 0x00AA
+char170 "
+Fo 24 0 0x00AB
+char171 "
+no 24 0 0x00AC
+char172 "
+rg 24 0 0x00AE
+char174 "
+a- 24 0 0x00AF
+char175 "
+de 24 0 0x00B0
+char176 "
++- 24 0 0x00B1
+char177 "
+S2 24 0 0x00B2
+char178 "
+S3 24 0 0x00B3
+char179 "
+aa 24 0 0x00B4
+char180 "
+char181 24 0 0x00B5
+ps 24 0 0x00B6
+char182 "
+md 24 0 0x00B7
+char183 "
+ac 24 0 0x00B8
+char184 "
+S1 24 0 0x00B9
+char185 "
+Om 24 0 0x00BA
+char186 "
+Fc 24 0 0x00BB
+char187 "
+14 24 0 0x00BC
+char188 "
+12 24 0 0x00BD
+char189 "
+34 24 0 0x00BE
+char190 "
+r? 24 0 0x00BF
+char191 "
+`A 24 0 0x00C0
+char192 "
+'A 24 0 0x00C1
+char193 "
+^A 24 0 0x00C2
+char194 "
+~A 24 0 0x00C3
+char195 "
+:A 24 0 0x00C4
+char196 "
+oA 24 0 0x00C5
+char197 "
+AE 24 0 0x00C6
+char198 "
+,C 24 0 0x00C7
+char199 "
+`E 24 0 0x00C8
+char200 "
+'E 24 0 0x00C9
+char201 "
+^E 24 0 0x00CA
+char202 "
+:E 24 0 0x00CB
+char203 "
+`I 24 0 0x00CC
+char204 "
+'I 24 0 0x00CD
+char205 "
+^I 24 0 0x00CE
+char206 "
+:I 24 0 0x00CF
+char207 "
+-D 24 0 0x00D0
+char208 "
+~N 24 0 0x00D1
+char209 "
+`O 24 0 0x00D2
+char210 "
+'O 24 0 0x00D3
+char211 "
+^O 24 0 0x00D4
+char212 "
+~O 24 0 0x00D5
+char213 "
+:O 24 0 0x00D6
+char214 "
+mu 24 0 0x00D7
+char215 "
+/O 24 0 0x00D8
+char216 "
+`U 24 0 0x00D9
+char217 "
+'U 24 0 0x00DA
+char218 "
+^U 24 0 0x00DB
+char219 "
+:U 24 0 0x00DC
+char220 "
+'Y 24 0 0x00DD
+char221 "
+TP 24 0 0x00DE
+char222 "
+ss 24 0 0x00DF
+char223 "
+`a 24 0 0x00E0
+char224 "
+'a 24 0 0x00E1
+char225 "
+^a 24 0 0x00E2
+char226 "
+~a 24 0 0x00E3
+char227 "
+:a 24 0 0x00E4
+char228 "
+oa 24 0 0x00E5
+char229 "
+ae 24 0 0x00E6
+char230 "
+,c 24 0 0x00E7
+char231 "
+`e 24 0 0x00E8
+char232 "
+'e 24 0 0x00E9
+char233 "
+^e 24 0 0x00EA
+char234 "
+:e 24 0 0x00EB
+char235 "
+`i 24 0 0x00EC
+char236 "
+'i 24 0 0x00ED
+char237 "
+^i 24 0 0x00EE
+char238 "
+:i 24 0 0x00EF
+char239 "
+Sd 24 0 0x00F0
+char240 "
+~n 24 0 0x00F1
+char241 "
+`o 24 0 0x00F2
+char242 "
+'o 24 0 0x00F3
+char243 "
+^o 24 0 0x00F4
+char244 "
+~o 24 0 0x00F5
+char245 "
+:o 24 0 0x00F6
+char246 "
+di 24 0 0x00F7
+char247 "
+/o 24 0 0x00F8
+char248 "
+`u 24 0 0x00F9
+char249 "
+'u 24 0 0x00FA
+char250 "
+^u 24 0 0x00FB
+char251 "
+:u 24 0 0x00FC
+char252 "
+'y 24 0 0x00FD
+char253 "
+Tp 24 0 0x00FE
+char254 "
+:y 24 0 0x00FF
+char255 "
+.i 24 0 0x0131
+/L 24 0 0x0141
+/l 24 0 0x0142
+OE 24 0 0x0152
+oe 24 0 0x0153
+Fn 24 0 0x0192
+ah 24 0 0x02C7
+ab 24 0 0x02D8
+a. 24 0 0x02D9
+ao 24 0 0x02DA
+ho 24 0 0x02DB
+a" 24 0 0x02DD
+*A 24 0 0x0391
+*B 24 0 0x0392
+*G 24 0 0x0393
+*D 24 0 0x0394
+*E 24 0 0x0395
+*Z 24 0 0x0396
+*Y 24 0 0x0397
+*H 24 0 0x0398
+*I 24 0 0x0399
+*K 24 0 0x039A
+*L 24 0 0x039B
+*M 24 0 0x039C
+*N 24 0 0x039D
+*C 24 0 0x039E
+*O 24 0 0x039F
+*P 24 0 0x03A0
+*R 24 0 0x03A1
+*S 24 0 0x03A3
+*T 24 0 0x03A4
+*U 24 0 0x03A5
+*F 24 0 0x03A6
+*X 24 0 0x03A7
+*Q 24 0 0x03A8
+*W 24 0 0x03A9
+*a 24 0 0x03B1
+*b 24 0 0x03B2
+*g 24 0 0x03B3
+*d 24 0 0x03B4
+*e 24 0 0x03B5
+*z 24 0 0x03B6
+*y 24 0 0x03B7
+*h 24 0 0x03B8
+*i 24 0 0x03B9
+*k 24 0 0x03BA
+*l 24 0 0x03BB
+*m 24 0 0x03BC
+*n 24 0 0x03BD
+*c 24 0 0x03BE
+*o 24 0 0x03BF
+*p 24 0 0x03C0
+*r 24 0 0x03C1
+ts 24 0 0x03C2
+*s 24 0 0x03C3
+*t 24 0 0x03C4
+*u 24 0 0x03C5
+*f 24 0 0x03C6
+*x 24 0 0x03C7
+*q 24 0 0x03C8
+*w 24 0 0x03C9
++h 24 0 0x03D1
++f 24 0 0x03D5
++p 24 0 0x03D6
+- 24 0 0x2010
+hy "
+en 24 0 0x2013
+em 24 0 0x2014
+` 24 0 0x2018
+oq "
+' 24 0 0x2019
+bq 24 0 0x201A
+lq 24 0 0x201C
+rq 24 0 0x201D
+Bq 24 0 0x201E
+dg 24 0 0x2020
+dd 24 0 0x2021
+bu 24 0 0x2022
+%0 24 0 0x2030
+fm 24 0 0x2032
+sd 24 0 0x2033
+fo 24 0 0x2039
+fc 24 0 0x203A
+rn 24 0 0x203E
+f/ 24 0 0x2044
+Im 24 0 0x2111
+wp 24 0 0x2118
+Re 24 0 0x211C
+tm 24 0 0x2122
+Ah 24 0 0x2135
+<- 24 0 0x2190
+ua 24 0 0x2191
+-> 24 0 0x2192
+da 24 0 0x2193
+<> 24 0 0x2194
+lA 24 0 0x21D0
+uA 24 0 0x21D1
+rA 24 0 0x21D2
+dA 24 0 0x21D3
+hA 24 0 0x21D4
+fa 24 0 0x2200
+pd 24 0 0x2202
+te 24 0 0x2203
+es 24 0 0x2205
+gr 24 0 0x2207
+mo 24 0 0x2208
+nm 24 0 0x2209
+st 24 0 0x220B
+\- 24 0 0x2212
+mi "
+** 24 0 0x2217
+sr 24 0 0x221A
+pt 24 0 0x221D
+if 24 0 0x221E
+/_ 24 0 0x2220
+AN 24 0 0x2227
+OR 24 0 0x2228
+ca 24 0 0x2229
+cu 24 0 0x222A
+is 24 0 0x222B
+tf 24 0 0x2234
+ti 24 0 0x223C
+ap "
+=~ 24 0 0x2245
+~~ 24 0 0x2248
+~= "
+!= 24 0 0x2260
+== 24 0 0x2261
+<= 24 0 0x2264
+>= 24 0 0x2265
+sb 24 0 0x2282
+sp 24 0 0x2283
+ib 24 0 0x2286
+ip 24 0 0x2287
+c+ 24 0 0x2295
+c* 24 0 0x2297
+pp 24 0 0x22A5
+lc 24 0 0x2308
+rc 24 0 0x2309
+lf 24 0 0x230A
+rf 24 0 0x230B
+la 24 0 0x2329
+ra 24 0 0x232A
+CR 24 0 0x240D
+an 24 0 0x2500
+br 24 0 0x2502
+bv "
+rk 24 0 0x251D
+lk 24 0 0x2525
+lt 24 0 0x256D
+rt 24 0 0x256E
+rb 24 0 0x256F
+lb 24 0 0x2570
+sq 24 0 0x25A1
+lz 24 0 0x25CA
+ci 24 0 0x25EF
+lh 24 0 0x261C
+rh 24 0 0x261E
+ff 24 0 0xFB00
+fi 24 0 0xFB01
+fl 24 0 0xFB02
+Fi 24 0 0xFB03
+Fl 24 0 0xFB04
diff --git a/gendef.sh b/gendef.sh
new file mode 100644
index 00000000..e2b2575f
--- /dev/null
+++ b/gendef.sh
@@ -0,0 +1,24 @@
+# gendef filename var=val var=val
+
+file=$1
+shift
+
+defs="#define $1"
+shift
+for def
+do
+ defs="$defs
+#define $def"
+done
+
+t=/tmp/groff.$$
+
+sed -e 's/=/ /' >$t <<EOF
+$defs
+EOF
+
+test -r $file && cmp -s $t $file || cp $t $file
+
+rm -f $t
+
+exit 0
diff --git a/install-sh b/install-sh
new file mode 100755
index 00000000..89fc9b09
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# 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.
+#
+
+
+# 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}"
+
+tranformbasename=""
+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=:
+ 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/man/Makefile.sub b/man/Makefile.sub
new file mode 100644
index 00000000..cb596da4
--- /dev/null
+++ b/man/Makefile.sub
@@ -0,0 +1,5 @@
+MAN5=\
+ groff_font.n \
+ groff_out.n
+MAN7=\
+ groff_char.n
diff --git a/man/groff_char.man b/man/groff_char.man
new file mode 100644
index 00000000..18085dce
--- /dev/null
+++ b/man/groff_char.man
@@ -0,0 +1,563 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.\" For best results, print this with groff.
+.ds aq \(aq
+.ie !\n(.g .if '\(aq'' .ds aq \'
+.el \{\
+. tr \(aq\(aq
+. if !c\(aq .ds aq \'
+.\}
+.if !\n(.g .ig
+.\" .Ac accented-char accent char
+.de Ac
+.char \\$1 \\$3\
+\k[acc]\
+\h'(u;-\w'\\$2'-\w'\\$3'/2+\\\\n[skw]+(\w'x'*0)-\\\\n[skw])'\
+\v'(u;\w'x'*0+\\\\n[rst]+(\w'\\$3'*0)-\\\\n[rst])'\
+\\$2\
+\v'(u;\w'x'*0-\\\\n[rst]+(\w'\\$3'*0)+\\\\n[rst])'\
+\h'|\\\\n[acc]u'
+.hcode \\$1\\$3
+..
+.Ac \(vc \(ah c
+.Ac \(vC \(ah C
+.TH GROFF_CHAR @MAN7EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+groff_char \- groff character names
+.SH DESCRIPTION
+This manual page lists the standard
+.B groff
+input characters.
+Only the characters that are available for the device that
+is being used to print this manual page will be displayed.
+The
+.I "Input code"
+column applies to characters which can be
+input with a single character, and gives the ISO Latin-1 code
+of that input character.
+The
+.I "PostScript name\"
+column gives the usual PostScript name of the output character.
+.LP
+The ISO Latin-1 no-break space (code 0240 octal) is equivalent to
+.BR \e (space).
+All other ISO Latin-1 characters print as themselves with the following
+exceptions:
+.B \`
+prints as `,
+.B \*(aq
+prints as ';
+the corresponding ISO Latin-1 characters can be obtained with
+.B \e`
+and
+.BR \e(aq .
+The ISO Latin-1 `Hyphen, Minus Sign' (code 45) prints as a hyphen;
+a minus sign can be obtained with
+.BR \e- .
+The ISO Latin-1 `Tilde' (code 126) prints as ~;
+the larger glyph can be obtained with
+.BR \e(ti .
+The ISO Latin-1 `Circumflex Accent' (code 94) prints as ^;
+a larger glyph can be obtained with
+.BR \e(ha .
+.sp
+'nf
+.nr Sp 3n
+.ta \w'\fIOutput'u+\n(Spu +\w'\fIInput'u+\n(Spu +\w'\fIInput'u+\n(Spu \
++\w'periodcentered'u+\n(Spu
+.de C0
+.C \\$1 "" \\$1 \\$2 "\\$3"
+..
+.de C1
+.C \e\\$1 "" \\\\\\$1 \\$2 "\\$3"
+..
+.de C2
+.C \e(\\$1 "" \\(\\$1 \\$2 "\\$3"
+..
+.if !\n(.g .ig
+.de CD
+.C \[char\\$1] \\$1 \[char\\$1] \\$2 "\\$3"
+..
+.do fspecial CR R
+.\" input-name decimal-code output-name ps-name description
+.if !\n(.g .ig
+.de C
+.if c\\$3 \{\
+.ft CR
+.tr `\`'\*(aq
+.in 0
+.di CH
+\&\\$1
+.br
+.di
+.in
+.ft
+.ds CH \\*(CH\
+.tr ``''
+\&\\$3\t\\*(CH\t\\$2\t\\$4\t\\$5
+.\}
+..
+.if \n(.g .ig
+.de C
+.if !'\\$3'' \{\
+.ft B
+.tr `\`'\*(aq
+.in 0
+.di CH
+\&\\$1
+.br
+.di
+.in
+.ft
+.ds CH \\*(CH\
+.tr ``''
+\&\\$3\t\\*(CH\t\\$2\t\\$4\t\\$5
+.\}
+..
+.wh \n(nlu+\n(.tu-\n(.Vu Fo
+.de Fo
+'bp
+.He
+..
+.de He
+.ft I
+Output Input Input PostScript Notes
+ name code name
+.ft
+.LP
+'nf
+..
+.He
+.CD 33 exclam
+.CD 34 quotedbl
+.CD 35 numbersign
+.CD 36 dollar
+.CD 37 percent
+.CD 38 ampersand
+.CD 39 quoteright
+.CD 40 parenleft
+.CD 41 parenright
+.CD 42 asterisk
+.CD 43 plus
+.CD 44 comma
+.CD 45 hyphen
+.CD 46 period
+.CD 47 slash
+.CD 58 colon
+.CD 59 semicolon
+.CD 60 less
+.CD 61 equal
+.CD 62 greater
+.CD 63 question
+.CD 64 at
+.CD 91 bracketleft
+.CD 92 backslash
+.CD 93 bracketright
+.CD 94 circumflex "circumflex accent"
+.CD 95 underscore
+.CD 96 quoteleft
+.CD 123 braceleft
+.CD 124 bar
+.CD 125 braceright
+.CD 126 tilde "tilde accent"
+.CD 161 exclamdown
+.CD 162 cent
+.CD 163 sterling
+.CD 164 currency
+.CD 165 yen
+.CD 166 brokenbar
+.CD 167 section
+.CD 168 dieresis
+.CD 169 copyright
+.CD 170 ordfeminine
+.CD 171 guillemotleft
+.CD 172 logicalnot
+.CD 173 hyphen
+.CD 174 registered
+.CD 175 macron
+.CD 176 degree
+.CD 177 plusminus
+.CD 178 twosuperior
+.CD 179 threesuperior
+.CD 180 acute "acute accent"
+.CD 181 mu
+.CD 182 paragraph
+.CD 183 periodcentered
+.CD 184 cedilla
+.CD 185 onesuperior
+.CD 186 ordmasculine
+.CD 187 guillemotright
+.CD 188 onequarter
+.CD 189 onehalf
+.CD 190 threequarters
+.CD 191 questiondown
+.CD 192 Agrave
+.CD 193 Aacute
+.CD 194 Acircumflex
+.CD 195 Atilde
+.CD 196 Adieresis
+.CD 197 Aring
+.CD 198 AE
+.CD 199 Ccedilla
+.CD 200 Egrave
+.CD 201 Eacute
+.CD 202 Ecircumflex
+.CD 203 Edieresis
+.CD 204 Igrave
+.CD 205 Iacute
+.CD 206 Icircumflex
+.CD 207 Idieresis
+.CD 208 Eth
+.CD 209 Ntilde
+.CD 210 Ograve
+.CD 211 Oacute
+.CD 212 Ocircumflex
+.CD 213 Otilde
+.CD 214 Odieresis
+.CD 215 multiply
+.CD 216 Oslash
+.CD 217 Ugrave
+.CD 218 Uacute
+.CD 219 Ucircumflex
+.CD 220 Udieresis
+.CD 221 Yacute
+.CD 222 Thorn
+.CD 223 germandbls
+.CD 224 agrave
+.CD 225 aacute
+.CD 226 acircumflex
+.CD 227 atilde
+.CD 228 adieresis
+.CD 229 aring
+.CD 230 ae
+.CD 231 ccedilla
+.CD 232 egrave
+.CD 233 eacute
+.CD 234 ecircumflex
+.CD 235 edieresis
+.CD 236 igrave
+.CD 237 iacute
+.CD 238 icircumflex
+.CD 239 idieresis
+.CD 240 eth
+.CD 241 ntilde
+.CD 242 ograve
+.CD 243 oacute
+.CD 244 ocircumflex
+.CD 245 otilde
+.CD 246 odieresis
+.CD 247 divide
+.CD 248 oslash
+.CD 249 ugrave
+.CD 250 uacute
+.CD 251 ucircumflex
+.CD 252 udieresis
+.CD 253 yacute
+.CD 254 thorn
+.CD 255 ydieresis
+.C2 -D Eth "Icelandic uppercase eth"
+.C2 Sd eth "Icelandic lowercase eth"
+.C2 TP Thorn "Icelandic uppercase thorn"
+.C2 Tp thorn "Icelandic lowercase thorn"
+.C2 AE AE
+.C2 ae ae
+.C2 OE OE
+.C2 oe oe
+.C2 IJ IJ "Dutch IJ ligature"
+.C2 ij ij "Dutch ij ligature"
+.C2 ss germandbls
+.C2 'A Aacute
+.C2 'C Cacute
+.C2 'E Eacute
+.C2 'I Iacute
+.C2 'O Oacute
+.C2 'U Uacute
+.C2 'a aacute
+.C2 'c cacute
+.C2 'e eacute
+.C2 'i iacute
+.C2 'o oacute
+.C2 'u uacute
+.C2 :A Adieresis
+.C2 :E Edieresis
+.C2 :I Idieresis
+.C2 :O Odieresis
+.C2 :U Udieresis
+.C2 :Y Ydieresis
+.C2 :a adieresis
+.C2 :e edieresis
+.C2 :i idieresis
+.C2 :o odieresis
+.C2 :u udieresis
+.C2 :y ydieresis
+.C2 ^A Acircumflex
+.C2 ^E Ecircumflex
+.C2 ^I Icircumflex
+.C2 ^O Ocircumflex
+.C2 ^U Ucircumflex
+.C2 ^a acircumflex
+.C2 ^e ecircumflex
+.C2 ^i icircumflex
+.C2 ^o ocircumflex
+.C2 ^u ucircumflex
+.C2 `A Agrave
+.C2 `E Egrave
+.C2 `I Igrave
+.C2 `O Ograve
+.C2 `U Ugrave
+.C2 `a agrave
+.C2 `e egrave
+.C2 `i igrave
+.C2 `o ograve
+.C2 `u ugrave
+.C2 ~A Atilde
+.C2 ~N Ntilde
+.C2 ~O Otilde
+.C2 ~a atilde
+.C2 ~n ntilde
+.C2 ~o otilde
+.C2 vS Scaron
+.C2 vs scaron
+.C2 vZ Zcaron
+.C2 vz zcaron
+.C2 ,C Ccedilla
+.C2 ,c ccedilla
+.C2 /L Lslash "Polish L with a slash"
+.C2 /l lslash "Polish l with a slash"
+.C2 /O Oslash
+.C2 /o oslash
+.C2 oA Aring
+.C2 oa aring
+.C2 a" hungarumlaut "Hungarian umlaut"
+.C2 a- macron "macron or bar accent"
+.C2 a. dotaccent "dot accent"
+.C2 a^ circumflex "circumflex accent"
+.C2 aa acute "acute accent"
+.C2 ga grave "grave accent"
+.C2 ab breve "breve accent"
+.C2 ac cedilla "cedilla accent"
+.C2 ad dieresis "umlaut or dieresis"
+.C2 ah caron "h\('a\(vcek accent"
+.C2 ao ring "ring or circle accent"
+.C2 a~ tilde "tilde accent"
+.C2 ho ogonek "hook or ogonek accent"
+.C2 .i dotlessi "i without a dot"
+.C2 .j dotlessj "j without a dot"
+.C2 Cs currency "Scandinavian currency sign"
+.C2 Do dollar
+.C2 Po sterling
+.C2 Ye yen
+.C2 Fn florin
+.C2 ct cent
+.C2 Fo guillemotleft
+.C2 Fc guillemotright
+.C2 fo guilsinglleft
+.C2 fc guilsinglright
+.C2 r! exclamdown
+.C2 r? questiondown
+.C2 ff ff "ff ligature"
+.C2 fi fi "fi ligature"
+.C2 fl fl "fl ligature"
+.C2 Fi ffi "ffi ligature"
+.C2 Fl ffl "ffl ligature"
+.C2 OK \& "check mark, tick"
+.C2 Of ordfeminine
+.C2 Om ordmasculine
+.C2 S1 onesuperior
+.C2 S2 twosuperior
+.C2 S3 threesuperior
+.C2 <- arrowleft
+.C2 -> arrowright
+.C2 <> arrowboth "horizontal double-headed arrow"
+.C2 da arrowdown
+.C2 ua arrowup
+.C2 va \& "vertical double-headed arrow"
+.C2 lA arrowdblleft
+.C2 rA arrowdblright
+.C2 hA arrowdblboth "horizontal double-headed double arrow"
+.C2 dA arrowdbldown
+.C2 uA arrowdblup
+.C2 vA \& "vertical double-headed double arrow"
+.C2 ba bar
+.C2 bb brokenbar
+.C2 br br "box rule with traditional troff metrics"
+.C2 ru ru "baseline rule"
+.C2 ul ul "underline with traditional troff metrics"
+.C2 bv bv "bold vertical"
+.C2 bs bell
+.C2 ci circle
+.C2 bu bullet
+.C2 co copyright
+.C2 rg registered
+.C2 tm trademark
+.C2 dd daggerdbl "double dagger sign"
+.C2 dg dagger
+.C2 ps paragraph
+.C2 sc section
+.C2 de degree
+.C2 em emdash "em dash"
+.C2 en endash "en dash"
+.C2 %0 perthousand "per thousand, per mille sign"
+.C2 12 onehalf
+.C2 14 onequarter
+.C2 34 threequarters
+.C2 f/ fraction "bar for fractions"
+.C2 fm minute "footmark, prime"
+.C2 sd second
+.C2 ha asciicircum "\s-2ASCII\s+2 circumflex, hat, caret"
+.C2 ti asciitilde "\s-2ASCII\s0 tilde, large tilde"
+.C2 hy hyphen
+.C2 lB bracketleft
+.C2 rB bracketright
+.C2 lC braceleft
+.C2 rC braceright
+.C2 la angleleft "left angle bracket"
+.C2 ra angleright "right angle bracket"
+.C2 lh handleft
+.C2 rh handright
+.C2 Bq quotedblbase "low double comma quote"
+.C2 bq quotesinglbase "low single comma quote"
+.C2 lq quotedblleft
+.C2 rq quotedblright
+.C2 oq quoteleft "single open quote"
+.C2 aq quotesingle "apostrophe quote"
+.C2 or bar
+.C2 at at
+.C1 - minus "minus sign from current font"
+.C2 sh numbersign
+.C2 sl slash
+.C2 rs backslash
+.C2 sq square
+.C2 3d therefore
+.C2 tf therefore
+.C2 *A Alpha
+.C2 *B Beta
+.C2 *C Xi
+.C2 *D Delta
+.C2 *E Epsilon
+.C2 *F Phi
+.C2 *G Gamma
+.C2 *H Theta
+.C2 *I Iota
+.C2 *K Kappa
+.C2 *L Lambda
+.C2 *M Mu
+.C2 *N Nu
+.C2 *O Omicron
+.C2 *P Pi
+.C2 *Q Psi
+.C2 *R Rho
+.C2 *S Sigma
+.C2 *T Tau
+.C2 *U Upsilon
+.C2 *W Omega
+.C2 *X Chi
+.C2 *Y Eta
+.C2 *Z Zeta
+.C2 *a alpha
+.C2 *b beta
+.C2 *c xi
+.C2 *d delta
+.C2 *e epsilon
+.C2 *f phi
+.C2 +f phi1 "variant phi"
+.C2 *g gamma
+.C2 *h theta
+.C2 +h theta1 "variant theta"
+.C2 *i iota
+.C2 *k kappa
+.C2 *l lambda
+.C2 *m mu
+.C2 *n nu
+.C2 *o omicron
+.C2 *p pi
+.C2 +p omega1 "variant pi, looking like omega"
+.C2 *q psi
+.C2 *r rho
+.C2 *s sigma
+.C2 *t tau
+.C2 *u upsilon
+.C2 *w omega
+.C2 *x chi
+.C2 *y eta
+.C2 *z zeta
+.C2 ts sigma1 "terminal sigma"
+.C2 ~~ approxequal
+.C2 ~= approxequal
+.C2 != notequal
+.C2 ** asteriskmath
+.C2 -+ minusplus
+.C2 +- plusminus
+.C2 <= lessequal
+.C2 == equivalence
+.C2 =~ congruent
+.C2 >= greaterequal
+.C2 AN logicaland
+.C2 OR logicalor
+.C2 no logicalnot
+.C2 te existential "there exists, existential quantifier"
+.C2 fa universal "for all, universal quantifier"
+.C2 Ah aleph
+.C2 Im Ifraktur "Fraktur I, imaginary"
+.C2 Re Rfraktur "Fraktur R, real"
+.C2 if infinity
+.C2 md dotmath
+.C2 mo element
+.C2 mu multiply
+.C2 nb notsubset
+.C2 nc notpropersuperset
+.C2 ne notequivalence
+.C2 nm notelement
+.C2 pl plusmath "plus sign in special font"
+.C2 eq equalmath "equals sign in special font"
+.C2 pt proportional
+.C2 pp perpendicular
+.C2 sb propersubset
+.C2 sp propersuperset
+.C2 ib reflexsubset
+.C2 ip reflexsuperset
+.C2 ap similar
+.C2 pd partialdiff "partial differentiation sign"
+.C2 c* circlemultiply "multiply sign in a circle"
+.C2 c+ circleplus "plus sign in a circle"
+.C2 ca intersection "intersection, cap"
+.C2 cu union "union, cup"
+.C2 di divide "division sign"
+.C2 -h hbar
+.C2 gr gradient
+.C2 es emptyset
+.C2 CL club "club suit"
+.C2 SP spade "spade suit"
+.C2 HE heart "heart suit"
+.C2 DI diamond "diamond suit"
+.C2 CR carriagereturn "carriage return symbol"
+.C2 st suchthat
+.C2 /_ angle
+.C2 << "" "much less"
+.C2 >> "" "much greater"
+.C2 wp weierstrass "Weierstrass p"
+.C2 lz lozenge
+.C2 an arrowhorizex "horizontal arrow extension"
+.ch Fo
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@)
+.br
+.IR "An extension to the troff character set for Europe" ,
+E.G. Keizer, K.J. Simonsen, J. Akkerhuis,
+EUUG Newsletter, Volume 9, No. 2, Summer 1989
diff --git a/man/groff_font.man b/man/groff_font.man
new file mode 100644
index 00000000..e551e0a6
--- /dev/null
+++ b/man/groff_font.man
@@ -0,0 +1,389 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.de TQ
+.br
+.ns
+.TP \\$1
+..
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.TH GROFF_FONT @MAN5EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+groff_font \- format of groff device and font description files
+.SH DESCRIPTION
+The groff font format is roughly a superset of the ditroff
+font format.
+Unlike the ditroff font format, there is no associated binary
+format.
+The font files for device
+.I name
+are stored in a directory
+.BI dev name.
+There are two types of file: a
+device description file called
+.B DESC
+and for each font
+.I F
+a font file called
+.IR F .
+These are text files;
+there is no associated binary format.
+.SS DESC file format
+The DESC file can contain the following types of line:
+.TP
+.BI res\ n
+There are
+.I n
+machine units per inch.
+.TP
+.BI hor\ n
+The horizontal resolution is
+.I n
+machine units.
+.TP
+.BI vert\ n
+The vertical resolution is
+.I n
+machine units.
+.TP
+.BI sizescale\ n
+The scale factor for pointsizes.
+By default this has a value of 1.
+One
+.I
+scaled point
+is equal to
+one
+.RI point/ n .
+The arguments to the
+.B unitwidth
+and
+.B sizes
+commands are given in scaled points.
+.TP
+.BI unitwidth\ n
+Quantities in the font files are given in machine units
+for fonts whose point size is
+.I n
+scaled points.
+.TP
+.B tcommand
+This means that the postprocessor can handle the
+.B t
+and
+.B u
+output commands.
+.TP
+.BI sizes\ s1\ s2\|.\|.\|.\|sn\ 0
+This means that the device has fonts at
+.IR s1 ,
+.IR s2 ,\|.\|.\|.\| sn
+scaled points.
+The list of sizes must be terminated by a
+.BR 0 .
+Each
+.BI s i
+can also be a range of sizes
+.IR m \- n .
+The list can extend over more than one line.
+.TP
+.BI styles\ S1\ S2\|.\|.\|.\|Sm
+The first
+.I m
+font positions will be associated with styles
+.IR S1\|.\|.\|.\|Sm .
+.TP
+.BI fonts\ n\ F1\ F2\ F3\|.\|.\|.\|Fn
+Fonts
+.I F1\|.\|.\|.\|Fn
+will be mounted in the font positions
+.IR m +1,\|.\|.\|., m + n
+where
+.I m
+is the number of styles.
+This command may extend over more than one line.
+A font name of
+.B 0
+will cause no font to be mounted on the corresponding font position.
+.TP
+.BI family\ fam
+The default font family is
+.IR fam .
+.TP
+.B use_charnames_in_special
+This command indicates that troff should encode named characters inside
+special commands.
+.TP
+.B pass_filenames
+requests that troff tells the driver the source file name being processed.
+This is achieved by another tcommand:
+.B F
+.IR filename .
+.TP
+.B charset
+This line and everything following in the file are ignored.
+It is allowed for the sake of backwards compatibility.
+.LP
+The res, unitwidth, fonts and sizes lines are compulsory.
+Other commands are ignored by
+.B troff
+but may be used by postprocessors to store arbitrary information
+about the device in the DESC file.
+.SS Font file format
+A font file has two sections. The first section is a sequence
+of lines each containing a sequence of blank delimited
+words; the first word in the line is a key, and subsequent
+words give a value for that key.
+.TP
+.BI name\ F
+The name of the font is
+.IR F .
+.TP
+.BI spacewidth\ n
+The normal width of a space is
+.IR n .
+.TP
+.BI slant\ n
+The characters of the font have a slant of
+.I n
+degrees. (Positive means forward.)
+.TP
+.BI ligatures\ lig1\ lig2\|.\|.\|.\|lign\ \fR[ 0 \fR]
+Characters
+.IR lig1 ,
+.IR lig2 ,\|.\|.\|., lign
+are ligatures; possible ligatures are
+.BR ff ,
+.BR fi ,
+.BR fl
+and
+.BR ffl .
+For backwards compatibility, the list of ligatures may be terminated
+with a
+.BR 0.
+The list of ligatures may not extend over more than one line.
+.TP
+.B special
+The font is
+.IR special ;
+this means that when a character is requested that is not present in
+the current font, it will be searched for in any special fonts that
+are mounted.
+.LP
+Other commands are ignored by
+.B troff
+but may be used by postprocessors to store arbitrary information
+about the font in the font file.
+.LP
+The first section can contain comments which start with the
+.B #
+character and extend to the end of a line.
+.LP
+The second section contains one or two subsections.
+It must contain a
+.I charset
+subsection
+and it may also contain a
+.I kernpairs
+subsection.
+These subsections can appear in any order.
+Each subsection starts with a word on a line by itself.
+.LP
+The word
+.B charset
+starts the charset subsection.
+The
+.B charset
+line is followed by a sequence of lines.
+Each line gives information for one character.
+A line comprises a number of fields separated
+by blanks or tabs. The format is
+.IP
+.I name metrics type code
+.RI [ entity_name ]
+.RB [ --
+.IR comment ]
+.LP
+.I name
+identifies the character:
+if
+.I name
+is a single character
+.I c
+then it corresponds to the groff input character
+.IR c ;
+if it is of the form
+.BI \e c
+where c is a single character, then it
+corresponds to the groff input character
+.BI \e c\fR;
+otherwise it corresponds to the groff input character
+.BI \e[ name ]
+(if it is exactly two characters
+.I xx
+it can be entered as
+.BI \e( xx\fR.)
+Groff supports eight bit characters; however some utilities
+has difficulties with eight bit characters.
+For this reason, there is a convention that the name
+.BI char n
+is equivalent to the single character whose code is
+.I n .
+For example,
+.B char163
+would be equivalent to the character with code 163
+which is the pounds sterling sign in ISO Latin-1.
+The name
+.B \-\-\-
+is special and indicates that the character is unnamed;
+such characters can only be used by means of the
+.B \eN
+escape sequence in
+.BR troff .
+.LP
+The
+.I type
+field gives the character type:
+.TP
+1
+means the character has an descender, for example, p;
+.TP
+2
+means the character has an ascender, for example, b;
+.TP
+3
+means the character has both an ascender and a descender, for example,
+(.
+.LP
+The
+.I code
+field gives the code which the postprocessor uses to print the character.
+The character can also be input to groff using this code by means of the
+.B \eN
+escape sequence.
+The code can be any integer.
+If it starts with a
+.B 0
+it will be interpreted as octal;
+if it starts with
+.B 0x
+or
+.B 0X
+it will be intepreted as hexadecimal.
+.LP
+The
+.I entity_name
+field gives an ascii string identifying the glyph which the postprocessor
+uses to print the character.
+This field is optional and has been introduced so that the html device driver
+can encode its character set.
+For example, the character `\e[Po]' is represented as `&pound;' in html 4.0.
+.LP
+Anything on the line after the encoding field resp. after `-\&-' will
+be ignored.
+.LP
+The
+.I metrics
+field has the form:
+.IP
+.IR width [\fB, height [\fB, depth [\fB, italic_correction [\fB, \
+left_italic_correction [\fB, subscript_correction ]]]]]
+.LP
+There must not be any spaces between these subfields.
+Missing subfields are assumed to be 0.
+The subfields are all decimal integers.
+Since there is no associated binary format, these
+values are not required to fit into a variable of type
+.B char
+as they are in ditroff.
+The
+.I width
+subfields gives the width of the character.
+The
+.I height
+subfield gives the height of the character (upwards is positive);
+if a character does not extend above the baseline, it should be
+given a zero height, rather than a negative height.
+The
+.I depth
+subfield gives the depth of the character, that is, the distance
+below the lowest point below the baseline to which the
+character extends (downwards is positive);
+if a character does not extend below above the baseline, it should be
+given a zero depth, rather than a negative depth.
+The
+.I italic_correction
+subfield gives the amount of space that should be added after the
+character when it is immediately to be followed by a character
+from a roman font.
+The
+.I left_italic_correction
+subfield gives the amount of space that should be added before the
+character when it is immediately to be preceded by a character
+from a roman font.
+The
+.I subscript_correction
+gives the amount of space that should be added after a character
+before adding a subscript.
+This should be less than the italic correction.
+.LP
+A line in the charset section can also have the format
+.IP
+.I
+name \fB"
+.LP
+This indicates that
+.I name
+is just another name for the character mentioned in the
+preceding line.
+.LP
+The word
+.B kernpairs
+starts the kernpairs section.
+This contains a sequence of lines of the form:
+.IP
+.I
+c1 c2 n
+.LP
+This means that when character
+.I c1
+appears next to character
+.I c2
+the space between them should be increased by
+.IR n .
+Most entries in kernpairs section will have a negative value for
+.IR n .
+.SH FILES
+.Tp \w'@FONTDIR@/devname/DESC'u+3n
+.BI @FONTDIR@/dev name /DESC
+Device description file for device
+.IR name .
+.TP
+.BI @FONTDIR@/dev name / F
+Font file for font
+.I F
+of device
+.IR name .
+.SH "SEE ALSO"
+.BR groff_out (@MAN5EXT@),
+.BR @g@troff (@MAN1EXT@).
diff --git a/man/groff_out.man b/man/groff_out.man
new file mode 100644
index 00000000..09098232
--- /dev/null
+++ b/man/groff_out.man
@@ -0,0 +1,232 @@
+'\" e
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1999 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.\" This man page must be preprocessed with eqn.
+.ie \n(.g .ds ic \/
+.el .ds ic \^
+.TH GROFF_OUT @MAN5EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+groff_out \- groff intermediate output format
+.SH DESCRIPTION
+This manual page describes the format output by GNU troff.
+The output format used by GNU troff is very similar to that used
+by Unix device-independent troff. Only the differences are documented
+here.
+.LP
+The argument to the
+.B s
+command is in scaled points (units of
+.IR points/ n ,
+where
+.I n
+is the argument to the
+.B sizescale
+command in the DESC file.)
+The argument to the
+.B x\ Height
+command is also in scaled points.
+.LP
+The first three output commands are guaranteed to be:
+.IP
+.BI x\ T\ device
+.br
+.BI x\ res\ n\ h\ v
+.br
+.B x init
+.LP
+If the
+.B tcommand
+line is present in the DESC file, troff will use the following
+two commands
+.TP
+.BI t xxx
+.I xxx
+is any sequence of characters terminated by a space or a newline;
+the first character should be printed at the current position,
+the the current horizontal position should be increased by
+the width of the first character, and so on for each character.
+The width of the character is that given in the font file,
+appropriately scaled for the current point size, and rounded
+so that it is a multiple of the horizontal resolution.
+Special characters cannot be printed using this command.
+.TP
+.BI u n\ xxx
+This is same as the
+.B t
+command except that after printing each character, the current horizontal
+position is increased by the sum of the width of that character
+and
+.IR n .
+.LP
+Note that single characters can have the eighth bit set, as can the
+names of fonts and special characters.
+.LP
+The names of characters and fonts can be of arbitrary length; drivers
+should not assume that they will be only two characters long.
+.LP
+When a character is to be printed, that character will always be
+in the current font.
+Unlike device-independent troff, it is not necessary
+for drivers to search special fonts to find a character.
+.LP
+The
+.B D
+drawing command has been extended.
+These extensions will not be used by GNU pic if the
+.B \-n
+option is given.
+.TP
+\fBDf \fIn\fR\*(ic\en
+Set the shade of gray to be used for filling solid objects to
+.IR n ;
+.I n
+must be an integer between 0 and 1000, where 0 corresponds solid white
+and 1000 to solid black, and values in between correspond to
+intermediate shades of gray.
+This applies only to solid circles, solid ellipses and solid
+polygons.
+By default, a level of 1000 will be used.
+Whatever color a solid object has, it should completely obscure
+everything beneath it.
+A value greater than 1000 or less than 0 can also be used:
+this means fill with the shade of gray that is currently being used
+for lines and text.
+Normally this will be black, but some drivers may provide
+a way of changing this.
+.TP
+\fBDC \fId\fR\*(ic\en
+Draw a solid circle with a diameter of
+.I d
+with the leftmost point at the current position.
+.TP
+\fBDE \fIdx dy\fR\*(ic\en
+Draw a solid ellipse with a horizontal diameter of
+.I dx
+and a vertical diameter of
+.I dy
+with the leftmost point at the current position.
+.EQ
+delim $$
+.EN
+.TP
+\fBDp\fR $dx sub 1$ $dy sub 1$ $dx sub 2$ $dy sub 2$ $...$ $dx sub n$ $dy sub n$\en
+Draw a polygon with,
+for $i = 1 ,..., n+1$, the
+.IR i -th
+vertex at the current position
+$+ sum from j=1 to i-1 ( dx sub j , dy sub j )$.
+At the moment,
+GNU pic only uses this command to generate triangles and rectangles.
+.TP
+\fBDP\fR $dx sub 1$ $dy sub 1$ $dx sub 2$ $dy sub 2$ $...$ $dx sub n$ $dy sub n$\en
+Like
+.B Dp
+but draw a solid rather than outlined polygon.
+.TP
+\fBDt \fIn\fR\*(ic\en
+Set the current line thickness to
+.I n
+machine units.
+Traditionally Unix troff drivers use a line thickness proportional to the current
+point size; drivers should continue to do this if no
+.B Dt
+command has been given, or if a
+.B Dt
+command has been given with a negative value of
+.IR n .
+A zero value of
+.I n
+selects the smallest available line thickness.
+.LP
+A difficulty arises in how the current position should be changed after
+the execution of these commands.
+This is not of great importance since the code generated by GNU pic
+does not depend on this.
+Given a drawing command of the form
+.IP
+\fB\eD\(fm\fIc\fR $x sub 1$ $y sub 1$ $x sub 2$ $y sub 2$ $...$ $x sub n$ $y sub n$\(fm
+.LP
+where
+.I c
+is not one of
+.BR c ,
+.BR e ,
+.BR l ,
+.B a
+or
+.BR ~ ,
+Unix troff will treat each of the $x sub i$ as a horizontal quantity,
+and each of the $y sub i$ as a vertical quantity and will assume that
+the width of the drawn object is $sum from i=1 to n x sub i$,
+and that the height is $sum from i=1 to n y sub i$.
+(The assumption about the height can be seen by examining the
+.B st
+and
+.B sb
+registers after using such a
+.B D
+command in a \ew escape sequence.)
+This rule also holds for all the original drawing commands
+with the exception of
+.BR De .
+For the sake of compatibility GNU troff also follows this rule,
+even though it produces an ugly result in the case of the
+.BR Df ,
+.BR Dt ,
+and, to a lesser extent,
+.B DE
+commands.
+Thus after executing a
+.B D
+command of the form
+.IP
+\fBD\fIc\fR $x sub 1$ $y sub 1$ $x sub 2$ $y sub 2$ $...$ $x sub n$ $y sub n$\en
+.LP
+the current position should be increased by
+$( sum from i=1 to n x sub i , sum from i=1 to n y sub i )$.
+.LP
+There is a continuation convention which permits the argument to the
+.B x\ X
+command to contain newlines:
+when outputting the argument to the
+.B x\ X
+command, GNU troff
+will follow each newline in the argument with a
+.B +
+character
+(as usual, it will terminate the entire argument with a newline);
+thus if the line after the line containing the
+.B x\ X
+command starts with
+.BR + ,
+then the newline ending the line containing the
+.B x\ X
+command should be treated as part of the argument to the
+.B x\ X
+command,
+the
+.B +
+should be ignored,
+and the part of the line following the
+.B +
+should be treated like the part of the line following the
+.B x\ X
+command.
+.SH "SEE ALSO"
+.BR groff_font (@MAN5EXT@)
diff --git a/mdate.sh b/mdate.sh
new file mode 100644
index 00000000..6bdac9d4
--- /dev/null
+++ b/mdate.sh
@@ -0,0 +1,41 @@
+#! /bin/sh
+
+# Print the modification date of $1 `nicely'.
+
+# Don't want foreign dates.
+
+LANGUAGE=
+
+
+(date;
+if ls -L /dev/null 1>/dev/null 2>&1; then ls -L -l $1; else ls -l $1; fi
+) | awk '
+BEGIN {
+ full["Jan"] = "January"; number["Jan"] = 1;
+ full["Feb"] = "February"; number["Feb"] = 2;
+ full["Mar"] = "March"; number["Mar"] = 3;
+ full["Apr"] = "April"; number["Apr"] = 4;
+ full["May"] = "May"; number["May"] = 5;
+ full["Jun"] = "June"; number["Jun"] = 6;
+ full["Jul"] = "July"; number["Jul"] = 7;
+ full["Aug"] = "August"; number["Aug"] = 8;
+ full["Sep"] = "September"; number["Sep"] = 9;
+ full["Oct"] = "October"; number["Oct"] = 10;
+ full["Nov"] = "November"; number["Nov"] = 11;
+ full["Dec"] = "December"; number["Dec"] = 12;
+}
+
+NR == 1 {
+ month = $2;
+ year = $NF;
+}
+
+NR == 2 {
+ if ($(NF-1) ~ /:/) {
+ if (number[$(NF-3)] > number[month])
+ year--;
+ }
+ else
+ year = $(NF-1);
+ print $(NF-2), full[$(NF-3)], year
+}'
diff --git a/mkinstalldirs b/mkinstalldirs
new file mode 100755
index 00000000..69180fe8
--- /dev/null
+++ b/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 2000/02/06 09:34:43 wlemb 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" 1>&2
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/src/devices/grodvi/Makefile.sub b/src/devices/grodvi/Makefile.sub
new file mode 100644
index 00000000..0e5d32ca
--- /dev/null
+++ b/src/devices/grodvi/Makefile.sub
@@ -0,0 +1,6 @@
+PROG=grodvi
+MAN1=grodvi.n
+XLIBS=$(LIBDRIVER) $(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=dvi.o
+CCSRCS=$(srcdir)/dvi.cc
diff --git a/src/devices/grodvi/dvi.cc b/src/devices/grodvi/dvi.cc
new file mode 100644
index 00000000..5c62163a
--- /dev/null
+++ b/src/devices/grodvi/dvi.cc
@@ -0,0 +1,896 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "driver.h"
+
+#define DEFAULT_LINEWIDTH 40
+static int linewidth = DEFAULT_LINEWIDTH;
+
+static int draw_flag = 1;
+
+/* These values were chosen because:
+
+(MULTIPLIER*SIZESCALE)/(RES*UNITWIDTH) == 1/(2^20 * 72.27)
+
+and 57816 is an exact multiple of both 72.27*SIZESCALE and 72.
+
+The width in the groff font file is the product of MULTIPLIER and the
+width in the tfm file. */
+
+#define RES 57816
+#define RES_7227 (RES/7227)
+#define UNITWIDTH 131072
+#define SIZESCALE 100
+#define MULTIPLIER 1
+
+#define FILL_MAX 1000
+
+class dvi_font : public font {
+ dvi_font(const char *);
+public:
+ int checksum;
+ int design_size;
+ ~dvi_font();
+ void handle_unknown_font_command(const char *command, const char *arg,
+ const char *filename, int lineno);
+ static dvi_font *load_dvi_font(const char *);
+};
+
+dvi_font *dvi_font::load_dvi_font(const char *s)
+{
+ dvi_font *f = new dvi_font(s);
+ if (!f->load()) {
+ delete f;
+ return 0;
+ }
+ return f;
+}
+
+dvi_font::dvi_font(const char *nm)
+: font(nm), checksum(0), design_size(0)
+{
+}
+
+dvi_font::~dvi_font()
+{
+}
+
+void dvi_font::handle_unknown_font_command(const char *command,
+ const char *arg,
+ const char *filename, int lineno)
+{
+ char *ptr;
+ if (strcmp(command, "checksum") == 0) {
+ if (arg == 0)
+ fatal_with_file_and_line(filename, lineno,
+ "`checksum' command requires an argument");
+ checksum = int(strtol(arg, &ptr, 10));
+ if (checksum == 0 && ptr == arg) {
+ fatal_with_file_and_line(filename, lineno, "bad checksum");
+ }
+ }
+ else if (strcmp(command, "designsize") == 0) {
+ if (arg == 0)
+ fatal_with_file_and_line(filename, lineno,
+ "`designsize' command requires an argument");
+ design_size = int(strtol(arg, &ptr, 10));
+ if (design_size == 0 && ptr == arg) {
+ fatal_with_file_and_line(filename, lineno, "bad design size");
+ }
+ }
+}
+
+#define FONTS_MAX 256
+
+struct output_font {
+ dvi_font *f;
+ int point_size;
+ output_font() : f(0) { }
+};
+
+class dvi_printer : public printer {
+ FILE *fp;
+ int max_drift;
+ int byte_count;
+ int last_bop;
+ int page_count;
+ int cur_h;
+ int cur_v;
+ int end_h;
+ int max_h;
+ int max_v;
+ output_font output_font_table[FONTS_MAX];
+ font *cur_font;
+ int cur_point_size;
+ int pushed;
+ int pushed_h;
+ int pushed_v;
+ int have_pushed;
+ void preamble();
+ void postamble();
+ void define_font(int);
+ void set_font(int);
+ void possibly_begin_line();
+protected:
+ enum {
+ id_byte = 2,
+ set1 = 128,
+ put1 = 133,
+ put_rule = 137,
+ bop = 139,
+ eop = 140,
+ push = 141,
+ pop = 142,
+ right1 = 143,
+ down1 = 157,
+ fnt_num_0 = 171,
+ fnt1 = 235,
+ xxx1 = 239,
+ fnt_def1 = 243,
+ pre = 247,
+ post = 248,
+ post_post = 249,
+ filler = 223
+ };
+ int line_thickness;
+
+ void out1(int);
+ void out2(int);
+ void out3(int);
+ void out4(int);
+ void moveto(int, int);
+ void out_string(const char *);
+ void out_signed(unsigned char, int);
+ void out_unsigned(unsigned char, int);
+ void do_special(const char *);
+public:
+ dvi_printer();
+ ~dvi_printer();
+ font *make_font(const char *);
+ void begin_page(int);
+ void end_page(int);
+ void set_char(int, font *, const environment *, int w, const char *name);
+ void special(char *arg, const environment *env);
+ void end_of_line();
+ void draw(int code, int *p, int np, const environment *env);
+};
+
+
+class draw_dvi_printer : public dvi_printer {
+ int output_pen_size;
+ int fill;
+ void set_line_thickness(const environment *);
+ void fill_next();
+public:
+ draw_dvi_printer();
+ ~draw_dvi_printer();
+ void draw(int code, int *p, int np, const environment *env);
+ void end_page(int);
+};
+
+dvi_printer::dvi_printer()
+: fp(stdout), byte_count(0), last_bop(-1), page_count(0), max_h(0), max_v(0),
+ cur_font(0), cur_point_size(-1), pushed(0), line_thickness(-1)
+{
+ if (font::res != RES)
+ fatal("resolution must be %1", RES);
+ if (font::unitwidth != UNITWIDTH)
+ fatal("unitwidth must be %1", UNITWIDTH);
+ if (font::hor != 1)
+ fatal("hor must be equal to 1");
+ if (font::vert != 1)
+ fatal("vert must be equal to 1");
+ if (font::sizescale != SIZESCALE)
+ fatal("sizescale must be equal to %1", SIZESCALE);
+ max_drift = font::res/1000; // this is fairly arbitrary
+ preamble();
+}
+
+dvi_printer::~dvi_printer()
+{
+ postamble();
+}
+
+
+draw_dvi_printer::draw_dvi_printer()
+: output_pen_size(-1), fill(FILL_MAX)
+{
+}
+
+draw_dvi_printer::~draw_dvi_printer()
+{
+}
+
+
+void dvi_printer::out1(int n)
+{
+ byte_count += 1;
+ putc(n & 0xff, fp);
+}
+
+void dvi_printer::out2(int n)
+{
+ byte_count += 2;
+ putc((n >> 8) & 0xff, fp);
+ putc(n & 0xff, fp);
+}
+
+void dvi_printer::out3(int n)
+{
+ byte_count += 3;
+ putc((n >> 16) & 0xff, fp);
+ putc((n >> 8) & 0xff, fp);
+ putc(n & 0xff, fp);
+}
+
+void dvi_printer::out4(int n)
+{
+ byte_count += 4;
+ putc((n >> 24) & 0xff, fp);
+ putc((n >> 16) & 0xff, fp);
+ putc((n >> 8) & 0xff, fp);
+ putc(n & 0xff, fp);
+}
+
+void dvi_printer::out_string(const char *s)
+{
+ out1(strlen(s));
+ while (*s != 0)
+ out1(*s++);
+}
+
+
+void dvi_printer::end_of_line()
+{
+ if (pushed) {
+ out1(pop);
+ pushed = 0;
+ cur_h = pushed_h;
+ cur_v = pushed_v;
+ }
+}
+
+void dvi_printer::possibly_begin_line()
+{
+ if (!pushed) {
+ have_pushed = pushed = 1;
+ pushed_h = cur_h;
+ pushed_v = cur_v;
+ out1(push);
+ }
+}
+
+int scale(int x, int z)
+{
+ int sw;
+ int a, b, c, d;
+ int alpha, beta;
+ alpha = 16*z; beta = 16;
+ while (z >= 040000000L) {
+ z /= 2; beta /= 2;
+ }
+ d = x & 255;
+ c = (x >> 8) & 255;
+ b = (x >> 16) & 255;
+ a = (x >> 24) & 255;
+ sw = (((((d * z) / 0400) + (c * z)) / 0400) + (b * z)) / beta;
+ if (a == 255)
+ sw -= alpha;
+ else
+ assert(a == 0);
+ return sw;
+}
+
+
+void dvi_printer::set_char(int index, font *f, const environment *env, int w, const char *name)
+{
+ int code = f->get_code(index);
+ if (env->size != cur_point_size || f != cur_font) {
+ cur_font = f;
+ cur_point_size = env->size;
+ int i;
+ for (i = 0;; i++) {
+ if (i >= FONTS_MAX) {
+ fatal("too many output fonts required");
+ }
+ if (output_font_table[i].f == 0) {
+ output_font_table[i].f = (dvi_font *)cur_font;
+ output_font_table[i].point_size = cur_point_size;
+ define_font(i);
+ }
+ if (output_font_table[i].f == cur_font
+ && output_font_table[i].point_size == cur_point_size)
+ break;
+ }
+ set_font(i);
+ }
+ int distance = env->hpos - cur_h;
+ if (env->hpos != end_h && distance != 0) {
+ out_signed(right1, distance);
+ cur_h = env->hpos;
+ }
+ else if (distance > max_drift) {
+ out_signed(right1, distance - max_drift);
+ cur_h = env->hpos - max_drift;
+ }
+ else if (distance < -max_drift) {
+ out_signed(right1, distance + max_drift);
+ cur_h = env->hpos + max_drift;
+ }
+ if (env->vpos != cur_v) {
+ out_signed(down1, env->vpos - cur_v);
+ cur_v = env->vpos;
+ }
+ possibly_begin_line();
+ end_h = env->hpos + w;
+ cur_h += scale(f->get_width(index, UNITWIDTH)/MULTIPLIER,
+ cur_point_size*RES_7227);
+ if (cur_h > max_h)
+ max_h = cur_h;
+ if (cur_v > max_v)
+ max_v = cur_v;
+ if (code >= 0 && code <= 127)
+ out1(code);
+ else
+ out_unsigned(set1, code);
+}
+
+void dvi_printer::define_font(int i)
+{
+ out_unsigned(fnt_def1, i);
+ dvi_font *f = output_font_table[i].f;
+ out4(f->checksum);
+ out4(output_font_table[i].point_size*RES_7227);
+ out4(int((double(f->design_size)/(1<<20))*RES_7227*100 + .5));
+ const char *nm = f->get_internal_name();
+ out1(0);
+ out_string(nm);
+}
+
+void dvi_printer::set_font(int i)
+{
+ if (i >= 0 && i <= 63)
+ out1(fnt_num_0 + i);
+ else
+ out_unsigned(fnt1, i);
+}
+
+void dvi_printer::out_signed(unsigned char base, int param)
+{
+ if (-128 <= param && param < 128) {
+ out1(base);
+ out1(param);
+ }
+ else if (-32768 <= param && param < 32768) {
+ out1(base+1);
+ out2(param);
+ }
+ else if (-(1 << 23) <= param && param < (1 << 23)) {
+ out1(base+2);
+ out3(param);
+ }
+ else {
+ out1(base+3);
+ out4(param);
+ }
+}
+
+void dvi_printer::out_unsigned(unsigned char base, int param)
+{
+ if (param >= 0) {
+ if (param < 256) {
+ out1(base);
+ out1(param);
+ }
+ else if (param < 65536) {
+ out1(base+1);
+ out2(param);
+ }
+ else if (param < (1 << 24)) {
+ out1(base+2);
+ out3(param);
+ }
+ else {
+ out1(base+3);
+ out4(param);
+ }
+ }
+ else {
+ out1(base+3);
+ out4(param);
+ }
+}
+
+void dvi_printer::preamble()
+{
+ out1(pre);
+ out1(id_byte);
+ out4(254000);
+ out4(font::res);
+ out4(1000);
+ out1(0);
+}
+
+void dvi_printer::postamble()
+{
+ int tem = byte_count;
+ out1(post);
+ out4(last_bop);
+ out4(254000);
+ out4(font::res);
+ out4(1000);
+ out4(max_v);
+ out4(max_h);
+ out2(have_pushed); // stack depth
+ out2(page_count);
+ int i;
+ for (i = 0; i < FONTS_MAX && output_font_table[i].f != 0; i++)
+ define_font(i);
+ out1(post_post);
+ out4(tem);
+ out1(id_byte);
+ for (i = 0; i < 4 || byte_count % 4 != 0; i++)
+ out1(filler);
+}
+
+void dvi_printer::begin_page(int i)
+{
+ page_count++;
+ int tem = byte_count;
+ out1(bop);
+ out4(i);
+ for (int j = 1; j < 10; j++)
+ out4(0);
+ out4(last_bop);
+ last_bop = tem;
+ // By convention position (0,0) in a dvi file is placed at (1in, 1in).
+ cur_h = font::res;
+ cur_v = font::res;
+ end_h = 0;
+}
+
+void dvi_printer::end_page(int)
+{
+ if (pushed)
+ end_of_line();
+ out1(eop);
+ cur_font = 0;
+}
+
+void draw_dvi_printer::end_page(int len)
+{
+ dvi_printer::end_page(len);
+ output_pen_size = -1;
+}
+
+void dvi_printer::do_special(const char *s)
+{
+ int len = strlen(s);
+ if (len == 0)
+ return;
+ possibly_begin_line();
+ out_unsigned(xxx1, len);
+ while (*s)
+ out1(*s++);
+}
+
+void dvi_printer::special(char *arg, const environment *env)
+{
+ moveto(env->hpos, env->vpos);
+ do_special(arg);
+}
+
+void dvi_printer::moveto(int h, int v)
+{
+ if (h != cur_h) {
+ out_signed(right1, h - cur_h);
+ cur_h = h;
+ if (cur_h > max_h)
+ max_h = cur_h;
+ }
+ if (v != cur_v) {
+ out_signed(down1, v - cur_v);
+ cur_v = v;
+ if (cur_v > max_v)
+ max_v = cur_v;
+ }
+ end_h = 0;
+}
+
+void dvi_printer::draw(int code, int *p, int np, const environment *env)
+{
+ if (code == 'l') {
+ int x, y;
+ int height = 0, width;
+ int thickness;
+ if (line_thickness < 0)
+ thickness = env->size*RES_7227*linewidth/1000;
+ else if (line_thickness > 0)
+ thickness = line_thickness;
+ else
+ thickness = 1;
+ if (np != 2) {
+ error("2 arguments required for line");
+ }
+ else if (p[0] == 0) {
+ // vertical rule
+ if (p[1] > 0) {
+ x = env->hpos - thickness/2;
+ y = env->vpos + p[1] + thickness/2;
+ height = p[1] + thickness;
+ width = thickness;
+ }
+ else if (p[1] < 0) {
+ x = env->hpos - thickness/2;
+ y = env->vpos + thickness/2;
+ height = thickness - p[1];
+ width = thickness;
+ }
+ }
+ else if (p[1] == 0) {
+ if (p[0] > 0) {
+ x = env->hpos - thickness/2;
+ y = env->vpos + thickness/2;
+ height = thickness;
+ width = p[0] + thickness;
+ }
+ else if (p[0] < 0) {
+ x = env->hpos - p[0] - thickness/2;
+ y = env->vpos + thickness/2;
+ height = thickness;
+ width = thickness - p[0];
+ }
+ }
+ if (height != 0) {
+ moveto(x, y);
+ out1(put_rule);
+ out4(height);
+ out4(width);
+ }
+ }
+ else if (code == 't') {
+ if (np == 0) {
+ line_thickness = -1;
+ }
+ else {
+ // troff gratuitously adds an extra 0
+ if (np != 1 && np != 2)
+ error("0 or 1 argument required for thickness");
+ else
+ line_thickness = p[0];
+ }
+ }
+ else if (code == 'R') {
+ if (np != 2)
+ error("2 arguments required for rule");
+ else if (p[0] != 0 || p[1] != 0) {
+ int dh = p[0];
+ int dv = p[1];
+ int oh = env->hpos;
+ int ov = env->vpos;
+ if (dv > 0) {
+ ov += dv;
+ dv = -dv;
+ }
+ if (dh < 0) {
+ oh += dh;
+ dh = -dh;
+ }
+ moveto(oh, ov);
+ out1(put_rule);
+ out4(-dv);
+ out4(dh);
+ }
+ }
+}
+
+// XXX Will this overflow?
+
+inline int milliinches(int n)
+{
+ return (n*1000 + font::res/2)/font::res;
+}
+
+void draw_dvi_printer::set_line_thickness(const environment *env)
+{
+ int desired_pen_size
+ = milliinches(line_thickness < 0
+ // Will this overflow?
+ ? env->size*RES_7227*linewidth/1000
+ : line_thickness);
+ if (desired_pen_size != output_pen_size) {
+ char buf[256];
+ sprintf(buf, "pn %d", desired_pen_size);
+ do_special(buf);
+ output_pen_size = desired_pen_size;
+ }
+}
+
+void draw_dvi_printer::fill_next()
+{
+ char buf[256];
+ sprintf(buf, "sh %.3f", double(fill)/FILL_MAX);
+ do_special(buf);
+}
+
+void draw_dvi_printer::draw(int code, int *p, int np, const environment *env)
+{
+ char buf[1024];
+ int fill_flag = 0;
+ switch (code) {
+ case 'C':
+ fill_flag = 1;
+ // fall through
+ case 'c':
+ // troff adds an extra argument to C
+ if (np != 1 && !(code == 'C' && np == 2)) {
+ error("1 argument required for circle");
+ break;
+ }
+ moveto(env->hpos+p[0]/2, env->vpos);
+ if (fill_flag)
+ fill_next();
+ else
+ set_line_thickness(env);
+ int rad;
+ rad = milliinches(p[0]/2);
+ sprintf(buf, "%s 0 0 %d %d 0 6.28319",
+ (fill_flag ? "ia" : "ar"),
+ rad,
+ rad);
+ do_special(buf);
+ break;
+ case 'l':
+ if (np != 2) {
+ error("2 arguments required for line");
+ break;
+ }
+ moveto(env->hpos, env->vpos);
+ set_line_thickness(env);
+ do_special("pa 0 0");
+ sprintf(buf, "pa %d %d", milliinches(p[0]), milliinches(p[1]));
+ do_special(buf);
+ do_special("fp");
+ break;
+ case 'E':
+ fill_flag = 1;
+ // fall through
+ case 'e':
+ if (np != 2) {
+ error("2 arguments required for ellipse");
+ break;
+ }
+ moveto(env->hpos+p[0]/2, env->vpos);
+ if (fill_flag)
+ fill_next();
+ sprintf(buf, "%s 0 0 %d %d 0 6.28319",
+ (fill_flag ? "ia" : "ar"),
+ milliinches(p[0]/2),
+ milliinches(p[1]/2));
+ do_special(buf);
+ break;
+ case 'P':
+ fill_flag = 1;
+ // fall through
+ case 'p':
+ {
+ if (np & 1) {
+ error("even number of arguments required for polygon");
+ break;
+ }
+ if (np == 0) {
+ error("no arguments for polygon");
+ break;
+ }
+ moveto(env->hpos, env->vpos);
+ if (fill_flag)
+ fill_next();
+ else
+ set_line_thickness(env);
+ do_special("pa 0 0");
+ int h = 0, v = 0;
+ for (int i = 0; i < np; i += 2) {
+ h += p[i];
+ v += p[i+1];
+ sprintf(buf, "pa %d %d", milliinches(h), milliinches(v));
+ do_special(buf);
+ }
+ do_special("pa 0 0");
+ do_special(fill_flag ? "ip" : "fp");
+ break;
+ }
+ case '~':
+ {
+ if (np & 1) {
+ error("even number of arguments required for spline");
+ break;
+ }
+ if (np == 0) {
+ error("no arguments for spline");
+ break;
+ }
+ moveto(env->hpos, env->vpos);
+ set_line_thickness(env);
+ do_special("pa 0 0");
+ int h = 0, v = 0;
+ for (int i = 0; i < np; i += 2) {
+ h += p[i];
+ v += p[i+1];
+ sprintf(buf, "pa %d %d", milliinches(h), milliinches(v));
+ do_special(buf);
+ }
+ do_special("sp");
+ break;
+ }
+ case 'a':
+ {
+ if (np != 4) {
+ error("4 arguments required for arc");
+ break;
+ }
+ set_line_thickness(env);
+ double c[2];
+ if (adjust_arc_center(p, c)) {
+ int rad = milliinches(int(sqrt(c[0]*c[0] + c[1]*c[1]) + .5));
+ moveto(env->hpos + int(c[0]), env->vpos + int(c[1]));
+ sprintf(buf, "ar 0 0 %d %d %f %f",
+ rad,
+ rad,
+ atan2(p[1] + p[3] - c[1], p[0] + p[2] - c[0]),
+ atan2(-c[1], -c[0]));
+ do_special(buf);
+ }
+ else {
+ moveto(env->hpos, env->vpos);
+ do_special("pa 0 0");
+ sprintf(buf,
+ "pa %d %d",
+ milliinches(p[0] + p[2]),
+ milliinches(p[1] + p[3]));
+ do_special(buf);
+ do_special("fp");
+ }
+ break;
+ }
+ case 't':
+ {
+ if (np == 0) {
+ line_thickness = -1;
+ }
+ else {
+ // troff gratuitously adds an extra 0
+ if (np != 1 && np != 2) {
+ error("0 or 1 argument required for thickness");
+ break;
+ }
+ line_thickness = p[0];
+ }
+ break;
+ }
+ case 'f':
+ {
+ if (np != 1 && np != 2) {
+ error("1 argument required for fill");
+ break;
+ }
+ fill = p[0];
+ if (fill < 0 || fill > FILL_MAX)
+ fill = FILL_MAX;
+ break;
+ }
+ case 'R':
+ {
+ if (np != 2) {
+ error("2 arguments required for rule");
+ break;
+ }
+ int dh = p[0];
+ if (dh == 0)
+ break;
+ int dv = p[1];
+ if (dv == 0)
+ break;
+ int oh = env->hpos;
+ int ov = env->vpos;
+ if (dv > 0) {
+ ov += dv;
+ dv = -dv;
+ }
+ if (dh < 0) {
+ oh += dh;
+ dh = -dh;
+ }
+ moveto(oh, ov);
+ out1(put_rule);
+ out4(-dv);
+ out4(dh);
+ break;
+ }
+ default:
+ error("unrecognised drawing command `%1'", char(code));
+ break;
+ }
+}
+
+font *dvi_printer::make_font(const char *nm)
+{
+ return dvi_font::load_dvi_font(nm);
+}
+
+printer *make_printer()
+{
+ if (draw_flag)
+ return new draw_dvi_printer;
+ else
+ return new dvi_printer;
+}
+
+static void usage();
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int c;
+ while ((c = getopt(argc, argv, "F:vw:d")) != EOF)
+ switch(c) {
+ case 'v':
+ {
+ extern const char *Version_string;
+ fprintf(stderr, "grodvi version %s\n", Version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'w':
+ if (sscanf(optarg, "%d", &linewidth) != 1
+ || linewidth < 0 || linewidth > 1000) {
+ error("bad line width");
+ linewidth = DEFAULT_LINEWIDTH;
+ }
+ break;
+ case 'd':
+ draw_flag = 0;
+ break;
+ case 'F':
+ font::command_line_font_dir(optarg);
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ }
+ if (optind >= argc)
+ do_file("-");
+ else {
+ for (int i = optind; i < argc; i++)
+ do_file(argv[i]);
+ }
+ delete pr;
+ return 0;
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-dv] [-F dir] [-w n] [files ...]\n",
+ program_name);
+ exit(1);
+}
diff --git a/src/devices/grodvi/grodvi.man b/src/devices/grodvi/grodvi.man
new file mode 100644
index 00000000..aeb894cd
--- /dev/null
+++ b/src/devices/grodvi/grodvi.man
@@ -0,0 +1,171 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X
+.el .ds tx TeX
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.TH GRODVI @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+grodvi \- convert groff output to TeX dvi format
+.SH SYNOPSIS
+.B grodvi
+[
+.B \-dv
+] [
+.BI \-w n
+] [
+.BI \-F dir
+] [
+.IR files \|.\|.\|.
+]
+.SH DESCRIPTION
+.B grodvi
+is a driver for
+.B groff
+that produces \*(tx dvi format.
+Normally it should be run by
+.BR groff\ \-Tdvi .
+This will run
+.BR @g@troff\ \-Tdvi ;
+it will also input the macros
+.BR @MACRODIR@/tmac.dvi ;
+if the input is being preprocessed with
+.B @g@eqn
+it will also input
+.BR @FONTDIR@/devdvi/eqnchar .
+.LP
+The dvi file generated by
+.B grodvi
+can be printed by any correctly-written dvi driver.
+The troff drawing primitives are implemented
+using the tpic version 2 specials.
+If the driver does not support these, the
+.B \eD
+commands will not produce any output.
+.LP
+There is an additional drawing command available:
+.TP
+.BI \eD'R\ dh\ dv '
+Draw a rule (solid black rectangle), with one corner
+at the current position, and the diagonally opposite corner
+at the current position
+.RI +( dh , dv ).
+Afterwards the current position will be at the opposite corner. This
+produces a rule in the dvi file and so can be printed even with a
+driver that does not support the tpic specials unlike the other
+.B \eD
+commands.
+.LP
+The groff command
+.BI \eX' anything '
+is translated into the same command in the dvi file as would be
+produced by
+.BI \especial{ anything }
+in \*(tx;
+.I anything may not contain a newline.
+.LP
+Font files for
+.B grodvi
+can be created from tfm files using
+.BR tfmtodit (@MAN1EXT@).
+The font description file should contain the following
+additional commands:
+.Tp \w'\fBinternalname'u+2n
+.BI internalname\ name
+The name of the tfm file (without the
+.B .tfm
+extension) is
+.IR name .
+.TP
+.BI checksum\ n
+The checksum in the tfm file is
+.IR n .
+.TP
+.BI designsize\ n
+The designsize in the tfm file is
+.IR n .
+.LP
+These are automatically generated by
+.B tfmtodit.
+.LP
+In
+.B troff
+the
+.B \eN
+escape sequence can be used to access characters by their position
+in the corresponding tfm file;
+all characters in the tfm file can be accessed this way.
+.SH OPTIONS
+.TP
+.B \-d
+Do not use tpic specials to implement drawing commands.
+Horizontal and vertical lines will be implemented by rules.
+Other drawing commands will be ignored.
+.TP
+.B \-v
+Print the version number.
+.TP
+.BI \-w n
+Set the default line thickness to
+.I n
+thousandths of an em.
+.TP
+.BI \-F dir
+Search directory
+.IB dir /devdvi
+for font and device description files.
+.SH FILES
+.TP
+.B @FONTDIR@/devdvi/DESC
+Device description file.
+.TP
+.B @FONTDIR@/devdvi/ F
+Font description file for font
+.IR F .
+.TP
+.B @MACRODIR@/tmac.dvi
+Macros for use with
+.BR grodvi .
+.SH BUGS
+Dvi files produced by
+.B grodvi
+use a different resolution (57816 units per inch) to those produced by
+\*(tx.
+Incorrectly written drivers which assume the resolution used by \*(tx,
+rather than using the resolution specified in the dvi file will not
+work with grodvi.
+.LP
+When using the
+.B \-d
+option with boxed tables,
+vertical and horizontal lines can sometimes protrude by one pixel.
+This is a consequence of the way \*(tx requires that the heights
+and widths of rules be rounded.
+.SH "SEE ALSO"
+.BR tfmtodit (@MAN1EXT@),
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@),
+.BR @g@eqn (@MAN1EXT@),
+.BR groff_out (@MAN5EXT@),
+.BR groff_font (@MAN5EXT@),
+.BR groff_char (@MAN7EXT@)
diff --git a/src/devices/grohtml/ChangeLog b/src/devices/grohtml/ChangeLog
new file mode 100755
index 00000000..136fbc5f
--- /dev/null
+++ b/src/devices/grohtml/ChangeLog
@@ -0,0 +1,172 @@
+2000-01-28 Gaius Mulley <gaius@glam.ac.uk>
+
+ * html.cc: Minor fixes.
+
+2000-01-27 Gaius Mulley <gaius@glam.ac.uk>
+
+ * html.cc: Added support for the new tcommand `F'.
+ * TODO: Updated.
+
+2000-01-24 Gaius Mulley <gaius@glam.ac.uk>
+
+ * design.ms: Revised. Removed TODO stuff.
+
+ * TODO: New file.
+
+2000-01-21 Gaius Mulley <gaius@glam.ac.uk>
+
+ * html.cc: Add support for char names in special requests (to
+ support e.g. accented characters in HTML specials).
+
+2000-01-14 Gaius Mulley <gaius@glam.ac.uk>
+
+ * html.cc, html.h: Many fixes to table code.
+
+ Fixes to manual page handling, font changes, spaces, and
+ diacritical characters. All *standard* html character encodings
+ are handled.
+
+ Added -T option which turns off all image generation for tables.
+ One day grohtml should be able to determine this for itself.
+
+ Altered image name to: <groff_input_file>-<index>.png as per
+ Werners suggestion.
+
+ * grohtml.man: Document -T option.
+
+ * html_chars.h: New file, providing diacritical table support.
+
+ * output.cc: New file, providing basic output routines for grohtml.
+
+ * Makefile.sub: Added output.cc.
+
+ * Makefile.dep: Updated.
+
+2000-01-13 Bruno Haible <haible@clisp.cons.org>
+
+ * html.cc: Avoid most "g++ -Wall -Wno-sign-compare" warnings.
+
+2000-01-10 Werner Lemberg <wl@gnu.org>
+
+ * html.cc: Use Version_string instead of version_string.
+
+1999-12-30 Gaius Mulley <gaius@glam.ac.uk>
+
+ * html.cc (is_appropriate_to_start_table): Added a missing
+ declaration.
+
+1999-12-28 Gaius Mulley <gaius@glam.ac.uk>
+
+ * html.cc: Revisited the table handling code with a vengeance,
+ aiming to make manual pages generate sensible html.
+ Superscripting/subscripting revisited. Fixed wierd table lengths.
+ Table widths are now specified in percentages. Fixed the man.n
+ test example which Werner reported.
+
+Version 1.15 released
+=====================
+
+1999-12-21 Werner LEMBERG <wl@gnu.org>
+
+ * grohtml.man: Fixed copyright year.
+
+1999-12-15 Gaius Mulley <gaius@glam.ac.uk>
+
+ * html.cc: Some other fixes.
+
+1999-12-13 Gaius Mulley <gaius@glam.ac.uk>
+
+ * html.cc (main): Added new option `-x' to help debugging tables.
+
+1999-12-11 Gaius Mulley <gaius@glam.ac.uk>
+
+ * html.cc: Fixed image position bugs. However, three major bugs
+ remain: Firstly, grohtml sometimes miscalculates the end of an
+ html table resulting in text which appears twice. Secondly,
+ equation numbers are not handled correctly. Thirdly, equation
+ macros and pic macros can confuse grohtml; this can be seen by
+ nested `graphic-start's -- I believe the best method to solve this
+ is to detect .EQ, .EN, .TS, .TE, .PS, .PE sequences in troff and
+ add the graphic-start special character at this point.
+
+ * grohtml.man: Minor fixes.
+
+1999-11-29 Gaius Mulley <gaius@glam.ac.uk>
+
+ * design.ms: More updates; added some basic introductional
+ information.
+
+ * html.cc: Fixed more bugs mainly in the table handling code.
+ Making the code terminate a table at the correct position.
+ Indented .IPs appear to work now. Region ends also correctly
+ terminate tables.
+
+1999-11-16 Gaius Mulley <gaius@glam.ac.uk>
+
+ * design.ms, grohtml.man: Updated.
+
+ * html.cc, ordered_list.h: Fixed many bugs in the table handling
+ code. Reverted the -t switch so that table handling code is used
+ by default and users must turn it off with -t.
+
+ Manual page generation using `groff -Thtml -man' is much better
+ due in large part to the table code and minor alterations in
+ tmac.an.
+
+1999-10-30 Gaius Mulley <gaius@glam.ac.uk>
+
+ * implemented auto formatting and introduced html table
+ code. Fixed several text handling bugs and grohtml will
+ detect centered lines - an offshoot of the html table code.
+
+ * reverted meaning of grohtml's `-a' switch: using -a means that
+ output will be preformatted.
+
+1999-10-05 Gaius Mulley <gaius@glam.ac.uk>
+
+ * Introduced command line options -r to determine the resolution
+ of generated images, -I to determine the format of images
+ generated.
+
+ * Fixed many bugs to do with superscripts, subscripts,
+ indentation, font changes, and extraneous spaces.
+
+ * Fixed bug in determining the range of polygons and splines.
+
+ * Updated the manual page to reflect the new options.
+
+ * The default image type is png format, however this will only
+ work if you have a gs with a png output device. If you don't have
+ a gs with this ability you can either reconfigure html to generate
+ gif images by default (alter a #define in html.cc). Or
+ alternatively you can use the -Igif option.
+
+1999-09-27 Werner LEMBERG <wl@gnu.org>
+
+ * html.cc (move_horizontal): Fonts have changed one character too
+ late.
+
+1999-09-26 Werner LEMBERG <wl@gnu.org>
+
+ * grohtml.man: Minor cosmetic fixes.
+
+1999-09-25 Gaius Mulley <gaius@glam.ac.uk>
+
+ * grohtml.man, html.cc: Rewrite of the html text component. Basic
+ font faces supported together with font types. Superscript and
+ subscript have also been implemented. Temporarily removed the
+ -P-a switch on grohtml as it is not working (never worked). This
+ is the next `to do'. Added a simple macro tmac.arkup which
+ contains simple html features. This macro needs further work.
+ Arc, spline, polygon fill have all been added and arc max/min xy
+ limits are calculated, the same needs to be done for spline. Many
+ bugs have been fixed regarding basic html text.
+
+ * design.ms: New file describing how html.cc works.
+
+Aug 1999
+
+ Initial release, very basic html text generated, quite ugly text
+ is generated according to many reports :-) Equations, tables,
+ pictures generate gif files via gs and ppmquant, ppmtogif, grops.
+
diff --git a/src/devices/grohtml/Makefile.sub b/src/devices/grohtml/Makefile.sub
new file mode 100644
index 00000000..a1e301f0
--- /dev/null
+++ b/src/devices/grohtml/Makefile.sub
@@ -0,0 +1,10 @@
+PROG=grohtml
+MAN1=grohtml.n
+XLIBS=$(LIBDRIVER) $(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=\
+ html.o \
+ output.o
+CCSRCS=\
+ $(srcdir)/html.cc \
+ $(srcdir)/output.cc
diff --git a/src/devices/grohtml/TODO b/src/devices/grohtml/TODO
new file mode 100755
index 00000000..4924bd1c
--- /dev/null
+++ b/src/devices/grohtml/TODO
@@ -0,0 +1,294 @@
+
+------------------------------------------------------------------
+ T O D O L I S T
+------------------------------------------------------------------
+finish working out the max and min x, y, extents for splines.
+------------------------------------------------------------------
+check and test thoroughly all the character descriptions in devhtml
+(originally taken from devX100)
+------------------------------------------------------------------
+improve tmac.arkup
+------------------------------------------------------------------
+also improve documentation.
+------------------------------------------------------------------
+fix the bugs which are exposed by Eric Raymonds pic guide,
+"Making Pictures With GNU PIC". It appears that grohtml becomes confused
+about which sections of the document are text and which sections need
+to be rendered as an image.
+------------------------------------------------------------------
+it would be nice to modularise the source. A natural division might be
+to extract the table handling code from html.cc into table.cc.
+The table.cc could be expanded to recognise output from tbl and try
+and generate html tables with lines/rules/boxes. The code as it stands
+should cope with very simple plain text tables. But of course at present
+it does not get a chance to do this because the output of gtbl is
+bracketed by \fCgraphic-start\fR and \fCgraphic-end\fR.
+------------------------------------------------------------------
+introduce anti aliasing for the images as mentioned by Werner.
+------------------------------------------------------------------
+improve generation of html. Perhaps by using a stack of current
+html commands and using a kind of peephole optimizer on the stack?
+Certainly the html should be buffered and optimized.
+------------------------------------------------------------------
+
+
+Informal to do bug list and done list
+=====================================
+
+This very informal and I've included some comments. Mainly consists
+of a emailed bugs and wish lists. All very useful and welcome.
+
+------------------------------------------------------------------
+Dean writes: (provinsd@enf403-2.ensu.ucalgary.ca)
+
+I noticed also that the TOC appears immediately after the title, splitting
+it from the author and abstract. Any chance it can be moved down?
+
+gaius> this should be straight forward. (Not done yet though)
+------------------------------------------------------------------
+
+.) The command `\(->', translates to the `registered' sign (or rather
+ the character `0xAE') instead of a right arrow.
+
+--nearly fixed-- 4/01/2000
+
+gaius> if we know the standard html character encoding for farrow which
+gaius> will work on *all* browsers then this can be fixed inside devhtml/TR
+gaius> etc. Otherwise I guess we could translate this character into ->
+gaius> in tmac.html ?
+
+------------------------------------------------------------------
+
+Werner writes:
+
+Nevertheless, still some bugs in it. As usual, I'm refering to man.1
+of the mandb package; my command to create man.html was
+
+ groff -U -t -man -Thtml -P-r -P200 man.1 > man.html
+
+.) The `-w , --where, --location' node at the beginning of man.html
+ shouldn't be there at all.
+
+> .) Some paragraphs still contain hyphenated words (e.g. first
+> paragraph of the `DESCRIPTION' section).
+
+Oops! Please ignore this. I forgot to include `-mhtml' :-)
+
+.) Is it possible to have anti-aliased PNG images?
+
+.) The item `man --help' in the `EXAMPLES' section doesn't start a new
+ paragraph.
+
+.) In the description of the -r switch (in the `OPTIONS' section),
+ there is a new paragraph in the middle of a sentence.
+
+.) What about centering the images? Or does it depend on the table
+ itself?
+
+gaius> yes, grohtml places images at their relative position on the page.
+
+.) In the `OPTIONS' section, `-c, --catman' and `-d, --debug' are
+ glued together which shouldn't happen.
+--fixed--
+
+.) Sometimes, an empty line is missing between items, e.g. between the
+ description of the -e and the -f options.
+
+.) After the `-w, --where, --location' line, there is a superfluous
+ empty line.
+
+.) The indentation in the `FILES' section is inconsistent. The same
+ is true for `-V, --version' a few lines above.
+
+.) The formatting of the paragraph after the first table is completely
+ wrong. It appears that the first few words are set in two columns;
+ additionally, the indentation is incorrect.
+
+.) Similarly, the description of `-l' in the OPTIONS section is
+ idented incorrectly. Wrong indentations happen still quite
+ frequently.
+
+.) In the description of the `-D' option, there is a blank line in the
+ middle of a paragraph.
+
+
+ Werner
+
+------------------------------------------------------------------
+Werner writes:
+
+Gaius,
+
+checking a weird man page written by myself in German (using German
+hyphenation patterns also :-), I found some more bugs:
+
+.) Look at the following:
+
+[\c
+...\^\c
+]
+[\c
+.BI -P \ \%Plattform-ID\^\c
+]
+
+ This translates to
+
+[<font size=3><B>-E</B> <font size=3><I>Kodierungs-ID</I> <font size=3>]
+ ^
+ (groff breaks the line after the final `]'.)
+
+ There are two errors in it: First of all, the `\ ' command should
+ be translated to `&nbsp;'. Secondly, a blank has crept in (marked
+ with `^'. Apparently, this is related to whether it is the last
+ item of a line or not.
+
+--fixed-- 4 01 2000
+------------------------------------------------------------------
+
+from Steve Blinkhorn <steve@prd.co.uk>
+
+One thought that came immediately to mind after our first trials.
+If grohtml depends on grops, should there not be an easy interface to
+allow PostScript code to be interpreted into the output? For
+instance, we generate our letterhead, including a logo, on the fly in
+groff. The logo is pure PostScript. We use PostScript for colour
+manipulation, and recently for generating a lot of graphics for
+printing.
+
+gaius> should be interesting - if we can generate PS then GS it
+gaius> we should be in business
+
+------------------------------------------------------------------
+ D O N E L I S T
+------------------------------------------------------------------
+the logical place and name for a file describing tmac.arkup is
+groff_markup.man placed into the `tmac' subdirectory, and your html.ms
+looks like being this kind of file.
+
+So I won't check it in currently -- may I ask you to convert this file
+to a man page?
+
+-- fixed --
+
+Another related problem: I can imagine that a lot of people start to
+write man pages with HTML output in mind also. Nevertheless, it
+should be still possible to display such pages correctly with a plain
+text man pager. As a consequence, such man pages should contain at
+the beginning something like
+
+ .do mso tmac.arkup
+
+What do you think?
+
+ Werner
+
+-- fixed --
+gaius> fixed by using troffrc-end I believe
+--------------------------------------------------------------------
+Gaius,
+
+in troffrc, it appears to me that tmac.html is loaded if the output
+device is HTML. So why must I load it again (using -mhtml) to
+suppress hyphenation for HTML output? Can you provide a fix for this?
+
+ Werner
+
+gaius> fixed as above
+--------------------------------------------------------------------
+
+from (daeschler@shuttle.de) Rainer Daeschler
+
+I recognized s problem limiting the usage for
+"none-english aliens". The generation of PNG of GIF,
+skips all special characters like
+
+ äöü ÄÖÜ ß
+
+French, Spanish, and Scandinavian national letters, too.
+
+--fixed-- 14/01/2000
+
+An option which forces tables into HTML-code instead of building
+an image would be most valuable. Of course it would not preserve
+the original layout in many cases, but ease modifications of
+the HTML-output to the users demand afterwards.
+
+--fixed-- 14/01/2000
+
+gaius> use the new -T option to grohtml (-P-T to groff)
+
+-----------------------------------------------------------------
+from Werner
+
+ but `pre-defined' appears as `pre&shy; line' (note the space
+ character after the soft hyphen). Something in the code makes
+ problems here...
+
+ (IIRC, I've sent you this man.1 file a few weeks ago).
+
+gaius> Werner fixed this by adding .cflags 0 -\(hy\(em\(en to tmac.html
+
+-----------------------------------------------------------------
+from Werner and Eddie
+> > > .LP
+> > > .URL Germany "ftp://groff.ffii.org/pub/groff/"
+> > > |
+> > > .URL USA "ftp://ftp.gnu.org/gnu/groff/"
+> >
+> > Problem: the first "|" of each line is missing a leading white space
+> > space.
+> >
+> > How to ensure the spaces get put there?
+>
+> This is a feature grohtml (unfortunately -- AFAIK, Gaius hasn't found
+> a good workaround yet). HTML stuff gets written as specials which
+> don't consume space for troff, causing some miscalculation if placed
+> at the beginning of a paragraph. A workaround is to write
+>
+> .LP
+> \&
+> .URL ...
+> |
+> .URL ...
+
+gaius> fixed by adding \& to HTML as per Werner's suggestion
+
+
+Werner writes:
+
+PNGs created by grohtml have apparently a white background -- isn't it
+possible to make the background transparent optionally?
+
+Another suggestion: What do you think about calling the PNG files
+<groff_input_file>-<index>.png or something like this? I can't see an
+advantage in the current naming scheme except for debugging purposes
+where it may be necessary to stay with the old files.
+
+--fixed-- 04 01 2000
+
+gaius> however I've had to retain a default grohtml-pid-index.png for all
+gaius> stdin as we don't know the filename.. sadly looks like everything..
+gaius> Nearly done by including a new tcommand 'F filename'
+
+--fixed-- 26 01 2000
+------------------------------------------------------------------
+
+.) The following code produces ugly results -- is it possible to make
+ the HTML result similar to the ascii output?
+
+.in +4m
+.ta 3iC
+.I "Plattform Plattform-ID (pid)"
+\&.sp
+.ta 3iR
+Apple Unicode 0
+.br
+Macintosh 1
+.br
+ISO 2
+.br
+Microsoft 3
+.PP
+
+--fixed-- 14/01/2000
+------------------------------------------------------------------
diff --git a/src/devices/grohtml/design.ms b/src/devices/grohtml/design.ms
new file mode 100755
index 00000000..6216d4eb
--- /dev/null
+++ b/src/devices/grohtml/design.ms
@@ -0,0 +1,129 @@
+.nr PS 12
+.nr VS 14
+.LP
+.TL
+Design of grohtml
+.sp 1i
+.SH
+What is grohtml
+.LP
+Grohtml is a back end for groff which generates html.
+The aim of grohtml is to produce respectible html given
+fairly typical groff input.
+.SH
+Limitations of grohtml
+.LP
+Although basic text can be translated
+in a straightforward fashion there are some areas where grohtml
+has to try and guess text relationship. In particular whenever
+grohtml encounters text tables and indented paragraphs or
+two column mode it will try and utilize the html table construct
+to preserve columns. Grohtml also attempts to work out which
+lines should be automatically formatted by the browser.
+Ultimately in trying to make reasonable guesses most of the time
+it will make mistakes occasionally.
+.PP
+Tbl, pic, eqn's are also generated using images which may be
+considered a limitation.
+.SH
+Overview of html.cc
+.LP
+This file briefly provides an overview of how html.cc operates.
+The html device driver works as follows:
+.IP (i) .5i
+firstly it creates a linked list of all words on a page.
+.IP (ii) .5i
+it runs through the page and finds the left most margin. Later
+on when generating the page it removes the margin.
+.IP (iii) .5i
+scans a page and builds two kinds of regions ascii text and graphical.
+The graphical regions consist of tbl's, eqn's, pic's
+(basically anything that cannot be textually displayed).
+It will scan through a page to find lines (such as footer etc)
+and places these into tiny graphical regions. Certain fonts
+also are treated as a graphical region - as html has no easy
+equivalent. For example Greek math symbols.
+.LP
+Finally all graphical regions are translated into png files and
+all text regions into html text.
+.PP
+To give grohtml a sporting chance of accuratly deciding which
+is a graphical region and which is text, the front end programs
+tbl, eqn, pic have all been tweeked to encapsulate pictures, tables
+and equations with the following lines:
+.sp
+.nf
+\f[CR]\&.if '\\*(.T'html' \\X(graphic-start(\c
+
+\&.if '\\*(.T'html' \\X(graphic-end(\c
+\fP
+.fi
+.sp
+these appear to grohtml as:
+.sp
+.nf
+\f[CR]\&x X graphic-start
+
+\&...
+
+\&x X graphic-end\fP
+.fi
+.sp
+.LP
+In addition to graphic-start and graphic-end there are two
+other "special characters" which are used.
+.sp
+\f[CR]\&x X index:N\fP
+.sp
+where N is a number. The purpose of this sequence is to stop
+devhtml from automatically producing links to headings which
+have a header level >N.
+The line:
+.sp
+\f[CR]\&x X html:STRING\fR
+.sp
+.LP
+allows a STRING to be passed through to the output file with
+no processing whatsoever. Ie it allows users to include html
+commands, via macro, such as:
+.sp
+\f[CR]\&.URL "Latest Emacs" "ftp://somewonderful.gnu.software"\fP
+.sp
+.LP
+Where the URL macro bundles the info into STRING above.
+For more info consult: \f[CR]tmac/tmac.arkup\fP.
+.PP
+While scanning through a page the html device copies headings and titles
+into a list of links which are later written to the beginning
+of the html document.
+.SH
+Table handling code
+.LP
+Provided that the -t option is not present when grohtml is run the grohtml
+driver will attempt to find textual tables and generate html tables.
+This allows .RS and .RE commands to operate with auto formatting. It also
+should grohtml to process .2C correctly. However, the table handling code
+has to examine the troff output and \fIguess\fR when a table starts and
+finishes. It is well to know the limitations of this approach as it
+sometimes makes the wrong decision.
+.LP
+Here are some of the rules that grohtml uses for terminating a html table:
+.LP
+.IP "(i)" .5i
+A table will be terminated when grohtml finds line which is all in bold
+font (it believes that this is a header which is outside of a table).
+This might be considered incorrect behaviour especially if you use .2C
+which generates a heading on the left column when the corresponding
+right row is blank.
+.IP "(ii)" .5i
+A table is terminated when grohtml sees that the complete line is
+has been spanned by words. Ie no gaps exist.
+.IP "(nb)" .5i
+the documentation about these rules is particularly incomplete and needs finishing
+when time prevails.
+.SH
+Dependencies
+.LP
+Grohtml is dependent upon grops, gs which are invoked to
+generate all png files. Png files are generated whenever a table, picture,
+equation or line is encountered.
diff --git a/src/devices/grohtml/grohtml.man b/src/devices/grohtml/grohtml.man
new file mode 100644
index 00000000..1da666bc
--- /dev/null
+++ b/src/devices/grohtml/grohtml.man
@@ -0,0 +1,179 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1999 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.TH GROHTML @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+grohtml \- html driver for groff
+.SH SYNOPSIS
+.B grohtml
+[
+.B \-atTvdgm?
+] [
+.BI \-F dir
+] [
+.BI \-I imagetype
+] [
+.BI \-r resolution
+] [
+.IR files \|.\|.\|.
+]
+.SH DESCRIPTION
+.B grohtml
+translates the output of GNU
+.B troff
+to html.
+Normally
+.B grohtml
+should be invoked by using the groff command with a
+.B \-Thtml
+option.
+If no files are given,
+.B grohtml
+will read the standard input.
+A filename of
+.B \-
+will also cause
+.B grohtml
+to read the standard input.
+Html output is written to the standard output.
+When
+.B grohtml
+is run by
+.B groff
+options can be passed to
+.B grohtml
+using the
+.B groff
+.B \-P
+option.
+.SH OPTIONS
+.TP
+.B \-a
+force
+.B grohtml
+to generate html line breaks in the same position as troff dictates.
+Without this option
+.B grohtml
+generates text in paragraphs which is formatted by the html browser.
+.TP
+.B \-d
+turn on internal debugging.
+.TP
+.B \-g
+tell
+.B grohtml
+not to try and guess titles and headings.
+By using this flag together with the -m and -a flag
+.B grohtml
+will treat the html browser as a printer, not as a formatter.
+.TP
+.B \-m
+leave margins alone.
+.B grohtml
+will not remove left margins.
+.TP
+.B \-t
+forbids
+.B grohtml
+from generating html tables when implementing indentation and tabular text.
+.B grohtml
+can implement .IP by tables or html indents.
+However if .2C is used it can only be sensibly converted to html using a
+table structure.
+As a few known bugs still exist with the html table code this option is
+present to supress execution of this development code.
+The default in
+.B grohtml
+is that html tables are generated when appropriate.
+.TP
+.B \-T
+forbids
+.B grohtml
+from generating images when processing output from tbl.
+This is useful when simple textual tables are being produced.
+.TP
+.BI \-F dir
+Search the directory
+.IB dir /dev name
+for font and device description files;
+.I name
+is the name of the device, usually
+.BR html .
+.TP
+.BI \-I imagetype
+select the type of image generated when grohtml encounters an equation,
+table, or picture.
+By default this is png256.
+Legal image types are: gif and any of the png formats which are supported by
+ghostscript gs(1).
+.TP
+.BI \-r resolution
+select the resolution for all images.
+By default this is 80 pixels per inch.
+Example: -r100 indicates 100 pixels per inch.
+.TP
+.B \-v
+Print the version number.
+.TP
+.B \-?
+Display usage.
+.SH USAGE
+There are styles called
+.BR R ,
+.BR I ,
+.BR B ,
+and
+.B BI
+mounted at font positions 1 to 4.
+It is advisable to invoke groff with the -mhtml macro set, which turns off
+headers, footers, and hyphenation; additionally, it will right justify text.
+.SH DEPENDENCIES
+.B grohtml
+is dependent upon grops and gs.
+If
+.B grohtml
+has been configured to generate gif files then it is further dependent upon,
+ppmtogif, and ppmquant.
+However if it has been configured to generate png files (the default) then
+it is dependent upon gs having a png output device.
+Images are generated whenever a table, picture, equation or line is
+encountered.
+.SH BUGS
+This is still very alpha.
+At least three major bugs remain:
+Firstly,
+.B grohtml
+sometimes miscalculates the end of an html table resulting in text which
+appears twice.
+Secondly equation numbers are not handled correctly.
+Thirdly equation macros and pic macros can confuse
+.BR grohtml .
+.SH "SEE ALSO"
+.BR afmtodit (@MAN1EXT@),
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@),
+.BR psbb (@MAN1EXT@),
+.BR groff_out (@MAN5EXT@),
+.BR groff_font (@MAN5EXT@),
+.BR groff_char (@MAN7EXT@)
diff --git a/src/devices/grohtml/html.cc b/src/devices/grohtml/html.cc
new file mode 100755
index 00000000..3dbbe05b
--- /dev/null
+++ b/src/devices/grohtml/html.cc
@@ -0,0 +1,6505 @@
+// -*- C++ -*-
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+ *
+ * Gaius Mulley (gaius@glam.ac.uk) wrote grohtml
+ * but it owes a huge amount of ideas and raw code from
+ * James Clark (jjc@jclark.com) grops/ps.cc.
+ */
+
+/*
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "driver.h"
+#include "stringclass.h"
+#include "cset.h"
+
+#include "html.h"
+#include "html_chars.h"
+#include <time.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ordered_list.h"
+
+#if !defined(TRUE)
+# define TRUE (1==1)
+#endif
+#if !defined(FALSE)
+# define FALSE (1==0)
+#endif
+
+#define MAX_TEMP_NAME 1024
+#define MAX_STRING_LENGTH 4096
+#define MAX_CHAR_SIZE 50 // maximum length of character name
+
+#define Y_FUDGE_MARGIN +0.83
+#define A4_PAGE_LENGTH (11.6944-Y_FUDGE_MARGIN)
+#define DEFAULT_IMAGE_RES 80
+#define IMAGE_BOARDER_PIXELS 10
+#define MAX_WORDS_PER_LINE 1000 // only used for table indentation
+#define GAP_SPACES 3 // how many spaces needed to guess a gap?
+#define GAP_WIDTH_ONE_LINE 2 // 1/GAP_WIDTH_ONE_LINE inches required for one line table
+#define CENTER_TOLERANCE 2 // how many pixels off center will we think a line or region is centered
+#define MIN_COLUMN 7 // minimum column size pixels for multiple lines
+#define MIN_COLUMN_FOR_TWO_LINES 20 // minimum column size pixels for a 2 line table
+#define MIN_TEXT_PERCENT 5 // try and round to this percentage value for used columns
+#define PERCENT_THRESHOLD 20 // don't bother trying to increase and width greater than this
+
+
+/*
+ * Only uncomment one of the following to determine default image type.
+ */
+
+#define IMAGE_DEFAULT_PNG
+/* #define IMAGE_DEFAULT_GIF */
+
+
+#if defined(IMAGE_DEFAULT_GIF)
+static enum { gif, png } image_type = gif;
+static char *image_device = "gif";
+#elif defined(IMAGE_DEFAULT_PNG)
+static enum { gif, png } image_type = png;
+static char *image_device = "png256";
+#else
+# error "you must define either IMAGE_DEFAULT_GIF or IMAGE_DEFAULT_PNG"
+#endif
+
+static int debug_on = FALSE;
+static int guess_on = TRUE;
+static int margin_on = FALSE;
+static int auto_on = TRUE;
+static int table_on = TRUE;
+static int image_res = DEFAULT_IMAGE_RES;
+static int debug_table_on = FALSE;
+static int table_image_on = TRUE; // default is to create images for tbl
+
+static int linewidth = -1;
+
+#define DEFAULT_LINEWIDTH 40 /* in ems/1000 */
+#define MAX_LINE_LENGTH 72
+#define FILL_MAX 1000
+
+void stop () {}
+
+
+/*
+ * start with a few favorites
+ */
+
+static int min (int a, int b)
+{
+ if (a < b) {
+ return( a );
+ } else {
+ return( b );
+ }
+}
+
+static int max (int a, int b)
+{
+ if (a > b) {
+ return( a );
+ } else {
+ return( b );
+ }
+}
+
+/*
+ * is_subsection - returns TRUE if a1..a2 is within b1..b2
+ */
+
+static int is_subsection (int a1, int a2, int b1, int b2)
+{
+ // easier to see whether this is not the case
+ return( !((a1 < b1) || (a1 > b2) || (a2 < b1) || (a2 > b2)) );
+}
+
+/*
+ * is_intersection - returns TRUE if range a1..a2 intersects with b1..b2
+ */
+
+static int is_intersection (int a1, int a2, int b1, int b2)
+{
+ // again easier to prove NOT outside limits
+ return( ! ((a1 > b2) || (a2 < b1)) );
+}
+
+/*
+ * is_digit - returns TRUE if character, ch, is a digit.
+ */
+
+static int is_digit (char ch)
+{
+ return( (ch >= '0') && (ch <= '9') );
+}
+
+/*
+ * more_than_line_break - returns TRUE should v1 and v2 differ by more than
+ * a simple line break.
+ */
+
+static int more_than_line_break (int v1, int v2, int size)
+{
+ return( abs(v1-v2)>size );
+}
+
+/*
+ * the class and methods for styles
+ */
+
+struct style {
+ font *f;
+ int point_size;
+ int font_no;
+ int height;
+ int slant;
+ style ();
+ style (font *, int, int, int, int);
+ int operator == (const style &) const;
+ int operator != (const style &) const;
+};
+
+style::style()
+ : f(0)
+{
+}
+
+style::style(font *p, int sz, int h, int sl, int no)
+ : f(p), point_size(sz), font_no(no), height(h), slant(sl)
+{
+}
+
+int style::operator==(const style &s) const
+{
+ return (f == s.f && point_size == s.point_size
+ && height == s.height && slant == s.slant);
+}
+
+int style::operator!=(const style &s) const
+{
+ return !(*this == s);
+}
+
+
+/*
+ * the class and methods for retaining ascii text
+ */
+
+struct char_block {
+ enum { SIZE = 256 };
+ char buffer[SIZE];
+ int used;
+ char_block *next;
+
+ char_block();
+};
+
+char_block::char_block()
+: used(0), next(0)
+{
+}
+
+class char_buffer {
+public:
+ char_buffer();
+ ~char_buffer();
+ char *add_string(char *, unsigned int);
+private:
+ char_block *head;
+ char_block *tail;
+};
+
+char_buffer::char_buffer()
+: head(0), tail(0)
+{
+}
+
+char_buffer::~char_buffer()
+{
+ while (head != 0) {
+ char_block *temp = head;
+ head = head->next;
+ delete temp;
+ }
+}
+
+char *char_buffer::add_string (char *s, unsigned int length)
+{
+ int i=0;
+ unsigned int old_used;
+
+ if (tail == 0) {
+ tail = new char_block;
+ head = tail;
+ } else {
+ if (tail->used + length+1 > char_block::SIZE) {
+ tail->next = new char_block;
+ tail = tail->next;
+ }
+ }
+ // at this point we have a tail which is ready for the string.
+ if (tail->used + length+1 > char_block::SIZE) {
+ fatal("need to increase char_block::SIZE");
+ }
+
+ old_used = tail->used;
+ do {
+ tail->buffer[tail->used] = s[i];
+ tail->used++;
+ i++;
+ length--;
+ } while (length>0);
+
+ // add terminating nul character
+
+ tail->buffer[tail->used] = '\0';
+ tail->used++;
+
+ // and return start of new string
+
+ return( &tail->buffer[old_used] );
+}
+
+/*
+ * the classes and methods for maintaining pages and text positions and graphic regions
+ */
+
+class text_glob {
+public:
+ int is_less (text_glob *a, text_glob *b);
+ text_glob (style *s, char *string, unsigned int length,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal, int is_command, int is_html);
+ text_glob (void);
+ ~text_glob (void);
+
+ style text_style;
+ char *text_string;
+ unsigned int text_length;
+ int minv, maxv, minh, maxh;
+ int is_raw_command; // should the text be sent directly to the device?
+ int is_html_command; // is the raw command definitely for the html device ie not an eqn?
+};
+
+text_glob::text_glob (style *s, char *string, unsigned int length,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal, int is_command, int is_html)
+ : text_style(*s), text_string(string), text_length(length),
+ minv(min_vertical), maxv(max_vertical), minh(min_horizontal), maxh(max_horizontal),
+ is_raw_command(is_command), is_html_command(is_html)
+{
+}
+
+text_glob::text_glob ()
+ : text_string(0), text_length(0), minv(-1), maxv(-1), minh(-1), maxh(-1),
+ is_raw_command(FALSE), is_html_command(FALSE)
+{
+}
+
+text_glob::~text_glob ()
+{
+}
+
+int text_glob::is_less (text_glob *a, text_glob *b)
+{
+ if (is_intersection(a->minv+1, a->maxv-1, b->minv+1, b->maxv-1)) {
+ return( a->minh < b->minh );
+ } else {
+ return( a->maxv < b->maxv );
+ }
+}
+
+struct xycoord {
+ int x;
+ int y;
+};
+
+class graphic_glob {
+public:
+ int is_less (graphic_glob *a, graphic_glob *b);
+ graphic_glob (int troff_code);
+ graphic_glob (void);
+ ~graphic_glob (void);
+
+ int minv, maxv, minh, maxh;
+ int xc, yc;
+ int nopoints; // number of points allocated in array below
+ struct xycoord *point;
+ int size;
+ int fill;
+ int code;
+};
+
+graphic_glob::graphic_glob ()
+ : minv(-1), maxv(-1), minh(-1), maxh(-1), nopoints(0), point(0), size(0), code(0)
+{
+}
+
+graphic_glob::~graphic_glob ()
+{
+ if (point != 0) {
+ free(point);
+ }
+}
+
+graphic_glob::graphic_glob (int troff_code)
+ : minv(-1), maxv(-1), minh(-1), maxh(-1), nopoints(0), point(0), size(0), code(troff_code)
+{
+}
+
+int graphic_glob::is_less (graphic_glob *a, graphic_glob *b)
+{
+ return( (a->minv < b->minv) || ((a->minv == b->minv) && (a->minh < b->minh)) );
+}
+
+class region_glob {
+public:
+ region_glob (void);
+ ~region_glob (void);
+ int is_less (region_glob *a, region_glob *b);
+
+ int minv, maxv, minh, maxh;
+};
+
+int region_glob::is_less (region_glob *a, region_glob *b)
+{
+ return( (a->minv < b->minv) || ((a->minv == b->minv) && (a->minh < b->minh)) );
+}
+
+region_glob::region_glob (void)
+ : minv(-1), maxv(-1), minh(-1), maxh(-1)
+{
+}
+
+region_glob::~region_glob (void)
+{
+}
+
+class page {
+public:
+ page (void);
+ void add (style *s, char *string, unsigned int length,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal);
+ void add_html_command (style *s, char *string, unsigned int length,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal);
+ void add_special_char (style *s, char *string, unsigned int length,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal);
+ void add_line (int code, int x1, int y1, int x2, int y2, int size, int fill);
+ void add_arc (int code, int xc, int yc, int *p, double *c, int size, int fill);
+ void add_polygon (int code, int np, int *p, int oh, int ov, int size, int fill);
+ void add_spline (int code, int xc, int yc, int np, int *p, int size, int fill);
+ void calculate_region (void);
+ int is_in_region (graphic_glob *g);
+ int can_grow_region (graphic_glob *g);
+ void make_new_region (graphic_glob *g);
+ int has_line (region_glob *r);
+ int has_word (region_glob *r);
+ int no_raw_commands (int minv, int maxv);
+
+ // and the data
+
+ ordered_list <region_glob> regions; // squares of bitmapped pics,eqn,tbl's
+ ordered_list <text_glob> words; // position of words on page
+ ordered_list <graphic_glob> lines; // position of lines on page
+ char_buffer buffer; // all characters for this page
+ int is_in_graphic; // should graphics and words go below or above
+ ordered_list <text_glob> region_words; // temporary accumulation of words in a region
+ ordered_list <graphic_glob> region_lines; // (as above) and used so that we can determine
+ // the regions vertical limits
+};
+
+page::page()
+ : is_in_graphic(FALSE)
+{
+}
+
+void page::add (style *s, char *string, unsigned int length,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal)
+{
+ if (length > 0) {
+ text_glob *g=new text_glob(s, buffer.add_string(string, length), length,
+ min_vertical, min_horizontal, max_vertical, max_horizontal, FALSE, FALSE);
+ if (is_in_graphic) {
+ region_words.add(g);
+ } else {
+ words.add(g);
+ }
+ }
+}
+
+/*
+ * add_html_command - it only makes sense to add html commands when we are not inside
+ * a graphical entity.
+ */
+
+void page::add_html_command (style *s, char *string, unsigned int length,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal)
+{
+ if ((length > 0) && (! is_in_graphic)) {
+ text_glob *g=new text_glob(s, buffer.add_string(string, length), length,
+ min_vertical, min_horizontal, max_vertical, max_horizontal, TRUE, TRUE);
+ words.add(g);
+ }
+}
+
+/*
+ * add_special_char - it only makes sense to add special characters when we are inside
+ * a graphical entity.
+ */
+
+void page::add_special_char (style *s, char *string, unsigned int length,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal)
+{
+ if ((length > 0) && (is_in_graphic)) {
+ text_glob *g=new text_glob(s, buffer.add_string(string, length), length,
+ min_vertical, min_horizontal, max_vertical, max_horizontal, TRUE, FALSE);
+ region_words.add(g);
+ }
+}
+
+void page::add_line (int code, int x1, int y1, int x2, int y2, int size, int fill)
+{
+ graphic_glob *g = new graphic_glob(code);
+
+ g->minh = min(x1, x2);
+ g->maxh = max(x1, x2);
+ g->minv = min(y1, y2);
+ g->maxv = max(y1, y2);
+ g->point = (struct xycoord *)malloc(sizeof(xycoord)*2);
+ g->nopoints = 2;
+ g->point[0].x = x1 ;
+ g->point[0].y = y1 ;
+ g->point[1].x = x2 ;
+ g->point[1].y = y2 ;
+ g->xc = 0;
+ g->yc = 0;
+ g->size = size;
+ g->fill = fill;
+
+ if (is_in_graphic) {
+ region_lines.add(g);
+ } else {
+ lines.add(g);
+ }
+}
+
+/*
+ * assign_min_max_for_arc - works out the smallest box that will encompass an
+ * arc defined by: origin: g->xc, g->xc
+ * and vector (p[0], p[1]) and (p[2], p[3])
+ */
+
+void assign_min_max_for_arc (graphic_glob *g, int *p, double *c)
+{
+ int radius = (int) sqrt(c[0]*c[0]+c[1]*c[1]);
+ int xv1 = p[0];
+ int yv1 = p[1];
+ int xv2 = p[2];
+ int yv2 = p[3];
+ int x1 = g->xc+xv1;
+ int y1 = g->yc+yv1;
+ int x2 = g->xc+xv1+xv2;
+ int y2 = g->yc+yv1+yv2;
+
+ // firstly lets use the 'circle' limitation
+ g->minh = x1-radius;
+ g->maxh = x1+radius;
+ g->minv = y1-radius;
+ g->maxv = y1+radius;
+
+ // incidentally I'm sure there is a better way to do this, but I don't know it
+ // please can someone let me know or "improve" this function
+
+ // now see which min/max can be reduced and increased for the limits of the arc
+ //
+ //
+ // Q2 | Q1
+ // -----+-----
+ // Q3 | Q4
+ //
+
+
+ if ((xv1>=0) && (yv1>=0)) {
+ // first vector in Q3
+ if ((xv2>=0) && (yv2>=0)) {
+ // second in Q1
+ g->maxh = x2;
+ g->minv = y1;
+ } else if ((xv2<0) && (yv2>=0)) {
+ // second in Q2
+ g->maxh = x2;
+ g->minv = y1;
+ } else if ((xv2>=0) && (yv2<0)) {
+ // second in Q4
+ g->minv = min(y1, y2);
+ } else if ((xv2<0) && (yv2<0)) {
+ // second in Q3
+ if (x1>=x2) {
+ g->minh = x2;
+ g->maxh = x1;
+ g->minv = min(y1, y2);
+ g->maxv = max(y1, y2);
+ } else {
+ // xv2, yv2 could all be zero?
+ }
+ }
+ } else if ((xv1>=0) && (yv1<0)) {
+ // first vector in Q2
+ if ((xv2>=0) && (yv2>=0)) {
+ // second in Q1
+ g->maxh = max(x1, x2);
+ g->minh = min(x1, x2);
+ g->minv = y1;
+ } else if ((xv2<0) && (yv2>=0)) {
+ // second in Q2
+ if (x1<x2) {
+ g->maxh = x2;
+ g->minh = x1;
+ g->minv = min(y1, y2);
+ g->maxv = max(y1, y2);
+ } else {
+ // otherwise almost full circle anyway
+ }
+ } else if ((xv2>=0) && (yv2<0)) {
+ // second in Q4
+ g->minv = y2;
+ g->minh = x1;
+ } else if ((xv2<0) && (yv2<0)) {
+ // second in Q3
+ g->minh = min(x1, x2);
+ }
+ } else if ((xv1<0) && (yv1<0)) {
+ // first vector in Q1
+ if ((xv2>=0) && (yv2>=0)) {
+ // second in Q1
+ if (x1<x2) {
+ g->minh = x1;
+ g->maxh = x2;
+ g->minv = min(y1, y2);
+ g->maxv = max(y1, y2);
+ } else {
+ // nearly full circle
+ }
+ } else if ((xv2<0) && (yv2>=0)) {
+ // second in Q2
+ g->maxv = max(y1, y2);
+ } else if ((xv2>=0) && (yv2<0)) {
+ // second in Q4
+ g->minv = min(y1, y2);
+ g->maxv = max(y1, y2);
+ g->minh = min(x1, x2);
+ } else if ((xv2<0) && (yv2<0)) {
+ // second in Q3
+ g->minh = x2;
+ g->maxv = y1;
+ }
+ } else if ((xv1<0) && (yv1>=0)) {
+ // first vector in Q4
+ if ((xv2>=0) && (yv2>=0)) {
+ // second in Q1
+ g->maxh = max(x1, x2);
+ } else if ((xv2<0) && (yv2>=0)) {
+ // second in Q2
+ g->maxv = max(y1, y2);
+ g->maxh = max(x1, x2);
+ } else if ((xv2>=0) && (yv2<0)) {
+ // second in Q4
+ if (x1>=x2) {
+ g->minv = min(y1, y2);
+ g->maxv = max(y1, y2);
+ g->minh = min(x1, x2);
+ g->maxh = max(x2, x2);
+ } else {
+ // nearly full circle
+ }
+ } else if ((xv2<0) && (yv2<0)) {
+ // second in Q3
+ g->maxv = max(y1, y2);
+ g->minh = min(x1, x2);
+ g->maxh = max(x1, x2);
+ }
+ }
+ // this should *never* happen but if it does it means a case above is wrong..
+
+ // this code is only present for safety sake
+ if (g->maxh < g->minh) {
+ if (debug_on) {
+ fprintf(stderr, "assert failed minh > maxh\n"); fflush(stderr);
+ // stop();
+ }
+ g->maxh = g->minh;
+ }
+ if (g->maxv < g->minv) {
+ if (debug_on) {
+ fprintf(stderr, "assert failed minv > maxv\n"); fflush(stderr);
+ // stop();
+ }
+ g->maxv = g->minv;
+ }
+}
+
+void page::add_arc (int code, int xc, int yc, int *p, double *c, int size, int fill)
+{
+ graphic_glob *g = new graphic_glob(code);
+
+ g->point = (struct xycoord *)malloc(sizeof(xycoord)*2);
+ g->nopoints = 2;
+ g->point[0].x = p[0] ;
+ g->point[0].y = p[1] ;
+ g->point[1].x = p[2] ;
+ g->point[1].y = p[3] ;
+ g->xc = xc;
+ g->yc = yc;
+ g->size = size;
+ g->fill = fill;
+
+ assign_min_max_for_arc(g, p, c);
+
+ if (is_in_graphic) {
+ region_lines.add(g);
+ } else {
+ lines.add(g);
+ }
+}
+
+
+void page::add_polygon (int code, int np, int *p, int oh, int ov, int size, int fill)
+{
+ graphic_glob *g = new graphic_glob(code);
+ int j = 0;
+ int i;
+
+ g->point = (struct xycoord *)malloc(sizeof(xycoord)*np/2);
+ g->nopoints = np/2;
+
+ for (i=0; i<g->nopoints; i++) {
+ g->point[i].x = p[j];
+ j++;
+ g->point[i].y = p[j];
+ j++;
+ }
+ // now calculate min/max
+ g->minh = g->point[0].x;
+ g->minv = g->point[0].y;
+ g->maxh = g->point[0].x;
+ g->maxv = g->point[0].y;
+ for (i=1; i<g->nopoints; i++) {
+ g->minh = min(g->minh, g->point[i].x);
+ g->minv = min(g->minv, g->point[i].y);
+ g->maxh = max(g->maxh, g->point[i].x);
+ g->maxv = max(g->maxv, g->point[i].y);
+ }
+ g->size = size;
+ g->xc = oh;
+ g->yc = ov;
+ g->fill = fill;
+
+ if (is_in_graphic) {
+ region_lines.add(g);
+ } else {
+ lines.add(g);
+ }
+}
+
+void page::add_spline (int code, int xc, int yc, int np, int *p, int size, int fill)
+{
+ graphic_glob *g = new graphic_glob(code);
+ int j = 0;
+ int i;
+
+ g->point = (struct xycoord *)malloc(sizeof(xycoord)*np/2);
+ g->nopoints = np/2;
+
+ for (i=0; i<g->nopoints; i++) {
+ g->point[i].x = p[j];
+ j++;
+ g->point[i].y = p[j];
+ j++;
+ }
+ // now calculate min/max
+ g->minh = min(g->point[0].x, g->point[0].x/2);
+ g->minv = min(g->point[0].y, g->point[0].y/2);
+ g->maxh = max(g->point[0].x, g->point[0].x/2);
+ g->maxv = max(g->point[0].y, g->point[0].y/2);
+
+ /* tnum/tden should be between 0 and 1; the closer it is to 1
+ the tighter the curve will be to the guiding lines; 2/3
+ is the standard value */
+ const int tnum = 2;
+ const int tden = 3;
+
+ for (i=1; i<g->nopoints-1; i++) {
+ g->minh = min(g->minh, g->point[i].x*tnum/(2*tden));
+ g->minv = min(g->minv, g->point[i].y*tnum/(2*tden));
+ g->maxh = max(g->maxh, g->point[i].x*tnum/(2*tden));
+ g->maxv = max(g->maxv, g->point[i].y*tnum/(2*tden));
+
+ g->minh = min(g->minh, g->point[i].x/2+(g->point[i+1].x*(tden-tden))/(2*tden));
+ g->minv = min(g->minv, g->point[i].y/2+(g->point[i+1].y*(tden-tden))/(2*tden));
+ g->maxh = max(g->maxh, g->point[i].x/2+(g->point[i+1].x*(tden-tden))/(2*tden));
+ g->maxv = max(g->maxv, g->point[i].y/2+(g->point[i+1].y*(tden-tden))/(2*tden));
+
+ g->minh = min(g->minh, (g->point[i].x-g->point[i].x/2) + g->point[i+1].x/2);
+ g->minv = min(g->minv, (g->point[i].y-g->point[i].y/2) + g->point[i+1].y/2);
+ g->maxh = max(g->maxh, (g->point[i].x-g->point[i].x/2) + g->point[i+1].x/2);
+ g->maxv = max(g->maxv, (g->point[i].y-g->point[i].y/2) + g->point[i+1].y/2);
+ }
+ i = g->nopoints-1;
+
+ g->minh = min(g->minh, (g->point[i].x-g->point[i].x/2)) + xc;
+ g->minv = min(g->minv, (g->point[i].y-g->point[i].y/2)) + yc;
+ g->maxh = max(g->maxh, (g->point[i].x-g->point[i].x/2)) + xc;
+ g->maxv = max(g->maxv, (g->point[i].y-g->point[i].y/2)) + yc;
+
+ g->size = size;
+ g->xc = xc;
+ g->yc = yc;
+ g->fill = fill;
+
+ if (is_in_graphic) {
+ region_lines.add(g);
+ } else {
+ lines.add(g);
+ }
+}
+
+class html_font : public font {
+ html_font(const char *);
+public:
+ int encoding_index;
+ char *encoding;
+ char *reencoded_name;
+ ~html_font();
+ void handle_unknown_font_command(const char *command, const char *arg,
+ const char *filename, int lineno);
+ static html_font *load_html_font(const char *);
+};
+
+html_font *html_font::load_html_font(const char *s)
+{
+ html_font *f = new html_font(s);
+ if (!f->load()) {
+ delete f;
+ return 0;
+ }
+ return f;
+}
+
+html_font::html_font(const char *nm)
+: font(nm)
+{
+}
+
+html_font::~html_font()
+{
+}
+
+void html_font::handle_unknown_font_command(const char *command, const char *arg,
+ const char *filename, int lineno)
+{
+ if (strcmp(command, "encoding") == 0) {
+ if (arg == 0)
+ error_with_file_and_line(filename, lineno,
+ "`encoding' command requires an argument");
+ else
+ encoding = strsave(arg);
+ }
+}
+
+
+/*
+ * a simple class to contain the header to this document
+ */
+
+class title_desc {
+public:
+ title_desc ();
+ ~title_desc ();
+
+ int has_been_written;
+ int has_been_found;
+ char text[MAX_STRING_LENGTH];
+};
+
+
+title_desc::title_desc ()
+ : has_been_written(FALSE), has_been_found(FALSE)
+{
+}
+
+title_desc::~title_desc ()
+{
+}
+
+class header_desc {
+public:
+ header_desc ();
+ ~header_desc ();
+
+ int no_of_headings; // how many headings have we found?
+ char_buffer headings; // all the headings used in the document
+ ordered_list <text_glob> headers;
+ int header_level; // current header level
+ int written_header; // have we written the header yet?
+ char header_buffer[MAX_STRING_LENGTH]; // current header text
+
+ void write_headings (FILE *f);
+};
+
+header_desc::header_desc ()
+ : no_of_headings(0), header_level(2), written_header(0)
+{
+}
+
+header_desc::~header_desc ()
+{
+}
+
+/*
+ * paragraph_type - alignment for a new paragraph
+ */
+
+typedef enum { left_alignment, center_alignment } paragraph_type;
+
+/*
+ * text_defn - defines the limit of text, initially these are stored in the
+ * column array as words. Later we examine the white space between
+ * the words in successive lines to find out whether we can detect
+ * distinct columns. The columns are generated via html tables.
+ */
+
+struct text_defn {
+ int left; // the start of a word or text
+ int right; // the end of the text and beginning of white space
+ int is_used; // will this this column be used for words or space
+ int right_hits; // count of the number of words touching right position
+ int percent; // what percentage width should we use for this cell?
+};
+
+/*
+ * introduce a paragraph class so that we can nest paragraphs
+ * from plain html text and html tables.
+ */
+
+class html_paragraph {
+public:
+ html_paragraph (int in, int need, paragraph_type type, html_paragraph *prev);
+ ~html_paragraph ();
+
+ int in_paragraph;
+ int need_paragraph;
+ paragraph_type para_type;
+ html_paragraph *previous;
+};
+
+/*
+ * html_paragraph - constructor, fill in the public fields.
+ */
+
+html_paragraph::html_paragraph (int in, int need, paragraph_type type, html_paragraph *prev)
+ : in_paragraph(in), need_paragraph(need),
+ para_type(type), previous(prev)
+{
+}
+
+/*
+ * html_paragraph - deconstructor
+ */
+
+html_paragraph::~html_paragraph ()
+{
+}
+
+/*
+ * note that html_tables are currently only used to provide a better
+ * indentation mechanism for html text (in particular it allows grohtml
+ * to render .IP and .2C together with autoformatting).
+ */
+
+class html_table {
+public:
+ html_table ();
+ ~html_table ();
+
+ int no_of_columns; // how many columns are we using?
+ struct text_defn *columns; // left and right margins for each column
+ int vertical_limit; // the limit of the table
+ int wrap_margin; // is the current rightmost margin able to wrap words?
+};
+
+html_table::html_table ()
+ : no_of_columns(0), columns(0), vertical_limit(0), wrap_margin(0)
+{
+}
+
+html_table::~html_table ()
+{
+}
+
+class html_printer : public printer {
+ FILE *tempfp;
+ simple_output html;
+ simple_output troff;
+ int res;
+ int postscript_res;
+ int space_char_index;
+ int no_of_printed_pages;
+ int paper_length;
+ enum { SBUF_SIZE = 8192 };
+ char sbuf[SBUF_SIZE];
+ int sbuf_len;
+ int sbuf_start_hpos;
+ int sbuf_vpos;
+ int sbuf_end_hpos;
+ int sbuf_kern;
+ style sbuf_style;
+ int sbuf_dmark_hpos;
+ style output_style;
+ int output_hpos;
+ int output_vpos;
+ int output_draw_point_size;
+ int line_thickness;
+ int output_line_thickness;
+ int fill;
+ unsigned char output_space_code;
+ string defs;
+ char *inside_font_style;
+ int page_number;
+ title_desc title;
+ header_desc header;
+ int header_indent;
+ page *page_contents;
+ html_table indentation;
+ int left_margin_indent;
+ int right_margin_indent;
+ int need_one_newline;
+ int issued_newline;
+ html_paragraph *current_paragraph;
+ char image_name[MAX_STRING_LENGTH];
+ int image_number;
+ int graphic_level;
+ int supress_sub_sup;
+
+ int start_region_vpos;
+ int start_region_hpos;
+ int end_region_vpos;
+ int end_region_hpos;
+ int cutoff_heading;
+
+ struct graphic_glob *start_graphic;
+ struct text_glob *start_text;
+
+ void flush_sbuf ();
+ void set_style (const style &);
+ void set_space_code (unsigned char c);
+ void do_exec (char *, const environment *);
+ void do_import (char *, const environment *);
+ void do_def (char *, const environment *);
+ void do_mdef (char *, const environment *);
+ void do_file (char *, const environment *);
+ void set_line_thickness (const environment *);
+ void change_font (text_glob *g, int is_to_html);
+ void terminate_current_font (void);
+ void flush_font (void);
+ void flush_page (void);
+ void add_char_to_sbuf (unsigned char code);
+ void add_to_sbuf (char code, const char *name);
+ void display_word (text_glob *g, int is_to_html);
+ void html_display_word (text_glob *g);
+ void troff_display_word (text_glob *g);
+ void display_line (graphic_glob *g, int is_to_html);
+ void display_fill (graphic_glob *g);
+ void calculate_margin (void);
+ void traverse_page_regions (void);
+ void dump_page (void);
+ int is_within_region (graphic_glob *g);
+ int is_within_region (text_glob *t);
+ int is_less (graphic_glob *g, text_glob *t);
+ void display_globs (int is_to_html);
+ void move_horizontal (text_glob *g, int left_margin);
+ void move_vertical (text_glob *g, paragraph_type p);
+ void write_html_font_face (const char *fontname, const char *left, const char *right);
+ void write_html_font_type (const char *fontname, const char *left, const char *right);
+ void html_change_font (text_glob *g, const char *fontname, int size);
+ char *html_position_text (text_glob *g, int left_margin, int right_margin);
+ int html_position_region (void);
+ void troff_change_font (const char *fontname, int size, int font_no);
+ void troff_position_text (text_glob *g);
+ int pretend_is_on_same_line (text_glob *g, int left_margin, int right_margin);
+ int is_on_same_line (text_glob *g, int vpos);
+ int looks_like_subscript (text_glob *g);
+ int looks_like_superscript (text_glob *g);
+ int looks_like_smaller_font (text_glob *g);
+ int looks_like_larger_font (text_glob *g);
+ void begin_paragraph (paragraph_type p);
+ void begin_paragraph_no_height (paragraph_type p);
+ void force_begin_paragraph (void);
+ void end_paragraph (void);
+ void save_paragraph (void);
+ void restore_paragraph (void);
+ void html_newline (void);
+ void convert_to_image (char *name);
+ void write_title (int in_head);
+ void find_title (void);
+ int is_bold (text_glob *g);
+ void write_header (text_glob *g);
+ void determine_header_level (void);
+ void build_header (text_glob *g);
+ void make_html_indent (int indent);
+ int is_whole_line_bold (text_glob *g);
+ int is_a_header (text_glob *g);
+ int processed_header (text_glob *g);
+ void make_new_image_name (void);
+ void create_temp_name (char *name, char *extension);
+ void calculate_region_margins (region_glob *r);
+ void remove_redundant_regions (void);
+ void remove_duplicate_regions (void);
+ void move_region_to_page (void);
+ void calculate_region_range (graphic_glob *r);
+ void flush_graphic (void);
+ void write_string (graphic_glob *g, int is_to_html);
+ void prologue (void);
+ int gs_x (int x);
+ int gs_y (int y);
+ void display_regions (void);
+ int check_able_to_use_table (text_glob *g);
+ int using_table_for_indent (void);
+ int collect_columns (struct text_defn *next_words, struct text_defn *next_cols,
+ struct text_defn *last_words, struct text_defn *last_cols,
+ int max_words);
+ void include_into_list (struct text_defn *line, struct text_defn *item);
+ int is_in_column (struct text_defn *line, struct text_defn *item, int max_words);
+ int is_column_match (struct text_defn *match, struct text_defn *line1,
+ struct text_defn *line2, int max_words);
+ int count_columns (struct text_defn *line);
+ void rewind_text_to (text_glob *g);
+ int found_use_for_table (text_glob *start);
+ void column_display_word (int cell, int vert, int left, int right, int next);
+ void start_table (void);
+ void end_table (void);
+ void foreach_column_include_text (text_glob *start);
+ void define_cell (int i);
+ int column_calculate_left_margin (int left, int right);
+ int column_calculate_right_margin (int left, int right);
+ void display_columns (const char *word, const char *name, text_defn *line);
+ void calculate_right (struct text_defn *line, int max_words);
+ void determine_right_most_column (struct text_defn *line, int max_words);
+ int remove_white_using_words (struct text_defn *next_guess, struct text_defn *last_guess, struct text_defn *next_line);
+ void copy_line (struct text_defn *dest, struct text_defn *src);
+ void combine_line (struct text_defn *dest, struct text_defn *src);
+ int conflict_with_words (struct text_defn *column_guess, struct text_defn *words);
+ void remove_entry_in_line (struct text_defn *line, int j);
+ void remove_redundant_columns (struct text_defn *line);
+ void add_column_gaps (struct text_defn *line);
+ int continue_searching_column (text_defn *next_col, text_defn *last_col, text_defn *all_words);
+ void add_right_full_width (struct text_defn *line, int mingap);
+ int is_continueous_column (text_defn *last_col, text_defn *next_line);
+ int is_exact_left (text_defn *last_col, text_defn *next_line);
+ int find_column_index_in_line (text_glob *t, text_defn *line);
+ void emit_space (text_glob *g, int force_space);
+ int is_in_middle (int left, int right);
+ int check_able_to_use_center (text_glob *g);
+ void write_centered_line (text_glob *g);
+ int single_centered_line (text_defn *first, text_defn *second, text_glob *g);
+ int determine_row_limit (text_glob *start, int v);
+ void assign_used_columns (text_glob *start);
+ int find_column_index (text_glob *t);
+ int large_enough_gap (text_defn *last_col);
+ int is_worth_column (int left, int right);
+ int is_subset_of_columns (text_defn *a, text_defn *b);
+ void count_hits (text_defn *col, int no_of_columns, int limit);
+ void count_right_hits (text_defn *col, int no_of_columns);
+ int calculate_min_gap (text_glob *g);
+ int right_indentation (struct text_defn *last_guess);
+ void calculate_percentage_width (text_glob *start);
+ int able_to_steal_width (void);
+ int need_to_steal_width (void);
+ int can_distribute_fairly (void);
+ void utilize_round_off (void);
+ int will_wrap_text (int i, text_glob *start);
+ int next_line_on_left_column (int i, text_glob *start);
+ void remove_table_column (int i);
+ void remove_unnecessary_unused (text_glob *start);
+ int is_small_table (int lines, struct text_defn *last_guess,
+ struct text_defn *words_1, struct text_defn *cols_1,
+ struct text_defn *words_2, struct text_defn *cols_2,
+ int *limit, int *limit_1);
+ int is_column_subset (struct text_defn *cols_1, struct text_defn *cols_2);
+ int is_appropriate_to_start_table (struct text_defn *cols_1, struct text_defn *cols_2,
+ struct text_defn *last_guess);
+ int is_a_full_width_column (void);
+ int right_most_column (struct text_defn *col);
+ int large_enough_gap_for_two (struct text_defn *col);
+ void remove_zero_percentage_column (void);
+ void translate_to_html (text_glob *g);
+ int html_knows_about (char *troff);
+ void determine_diacritical_mark (const char *name, const environment *env);
+ int sbuf_continuation (unsigned char code, const char *name, const environment *env, int w);
+ char *remove_last_char_from_sbuf ();
+ const char *check_diacritical_combination (unsigned char code, const char *name);
+ int seen_backwards_escape (char *s, int l);
+ int should_defer_table (int lines, struct text_glob *start, struct text_defn *cols_1);
+ int is_new_exact_right (struct text_defn *last_guess, struct text_defn *last_cols, struct text_defn *next_cols);
+ void issue_left_paragraph (void);
+ void adjust_margin_percentages (void);
+ int total_percentages (void);
+ int get_left (void);
+ void can_loose_column (text_glob *start, struct text_defn *last_guess, int limit);
+ int check_lack_of_hits (struct text_defn *next_guess, struct text_defn *last_guess, text_glob *start, int limit);
+
+ // ADD HERE
+
+public:
+ html_printer();
+ ~html_printer();
+ void set_char(int i, font *f, const environment *env, int w, const char *name);
+ void draw(int code, int *p, int np, const environment *env);
+ void begin_page(int);
+ void end_page(int);
+ void special(char *arg, const environment *env);
+ font *make_font(const char *);
+ void end_of_line();
+};
+
+html_printer::html_printer()
+: html(0, MAX_LINE_LENGTH),
+ troff(0, MAX_LINE_LENGTH),
+ no_of_printed_pages(0),
+ sbuf_len(0),
+ sbuf_dmark_hpos(-1),
+ output_hpos(-1),
+ output_vpos(-1),
+ line_thickness(-1),
+ fill(FILL_MAX + 1),
+ inside_font_style(0),
+ page_number(0),
+ header_indent(-1),
+ left_margin_indent(0),
+ right_margin_indent(0),
+ need_one_newline(0),
+ issued_newline(0),
+ image_number(0),
+ graphic_level(0),
+ supress_sub_sup(TRUE),
+ start_region_vpos(0),
+ start_region_hpos(0),
+ end_region_vpos(0),
+ end_region_hpos(0),
+ cutoff_heading(100)
+{
+ tempfp = xtmpfile();
+ html.set_file(tempfp);
+ if (linewidth < 0)
+ linewidth = DEFAULT_LINEWIDTH;
+ if (font::hor != 1)
+ fatal("horizontal resolution must be 1");
+ if (font::vert != 1)
+ fatal("vertical resolution must be 1");
+#if 0
+ // should be sorted html..
+ if (font::res % (font::sizescale*72) != 0)
+ fatal("res must be a multiple of 72*sizescale");
+#endif
+ int r = font::res;
+ int point = 0;
+ while (r % 10 == 0) {
+ r /= 10;
+ point++;
+ }
+ res = r;
+ html.set_fixed_point(point);
+ space_char_index = font::name_to_index("space");
+ paper_length = font::paperlength;
+ if (paper_length == 0)
+ paper_length = 11*font::res;
+ page_contents = new page;
+
+ postscript_res = 72000;
+ current_paragraph = new html_paragraph(FALSE, FALSE, left_alignment, 0);
+}
+
+/*
+ * add_char_to_sbuf - adds a single character to the sbuf.
+ */
+
+void html_printer::add_char_to_sbuf (unsigned char code)
+{
+ if (sbuf_len < SBUF_SIZE) {
+ sbuf[sbuf_len] = code;
+ sbuf_len++;
+ } else {
+ fatal("need to increase SBUF_SIZE");
+ }
+}
+
+/*
+ * add_to_sbuf - adds character code or name to the sbuf.
+ * It escapes \ with \\
+ * We need to preserve the name of characters if they exist
+ * because we may need to send this character to two different
+ * devices: html and postscript.
+ */
+
+void html_printer::add_to_sbuf (char code, const char *name)
+{
+ if (name == 0) {
+ if (code == '\\') {
+ add_char_to_sbuf('\\');
+ }
+ add_char_to_sbuf(code);
+ } else {
+ int l=strlen(name);
+ int i=0;
+
+ add_char_to_sbuf('\\');
+ add_char_to_sbuf('(');
+ while (i<l) {
+ if (name[i] == '\\') {
+ add_char_to_sbuf('\\');
+ }
+ add_char_to_sbuf(name[i]);
+ i++;
+ }
+ add_char_to_sbuf('\\');
+ add_char_to_sbuf(')');
+ }
+}
+
+int html_printer::sbuf_continuation (unsigned char code, const char *name,
+ const environment *env, int w)
+{
+ if ((sbuf_end_hpos == env->hpos) || (sbuf_dmark_hpos == env->hpos)) {
+ name = check_diacritical_combination(code, name);
+ add_to_sbuf(code, name);
+ determine_diacritical_mark(name, env);
+ sbuf_end_hpos += w + sbuf_kern;
+ return( TRUE );
+ } else {
+ if ((sbuf_len < SBUF_SIZE-1) && (env->hpos >= sbuf_end_hpos) &&
+ ((sbuf_kern == 0) || (sbuf_end_hpos - sbuf_kern != env->hpos))) {
+ /*
+ * lets see whether a space is needed or not
+ */
+ int space_width = sbuf_style.f->get_space_width(sbuf_style.point_size);
+
+ if (env->hpos-sbuf_end_hpos < space_width) {
+ name = check_diacritical_combination(code, name);
+ add_to_sbuf(code, name);
+ determine_diacritical_mark(name, env);
+ sbuf_end_hpos = env->hpos + w;
+ return( TRUE );
+ }
+ } else if ((sbuf_len > 0) && (sbuf_dmark_hpos)) {
+ /*
+ * check whether the diacritical mark is on the same character
+ */
+ int space_width = sbuf_style.f->get_space_width(sbuf_style.point_size);
+
+ if (abs(sbuf_dmark_hpos-env->hpos) < space_width) {
+ name = check_diacritical_combination(code, name);
+ add_to_sbuf(code, name);
+ determine_diacritical_mark(name, env);
+ sbuf_end_hpos = env->hpos + w;
+ return( TRUE );
+ }
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * seen_backwards_escape - returns TRUE if we can see a escape at position i..l in s
+ */
+
+int html_printer::seen_backwards_escape (char *s, int l)
+{
+ /*
+ * this is tricky so it is broken into components for clarity
+ * (we let the compiler put in all back into a complex expression)
+ */
+ if ((l>0) && (sbuf[l] == '(') && (sbuf[l-1] == '\\')) {
+ /*
+ * ok seen '\(' but we must now check for '\\('
+ */
+ if ((l>1) && (sbuf[l-2] == '\\')) {
+ /*
+ * escaped the escape
+ */
+ return( FALSE );
+ } else {
+ return( TRUE );
+ }
+ } else {
+ return( FALSE );
+ }
+}
+
+/*
+ * reverse - return reversed string.
+ */
+
+char *reverse (char *s)
+{
+ int i=0;
+ int j=strlen(s)-1;
+ char t;
+
+ while (i<j) {
+ t = s[i];
+ s[i] = s[j];
+ s[j] = t;
+ i++;
+ j--;
+ }
+ return( s );
+}
+
+/*
+ * remove_last_char_from_sbuf - removes the last character from sbuf.
+ */
+
+char *html_printer::remove_last_char_from_sbuf ()
+{
+ int l=sbuf_len;
+ static char last[MAX_STRING_LENGTH];
+
+ if (l>0) {
+ l--;
+ if ((sbuf[l] == ')') && (l>0) && (sbuf[l-1] == '\\')) {
+ /*
+ * found terminating escape
+ */
+ int i=0;
+
+ l -= 2;
+ while ((l>0) && (! seen_backwards_escape(sbuf, l))) {
+ if (sbuf[l] == '\\') {
+ if (sbuf[l-1] == '\\') {
+ last[i] = sbuf[l];
+ i++;
+ l--;
+ }
+ } else {
+ last[i] = sbuf[l];
+ i++;
+ }
+ l--;
+ }
+ last[i] = (char)0;
+ sbuf_len = l;
+ if (seen_backwards_escape(sbuf, l)) {
+ sbuf_len--;
+ }
+ return( reverse(last) );
+ } else {
+ if ((sbuf[l] == '\\') && (l>0) && (sbuf[l-1] == '\\')) {
+ l -= 2;
+ sbuf_len = l;
+ return( "\\" );
+ } else {
+ sbuf_len--;
+ last[0] = sbuf[sbuf_len];
+ last[1] = (char)0;
+ return( last );
+ }
+ }
+ } else {
+ return( NULL );
+ }
+}
+
+/*
+ * check_diacriticial_combination - checks to see whether the character code
+ * if combined with the previous diacriticial mark
+ * forms a new character.
+ */
+
+const char *html_printer::check_diacritical_combination (unsigned char code, const char *name)
+{
+ static char troff_char[2];
+
+ if ((name == 0) && (sbuf_dmark_hpos >= 0)) {
+ // last character was a diacritical mark
+ char *last = remove_last_char_from_sbuf();
+
+ int i=0;
+ int j;
+
+ while (diacritical_table[i].mark != NULL) {
+ if (strcmp(diacritical_table[i].mark, last) == 0) {
+ j=0;
+ while ((diacritical_table[i].second_troff_char[j] != (char)0) &&
+ (diacritical_table[i].second_troff_char[j] != code)) {
+ j++;
+ }
+ if (diacritical_table[i].second_troff_char[j] == code) {
+ troff_char[0] = diacritical_table[i].translation;
+ troff_char[1] = code;
+ troff_char[2] = (char)0;
+ return( troff_char );
+ }
+ }
+ i++;
+ }
+ add_to_sbuf(last[0], last);
+ }
+ return( name );
+}
+
+/*
+ * determine_diacritical_mark - if name is a diacriticial mark the record the position.
+ * --fixme-- is there a better way of doing this
+ * this must be done in troff somewhere.
+ */
+
+void html_printer::determine_diacritical_mark (const char *name, const environment *env)
+{
+ if (name != 0) {
+ int i=0;
+
+ while (diacritical_table[i].mark != NULL) {
+ if (strcmp(name, diacritical_table[i].mark) == 0) {
+ sbuf_dmark_hpos = env->hpos;
+ return;
+ }
+ i++;
+ }
+ }
+ sbuf_dmark_hpos = -1;
+}
+
+/*
+ * set_char - adds a character into the sbuf if it is a continuation with the previous
+ * word otherwise flush the current sbuf and add character anew.
+ */
+
+void html_printer::set_char(int i, font *f, const environment *env, int w, const char *name)
+{
+ unsigned char code = f->get_code(i);
+
+#if 0
+ if (code == ' ') {
+ stop();
+ }
+#endif
+ style sty(f, env->size, env->height, env->slant, env->fontno);
+ if (sty.slant != 0) {
+ if (sty.slant > 80 || sty.slant < -80) {
+ error("silly slant `%1' degrees", sty.slant);
+ sty.slant = 0;
+ }
+ }
+ if ((name != 0) && (page_contents->is_in_graphic)) {
+ flush_sbuf();
+ int r=font::res; // resolution of the device
+ page_contents->add_special_char(&sty, (char *)name, strlen(name),
+ env->vpos-sty.point_size*r/72, env->hpos,
+ env->vpos , env->hpos+w);
+ sbuf_end_hpos = env->hpos + w;
+ sbuf_start_hpos = env->hpos;
+ sbuf_vpos = env->vpos;
+ sbuf_style = sty;
+ sbuf_kern = 0;
+ } else {
+ if ((sbuf_len > 0) && (sbuf_len < SBUF_SIZE) && (sty == sbuf_style) &&
+ (sbuf_vpos == env->vpos) && (sbuf_continuation(code, name, env, w))) {
+ return;
+ } else {
+ flush_sbuf();
+ sbuf_len = 0;
+ add_to_sbuf(code, name);
+ determine_diacritical_mark(name, env);
+ sbuf_end_hpos = env->hpos + w;
+ sbuf_start_hpos = env->hpos;
+ sbuf_vpos = env->vpos;
+ sbuf_style = sty;
+ sbuf_kern = 0;
+ }
+ }
+}
+
+/*
+ * make_new_image_name - creates a new file name ready for a image file.
+ */
+
+void html_printer::make_new_image_name (void)
+{
+ image_number++;
+ if ((strcmp(current_filename, "<standard input>") == 0) ||
+ (strcmp(current_filename, "-") == 0)) {
+ sprintf(image_name, "grohtml-%d-%ld", image_number, (long)getpid());
+ } else {
+ sprintf(image_name, "%s-%d-%ld", current_filename, image_number, (long)getpid());
+ }
+}
+
+/*
+ * write_title - writes the title to this document
+ */
+
+void html_printer::write_title (int in_head)
+{
+ if (title.has_been_found) {
+ if (in_head) {
+ html.put_string("<title>");
+ html.put_string(title.text);
+ html.put_string("</title>\n");
+ } else {
+ title.has_been_written = TRUE;
+ html.put_string("<h1 align=center>");
+ html.put_string(title.text);
+ html.put_string("</h1>\n");
+ }
+ }
+}
+
+/*
+ * get_html_translation - given the position of the character and its name
+ * return the device encoding for such character.
+ */
+
+char *get_html_translation (font *f, char *name)
+{
+ int index;
+
+ if ((f == 0) || (name == 0) || (strcmp(name, "") == 0)) {
+ return( NULL );
+ } else {
+ index = f->name_to_index(name);
+ if (index == 0) {
+ error("character `%s' not found", name);
+ return( NULL );
+ } else {
+ return( (char *)f->get_special_device_encoding(index) );
+ }
+ }
+}
+
+/*
+ * str_translate_to_html - converts a string, str, into html text. It places
+ * the output input buffer, buf. It truncates string, str, if
+ * there is not enough space in buf.
+ * It looks up the html character encoding of single characters
+ * if, and_single, is TRUE. Characters such as < > & etc.
+ */
+
+void str_translate_to_html (font *f, char *buf, int buflen, char *str, int len, int and_single)
+{
+ int l;
+ char *translation;
+ int e;
+ char escaped_char[MAX_STRING_LENGTH];
+ int i=0;
+ int b=0;
+ int t=0;
+
+#if 0
+ if (strcmp(str, "\\(\\\\-\\)") == 0) {
+ stop();
+ }
+#endif
+ while (str[i] != (char)0) {
+ if ((str[i]=='\\') && (i+1<len)) {
+ i++; // skip the leading backslash
+ if (str[i] == '(') {
+ // start of escape
+ i++;
+ e = 0;
+ while ((str[i] != (char)0) &&
+ (! ((str[i] == '\\') && (i+1<len) && (str[i+1] == ')')))) {
+ if (str[i] == '\\') {
+ i++;
+ }
+ escaped_char[e] = str[i];
+ e++;
+ i++;
+ }
+ if ((str[i] == '\\') && (i+1<len) && (str[i+1] == ')')) {
+ i += 2;
+ }
+ escaped_char[e] = (char)0;
+ if (e > 0) {
+ translation = get_html_translation(f, escaped_char);
+ if (translation) {
+ l = strlen(translation);
+ t = max(0, min(l, buflen-b));
+ strncpy(&buf[b], translation, t);
+ b += t;
+ } else {
+ int index=f->name_to_index(escaped_char);
+
+ if (index != 0) {
+ buf[b] = f->get_code(index);
+ b++;
+ }
+ }
+ }
+ }
+ } else {
+ if (and_single) {
+ char name[2];
+
+ name[0] = str[i];
+ name[1] = (char)0;
+ translation = get_html_translation(f, name);
+ if (translation) {
+ l = strlen(translation);
+ t = max(0, min(l, buflen-b));
+ strncpy(&buf[b], translation, t);
+ b += t;
+ } else {
+ if (b<buflen) {
+ buf[b] = str[i];
+ b++;
+ }
+ }
+ } else {
+ /*
+ * do not attempt to encode single characters
+ */
+ if (b<buflen) {
+ buf[b] = str[i];
+ b++;
+ }
+ }
+ i++;
+ }
+ }
+ buf[min(b, buflen)] = (char)0;
+}
+
+/*
+ * find_title - finds a title to this document, if it exists.
+ */
+
+void html_printer::find_title (void)
+{
+ text_glob *t;
+ int r=font::res;
+ int removed_from_head;
+ char buf[MAX_STRING_LENGTH];
+
+ if ((page_number == 1) && (guess_on)) {
+ if (! page_contents->words.is_empty()) {
+
+ int end_title_hpos = 0;
+ int start_title_vpos = 0;
+ int found_title_start = FALSE;
+ int height = 0;
+ int start_region =-1;
+
+ if (! page_contents->regions.is_empty()) {
+ region_glob *r;
+
+ page_contents->regions.start_from_head();
+ r = page_contents->regions.get_data();
+ if (r->minv > 0) {
+ start_region = r->minv;
+ }
+ }
+
+ page_contents->words.start_from_head();
+ do {
+ t = page_contents->words.get_data();
+ removed_from_head = FALSE;
+ if ((found_title_start) && (start_region != -1) && (t->maxv >= start_region)) {
+ /*
+ * we have just encountered the first graphic region so
+ * we stop looking for a title.
+ */
+ title.has_been_found = TRUE;
+ return;
+ } else if (t->is_raw_command) {
+ // skip raw commands
+ page_contents->words.move_right(); // move onto next word
+ } else if ((!found_title_start) && (t->minh > left_margin_indent) &&
+ ((start_region == -1) || (t->maxv < start_region))) {
+ start_title_vpos = t->minv;
+ end_title_hpos = t->minh;
+ str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE);
+ strcpy((char *)title.text, buf);
+ height = t->text_style.point_size*r/72;
+ found_title_start = TRUE;
+ page_contents->words.sub_move_right();
+ removed_from_head = ((!page_contents->words.is_empty()) &&
+ (page_contents->words.is_equal_to_head()));
+ } else if (found_title_start) {
+ if ((t->minv == start_title_vpos) ||
+ ((!more_than_line_break(start_title_vpos, t->minv, (height*3)/2)) &&
+ (t->minh > left_margin_indent)) ||
+ (is_bold(t) && (t->minh > left_margin_indent))) {
+ start_title_vpos = min(t->minv, start_title_vpos);
+ end_title_hpos = max(t->maxh, end_title_hpos);
+ strcat(title.text, " ");
+ str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE);
+ strcat(title.text, buf);
+ page_contents->words.sub_move_right();
+ removed_from_head = ((!page_contents->words.is_empty()) &&
+ (page_contents->words.is_equal_to_head()));
+ } else {
+ // end of title
+ title.has_been_found = TRUE;
+ return;
+ }
+ } else if (t->minh <= left_margin_indent) {
+ // no margin exists
+ return;
+ } else {
+ // move onto next word
+ page_contents->words.move_right();
+ }
+ } while ((! page_contents->words.is_equal_to_head()) || (removed_from_head));
+ }
+ }
+}
+
+/*
+ * html_newline - generates a newline <br>
+ */
+
+void html_printer::html_newline (void)
+{
+ int r = font::res;
+ int height = output_style.point_size*r/72;
+
+ if (current_paragraph->in_paragraph) {
+ // safe to generate a pretty newline
+ html.put_string("<br>\n");
+ } else {
+ html.put_string("<br>");
+ }
+ output_vpos += height;
+ issued_newline = TRUE;
+}
+
+/*
+ * issue_left_paragraph - emits a left paragraph together with appropriate
+ * margin if header_indent is < left_margin_indent.
+ */
+
+void html_printer::issue_left_paragraph (void)
+{
+ if ((header_indent < left_margin_indent) && (! using_table_for_indent())) {
+ html.put_string("<p style=\"margin-left: ");
+ html.put_number(((left_margin_indent-header_indent)*100)/(right_margin_indent-header_indent));
+ html.put_string("%\">");
+ } else {
+ html.put_string("<p>");
+ }
+}
+
+/*
+ * force_begin_paragraph - force the begin_paragraph to be emitted.
+ */
+
+void html_printer::force_begin_paragraph (void)
+{
+ if (current_paragraph->in_paragraph && current_paragraph->need_paragraph) {
+ switch (current_paragraph->para_type) {
+
+ case left_alignment: issue_left_paragraph();
+ break;
+ case center_alignment: html.put_string("<p align=center>");
+ break;
+ default: fatal("unknown paragraph alignment type");
+ }
+ current_paragraph->need_paragraph = FALSE;
+ }
+}
+
+/*
+ * begin_paragraph - starts a new paragraph. It does nothing if a paragraph
+ * has already been started.
+ */
+
+void html_printer::begin_paragraph (paragraph_type p)
+{
+ if (! current_paragraph->in_paragraph) {
+ int r = font::res;
+ int height = output_style.point_size*r/72;
+
+ if (output_vpos >=0) {
+ // we leave it alone if it is set to the top of page
+ output_vpos += height;
+ }
+ current_paragraph->need_paragraph = TRUE; // delay the <p> just in case we don't actually emit text
+ current_paragraph->in_paragraph = TRUE;
+ current_paragraph->para_type = p;
+ issued_newline = TRUE;
+ }
+}
+
+
+/*
+ * begin_paragraph_no_height - starts a new paragraph. It does nothing if a paragraph
+ * has already been started. Note it does not alter output_vpos.
+ */
+
+void html_printer::begin_paragraph_no_height (paragraph_type p)
+{
+ if (! current_paragraph->in_paragraph) {
+ current_paragraph->need_paragraph = TRUE; // delay the <p> just in case we don't actually emit text
+ current_paragraph->in_paragraph = TRUE;
+ current_paragraph->para_type = p;
+ issued_newline = TRUE;
+ }
+}
+
+/*
+ * end_paragraph - end the current paragraph. It does nothing if a paragraph
+ * has not been started.
+ */
+
+void html_printer::end_paragraph (void)
+{
+ if (current_paragraph->in_paragraph) {
+ // check whether we have generated any text inbetween the potential paragraph begin end
+ if (! current_paragraph->need_paragraph) {
+ int r = font::res;
+ int height = output_style.point_size*r/72;
+
+ output_vpos += height;
+ terminate_current_font();
+ html.put_string("</p>\n");
+ } else {
+ terminate_current_font();
+ }
+ current_paragraph->para_type = left_alignment;
+ current_paragraph->in_paragraph = FALSE;
+ }
+}
+
+/*
+ * save_paragraph - saves the current paragraph state and
+ * creates new paragraph state.
+ */
+
+void html_printer::save_paragraph (void)
+{
+ if (current_paragraph == 0) {
+ fatal("current_paragraph is NULL");
+ }
+ current_paragraph = new html_paragraph(current_paragraph->in_paragraph,
+ current_paragraph->need_paragraph,
+ current_paragraph->para_type,
+ current_paragraph);
+ terminate_current_font();
+}
+
+/*
+ * restore_paragraph - restores the previous paragraph state.
+ */
+
+void html_printer::restore_paragraph (void)
+{
+ html_paragraph *old = current_paragraph;
+
+ current_paragraph = current_paragraph->previous;
+ free(old);
+}
+
+/*
+ * calculate_margin - runs through the words and graphics globs
+ * and finds the start of the left most margin.
+ */
+
+void html_printer::calculate_margin (void)
+{
+ if (! margin_on) {
+ text_glob *w;
+ graphic_glob *g;
+
+ // remove margin
+
+ right_margin_indent = 0;
+
+ if (! page_contents->words.is_empty()) {
+
+ // firstly check the words to determine the right margin
+
+ page_contents->words.start_from_head();
+ do {
+ w = page_contents->words.get_data();
+ if ((w->maxh >= 0) && (w->maxh > right_margin_indent)) {
+ right_margin_indent = w->maxh;
+#if 0
+ if (right_margin_indent == 758) stop();
+#endif
+ }
+ page_contents->words.move_right();
+ } while (! page_contents->words.is_equal_to_head());
+ }
+
+ /*
+ * only examine graphics if no words present
+ */
+ if (! page_contents->lines.is_empty()) {
+ // now check for diagrams for right margin
+ page_contents->lines.start_from_head();
+ do {
+ g = page_contents->lines.get_data();
+ if ((g->maxh >= 0) && (g->maxh > right_margin_indent)) {
+ right_margin_indent = g->maxh;
+#if 0
+ if (right_margin_indent == 950) stop();
+#endif
+ }
+ page_contents->lines.move_right();
+ } while (! page_contents->lines.is_equal_to_head());
+ }
+
+ /*
+ * now we know the right margin lets do the same to find left margin
+ */
+
+ if (header_indent == -1) {
+ header_indent = right_margin_indent;
+ }
+ left_margin_indent = right_margin_indent;
+
+ if (! page_contents->words.is_empty()) {
+ do {
+ w = page_contents->words.get_data();
+ if ((w->minh >= 0) && (w->minh < left_margin_indent)) {
+ if (! is_a_header(w) && (! w->is_raw_command)) {
+ left_margin_indent = w->minh;
+ }
+ }
+ page_contents->words.move_right();
+ } while (! page_contents->words.is_equal_to_head());
+ }
+
+ /*
+ * only examine graphic for margins if text yields nothing
+ */
+
+ if (! page_contents->lines.is_empty()) {
+ // now check for diagrams
+ page_contents->lines.start_from_head();
+ do {
+ g = page_contents->lines.get_data();
+ if ((g->minh >= 0) && (g->minh < left_margin_indent)) {
+ left_margin_indent = g->minh;
+ }
+ page_contents->lines.move_right();
+ } while (! page_contents->lines.is_equal_to_head());
+ }
+ }
+}
+
+/*
+ * calculate_region - runs through the graphics globs and text globs
+ * and ensures that all graphic routines
+ * are defined by the region lists.
+ * This then allows us to easily
+ * determine the range of vertical and
+ * horizontal boundaries for pictures,
+ * tbl's and eqn's.
+ *
+ */
+
+void page::calculate_region (void)
+{
+ graphic_glob *g;
+
+ if (! lines.is_empty()) {
+ lines.start_from_head();
+ do {
+ g = lines.get_data();
+ if (! is_in_region(g)) {
+ if (! can_grow_region(g)) {
+ make_new_region(g);
+ }
+ }
+ lines.move_right();
+ } while (! lines.is_equal_to_head());
+ }
+}
+
+/*
+ * remove_redundant_regions - runs through the regions and ensures that
+ * all are needed. This is required as
+ * a picture may be empty, or EQ EN pair
+ * maybe empty.
+ */
+
+void html_printer::remove_redundant_regions (void)
+{
+ region_glob *r;
+
+ // firstly run through the region making sure that all are needed
+ // ie all contain a line or word
+ if (! page_contents->regions.is_empty()) {
+ page_contents->regions.start_from_tail();
+ do {
+ r = page_contents->regions.get_data();
+ calculate_region_margins(r);
+ if (page_contents->has_line(r) || page_contents->has_word(r)) {
+ page_contents->regions.move_right();
+ } else {
+ page_contents->regions.sub_move_right();
+ }
+ } while ((! page_contents->regions.is_empty()) &&
+ (! page_contents->regions.is_equal_to_tail()));
+ }
+}
+
+void html_printer::display_regions (void)
+{
+ if (debug_table_on) {
+ region_glob *r;
+
+ fprintf(stderr, "==========s t a r t===========\n");
+ if (! page_contents->regions.is_empty()) {
+ page_contents->regions.start_from_head();
+ do {
+ r = page_contents->regions.get_data();
+ fprintf(stderr, "region minv %d maxv %d\n", r->minv, r->maxv);
+ page_contents->regions.move_right();
+ } while (! page_contents->regions.is_equal_to_head());
+ }
+ fprintf(stderr, "============e n d=============\n");
+ fflush(stderr);
+ }
+}
+
+/*
+ * remove_duplicate_regions - runs through the regions and ensures that
+ * no duplicates exist.
+ */
+
+void html_printer::remove_duplicate_regions (void)
+{
+ region_glob *r;
+ region_glob *l=0;
+
+ if (! page_contents->regions.is_empty()) {
+ page_contents->regions.start_from_head();
+ l = page_contents->regions.get_data();
+ page_contents->regions.move_right();
+ r = page_contents->regions.get_data();
+ if (l != r) {
+ do {
+ r = page_contents->regions.get_data();
+ // we have a legit region so we check for an intersection
+ if (is_intersection(r->minv, r->minv, l->minv, l->maxv) &&
+ is_intersection(r->minh, r->maxh, l->minh, l->maxh)) {
+ l->minv = min(r->minv, l->minv);
+ l->maxv = max(r->maxv, l->maxv);
+ l->minh = min(r->minh, l->minh);
+ l->maxh = max(r->maxh, l->maxh);
+ calculate_region_margins(l);
+ page_contents->regions.sub_move_right();
+ } else {
+ l = r;
+ page_contents->regions.move_right();
+ }
+ } while ((! page_contents->regions.is_empty()) &&
+ (! page_contents->regions.is_equal_to_head()));
+ }
+ }
+}
+
+int page::has_line (region_glob *r)
+{
+ graphic_glob *g;
+
+ if (! lines.is_empty()) {
+ lines.start_from_head();
+ do {
+ g = lines.get_data();
+ if (is_subsection(g->minv, g->maxv, r->minv, r->maxv) &&
+ is_subsection(g->minh, g->maxh, r->minh, r->maxh)) {
+ return( TRUE );
+ }
+ lines.move_right();
+ } while (! lines.is_equal_to_head());
+ }
+ return( FALSE );
+}
+
+
+int page::has_word (region_glob *r)
+{
+ text_glob *g;
+
+ if (! words.is_empty()) {
+ words.start_from_head();
+ do {
+ g = words.get_data();
+ if (is_subsection(g->minv, g->maxv, r->minv, r->maxv) &&
+ is_subsection(g->minh, g->maxh, r->minh, r->maxh)) {
+ return( TRUE );
+ }
+ words.move_right();
+ } while (! words.is_equal_to_head());
+ }
+ return( FALSE );
+}
+
+
+void html_printer::calculate_region_margins (region_glob *r)
+{
+ text_glob *w;
+ graphic_glob *g;
+
+ r->minh = right_margin_indent;
+ r->maxh = left_margin_indent;
+
+ if (! page_contents->lines.is_empty()) {
+ page_contents->lines.start_from_head();
+ do {
+ g = page_contents->lines.get_data();
+ if (is_subsection(g->minv, g->maxv, r->minv, r->maxv)) {
+ r->minh = min(r->minh, g->minh);
+ r->maxh = max(r->maxh, g->maxh);
+ }
+ page_contents->lines.move_right();
+ } while (! page_contents->lines.is_equal_to_head());
+ }
+ if (! page_contents->words.is_empty()) {
+ page_contents->words.start_from_head();
+ do {
+ w = page_contents->words.get_data();
+ if (is_subsection(w->minv, w->maxv, r->minv, r->maxv)) {
+ r->minh = min(r->minh, w->minh);
+ r->maxh = max(r->maxh, w->maxh);
+ }
+ page_contents->words.move_right();
+ } while (! page_contents->words.is_equal_to_head());
+ }
+}
+
+
+int page::is_in_region (graphic_glob *g)
+{
+ region_glob *r;
+
+ if (! regions.is_empty()) {
+ regions.start_from_head();
+ do {
+ r = regions.get_data();
+ if (is_subsection(g->minv, g->maxv, r->minv, r->maxv) &&
+ is_subsection(g->minh, g->maxh, r->minh, r->maxh)) {
+ return( TRUE );
+ }
+ regions.move_right();
+ } while (! regions.is_equal_to_head());
+ }
+ return( FALSE );
+}
+
+
+/*
+ * no_raw_commands - returns TRUE if no html raw commands exist between
+ * minv and maxv.
+ */
+
+int page::no_raw_commands (int minv, int maxv)
+{
+ text_glob *g;
+
+ if (! words.is_empty()) {
+ words.start_from_head();
+ do {
+ g = words.get_data();
+ if ((g->is_raw_command) && (g->is_html_command) &&
+ (is_intersection(g->minv, g->maxv, minv, maxv))) {
+ return( FALSE );
+ }
+ words.move_right();
+ } while (! words.is_equal_to_head());
+ }
+ return( TRUE );
+}
+
+/*
+ * can_grow_region - returns TRUE if a region exists which can be extended
+ * to include graphic_glob *g. The region is extended.
+ */
+
+int page::can_grow_region (graphic_glob *g)
+{
+ region_glob *r;
+ int quarter_inch=font::res/4;
+
+ if (! regions.is_empty()) {
+ regions.start_from_head();
+ do {
+ r = regions.get_data();
+ // must prevent grohtml from growing a region through a html raw command
+ if (is_intersection(g->minv, g->maxv, r->minv, r->maxv+quarter_inch) &&
+ (no_raw_commands(r->minv, r->maxv+quarter_inch))) {
+#if defined(DEBUGGING)
+ stop();
+ printf("r minh=%d minv=%d maxh=%d maxv=%d\n",
+ r->minh, r->minv, r->maxh, r->maxv);
+ printf("g minh=%d minv=%d maxh=%d maxv=%d\n",
+ g->minh, g->minv, g->maxh, g->maxv);
+#endif
+ r->minv = min(r->minv, g->minv);
+ r->maxv = max(r->maxv, g->maxv);
+ r->minh = min(r->minh, g->minh);
+ r->maxh = max(r->maxh, g->maxh);
+#if defined(DEBUGGING)
+ printf(" r minh=%d minv=%d maxh=%d maxv=%d\n",
+ r->minh, r->minv, r->maxh, r->maxv);
+#endif
+ return( TRUE );
+ }
+ regions.move_right();
+ } while (! regions.is_equal_to_head());
+ }
+ return( FALSE );
+}
+
+
+/*
+ * make_new_region - creates a new region to contain, g.
+ */
+
+void page::make_new_region (graphic_glob *g)
+{
+ region_glob *r=new region_glob;
+
+ r->minv = g->minv;
+ r->maxv = g->maxv;
+ r->minh = g->minh;
+ r->maxv = g->maxv;
+ regions.add(r);
+}
+
+
+void html_printer::dump_page(void)
+{
+ text_glob *g;
+
+ printf("\n\ndebugging start\n");
+ page_contents->words.start_from_head();
+ do {
+ g = page_contents->words.get_data();
+ printf("%s ", g->text_string);
+ page_contents->words.move_right();
+ } while (! page_contents->words.is_equal_to_head());
+ printf("\ndebugging end\n\n");
+}
+
+
+/*
+ * traverse_page_regions - runs through the regions in current_page
+ * and generate html for text, and troff output
+ * for all graphics.
+ */
+
+void html_printer::traverse_page_regions (void)
+{
+ region_glob *r;
+
+ start_region_vpos = 0;
+ start_region_hpos = 0;
+ end_region_vpos = -1;
+ end_region_hpos = -1;
+
+ if (! page_contents->regions.is_empty()) {
+ page_contents->regions.start_from_head();
+ do {
+ r = page_contents->regions.get_data();
+ if (r->minv > 0) {
+ end_region_vpos = r->minv-1;
+ } else {
+ end_region_vpos = 0;
+ }
+ end_region_hpos = -1;
+ display_globs(TRUE);
+ calculate_region_margins(r);
+ start_region_vpos = end_region_vpos;
+ end_region_vpos = r->maxv;
+ start_region_hpos = r->minh;
+ end_region_hpos = r->maxh;
+ display_globs(FALSE);
+ start_region_vpos = end_region_vpos+1;
+ start_region_hpos = 0;
+ page_contents->regions.move_right();
+ } while (! page_contents->regions.is_equal_to_head());
+ start_region_vpos = end_region_vpos+1;
+ start_region_hpos = 0;
+ end_region_vpos = -1;
+ end_region_hpos = -1;
+ }
+ display_globs(TRUE);
+}
+
+int html_printer::is_within_region (text_glob *t)
+{
+ int he, ve, hs;
+
+ if (start_region_hpos == -1) {
+ hs = t->minh;
+ } else {
+ hs = start_region_hpos;
+ }
+ if (end_region_vpos == -1) {
+ ve = t->maxv;
+ } else {
+ ve = end_region_vpos;
+ }
+ if (end_region_hpos == -1) {
+ he = t->maxh;
+ } else {
+ he = end_region_hpos;
+ }
+ return( is_subsection(t->minv, t->maxv, start_region_vpos, ve) &&
+ is_subsection(t->minh, t->maxh, hs, he) );
+}
+
+int html_printer::is_within_region (graphic_glob *g)
+{
+ int he, ve, hs;
+
+ if (start_region_hpos == -1) {
+ hs = g->minh;
+ } else {
+ hs = start_region_hpos;
+ }
+ if (end_region_vpos == -1) {
+ ve = g->maxv;
+ } else {
+ ve = end_region_vpos;
+ }
+ if (end_region_hpos == -1) {
+ he = g->maxh;
+ } else {
+ he = end_region_hpos;
+ }
+ return( is_subsection(g->minv, g->maxv, start_region_vpos, ve) &&
+ is_subsection(g->minh, g->maxh, hs, he) );
+}
+
+int html_printer::is_less (graphic_glob *g, text_glob *t)
+{
+ return( (g->minv < t->minv) || ((g->minv == t->minv) && (g->minh < t->minh)) );
+}
+
+static FILE *create_file (char *filename)
+{
+ FILE *f;
+
+ errno = 0;
+ f = fopen(filename, "w");
+ if (f == 0) {
+ error("can't create `%1'", filename);
+ return( 0 );
+ } else {
+ return( f );
+ }
+}
+
+void html_printer::convert_to_image (char *name)
+{
+ char buffer[1024];
+
+ sprintf(buffer, "grops %s > %s.ps\n", name, name);
+ if (debug_on) {
+ fprintf(stderr, "%s", buffer);
+ }
+ system(buffer);
+
+ if (image_type == gif) {
+ sprintf(buffer,
+ "echo showpage | gs -q -dSAFER -sDEVICE=ppmraw -r%d -g%dx%d -sOutputFile=- %s.ps - | ppmquant 256 2> /dev/null | ppmtogif 2> /dev/null > %s.gif \n",
+ image_res,
+ (end_region_hpos-start_region_hpos)*image_res/font::res+IMAGE_BOARDER_PIXELS,
+ (end_region_vpos-start_region_vpos)*image_res/font::res+IMAGE_BOARDER_PIXELS,
+ name, image_name);
+ } else {
+ sprintf(buffer,
+ "echo showpage | gs -q -dSAFER -sDEVICE=%s -r%d -g%dx%d -sOutputFile=- %s.ps - 2> /dev/null > %s.png \n",
+ image_device,
+ image_res,
+ (end_region_hpos-start_region_hpos)*image_res/font::res+IMAGE_BOARDER_PIXELS,
+ (end_region_vpos-start_region_vpos)*image_res/font::res+IMAGE_BOARDER_PIXELS,
+ name, image_name);
+#if 0
+ sprintf(buffer,
+ "echo showpage | gs -q -dSAFER -sDEVICE=ppmraw -r%d -g%dx%d -sOutputFile=- %s.ps - > %s.pnm ; pnmtopng -transparent white %s.pnm > %s.png \n",
+ /* image_device, */
+ image_res,
+ (end_region_hpos-start_region_hpos)*image_res/font::res+IMAGE_BOARDER_PIXELS,
+ (end_region_vpos-start_region_vpos)*image_res/font::res+IMAGE_BOARDER_PIXELS,
+ name, name, name, image_name);
+#endif
+ }
+ if (debug_on) {
+ fprintf(stderr, "%s", buffer);
+ }
+ system(buffer);
+ sprintf(buffer, "/bin/rm -f %s %s.ps\n", name, name);
+ if (debug_on) {
+ fprintf(stderr, "%s", buffer);
+ } else {
+ system(buffer);
+ }
+}
+
+void html_printer::prologue (void)
+{
+ troff.put_string("x T ps\nx res ");
+ troff.put_number(postscript_res);
+ troff.put_string(" 1 1\nx init\np1\n");
+}
+
+void html_printer::create_temp_name (char *name, char *extension)
+{
+ make_new_image_name();
+ sprintf(name, "/tmp/grohtml-%d-%ld.%s", image_number, (long)getpid(), extension);
+}
+
+void html_printer::display_globs (int is_to_html)
+{
+ text_glob *t=0;
+ graphic_glob *g=0;
+ FILE *f=0;
+ char name[MAX_TEMP_NAME];
+ int something=FALSE;
+ int is_center=FALSE;
+
+ end_paragraph();
+
+ if (! is_to_html) {
+ is_center = html_position_region();
+ create_temp_name(name, "troff");
+ f = create_file(name);
+ troff.set_file(f);
+ prologue();
+ output_style.f = 0;
+ }
+ if (! page_contents->words.is_empty()) {
+ page_contents->words.start_from_head();
+ t = page_contents->words.get_data();
+ }
+
+ if (! page_contents->lines.is_empty()) {
+ page_contents->lines.start_from_head();
+ g = page_contents->lines.get_data();
+ }
+
+ do {
+#if 0
+ if ((t != 0) && (strcmp(t->text_string, "(1.a)") == 0)) {
+ stop();
+ }
+#endif
+ if ((t == 0) && (g != 0)) {
+ if (is_within_region(g)) {
+ something = TRUE;
+ display_line(g, is_to_html);
+ }
+ if (page_contents->lines.is_empty() || page_contents->lines.is_equal_to_tail()) {
+ g = 0;
+ } else {
+ g = page_contents->lines.move_right_get_data();
+ }
+ } else if ((g == 0) && (t != 0)) {
+ if (is_within_region(t)) {
+ display_word(t, is_to_html);
+ something = TRUE;
+ }
+ if (page_contents->words.is_empty() || page_contents->words.is_equal_to_tail()) {
+ t = 0;
+ } else {
+ t = page_contents->words.move_right_get_data();
+ }
+ } else {
+ if ((g == 0) || (t == 0)) {
+ // hmm nothing to print out...
+ } else if (is_less(g, t)) {
+ if (is_within_region(g)) {
+ display_line(g, is_to_html);
+ something = TRUE;
+ }
+ if (page_contents->lines.is_empty() || page_contents->lines.is_equal_to_tail()) {
+ g = 0;
+ } else {
+ g = page_contents->lines.move_right_get_data();
+ }
+ } else {
+ if (is_within_region(t)) {
+ display_word(t, is_to_html);
+ something = TRUE;
+ }
+ if (page_contents->words.is_empty() || page_contents->words.is_equal_to_tail()) {
+ t = 0;
+ } else {
+ t = page_contents->words.move_right_get_data();
+ }
+ }
+ }
+ } while ((t != 0) || (g != 0));
+
+ if ((! is_to_html) && (f != 0)) {
+ fclose(troff.get_file());
+ if (something) {
+ convert_to_image(name);
+
+ if (is_center) {
+ end_paragraph();
+ begin_paragraph(center_alignment);
+ force_begin_paragraph();
+ }
+ html.put_string("<img src=\"");
+ html.put_string(image_name);
+ if (image_type == gif) {
+ html.put_string(".gif\"");
+ } else {
+ html.put_string(".png\"");
+ }
+ html.put_string(">\n");
+ html_newline();
+ if (is_center) {
+ end_paragraph();
+ }
+
+ output_vpos = end_region_vpos;
+ output_hpos = 0;
+ need_one_newline = FALSE;
+ output_style.f = 0;
+ end_paragraph();
+ }
+ // unlink(name); // remove troff file
+ }
+}
+
+void html_printer::flush_page (void)
+{
+ calculate_margin();
+ output_vpos = -1;
+ output_hpos = get_left();
+ supress_sub_sup = TRUE;
+#if 0
+ dump_page();
+#endif
+ html.begin_comment("left margin: ").comment_arg(itoa(left_margin_indent)).end_comment();;
+ html.begin_comment("right margin: ").comment_arg(itoa(right_margin_indent)).end_comment();;
+ remove_redundant_regions();
+ page_contents->calculate_region();
+ remove_duplicate_regions();
+ find_title();
+ supress_sub_sup = TRUE;
+ traverse_page_regions();
+ terminate_current_font();
+ if (need_one_newline) {
+ html_newline();
+ }
+ end_paragraph();
+
+ // move onto a new page
+ delete page_contents;
+ page_contents = new page;
+}
+
+static int convertSizeToHTML (int size)
+{
+ if (size < 6) {
+ return( 0 );
+ } else if (size < 8) {
+ return( 1 );
+ } else if (size < 10) {
+ return( 2 );
+ } else if (size < 12) {
+ return( 3 );
+ } else if (size < 14) {
+ return( 4 );
+ } else if (size < 16) {
+ return( 5 );
+ } else if (size < 18) {
+ return( 6 );
+ } else {
+ return( 7 );
+ }
+}
+
+
+void html_printer::write_html_font_face (const char *fontname, const char *left, const char *right)
+{
+ switch (fontname[0]) {
+
+ case 'C': html.put_string(left) ; html.put_string("tt"); html.put_string(right);
+ break;
+ case 'H': break;
+ case 'T': break;
+ default: break;
+ }
+}
+
+
+void html_printer::write_html_font_type (const char *fontname, const char *left, const char *right)
+{
+ if (strcmp(&fontname[1], "B") == 0) {
+ html.put_string(left) ; html.put_string("B"); html.put_string(right);
+ } else if (strcmp(&fontname[1], "I") == 0) {
+ html.put_string(left) ; html.put_string("I"); html.put_string(right);
+ } else if (strcmp(&fontname[1], "BI") == 0) {
+ html.put_string(left) ; html.put_string("EM"); html.put_string(right);
+ }
+}
+
+
+void html_printer::html_change_font (text_glob *g, const char *fontname, int size)
+{
+ char buffer[1024];
+
+ if (output_style.f != 0) {
+ const char *oldfontname = output_style.f->get_name();
+
+ // firstly terminate the current font face and type
+ if ((oldfontname != 0) && (oldfontname != fontname)) {
+ write_html_font_face(oldfontname, "</", ">");
+ write_html_font_type(oldfontname, "</", ">");
+ }
+ }
+
+ if ((output_style.point_size != size) && (output_style.point_size != 0)) {
+ // shutdown the previous font size
+ html.put_string("</font>");
+ }
+
+ if ((output_style.point_size != size) && (size != 0)) {
+ // now emit the size if it has changed
+ sprintf(buffer, "<font size=%d>", convertSizeToHTML(size));
+ html.put_string(buffer);
+ output_style.point_size = size; // and remember the size
+ }
+ output_style.f = 0; // no style at present
+ output_style.point_size = size; // remember current font size
+
+ if (fontname != 0) {
+ if (! g->is_raw_command) {
+ // now emit the new font
+ write_html_font_face(fontname, "<", ">");
+
+ // now emit the new font type
+ write_html_font_type(fontname, "<", ">");
+
+ output_style = g->text_style; // remember style for next time
+ }
+ }
+}
+
+
+void html_printer::change_font (text_glob *g, int is_to_html)
+{
+ if (is_to_html) {
+ if (output_style != g->text_style) {
+ const char *fontname=0;
+ int size=0;
+
+ if (g->text_style.f != 0) {
+ fontname = g->text_style.f->get_name();
+ size = (font::res/(72*font::sizescale))*g->text_style.point_size;
+ }
+ html_change_font(g, fontname, size);
+ }
+ } else {
+ // is to troff
+ if (output_style != g->text_style) {
+ if (g->text_style.f != 0) {
+ const char *fontname = g->text_style.f->get_name();
+ int size = (font::res/(72*font::sizescale))*g->text_style.point_size;
+
+ if (fontname == 0) {
+ fatal("no internalname specified for font");
+ }
+
+ troff_change_font(fontname, size, g->text_style.font_no);
+ output_style = g->text_style; // remember style for next time
+ }
+ }
+ }
+}
+
+/*
+ * is_bold - returns TRUE if the text inside, g, is using a bold face.
+ * It returns FALSE is g contains a raw html command, even if this uses
+ * a bold font.
+ */
+
+int html_printer::is_bold (text_glob *g)
+{
+ if (g->text_style.f == 0) {
+ // unknown font
+ return( FALSE );
+ } else if (g->is_raw_command) {
+ return( FALSE );
+ } else {
+ const char *fontname = g->text_style.f->get_name();
+
+ if (strlen(fontname) >= 2) {
+ return( fontname[1] == 'B' );
+ } else {
+ return( FALSE );
+ }
+ }
+}
+
+void html_printer::terminate_current_font (void)
+{
+ text_glob g;
+
+ // we create a dummy glob just so we can tell html_change_font not to start up
+ // a new font
+ g.is_raw_command = TRUE;
+ html_change_font(&g, 0, 0);
+}
+
+void html_printer::write_header (text_glob *g)
+{
+ if (strlen(header.header_buffer) > 0) {
+ if (header.header_level > 7) {
+ header.header_level = 7;
+ }
+
+ if (cutoff_heading+2 > header.header_level) {
+ // firstly we must terminate any font and type faces
+ terminate_current_font();
+ end_paragraph();
+
+ // secondly we generate a tag
+ html.put_string("<a name=\"");
+ html.put_string(header.header_buffer);
+ html.put_string("\"></a>");
+ // now we save the header so we can issue a list of link
+ style st;
+
+ header.no_of_headings++;
+
+ text_glob *h=new text_glob(&st,
+ header.headings.add_string(header.header_buffer, strlen(header.header_buffer)),
+ strlen(header.header_buffer),
+ header.no_of_headings, header.header_level,
+ header.no_of_headings, header.header_level,
+ FALSE, FALSE);
+ header.headers.add(h); // and add this header to the header list
+ } else {
+ terminate_current_font();
+ end_paragraph();
+ }
+
+ // we adjust the margin if necessary
+
+ if (g->minh < left_margin_indent) {
+ header_indent = g->minh;
+ }
+
+ // and now we issue the real header
+ html.put_string("<h");
+ html.put_number(header.header_level);
+ html.put_string(">");
+ html.put_string(header.header_buffer);
+ html.put_string("</h");
+ html.put_number(header.header_level);
+ html.put_string(">");
+
+ need_one_newline = FALSE;
+ begin_paragraph(left_alignment);
+ header.written_header = TRUE;
+ }
+}
+
+/*
+ * translate_str_to_html - translates a string, str, into html representation.
+ * len indicates the string length.
+ */
+
+void translate_str_to_html (font *f, char *str, int len)
+{
+ char buf[MAX_STRING_LENGTH];
+
+ str_translate_to_html(f, buf, MAX_STRING_LENGTH, str, len, TRUE);
+ strncpy(str, buf, max(len, strlen(buf)+1));
+}
+
+/*
+ * write_headings - emits a list of links for the headings in this document
+ */
+
+void header_desc::write_headings (FILE *f)
+{
+ text_glob *g;
+
+ if (! headers.is_empty()) {
+ headers.start_from_head();
+ do {
+ g = headers.get_data();
+ fprintf(f, "<a href=\"#%s\">%s</a><br>\n", g->text_string, g->text_string);
+ headers.move_right();
+ } while (! headers.is_equal_to_head());
+ }
+}
+
+void html_printer::determine_header_level (void)
+{
+ int i;
+ int l=strlen(header.header_buffer);
+ int stops=0;
+
+ for (i=0; ((i<l) && ((header.header_buffer[i] == '.') || is_digit(header.header_buffer[i]))) ; i++) {
+ if (header.header_buffer[i] == '.') {
+ stops++;
+ }
+ }
+ if (stops > 0) {
+ header.header_level = stops;
+ }
+}
+
+
+void html_printer::build_header (text_glob *g)
+{
+ text_glob *l;
+ int current_vpos;
+ char buf[MAX_STRING_LENGTH];
+
+ strcpy(header.header_buffer, "");
+ do {
+ l = g;
+ current_vpos = g->minv;
+ str_translate_to_html(g->text_style.f, buf, MAX_STRING_LENGTH, g->text_string, g->text_length, TRUE);
+ strcat(header.header_buffer, (char *)buf);
+ page_contents->words.move_right();
+ g = page_contents->words.get_data();
+ if (g->minv == current_vpos) {
+ strcat(header.header_buffer, " ");
+ }
+ } while ((! page_contents->words.is_equal_to_head()) &&
+ ((g->minv == current_vpos) || (l->maxh == right_margin_indent)));
+
+ determine_header_level();
+ // finally set the output to neutral for after the header
+
+ g = page_contents->words.get_data();
+ output_vpos = g->minv; // set output_vpos to the next line since
+ output_hpos = left_margin_indent; // html header forces a newline anyway
+ page_contents->words.move_left(); // so that next time we use old g
+
+ need_one_newline = FALSE;
+}
+
+
+/*
+ * is_whole_line_bold - returns TRUE if the whole line is bold.
+ */
+
+int html_printer::is_whole_line_bold (text_glob *g)
+{
+ text_glob *n=g;
+ int current_vpos=g->minv;
+
+ do {
+ if (is_bold(n)) {
+ page_contents->words.move_right();
+ n = page_contents->words.get_data();
+ } else {
+ while (page_contents->words.get_data() != g) {
+ page_contents->words.move_left();
+ }
+ return( FALSE );
+ }
+ } while ((! page_contents->words.is_equal_to_head()) && (is_on_same_line(n, current_vpos)));
+ // was (n->minv == current_vpos)
+ while (page_contents->words.get_data() != g) {
+ page_contents->words.move_left();
+ }
+ return( TRUE );
+}
+
+
+/*
+ * is_a_header - returns TRUE if the whole sequence of contineous lines are bold.
+ * It checks to see whether a line is likely to be contineous and
+ * then checks that all words are bold.
+ */
+
+int html_printer::is_a_header (text_glob *g)
+{
+ text_glob *l;
+ text_glob *n=g;
+ int current_vpos;
+
+ do {
+ l = n;
+ current_vpos = n->minv;
+ if (is_bold(n)) {
+ page_contents->words.move_right();
+ n = page_contents->words.get_data();
+ } else {
+ while (page_contents->words.get_data() != g) {
+ page_contents->words.move_left();
+ }
+ return( FALSE );
+ }
+ } while ((! page_contents->words.is_equal_to_head()) &&
+ ((n->minv == current_vpos) || (l->maxh == right_margin_indent)));
+ while (page_contents->words.get_data() != g) {
+ page_contents->words.move_left();
+ }
+ return( TRUE );
+}
+
+
+int html_printer::processed_header (text_glob *g)
+{
+ if ((guess_on) && (g->minh <= left_margin_indent) && (! using_table_for_indent()) &&
+ (is_a_header(g))) {
+ build_header(g);
+ write_header(g);
+ return( TRUE );
+ } else {
+ return( FALSE );
+ }
+}
+
+int is_punctuation (char *s, int length)
+{
+ return( (length == 1) &&
+ ((s[0] == '(') || (s[0] == ')') || (s[0] == '!') || (s[0] == '.') || (s[0] == '[') ||
+ (s[0] == ']') || (s[0] == '?') || (s[0] == ',') || (s[0] == ';') || (s[0] == ':') ||
+ (s[0] == '@') || (s[0] == '#') || (s[0] == '$') || (s[0] == '%') || (s[0] == '^') ||
+ (s[0] == '&') || (s[0] == '*') || (s[0] == '+') || (s[0] == '-') || (s[0] == '=') ||
+ (s[0] == '{') || (s[0] == '}') || (s[0] == '|') || (s[0] == '\"') || (s[0] == '\''))
+ );
+}
+
+/*
+ * move_horizontal - moves right into the position, g->minh.
+ */
+
+void html_printer::move_horizontal (text_glob *g, int left_margin)
+{
+ if (g->text_style.f != 0) {
+ int w = g->text_style.f->get_space_width(g->text_style.point_size);
+
+ if (w == 0) {
+ fatal("space width is zero");
+ }
+ if ((output_hpos == left_margin) && (g->minh > output_hpos)) {
+ make_html_indent(g->minh-output_hpos);
+ } else {
+ emit_space(g, FALSE);
+ }
+ output_hpos = g->maxh;
+ output_vpos = g->minv;
+
+ change_font(g, TRUE);
+ }
+}
+
+/*
+ * looks_like_subscript - returns TRUE if, g, looks like a subscript.
+ */
+
+int html_printer::looks_like_subscript (text_glob *g)
+{
+ int r = font::res;
+ int height = output_style.point_size*r/72;
+
+ /* was return( ((output_vpos < g->minv) && (output_style.point_size != 0) &&
+ * (output_style.point_size > g->text_style.point_size)) );
+ */
+
+ return( (output_style.point_size != 0) && (! supress_sub_sup) && (output_vpos+height < g->maxv) );
+}
+
+/*
+ * looks_like_superscript - returns TRUE if, g, looks like a superscript.
+ */
+
+int html_printer::looks_like_superscript (text_glob *g)
+{
+ int r = font::res;
+ int height = output_style.point_size*r/72;
+
+/* was
+ * return(((output_vpos > g->minv) && (output_style.point_size != 0) &&
+ * (output_style.point_size > g->text_style.point_size)));
+ */
+
+ return( (output_style.point_size != 0) && (! supress_sub_sup) && (output_vpos+height > g->maxv) );
+}
+
+/*
+ * looks_like_larger_font - returns TRUE if, g, can be treated as a larger font.
+ * g needs to be on the same line
+ */
+
+int html_printer::looks_like_larger_font (text_glob *g)
+{
+ int r = font::res;
+ int height = output_style.point_size*r/72;
+
+ return( (output_vpos+height == g->maxv) && (output_style.point_size != 0) &&
+ (convertSizeToHTML(g->text_style.point_size)+1 == convertSizeToHTML(output_style.point_size)) );
+}
+
+/*
+ * looks_like_smaller_font - returns TRUE if, g, can be treated as a smaller font.
+ * g needs to be on the same line
+ */
+
+int html_printer::looks_like_smaller_font (text_glob *g)
+{
+ int r = font::res;
+ int height = output_style.point_size*r/72;
+
+ return( (output_vpos+height == g->maxv) && (output_style.point_size != 0) &&
+ (convertSizeToHTML(g->text_style.point_size) == convertSizeToHTML(output_style.point_size)+1) );
+}
+
+/*
+ * pretend_is_on_same_line - returns TRUE if we think, g, is on the same line as the previous glob.
+ * Note that it believes a single word spanning the left..right as being
+ * on a different line.
+ */
+
+int html_printer::pretend_is_on_same_line (text_glob *g, int left_margin, int right_margin)
+{
+ return( auto_on && (right_margin == output_hpos) && (left_margin == g->minh) &&
+ (right_margin != g->maxh) && ((! is_whole_line_bold(g)) || (g->text_style.f == output_style.f)) &&
+ (! (using_table_for_indent()) || (indentation.wrap_margin)) );
+}
+
+int html_printer::is_on_same_line (text_glob *g, int vpos)
+{
+#if 0
+ if (g->is_html_command) {
+ stop();
+ }
+#endif
+ return(
+ (vpos >= 0) &&
+ (is_intersection(vpos, vpos+g->text_style.point_size*font::res/72-1, g->minv, g->maxv))
+ );
+}
+
+
+/*
+ * make_html_indent - creates a relative indentation.
+ */
+
+void html_printer::make_html_indent (int indent)
+{
+ if (indent > 0) {
+ html.put_string("<span style=\" text-indent: ");
+ html.put_number((indent*100)/(right_margin_indent-get_left()));
+ html.put_string("%;\"></span>");
+ }
+}
+
+/*
+ * using_table_for_indent - returns TRUE if we currently using a table for indentation
+ * purposes.
+ */
+
+int html_printer::using_table_for_indent (void)
+{
+ return( indentation.no_of_columns != 0 );
+}
+
+/*
+ * calculate_min_gap - returns the minimum gap by which we deduce columns.
+ * This is a rough heuristic.
+ */
+
+int html_printer::calculate_min_gap (text_glob *g)
+{
+ text_glob *t = g;
+
+ while ((t->is_raw_command) && (! page_contents->words.is_equal_to_tail()) &&
+ ((t->minv < end_region_vpos) || (end_region_vpos < 0))) {
+ page_contents->words.move_right();
+ t=page_contents->words.get_data();
+ }
+ rewind_text_to(g);
+ if (t->is_raw_command) {
+ return( font::res * 10 ); // impossibly large gap width
+ } else {
+ return( t->text_style.f->get_space_width(t->text_style.point_size)*GAP_SPACES );
+ }
+}
+
+/*
+ * collect_columns - place html text in a column and return the vertical limit reached.
+ */
+
+int html_printer::collect_columns (struct text_defn *next_words,
+ struct text_defn *next_cols,
+ struct text_defn *last_words,
+ struct text_defn *last_cols,
+ int max_words)
+{
+ text_glob *start = page_contents->words.get_data();
+ text_glob *t = start;
+ int upper_limit = 0;
+
+ /*
+ * initialize cols and words
+ */
+ next_words[0].left = 0;
+ next_words[0].right = 0;
+ next_cols [0].left = 0;
+ next_cols [0].right = 0;
+
+ /*
+ * if we have not reached the end collect the words on the current line
+ */
+ if (start != 0) {
+ int graphic_limit = end_region_vpos;
+
+ if (is_whole_line_bold(t) && (t->minh <= left_margin_indent)) {
+ /*
+ * found header therefore terminate indentation table.
+ * Return a negative number so we know a header has
+ * stopped the column
+ */
+ upper_limit = -t->minv;
+ } else {
+ int i =0; // is the index into next_cols
+ int j =0; // is the column index for last_cols
+ int k =0; // is the index into next_words
+ int l =0; // is the index into next_words
+ int prevh =0;
+ int mingap =calculate_min_gap(start);
+
+ /*
+ * while words on the same line record them and any significant gaps
+ */
+ while ((t != 0) && (is_on_same_line(t, start->minv) && (i<max_words)) &&
+ ((graphic_limit == -1) || (graphic_limit > t->minv))) {
+
+ /*
+ * now find column index from the last line which corresponds to, t.
+ */
+ j = find_column_index_in_line(t, last_cols);
+
+ /*
+ * now find word index from the last line which corresponds to, t.
+ */
+ l = find_column_index_in_line(t, last_words);
+
+ /*
+ * Note t->minh might equal t->maxh when we are passing a special device character via \X
+ * we currently ignore this when considering tables
+ *
+ * if we have found a significant gap then record it
+ */
+ if (((t->minh - prevh >= mingap) ||
+ ((last_cols != 0) && (last_cols [j].left != 0) && (t->minh == last_cols [j].left))) &&
+ (t->minh != t->maxh)) {
+ next_cols[i].left = t->minh;
+ next_cols[i].right = t->maxh;
+ i++;
+ /*
+ * terminate the array
+ */
+ if (i<max_words) {
+ next_cols[i].left = 0;
+ next_cols[i].right = 0;
+ }
+ } else if (i>0) {
+ /*
+ * move previous right hand column to align with, t.
+ */
+
+ if (t->minh > next_cols[i-1].left) {
+ /*
+ * a simple precaution in case we get globs which are technically on the same line
+ * (sadly this does occur sometimes - maybe we should be stricter with is_on_same_line)
+ * --fixme--
+ */
+ next_cols[i-1].right = max(next_cols[i-1].right, t->maxh);
+ }
+ }
+ /*
+ * remember to record the individual words
+ */
+ next_words[k].left = t->minh;
+ next_words[k].right = t->maxh;
+ k++;
+
+ /*
+ * and record the vertical upper limit
+ */
+ upper_limit = max(t->minv, upper_limit);
+
+ /*
+ * and update prevh - used to detect a when a different line is seen
+ */
+ prevh = t->maxh;
+
+ /*
+ * get next word into, t, which equals 0, if no word is found
+ */
+ page_contents->words.move_right();
+ t = page_contents->words.get_data();
+ if (page_contents->words.is_equal_to_head()) {
+ t = 0;
+ }
+ }
+
+ /*
+ * and terminate the next_words array
+ */
+
+ if (k<max_words) {
+ next_words[k].left = 0;
+ next_words[k].right = 0;
+ }
+
+ /*
+ * consistency check, next_cols, after removing redundant colums.
+ */
+
+ remove_redundant_columns(next_cols);
+
+#if 0
+ for (k=0; k<count_columns(next_cols); k++) {
+ if (next_cols[k].left > next_cols[k].right) {
+ fprintf(stderr, "left > right\n"); fflush(stderr);
+ stop();
+ fatal("next_cols has messed up columns");
+ }
+ if ((k>0) && (k+1<count_columns(next_cols)) && (next_cols[k].right > next_cols[k+1].left)) {
+ fprintf(stderr, "next_cols[k].right > next_cols[k+1].left\n"); fflush(stderr);
+ stop();
+ fatal("next_cols has messed up columns");
+ }
+ }
+#endif
+ }
+ }
+ return( upper_limit );
+}
+
+/*
+ * conflict_with_words - returns TRUE if a word sequence crosses a column.
+ */
+
+int html_printer::conflict_with_words (struct text_defn *column_guess, struct text_defn *words)
+{
+ int i=0;
+ int j;
+
+ while ((column_guess[i].left != 0) && (i<MAX_WORDS_PER_LINE)) {
+ j=0;
+ while ((words[j].left != 0) && (j<MAX_WORDS_PER_LINE)) {
+ if ((words[j].left <= column_guess[i].right) && (i+1<MAX_WORDS_PER_LINE) &&
+ (column_guess[i+1].left != 0) && (words[j].right >= column_guess[i+1].left)) {
+ if (debug_table_on) {
+ fprintf(stderr, "is a conflict with words\n");
+ fflush(stderr);
+ }
+ return( TRUE );
+ }
+ j++;
+ }
+ i++;
+ }
+ if (debug_table_on) {
+ fprintf(stderr, "is NOT a conflict with words\n");
+ fflush(stderr);
+ }
+ return( FALSE );
+}
+
+/*
+ * combine_line - combines dest and src.
+ */
+
+void html_printer::combine_line (struct text_defn *dest, struct text_defn *src)
+{
+ int i;
+
+ for (i=0; (i<MAX_WORDS_PER_LINE) && (src[i].left != 0); i++) {
+ include_into_list(dest, &src[i]);
+ }
+ remove_redundant_columns(dest);
+}
+
+/*
+ * remove_entry_in_line - removes an entry, j, in, line.
+ */
+
+void html_printer::remove_entry_in_line (struct text_defn *line, int j)
+{
+ while (line[j].left != 0) {
+ line[j].left = line[j+1].left;
+ line[j].right = line[j+1].right;
+ j++;
+ }
+}
+
+/*
+ * remove_redundant_columns - searches through the array columns and removes any redundant entries.
+ */
+
+void html_printer::remove_redundant_columns (struct text_defn *line)
+{
+ int i=0;
+ int j=0;
+
+ while (line[i].left != 0) {
+ if ((i<MAX_WORDS_PER_LINE) && (line[i+1].left != 0)) {
+ j = 0;
+ while ((j<MAX_WORDS_PER_LINE) && (line[j].left != 0)) {
+ if ((j != i) && (is_intersection(line[i].left, line[i].right, line[j].left, line[j].right))) {
+ line[i].left = min(line[i].left , line[j].left);
+ line[i].right = max(line[i].right, line[j].right);
+ remove_entry_in_line(line, j);
+ } else {
+ j++;
+ }
+ }
+ }
+ i++;
+ }
+}
+
+/*
+ * include_into_list - performs an order set inclusion
+ */
+
+void html_printer::include_into_list (struct text_defn *line, struct text_defn *item)
+{
+ int i=0;
+
+ while ((i<MAX_WORDS_PER_LINE) && (line[i].left != 0) && (line[i].left<item->left)) {
+ i++;
+ }
+
+ if (line[i].left == 0) {
+ // add to the end
+ if (i<MAX_WORDS_PER_LINE) {
+ if ((i>0) && (line[i-1].left > item->left)) {
+ fatal("insertion error");
+ }
+ line[i].left = item->left;
+ line[i].right = item->right;
+ i++;
+ line[i].left = 0;
+ line[i].right = 0;
+ }
+ } else {
+ if (line[i].left == item->left) {
+ line[i].right = max(item->right, line[i].right);
+ } else {
+ // insert
+ int left = item->left;
+ int right = item->right;
+ int l = line[i].left;
+ int r = line[i].right;
+
+ while ((i+1<MAX_WORDS_PER_LINE) && (line[i].left != 0)) {
+ line[i].left = left;
+ line[i].right = right;
+ i++;
+ left = l;
+ right = r;
+ l = line[i].left;
+ r = line[i].right;
+ }
+ if (i+1<MAX_WORDS_PER_LINE) {
+ line[i].left = left;
+ line[i].right = right;
+ line[i+1].left = 0;
+ line[i+1].right = 0;
+ }
+ }
+ }
+}
+
+/*
+ * is_in_column - return TRUE if value is present in line.
+ */
+
+int html_printer::is_in_column (struct text_defn *line, struct text_defn *item, int max_words)
+{
+ int i=0;
+
+ while ((i<max_words) && (line[i].left != 0)) {
+ if (line[i].left == item->left) {
+ return( TRUE );
+ } else {
+ i++;
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * calculate_right - calculate the right most margin for each column in line.
+ */
+
+void html_printer::calculate_right (struct text_defn *line, int max_words)
+{
+ int i=0;
+
+ while ((i<max_words) && (line[i].left != 0)) {
+ if (i>0) {
+ line[i-1].right = line[i].left;
+ }
+ i++;
+ }
+}
+
+/*
+ * add_right_full_width - adds an extra column to the right to bring the table up to
+ * full width.
+ */
+
+void html_printer::add_right_full_width (struct text_defn *line, int mingap)
+{
+ int i=0;
+
+ while ((i<MAX_WORDS_PER_LINE) && (line[i].left != 0)) {
+ i++;
+ }
+
+ if ((i>0) && (line[i-1].right != right_margin_indent) && (i+1<MAX_WORDS_PER_LINE)) {
+ line[i].left = min(line[i-1].right+mingap, right_margin_indent);
+ line[i].right = right_margin_indent;
+ i++;
+ if (i<MAX_WORDS_PER_LINE) {
+ line[i].left = 0;
+ line[i].right = 0;
+ }
+ }
+}
+
+/*
+ * determine_right_most_column - works out the right most limit of the right most column.
+ * Required as we might be performing a .2C and only
+ * have enough text to fill the left column.
+ */
+
+void html_printer::determine_right_most_column (struct text_defn *line, int max_words)
+{
+ int i=0;
+
+ while ((i<max_words) && (line[i].left != 0)) {
+ i++;
+ }
+ if (i>0) {
+ // remember right_margin_indent is the right most position for this page
+ line[i-1].right = column_calculate_right_margin(line[i-1].left, right_margin_indent);
+ }
+}
+
+/*
+ * is_column_match - returns TRUE if a word is aligned in the same horizontal alignment
+ * between two lines, line1 and line2. If so then this horizontal
+ * position is saved in match.
+ */
+
+int html_printer::is_column_match (struct text_defn *match,
+ struct text_defn *line1, struct text_defn *line2, int max_words)
+{
+ int i=0;
+ int j=0;
+ int found=FALSE;
+ int first=(match[0].left==0);
+
+ if (first) {
+ struct text_defn t;
+
+ t.left = left_margin_indent;
+ t.right = 0;
+
+ include_into_list(match, &t);
+ }
+ while ((line1[i].left != 0) && (line2[i].left != 0)) {
+ if (line1[i].left == line2[j].left) {
+ // same horizontal alignment found
+ include_into_list(match, &line1[i]);
+ i++;
+ j++;
+ found = TRUE;
+ } else if (line1[i].left < line2[j].left) {
+ i++;
+ } else {
+ j++;
+ }
+ }
+ calculate_right(match, max_words);
+ return( found );
+}
+
+/*
+ * check_lack_of_hits - returns TRUE if a column has been moved to a position
+ * of only one hit from a position of more than one hit.
+ */
+
+int html_printer::check_lack_of_hits (struct text_defn *next_guess,
+ struct text_defn *last_guess,
+ text_glob *start, int limit)
+{
+ text_glob *current=page_contents->words.get_data();
+ int n=count_columns(last_guess);
+ int m=count_columns(next_guess);
+ int i, j;
+
+ if (limit > 0) {
+ rewind_text_to(start);
+ count_hits(last_guess, n, limit);
+ rewind_text_to(current);
+ i=0;
+ j=0;
+ while ((i<n) && (j<m) &&
+ (last_guess[i].left != 0) && (next_guess[j].left != 0)) {
+ if ((is_intersection(last_guess[i].left, last_guess[i].right,
+ next_guess[j].left, next_guess[j].right)) &&
+ (next_guess[j].left < last_guess[i].left) &&
+ (last_guess[i].is_used >= 2)) {
+ /*
+ * next_guess has to be = 1 as this position is new
+ */
+ return( TRUE );
+ }
+ if (last_guess[i].left < next_guess[j].left) {
+ i++;
+ } else {
+ j++;
+ }
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * remove_white_using_words - remove white space in, last_guess, by examining, next_line
+ * placing results into next_guess.
+ * It returns TRUE if the same columns exist in next_guess and last_guess
+ * we do allow columns to shrink but if a column disappears then we return FALSE.
+ */
+
+int html_printer::remove_white_using_words (struct text_defn *next_guess,
+ struct text_defn *last_guess, struct text_defn *next_line)
+{
+ int i=0;
+ int j=0;
+ int k=0;
+ int removed=FALSE;
+
+ while ((last_guess[j].left != 0) && (next_line[k].left != 0)) {
+ if (last_guess[j].left == next_line[k].left) {
+ // same horizontal alignment found
+ next_guess[i].left = last_guess[j].left;
+ next_guess[i].right = max(last_guess[j].right, next_line[k].right);
+ i++;
+ j++;
+ k++;
+ if ((next_guess[i-1].right > last_guess[j].left) && (last_guess[j].left != 0)) {
+ removed = TRUE;
+ }
+ } else if (last_guess[j].right < next_line[k].left) {
+ next_guess[i].left = last_guess[j].left;
+ next_guess[i].right = last_guess[j].right;
+ i++;
+ j++;
+ } else if (last_guess[j].left > next_line[k].right) {
+ // insert a word sequence from next_line[k]
+ next_guess[i].left = next_line[k].left;
+ next_guess[i].right = next_line[k].right;
+ i++;
+ k++;
+ } else if (is_intersection(last_guess[j].left, last_guess[j].right, next_line[k].left, next_line[k].right)) {
+ // potential for a column disappearing
+ next_guess[i].left = min(last_guess[j].left , next_line[k].left);
+ next_guess[i].right = max(last_guess[j].right, next_line[k].right);
+ i++;
+ j++;
+ k++;
+ if ((next_guess[i-1].right > last_guess[j].left) && (last_guess[j].left != 0)) {
+ removed = TRUE;
+ }
+ }
+ }
+ while (next_line[k].left != 0) {
+ next_guess[i].left = next_line[k].left;
+ next_guess[i].right = next_line[k].right;
+ i++;
+ k++;
+ }
+ if (i<MAX_WORDS_PER_LINE) {
+ next_guess[i].left = 0;
+ next_guess[i].right = 0;
+ }
+ if (debug_table_on) {
+ if (removed) {
+ fprintf(stderr, "have removed column\n");
+ } else {
+ fprintf(stderr, "have NOT removed column\n");
+ }
+ fflush(stderr);
+ }
+ remove_redundant_columns(next_guess);
+ return( removed );
+}
+
+/*
+ * count_columns - returns the number of elements inside, line.
+ */
+
+int html_printer::count_columns (struct text_defn *line)
+{
+ int i=0;
+
+ while (line[i].left != 0) {
+ i++;
+ }
+ return( i );
+}
+
+/*
+ * rewind_text_to - moves backwards until page_contents is looking at, g.
+ */
+
+void html_printer::rewind_text_to (text_glob *g)
+{
+ while (page_contents->words.get_data() != g) {
+ if (page_contents->words.is_equal_to_head()) {
+ page_contents->words.start_from_tail();
+ } else {
+ page_contents->words.move_left();
+ }
+ }
+}
+
+/*
+ * can_loose_column - checks to see whether we should combine two columns.
+ * This is allowed if there are is only one hit on the
+ * left hand edge and the previous column is very close.
+ */
+
+void html_printer::can_loose_column (text_glob *start, struct text_defn *last_guess, int limit)
+{
+ text_glob *current=page_contents->words.get_data();
+ int n=count_columns(last_guess);
+ int i;
+
+ rewind_text_to(start);
+ count_hits(last_guess, n, limit);
+ i=0;
+ while (i<n-1) {
+ if ((last_guess[i+1].is_used == 1) &&
+ (calculate_min_gap(start) > (last_guess[i+1].left-last_guess[i].right))) {
+ last_guess[i].right = last_guess[i+1].right;
+ remove_entry_in_line(last_guess, i+1);
+ n = count_columns(last_guess);
+ i = 0;
+ } else {
+ i++;
+ }
+ }
+ rewind_text_to(current);
+}
+
+/*
+ * display_columns - a long overdue debugging function, as this column code is causing me grief :-(
+ */
+
+void html_printer::display_columns (const char *word, const char *name, text_defn *line)
+{
+ int i=0;
+
+ fprintf(stderr, "[%s:%s]", name, word);
+ while (line[i].left != 0) {
+ fprintf(stderr, " <left=%d right=%d %d%%> ", line[i].left, line[i].right, line[i].percent);
+ i++;
+ }
+ fprintf(stderr, "\n");
+ fflush(stderr);
+}
+
+/*
+ * copy_line - dest = src
+ */
+
+void html_printer::copy_line (struct text_defn *dest, struct text_defn *src)
+{
+ int k;
+
+ for (k=0; ((src[k].left != 0) && (k<MAX_WORDS_PER_LINE)); k++) {
+ dest[k].left = src[k].left;
+ dest[k].right = src[k].right;
+ }
+ if (k<MAX_WORDS_PER_LINE) {
+ dest[k].left = 0;
+ dest[k].right = 0;
+ }
+}
+
+/*
+ * add_column_gaps - adds empty columns between columns which don't exactly align
+ */
+
+void html_printer::add_column_gaps (struct text_defn *line)
+{
+ int i=0;
+ struct text_defn t;
+
+ // firstly lets see whether we need an initial column on the left hand side
+ if ((line[0].left != get_left()) && (line[0].left != 0) &&
+ (get_left() < line[0].left) && (is_worth_column(get_left(), line[0].left))) {
+ t.left = get_left();
+ t.right = line[0].left;
+ include_into_list(line, &t);
+ }
+
+ while ((i<MAX_WORDS_PER_LINE) && (line[i].left != 0)) {
+ if ((i+1<MAX_WORDS_PER_LINE) && (line[i+1].left != 0) && (line[i].right != line[i+1].left) &&
+ (is_worth_column(line[i].right, line[i+1].left))) {
+ t.left = line[i].right;
+ t.right = line[i+1].left;
+ include_into_list(line, &t);
+ i=0;
+ } else {
+ i++;
+ }
+ }
+ // now let us see whether we need a final column on the right hand side
+ if ((i>0) && (line[i-1].right != right_margin_indent) &&
+ (is_worth_column(line[i-1].right, right_margin_indent))) {
+ t.left = line[i-1].right;
+ t.right = right_margin_indent;
+ include_into_list(line, &t);
+ }
+}
+
+/*
+ * is_continueous_column - returns TRUE if a line has a word on one
+ * of the last_col right most boundaries.
+ */
+
+int html_printer::is_continueous_column (text_defn *last_col, text_defn *next_line)
+{
+ int w = count_columns(next_line);
+ int c = count_columns(last_col);
+ int i, j;
+
+ for (i=0; i<c; i++) {
+ for (j=0; j<w; j++) {
+ if (last_col[i].right == next_line[j].right) {
+ return( TRUE );
+ }
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * is_exact_left - returns TRUE if a line has a word on one
+ * of the last_col left most boundaries.
+ */
+
+int html_printer::is_exact_left (text_defn *last_col, text_defn *next_line)
+{
+ int w = count_columns(next_line);
+ int c = count_columns(last_col);
+ int i, j;
+
+ for (i=0; i<c; i++) {
+ for (j=0; j<w; j++) {
+ if ((last_col[i].left == next_line[j].left) ||
+ (last_col[i].left != left_margin_indent)) {
+ return( TRUE );
+ }
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * continue_searching_column - decides whether we should carry on searching text for a column.
+ */
+
+int html_printer::continue_searching_column (text_defn *next_col,
+ text_defn *last_col,
+ text_defn *all_words)
+{
+ int count = count_columns(next_col);
+ int words = count_columns(all_words);
+
+ if ((words == 0) || ((words == 1) &&
+ (all_words[0].left == left_margin_indent) &&
+ (all_words[0].right == right_margin_indent))) {
+ // no point as we have now seen a full line of contineous text with no gap
+ return( FALSE );
+ }
+ return( (count == count_columns(last_col)) &&
+ (last_col[0].left != left_margin_indent) || (last_col[0].right != right_margin_indent) );
+}
+
+/*
+ * is_worth_column - returns TRUE if the size of this column is worth defining.
+ */
+
+int html_printer::is_worth_column (int left, int right)
+{
+#if 0
+ return( abs(right-left) >= MIN_COLUMN );
+#endif
+ return( TRUE );
+}
+
+/*
+ * large_enough_gap - returns TRUE if a large enough gap for one line was seen.
+ * We need to make sure that a single line definitely warrents
+ * a table.
+ * It also removes other smaller gaps.
+ */
+
+int html_printer::large_enough_gap (text_defn *last_col)
+{
+ int i=0;
+ int found=FALSE;
+ int r=font::res;
+ int gap=r/GAP_WIDTH_ONE_LINE;
+
+ if (abs(last_col[i].left - left_margin_indent) >= gap) {
+ found = TRUE;
+ }
+ while ((last_col[i].left != 0) && (last_col[i+1].left != 0)) {
+ if (abs(last_col[i+1].left-last_col[i].right) >= gap) {
+ found = TRUE;
+ i++;
+ } else {
+ // not good enough for a single line, remove it
+ last_col[i].right = last_col[i+1].right;
+ remove_entry_in_line(last_col, i+1);
+ }
+ }
+ return( found );
+}
+
+/*
+ * is_subset_of_columns - returns TRUE if line, a, is a subset of line, b.
+ */
+
+int html_printer::is_subset_of_columns (text_defn *a, text_defn *b)
+{
+ int i;
+ int j;
+
+ i=0;
+ while ((i<MAX_WORDS_PER_LINE) && (a[i].left != 0)) {
+ j=0;
+ while ((j<MAX_WORDS_PER_LINE) && (b[j].left != 0) &&
+ ((b[j].left != a[i].left) || (b[j].right != a[i].right))) {
+ j++;
+ }
+ if ((j==MAX_WORDS_PER_LINE) || (b[j].left == 0)) {
+ // found a different column - not a subset
+ return( FALSE );
+ }
+ i++;
+ }
+ return( TRUE );
+}
+
+/*
+ * count_hits - counts the number of hits per column. A left hit
+ * is when the left hand position of a glob hits
+ * the left hand column.
+ */
+
+void html_printer::count_hits (text_defn *col, int no_of_columns, int limit)
+{
+ int i;
+ text_glob *start = page_contents->words.get_data();
+ text_glob *g = start;
+
+ // firstly reset the used field
+ for (i=0; i<no_of_columns; i++) {
+ col[i].is_used = 0;
+ }
+ // now calculate the left hand hits
+ while ((g != 0) && (g->minv <= limit)) {
+ i=0;
+ while ((i<no_of_columns) && (col[i].right < g->minh)) {
+ i++;
+ }
+ if ((col[i].left == g->minh) && (col[i].left != 0)) {
+ col[i].is_used++;
+ }
+ page_contents->words.move_right();
+ if (page_contents->words.is_equal_to_head()) {
+ g = 0;
+ page_contents->words.start_from_tail();
+ } else {
+ g=page_contents->words.get_data();
+ }
+ }
+}
+
+/*
+ * count_right_hits - counts the number of right hits per column.
+ * A right hit is when the left hand position
+ * of a glob hits the right hand column.
+ */
+
+void html_printer::count_right_hits (text_defn *col, int no_of_columns)
+{
+ int i;
+ text_glob *start = page_contents->words.get_data();
+ text_glob *g = start;
+
+ // firstly reset the used field
+ for (i=0; i<no_of_columns; i++) {
+ col[i].right_hits = 0;
+ }
+ // now calculate the left hand hits
+ while ((g != 0) && (g->minv <= indentation.vertical_limit)) {
+ i=0;
+ while ((i<no_of_columns) && (col[i].right < g->minh)) {
+ i++;
+ }
+ if ((i<no_of_columns) && (col[i].right == g->maxh)) {
+ if (debug_table_on) {
+ fprintf(stderr, "found right hit [%s] at %d in %d\n",
+ g->text_string, g->maxh, i);
+ fflush(stderr);
+ }
+ col[i].right_hits++;
+ }
+ page_contents->words.move_right();
+ if (page_contents->words.is_equal_to_head()) {
+ g = 0;
+ page_contents->words.start_from_tail();
+ } else {
+ g=page_contents->words.get_data();
+ }
+ }
+}
+
+/*
+ * right_indentation - returns TRUE if a single column has been found and
+ * it resembles an indentation. Ie .RS/.RE or ABSTACT
+ */
+
+int html_printer::right_indentation (struct text_defn *last_guess)
+{
+ // it assumes that last_guess contains a single column
+ return( (last_guess[0].left > left_margin_indent) );
+}
+
+/*
+ * able_to_steal_width - returns TRUE if we have an unused column which we can steal from.
+ * It must have more than MIN_TEXT_PERCENT to do this.
+ */
+
+int html_printer::able_to_steal_width (void)
+{
+ int i;
+
+ for (i=0; i<indentation.no_of_columns; i++) {
+ if ((! indentation.columns[i].is_used) &&
+ (indentation.columns[i].percent > MIN_TEXT_PERCENT)) {
+ return( TRUE );
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * is_divisible_by - returns TRUE if n is divisible by d leaving no remainder.
+ */
+
+static int is_divisible_by (int n, int d)
+{
+ return( (n % d) == 0 );
+}
+
+/*
+ * need_to_steal_width - returns TRUE if a used column need to be
+ * given a little extra width for safty sake.
+ */
+
+int html_printer::need_to_steal_width (void)
+{
+ int i;
+
+ for (i=0; i<indentation.no_of_columns; i++) {
+ if ((indentation.columns[i].is_used) &&
+ (indentation.columns[i].percent == (((indentation.columns[i].right - indentation.columns[i].left) * 100) /
+ (right_margin_indent-left_margin_indent))) &&
+ (indentation.columns[i].percent < PERCENT_THRESHOLD)) {
+ return( TRUE );
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * utilize_round_off - utilize the remaining percent width in text columns
+ */
+
+void html_printer::utilize_round_off (void)
+{
+ int total = total_percentages();
+ int excess, i;
+
+ // use up the spare excess
+
+ excess = 100-total;
+
+ for (i=0; (i<indentation.no_of_columns) && (excess>0); i++) {
+ if ((indentation.columns[i].is_used) &&
+ (indentation.columns[i].percent < PERCENT_THRESHOLD)) {
+ indentation.columns[i].percent++;
+ excess--;
+ }
+ }
+ // we might as well try and keep any numbers simple if possible
+ for (i=0; (i<indentation.no_of_columns) && (excess>0); i++) {
+ if ((indentation.columns[i].is_used) &&
+ (! is_divisible_by(indentation.columns[i].percent, MIN_TEXT_PERCENT))) {
+ indentation.columns[i].percent++;
+ excess--;
+ }
+ }
+ // forget the niceties lets just use excess up now!
+ for (i=0; (i<indentation.no_of_columns) && (excess>0); i++) {
+ if (indentation.columns[i].is_used) {
+ indentation.columns[i].percent++;
+ excess--;
+ }
+ }
+}
+
+/*
+ * can_distribute_fairly - returns TRUE if we can redistribute some of the unused width into
+ * columns that are used.
+ */
+
+int html_printer::can_distribute_fairly (void)
+{
+ int i;
+ int total=0;
+ int used =0;
+ int excess;
+
+ // firstly total up all percentages - so we can use round offs
+ for (i=0; i<indentation.no_of_columns; i++) {
+ total += indentation.columns[i].percent;
+ if ((indentation.columns[i].is_used) &&
+ (indentation.columns[i].percent < PERCENT_THRESHOLD)) {
+ used++;
+ }
+ }
+ //
+ excess = 100-total;
+ if (excess < used) {
+ for (i=0; i<indentation.no_of_columns; i++) {
+ if (! indentation.columns[i].is_used) {
+ if (indentation.columns[i].percent > MIN_TEXT_PERCENT) {
+ indentation.columns[i].percent--;
+ excess++;
+ }
+ }
+ }
+ }
+ if (excess >= used) {
+ for (i=0; i<indentation.no_of_columns; i++) {
+ if ((indentation.columns[i].is_used) &&
+ (indentation.columns[i].percent < PERCENT_THRESHOLD) &&
+ (indentation.columns[i].percent == (((indentation.columns[i].right - indentation.columns[i].left) * 100) /
+ (right_margin_indent-left_margin_indent)))) {
+ indentation.columns[i].percent++;
+ excess--;
+ }
+ }
+ return( TRUE );
+ }
+ return( FALSE );
+}
+
+/*
+ * remove_table_column - removes column, i, from the indentation.
+ */
+
+void html_printer::remove_table_column (int i)
+{
+ while (i<indentation.no_of_columns) {
+ indentation.columns[i].left = indentation.columns[i+1].left;
+ indentation.columns[i].right = indentation.columns[i+1].right;
+ indentation.columns[i].is_used = indentation.columns[i+1].is_used;
+ indentation.columns[i].percent = indentation.columns[i+1].percent;
+ i++;
+ }
+ indentation.no_of_columns--;
+}
+
+/*
+ * next_line_on_left_column - returns TRUE if the next line in
+ * column, i, has a word on the left margin.
+ */
+
+int html_printer::next_line_on_left_column (int i, text_glob *start)
+{
+ int current_vpos=start->minv;
+
+ while ((start != 0) && (start->minv < indentation.vertical_limit) &&
+ (is_on_same_line(start, current_vpos))) {
+ if (page_contents->words.is_equal_to_tail()) {
+ start = 0;
+ } else {
+ page_contents->words.move_right();
+ start = page_contents->words.get_data();
+ }
+ }
+ if ((start != 0) && (start->minv < indentation.vertical_limit)) {
+ // onto next line now
+ current_vpos=start->minv;
+ while ((start != 0) && (start->minv < indentation.vertical_limit) &&
+ (is_on_same_line(start, current_vpos))) {
+ if (start->minh == indentation.columns[i].left) {
+ return( TRUE );
+ }
+ if (page_contents->words.is_equal_to_tail()) {
+ start = 0;
+ } else {
+ page_contents->words.move_right();
+ start = page_contents->words.get_data();
+ }
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * will_wrap_text - returns TRUE if text is wrapped in column, i.
+ */
+
+int html_printer::will_wrap_text (int i, text_glob *start)
+{
+ text_glob *current=page_contents->words.get_data();
+
+ if (auto_on) {
+ rewind_text_to(start);
+ while ((start != 0) && (start->minv < indentation.vertical_limit)) {
+ if (indentation.columns[i].right == start->maxh) {
+ // ok right word is on column boarder - check next line
+ if (next_line_on_left_column(i, start)) {
+ rewind_text_to(current);
+ return( TRUE );
+ }
+ }
+ if (page_contents->words.is_equal_to_tail()) {
+ start = 0;
+ } else {
+ page_contents->words.move_right();
+ start = page_contents->words.get_data();
+ }
+ }
+ }
+ rewind_text_to(current);
+ return( FALSE );
+}
+
+/*
+ * remove_unnecessary_unused - runs through a table and decides whether an unused
+ * column can be removed. This is only true if the
+ * column to the left does not wrap text.
+ */
+
+void html_printer::remove_unnecessary_unused (text_glob *start)
+{
+ int i=0;
+ int left=get_left();
+ int right;
+
+ while (i<indentation.no_of_columns) {
+ if ((indentation.columns[i].is_used) &&
+ (i+1<indentation.no_of_columns) && (! indentation.columns[i+1].is_used)) {
+ /*
+ * so i+1 is unused and there is a used column to the left.
+ * Now we check whether we can add the unused column to the column, i.
+ * This can only be done if column, i, is not wrapping text.
+ */
+ if (! will_wrap_text(i, start)) {
+#if 1
+ if (i+1 < indentation.no_of_columns) {
+ right = indentation.columns[i+1].right;
+ } else {
+ right = right_margin_indent;
+ }
+ indentation.columns[i].percent = (((right - indentation.columns[i].left) * 100) /
+ (right_margin_indent-left));
+#else
+ indentation.columns[i].percent = (((indentation.columns[i+1].right - indentation.columns[i].left) * 100) /
+ (right_margin_indent-left));
+#endif
+ remove_table_column(i+1);
+ i=-1;
+ }
+ }
+ i++;
+ }
+}
+
+/*
+ * remove_zero_percentage_column - removes all zero percentage width columns
+ */
+
+void html_printer::remove_zero_percentage_column (void)
+{
+ int i=0;
+
+ while (i<indentation.no_of_columns) {
+ if (indentation.columns[i].percent == 0) {
+ remove_table_column(i);
+ i=0;
+ } else {
+ i++;
+ }
+ }
+}
+
+/*
+ * get_left - returns the actual left most margin.
+ */
+
+int html_printer::get_left (void)
+{
+ if ((header_indent < left_margin_indent) && (header_indent != -1)) {
+ return( header_indent );
+ } else {
+ return( left_margin_indent );
+ }
+}
+
+/*
+ * calculate_percentage_width - calculates the percentage widths,
+ * this function will be generous to
+ * columns which have words as some browsers
+ * produce messy output if the percentage is exactly
+ * that required for text..
+ * We try and round up to MIN_TEXT_PERCENT
+ * of course we can only do this if we can steal from
+ * an unused column.
+ */
+
+void html_printer::calculate_percentage_width (text_glob *start)
+{
+ int i;
+ int left=get_left();
+ int right;
+
+ // firstly calculate raw percentages
+ for (i=0; i<indentation.no_of_columns; i++) {
+#if 0
+ indentation.columns[i].percent = (((indentation.columns[i].right - indentation.columns[i].left) * 100) /
+ (right_margin_indent-left));
+#else
+ if (i+1 < indentation.no_of_columns) {
+ right = indentation.columns[i+1].left;
+ } else {
+ right = right_margin_indent;
+ }
+ indentation.columns[i].percent = (((right - indentation.columns[i].left) * 100) /
+ (right_margin_indent-left));
+#endif
+ }
+ if (debug_table_on) {
+ display_columns(start->text_string, "[b4 steal] indentation.columns", indentation.columns);
+ }
+
+ // now steal from the unused columns..
+ remove_unnecessary_unused(start);
+
+ if (debug_table_on) {
+ display_columns(start->text_string, "[after steal] indentation.columns", indentation.columns);
+ }
+
+#if 0
+ utilize_round_off();
+#endif
+ remove_zero_percentage_column();
+}
+
+
+/*
+ * is_column_subset - returns TRUE if the columns described by small can be contained in
+ * the columns in large.
+ */
+
+int html_printer::is_column_subset (struct text_defn *small, struct text_defn *large)
+{
+ int ns=count_columns(small);
+ int nl=count_columns(large);
+ int found;
+ int i=0;
+ int j;
+
+ while (i<ns) {
+ j=0;
+ found = FALSE;
+ while (j<nl) {
+ if (is_intersection(small[i].left, small[i].right, large[j].left, large[j].right)) {
+ found = TRUE;
+ if (! is_subsection(small[i].left, small[i].right, large[j].left, large[j].right)) {
+ // found column which is not a subset
+ return( FALSE );
+ }
+ }
+ j++;
+ }
+ if (! found) {
+ return( FALSE );
+ }
+ i++;
+ }
+ // small cannot be an empty set
+ return( ns>0 );
+}
+
+/*
+ * right_most_column - returns the right most column position.
+ */
+
+int html_printer::right_most_column (struct text_defn *col)
+{
+ int i = count_columns(col);
+
+ if (i>0) {
+ return( col[i-1].right );
+ } else {
+ return( 0 );
+ }
+}
+
+/*
+ * large_enough_gap_for_two - returns TRUE if there exists a large enough gap
+ * for two lines.
+ */
+
+int html_printer::large_enough_gap_for_two (struct text_defn *col)
+{
+ int i=0;
+ int found=FALSE;
+ int gap=MIN_COLUMN_FOR_TWO_LINES;
+
+ if (abs(col[i].left - left_margin_indent) >= gap) {
+ found = TRUE;
+ }
+ while ((col[i].left != 0) && (col[i+1].left != 0)) {
+ if (abs(col[i+1].left-col[i].right) >= gap) {
+ found = TRUE;
+ i++;
+ } else {
+ // not good enough for this table, remove it
+ col[i].right = col[i+1].right;
+ remove_entry_in_line(col, i+1);
+ }
+ }
+ return( found );
+}
+
+/*
+ * is_small_table - applies some rigorous rules to test whether we should start this
+ * table at this point.
+ */
+
+int html_printer::is_small_table (int lines, struct text_defn *last_guess,
+ struct text_defn *words_1, struct text_defn *cols_1,
+ struct text_defn *words_2, struct text_defn *cols_2,
+ int *limit, int *limit_1)
+{
+ /*
+ * firstly we check for an indented paragraph
+ */
+
+ if ((lines >= 2) &&
+ (count_columns(cols_1) == count_columns(cols_2)) && (count_columns(cols_1) == 1) &&
+ right_indentation(cols_1) && (! right_indentation(cols_2)) &&
+ (cols_1[0].right == right_margin_indent)) {
+ return( FALSE );
+ }
+
+ if (lines == 2) {
+ /*
+ * as we only have two lines in our table we need to examine in detail whether
+ * we should construct a table from these two lines.
+ * For example if the text is the start of an indented paragraph and
+ * line1 and line2 are contineous then they should form one row in our table but
+ * if line1 and line2 are not contineous it is safer to treat them separately.
+ *
+ * We are prepared to reduce the table to one line
+ */
+ if (((count_columns(cols_1) != count_columns(cols_2)) && (cols_1[0].left > cols_2[0].left)) ||
+ (! ((is_column_subset(cols_1, cols_2)) ||
+ (is_column_subset(cols_2, cols_1))))) {
+ /*
+ * now we must check to see whether line1 and line2 join
+ */
+ if ((right_most_column(cols_1) == right_margin_indent) &&
+ (cols_2[0].left == left_margin_indent)) {
+ /*
+ * looks like they join, we don't want a table at all.
+ */
+ return( FALSE );
+ }
+ /*
+ * use single line table
+ */
+ lines--;
+ *limit = *limit_1;
+ copy_line(last_guess, cols_1);
+ }
+ }
+
+ if ((count_columns(last_guess)==1) && (right_indentation(last_guess))) {
+ if (lines == 1) {
+ *limit = *limit_1;
+ }
+ return( TRUE );
+ }
+
+ /*
+ * check for large gap with single line or if multiple lines with more than one column
+ */
+
+ if (lines == 1) {
+ if (large_enough_gap(last_guess)) {
+ *limit = *limit_1;
+ return( TRUE );
+ }
+ } else if (count_columns(last_guess)>1) {
+ if (lines == 2) {
+ return( large_enough_gap_for_two(last_guess) );
+ }
+ return( TRUE );
+ }
+ return( FALSE );
+}
+
+
+/*
+ * is_appropriate_to_start_table - returns TRUE if it is appropriate to start the table
+ * at this point.
+ */
+
+int html_printer::is_appropriate_to_start_table (struct text_defn *cols_1,
+ struct text_defn *cols_2,
+ struct text_defn *last_guess)
+{
+ if (count_columns(last_guess) == 1) {
+ if (debug_table_on) {
+ display_columns("", "[is] cols_1" , cols_1);
+ display_columns("", "[is] cols_2" , cols_2);
+ display_columns("", "[is] last_guess", last_guess);
+ }
+
+ if (! ((is_column_subset(cols_1, cols_2)) ||
+ (is_column_subset(cols_2, cols_1)))) {
+ return( FALSE );
+ }
+ if ((count_columns(cols_1) == 1) &&
+ (cols_1[0].left > left_margin_indent) && (cols_1[0].right < right_margin_indent) &&
+ (cols_1[0].right != cols_2[0].right) &&
+ (count_columns(last_guess) == 1)) {
+ return( FALSE );
+ }
+ }
+ return( TRUE );
+}
+
+/*
+ * is_a_full_width_column - returns TRUE if there exists a full width column.
+ */
+
+int html_printer::is_a_full_width_column (void)
+{
+ int i=0;
+
+ while (i<indentation.no_of_columns) {
+ if (((indentation.columns[i].left == get_left()) ||
+ (indentation.columns[i].left == left_margin_indent)) &&
+ (indentation.columns[i].right == right_margin_indent)) {
+ return( TRUE );
+ }
+ i++;
+ }
+ return( FALSE );
+}
+
+/*
+ * should_defer_table - returns TRUE if we should defer this table.
+ * This can occur if the first line seen indent
+ * is < than future lines. In which case it
+ * will cause future lines in this table
+ * to be indented. The lesser of the evils
+ * is to treat the first line by itself.
+ */
+
+int html_printer::should_defer_table (int lines, struct text_glob *start, struct text_defn *cols_1)
+{
+ if (lines > 2) {
+ int i=0;
+ int c=count_columns(cols_1);
+
+ count_hits(cols_1, count_columns(cols_1), indentation.vertical_limit);
+ rewind_text_to(start);
+ count_right_hits(cols_1, count_columns(cols_1));
+ rewind_text_to(start);
+ while (i<c) {
+ if ((cols_1[i].is_used > 1) || (cols_1[i].right_hits > 1)) {
+ return( FALSE );
+ }
+ i++;
+ }
+ /*
+ * first line (cols_1) is not aligned on any future column, we defer.
+ */
+ return( TRUE );
+ }
+ return( FALSE );
+}
+
+/*
+ * is_new_exact_right - returns TRUE if the, next_cols, has a word sitting
+ * on the right hand margin of last_guess. But only
+ * if no exact right word was found in last_cols.
+ */
+
+int html_printer::is_new_exact_right (struct text_defn *last_guess,
+ struct text_defn *last_cols,
+ struct text_defn *next_cols)
+{
+ int n=count_columns(last_guess)-1;
+ return( FALSE );
+
+ if ((n>=0) && (last_guess[n].left != 0) && (last_cols[n].left != 0) && (next_cols[n].left != 0)) {
+ if ((last_cols[n].right != last_guess[n].right) &&
+ ((next_cols[n].right == last_guess[n].right) || (next_cols[n].right == right_margin_indent))) {
+ return( TRUE );
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * found_use_for_table - checks whether the some words on one line directly match
+ * the horizontal alignment of the line below.
+ * This is rather complex as we need to detect text tables
+ * such as .2C .IP Abstracts and indentations
+ *
+ * Algorithm is:
+ *
+ * read first line of text and calculate the significant
+ * gaps between words
+ * next next line of text and do the same
+ * if a conflict between these lines exists and
+ * first line is centered
+ * then
+ * return centered line
+ * elsif start of a table is found
+ * then
+ * repeat
+ * read next line of text and calculate significant gaps
+ * until conflict between the gaps is found
+ * record table
+ * return table found
+ * else
+ * return no table found
+ * fi
+ */
+
+int html_printer::found_use_for_table (text_glob *start)
+{
+ text_glob *t;
+ struct text_defn all_words [MAX_WORDS_PER_LINE]; // logical OR of words on each line
+ struct text_defn words_1 [MAX_WORDS_PER_LINE]; // actual words found on first line
+ struct text_defn words_2 [MAX_WORDS_PER_LINE]; // actual words found on second line
+ struct text_defn cols_1 [MAX_WORDS_PER_LINE]; // columns found on line 1
+ struct text_defn cols_2 [MAX_WORDS_PER_LINE]; // columns found on line 2
+ struct text_defn last_words [MAX_WORDS_PER_LINE]; // actual words found on last line
+ struct text_defn last_cols [MAX_WORDS_PER_LINE]; // columns found so far
+ struct text_defn next_words [MAX_WORDS_PER_LINE]; // actual words found on last line (new)
+ struct text_defn next_cols [MAX_WORDS_PER_LINE]; // columns found on next line
+ struct text_defn last_guess [MAX_WORDS_PER_LINE]; // columns found on last line
+ // (logical AND of gaps (treat gaps = true))
+ struct text_defn next_guess [MAX_WORDS_PER_LINE]; // columns found on next line
+ // (logical AND of gaps (treat gaps = true))
+ struct text_defn prev_guess [MAX_WORDS_PER_LINE]; // temporary copy of last_guess
+ int i =0;
+ int lines =1; // number of lines read
+ int limit; // vertical limit reached in our table
+ int limit_1; // vertical position after line 1
+
+#if 1
+ if (strcmp(start->text_string, "This") == 0) {
+ stop();
+ }
+#endif
+
+ /*
+ * get first set of potential columns into last_line, call this last_guess
+ */
+ limit = collect_columns(words_1, cols_1, 0, 0, MAX_WORDS_PER_LINE);
+ limit_1 = limit;
+ copy_line(last_guess, cols_1);
+
+ /*
+ * initialize the all_words columns - if this should ever equal a complete line
+ * with no gaps then we terminate the table.
+ */
+ copy_line(all_words, cols_1);
+
+ /*
+ * and set the current limit found
+ */
+ indentation.vertical_limit = limit;
+
+ /*
+ * have we reached the end of page?
+ */
+ if (page_contents->words.is_equal_to_head() || (limit == 0)) {
+ cols_2[0].left = 0;
+ cols_2[0].right = 0;
+ } else {
+ /*
+ * the answer to the previous question was no.
+ * So we need to examine the next line
+ */
+ limit = collect_columns(words_2, cols_2, words_1, cols_1, MAX_WORDS_PER_LINE);
+ if (limit >= 0) {
+ lines++;
+ }
+ }
+
+ /*
+ * now check to see whether the first line looks like a single centered line
+ */
+ if (single_centered_line(cols_1, cols_2, start)) {
+ rewind_text_to(start);
+ write_centered_line(start);
+ /*
+ * indicate to caller than we have centered text, not found a table.
+ */
+ indentation.no_of_columns = 0;
+ return( TRUE );
+ } else if (! table_on) {
+ /*
+ * user does not allow us to find a table (we are allowed to find centered lines (above))
+ */
+ rewind_text_to(start);
+ return( FALSE );
+ }
+
+ /*
+ * remove any gaps from all_words
+ */
+ combine_line(all_words, cols_2);
+ if (debug_table_on) {
+ display_columns(start->text_string, "[1] all_words" , all_words);
+ display_columns(start->text_string, "[1] cols_1" , cols_1);
+ display_columns(start->text_string, "[1] words_1" , words_1);
+ display_columns(start->text_string, "[1] cols_2" , cols_2);
+ display_columns(start->text_string, "[1] words_2" , words_2);
+ display_columns(start->text_string, "[1] last_guess", last_guess);
+ }
+
+ /*
+ * next_guess = last_guess AND next_cols (where gap = true)
+ */
+
+ if (remove_white_using_words(prev_guess, last_guess, cols_2)) {
+ }
+ if (remove_white_using_words(next_guess, prev_guess, all_words)) {
+ }
+
+ if (debug_table_on) {
+ display_columns(start->text_string, "[2] next_guess", next_guess);
+ }
+
+ copy_line(prev_guess, cols_1);
+ combine_line(prev_guess, cols_2);
+
+ /*
+ * if no sequence of words crosses a column and
+ * both the last column and all_words are not a full solid line of text
+ */
+ if ((! conflict_with_words(next_guess, all_words)) &&
+ (continue_searching_column(next_guess, next_guess, all_words)) &&
+ (is_appropriate_to_start_table(cols_1, cols_2, prev_guess)) &&
+ (! page_contents->words.is_equal_to_head()) &&
+ ((end_region_vpos < 0) || (limit < end_region_vpos)) &&
+ (limit > 0)) {
+
+ /*
+ * subtract any columns which are bridged by a sequence of words
+ */
+
+ copy_line(next_cols , cols_2);
+ copy_line(next_words, words_2);
+
+ do {
+ copy_line(prev_guess, next_guess); // copy next_guess away so we can compare it later
+ combine_line(last_guess, next_guess);
+
+ if (debug_table_on) {
+ t = page_contents->words.get_data();
+ display_columns(t->text_string, "[l] last_guess", last_guess);
+ }
+ indentation.vertical_limit = limit;
+
+ copy_line(last_cols, next_cols);
+ copy_line(last_words, next_words);
+ if (page_contents->words.is_equal_to_head()) {
+ /*
+ * terminate the search
+ */
+ next_cols[0].left = 0;
+ next_cols[0].right = 0;
+ } else {
+ limit = collect_columns(next_words, next_cols, last_words, last_cols, MAX_WORDS_PER_LINE);
+ lines++;
+ }
+
+ combine_line(all_words, next_cols);
+ if (debug_table_on) {
+ display_columns(t->text_string, "[l] all_words" , all_words);
+ display_columns(t->text_string, "[l] last_cols" , last_cols);
+ display_columns(t->text_string, "[l] next_words", next_words);
+ display_columns(t->text_string, "[l] next_cols" , next_cols);
+ }
+
+ if (limit >= 0) {
+ /*
+ * (if limit is < 0 then the table ends anyway.)
+ * we check to see whether we should combine close columns.
+ */
+ can_loose_column(start, last_guess, limit);
+ }
+ t = page_contents->words.get_data();
+#if 0
+ if (strcmp(t->text_string, "heT") == 0) {
+ stop();
+ }
+#endif
+
+ } while ((! remove_white_using_words(next_guess, last_guess, next_cols)) &&
+ (! conflict_with_words(next_guess, all_words)) &&
+ (continue_searching_column(next_guess, last_guess, all_words)) &&
+ ((is_continueous_column(prev_guess, last_cols)) || (is_exact_left(last_guess, next_cols))) &&
+ (! is_new_exact_right(last_guess, last_cols, next_cols)) &&
+ (! page_contents->words.is_equal_to_head()) &&
+ (! check_lack_of_hits(next_guess, last_guess, start, limit)) &&
+ ((end_region_vpos <= 0) || (t->minv < end_region_vpos)) &&
+ (limit >= 0));
+ lines--;
+ }
+
+ if (limit < 0) {
+ indentation.vertical_limit = limit;
+ }
+
+ if (page_contents->words.is_equal_to_head()) {
+ // end of page check whether we should include everything
+ if ((! conflict_with_words(next_guess, all_words)) &&
+ (continue_searching_column(next_guess, last_guess, all_words)) &&
+ ((is_continueous_column(prev_guess, last_cols)) || (is_exact_left(last_guess, next_cols)))) {
+ // end of page reached - therefore include everything
+ page_contents->words.start_from_tail();
+ t = page_contents->words.get_data();
+ combine_line(last_guess, next_guess);
+ indentation.vertical_limit = t->minv;
+ }
+ } else {
+ t = page_contents->words.get_data();
+ if (((! conflict_with_words(last_guess, all_words))) &&
+ (t->minv > end_region_vpos) && (end_region_vpos > 0)) {
+ indentation.vertical_limit = limit;
+ }
+ if ((end_region_vpos > 0) && (t->minv > end_region_vpos)) {
+ indentation.vertical_limit = min(indentation.vertical_limit, end_region_vpos+1);
+ } else if (indentation.vertical_limit < 0) {
+ // -1 as we don't want to include section heading itself
+ indentation.vertical_limit = -indentation.vertical_limit-1;
+ }
+ }
+
+ if (debug_table_on) {
+ display_columns(start->text_string, "[1] all_words" , all_words);
+ display_columns(start->text_string, "[1] cols_1" , cols_1);
+ display_columns(start->text_string, "[1] words_1" , words_1);
+ display_columns(start->text_string, "[1] cols_2" , cols_2);
+ display_columns(start->text_string, "[1] words_2" , words_2);
+ display_columns(start->text_string, "[1] last_guess", last_guess);
+ display_columns(start->text_string, "[1] next_guess", next_guess);
+ }
+ rewind_text_to(start);
+
+ i = count_columns(last_guess);
+ if ((i>1) || (right_indentation(last_guess))) {
+
+ // was (continue_searching_column(last_guess, last_guess, all_words)))) {
+ if (should_defer_table(lines, start, cols_1)) {
+ /*
+ * yes, but let us check for a single line table
+ */
+ lines = 1;
+ copy_line(last_guess, cols_1);
+ }
+
+ if (is_small_table(lines, last_guess, words_1, cols_1, words_2, cols_2,
+ &indentation.vertical_limit, &limit_1)) {
+
+ // copy match into permenant html_table
+
+ if (indentation.columns != 0) {
+ free(indentation.columns);
+ }
+ if (debug_table_on) {
+ display_columns(start->text_string, "[x] last_guess", last_guess);
+ }
+ add_column_gaps(last_guess);
+ if (debug_table_on) {
+ display_columns(start->text_string, "[g] last_guess", last_guess);
+ }
+
+ /*
+ * +1 for the potential header_margin
+ * +1 for null
+ */
+
+ indentation.no_of_columns = count_columns(last_guess);
+ indentation.columns = (struct text_defn *)malloc((indentation.no_of_columns+2)*sizeof(struct text_defn));
+
+ i=0;
+ while (i<=indentation.no_of_columns) {
+ indentation.columns[i].left = last_guess[i].left;
+ indentation.columns[i].right = last_guess[i].right;
+ i++;
+ }
+
+ if (indentation.no_of_columns>0) {
+ assign_used_columns(start);
+ rewind_text_to(start);
+ calculate_percentage_width(start);
+
+ if (debug_table_on) {
+ display_columns(start->text_string, "[g] indentation.columns", indentation.columns);
+ }
+
+ /*
+ * clearly a single column 100% is not worth using a table.
+ * Also we check to see whether the first line is sensibly
+ * part of this table.
+ */
+ if (is_a_full_width_column()) {
+ indentation.no_of_columns = 0;
+ free( indentation.columns );
+ indentation.columns = 0;
+ } else {
+ return( TRUE );
+ }
+ }
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * define_cell - creates a table cell using the percentage width.
+ */
+
+void html_printer::define_cell (int i)
+{
+ html.put_string("<td valign=\"top\" align=\"left\" width=\"");
+ html.put_number(indentation.columns[i].percent);
+ html.put_string("%\">\n");
+}
+
+/*
+ * column_display_word - given a left, right pair and the indentation.vertical_limit
+ * write out html text within this region.
+ */
+
+void html_printer::column_display_word (int cell, int vert, int left, int right, int next)
+{
+ text_glob *g=page_contents->words.get_data();
+
+ supress_sub_sup = TRUE;
+ if (left != next) {
+ define_cell(cell);
+ begin_paragraph_no_height(left_alignment);
+ while ((g != 0) && (g->minv <= vert)) {
+ if ((left <= g->minh) && (g->minh<right)) {
+ char *postword=html_position_text(g, left, right);
+
+ if (header.written_header) {
+ fatal("should never generate a header inside a table");
+ } else {
+ if (g->is_raw_command) {
+ html.put_string((char *)g->text_string);
+ } else {
+ translate_to_html(g);
+ }
+ if (postword != 0) {
+ html.put_string(postword);
+ }
+ issued_newline = FALSE;
+ }
+ }
+ if (page_contents->words.is_equal_to_tail()) {
+ g = 0;
+ } else {
+ page_contents->words.move_right();
+ g=page_contents->words.get_data();
+ }
+ }
+ end_paragraph();
+ html.put_string("</td>\n");
+ if (g != 0) {
+ page_contents->words.move_left();
+ // and correct output_vpos
+ g=page_contents->words.get_data();
+ output_vpos = g->minv;
+ }
+ }
+}
+
+/*
+ * total_percentages - returns the total of all the percentages in the table.
+ */
+
+int html_printer::total_percentages ()
+{
+ int i;
+ int sum=0;
+
+ for (i=0; i<indentation.no_of_columns; i++) {
+ sum += indentation.columns[i].percent;
+ }
+ return( sum );
+}
+
+/*
+ * start_table - creates a table according with parameters contained within class html_table.
+ */
+
+void html_printer::start_table (void)
+{
+ save_paragraph();
+ html.put_string("\n<table width=\"");
+ html.put_number(total_percentages());
+ html.put_string("%\" rules=\"none\" frame=\"none\" cols=\"");
+ html.put_number(indentation.no_of_columns);
+ html.put_string("\" cellspacing=\"0\" cellpadding=\"0\">\n");
+}
+
+/*
+ * end_table - finishes off a table.
+ */
+
+void html_printer::end_table (void)
+{
+ html.put_string("</table>\n");
+ indentation.no_of_columns = 0;
+ restore_paragraph();
+ supress_sub_sup = TRUE;
+}
+
+/*
+ * column_calculate_right_margin - scan through the column and find the right most margin
+ */
+
+int html_printer::column_calculate_right_margin (int left, int right)
+{
+ if (left == right) {
+ return( right );
+ } else {
+ int rightmost =-1;
+ int count = 0;
+ text_glob *start = page_contents->words.get_data();
+ text_glob *g = start;
+
+ while ((g != 0) && (g->minv <= indentation.vertical_limit)) {
+ if ((left <= g->minh) && (g->minh<right)) {
+ if (debug_on) {
+ fprintf(stderr, "right word = %s %d\n", g->text_string, g->maxh); fflush(stderr);
+ }
+ if (g->maxh == rightmost) {
+ count++;
+ } else if (g->maxh > rightmost) {
+ count = 1;
+ rightmost = g->maxh;
+ }
+ if (g->maxh > right) {
+ if (debug_on) {
+ fprintf(stderr, "problem as right word = %s %d [%d..%d]\n",
+ g->text_string, right, g->minh, g->maxh); fflush(stderr);
+ // stop();
+ }
+ }
+ }
+ page_contents->words.move_right();
+ if (page_contents->words.is_equal_to_head()) {
+ g = 0;
+ page_contents->words.start_from_tail();
+ } else {
+ g=page_contents->words.get_data();
+ }
+ }
+ rewind_text_to(start);
+ if (rightmost == -1) {
+ return( right ); // no words in this column
+ } else {
+ return( rightmost );
+ }
+ }
+}
+
+/*
+ * column_calculate_left_margin - scan through the column and find the left most margin
+ */
+
+int html_printer::column_calculate_left_margin (int left, int right)
+{
+ if (left == right) {
+ return( left );
+ } else {
+ int leftmost=right;
+ text_glob *start = page_contents->words.get_data();
+ text_glob *g = start;
+
+ while ((g != 0) && (g->minv <= indentation.vertical_limit)) {
+ if ((left <= g->minh) && (g->minh<right)) {
+ leftmost = min(g->minh, leftmost);
+ }
+ page_contents->words.move_right();
+ if (page_contents->words.is_equal_to_head()) {
+ g = 0;
+ page_contents->words.start_from_tail();
+ } else {
+ g=page_contents->words.get_data();
+ }
+ }
+ rewind_text_to(start);
+ if (leftmost == right) {
+ return( left ); // no words in this column
+ } else {
+ return( leftmost );
+ }
+ }
+}
+
+/*
+ * find_column_index - returns the index to the column in which glob, t, exists.
+ */
+
+int html_printer::find_column_index_in_line (text_glob *t, text_defn *line)
+{
+ int i=0;
+
+ while ((line != 0) && ((line[i].left != 0) || (line[i].right != 0)) &&
+ (! ((line[i].left<=t->minh) && (line[i].right>t->minh)))) {
+ i++;
+ }
+ return( i );
+}
+
+/*
+ * find_column_index - returns the index to the column in which glob, t, exists.
+ */
+
+int html_printer::find_column_index (text_glob *t)
+{
+ int i=0;
+
+ while ((i<indentation.no_of_columns) &&
+ (! ((indentation.columns[i].left<=t->minh) &&
+ (indentation.columns[i].right>t->minh)))) {
+ i++;
+ }
+ return( i );
+}
+
+/*
+ * determine_row_limit - checks each row to see if there is a gap in a cell.
+ * We return the vertical position after the empty cell
+ * at the start of the next line.
+ */
+
+int html_printer::determine_row_limit (text_glob *start, int v)
+{
+ text_glob *t;
+ int i;
+ int vpos, last, prev;
+ text_glob *is_gap[MAX_WORDS_PER_LINE];
+ text_glob zero(&start->text_style, 0, 0, 0, 0, 0, 0, 0, 0);
+
+#if 1
+ if ((v == -1) && (strcmp(start->text_string, "CASE") == 0)) {
+ stop();
+ }
+#endif
+
+ if (v >= indentation.vertical_limit) {
+ return( v+1 );
+ } else {
+ /*
+ * initially we start with all gaps in our table
+ * after a gap we start a new row
+ * here we set the gap array to the previous line
+ */
+
+ if (v>=0) {
+ t = page_contents->words.get_data();
+ if (t->minv < v) {
+ do {
+ page_contents->words.move_right();
+ t = page_contents->words.get_data();
+ } while ((! page_contents->words.is_equal_to_head()) &&
+ (t->minv <= v));
+ }
+ }
+ if (page_contents->words.is_equal_to_head()) {
+ t = &zero;
+ } else {
+ page_contents->words.move_left();
+ t = page_contents->words.get_data();
+ }
+
+ prev = t->minv;
+ for (i=0; i<indentation.no_of_columns; i++) {
+ is_gap[i] = t;
+ }
+
+ if (page_contents->words.is_equal_to_tail()) {
+ rewind_text_to(start);
+ return( indentation.vertical_limit );
+ } else {
+ page_contents->words.move_right();
+ }
+ t = page_contents->words.get_data();
+ vpos = t->minv;
+
+ // now check each row for a gap
+ do {
+ last = vpos;
+ vpos = t->minv;
+ if (vpos > indentation.vertical_limit) {
+ // we have reached the end of the table, quit
+ rewind_text_to(start);
+ return( indentation.vertical_limit );
+ }
+
+ i = find_column_index(t);
+ if (i>=indentation.no_of_columns) {
+ error("find_column_index has failed");
+ stop();
+ } else {
+ if (! is_on_same_line(t, last)) {
+ prev = last;
+ }
+
+ if ((! is_on_same_line(is_gap[i], vpos)) && (! is_on_same_line(is_gap[i], prev)) &&
+ (indentation.columns[i].is_used)) {
+ // no word on previous line - must be a gap - force alignment of row
+ rewind_text_to(start);
+ return( prev );
+ }
+ is_gap[i] = t;
+ }
+ page_contents->words.move_right();
+ t = page_contents->words.get_data();
+ } while ((! page_contents->words.is_equal_to_head()) &&
+ (vpos < indentation.vertical_limit) && (vpos >= last));
+ page_contents->words.move_left();
+ t = page_contents->words.get_data();
+ rewind_text_to(start);
+ return( indentation.vertical_limit );
+ }
+}
+
+/*
+ * assign_used_columns - sets the is_used field of the column array of records.
+ */
+
+void html_printer::assign_used_columns (text_glob *start)
+{
+ text_glob *t = start;
+ int i;
+
+ for (i=0; i<indentation.no_of_columns; i++) {
+ indentation.columns[i].is_used = FALSE;
+ }
+
+ rewind_text_to(start);
+ if (! page_contents->words.is_empty()) {
+ do {
+ i = find_column_index(t);
+ if (indentation.columns[i].left != 0) {
+ if (debug_table_on) {
+ fprintf(stderr, "[%s] in column %d at %d..%d limit %d\n", t->text_string,
+ i, t->minv, t->maxv, indentation.vertical_limit); fflush(stderr);
+ }
+ indentation.columns[i].is_used = TRUE;
+ }
+ page_contents->words.move_right();
+ t = page_contents->words.get_data();
+ } while ((t->minv<indentation.vertical_limit) &&
+ (! page_contents->words.is_equal_to_head()));
+ }
+ if (debug_table_on) {
+ for (i=0; i<indentation.no_of_columns; i++) {
+ fprintf(stderr, " <left=%d right=%d is_used=%d> ",
+ indentation.columns[i].left,
+ indentation.columns[i].right,
+ indentation.columns[i].is_used);
+ }
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+}
+
+/*
+ * adjust_margin_percentages - so far we have ignored the header_indent
+ * and just considered left_margin_indent..right_margin_indent.
+ * (We do this since we can assume 100% is total width for main text).
+ * However as header_indent can be < left_margin_indent we need to
+ * recalculate the real percentages in the light of the extended width.
+ */
+
+void html_printer::adjust_margin_percentages (void)
+{
+ if ((header_indent < left_margin_indent) && (header_indent != -1)) {
+ /*
+ * recalculation necessary
+ */
+ int i=0;
+
+ while (i<indentation.no_of_columns) {
+ indentation.columns[i].percent = (indentation.columns[i].percent *
+ (right_margin_indent - left_margin_indent)) /
+ (right_margin_indent - header_indent);
+ i++;
+ }
+ // remove_zero_percentage_column();
+ }
+}
+
+/*
+ * foreach_column_include_text - foreach column in a table place the
+ * appropriate html text.
+ */
+
+void html_printer::foreach_column_include_text (text_glob *start)
+{
+ if (indentation.no_of_columns>0) {
+ int i;
+ int left, right;
+ int limit=-1;
+
+ start_table();
+ rewind_text_to(start);
+ count_right_hits(indentation.columns, indentation.no_of_columns);
+ rewind_text_to(start);
+
+ do {
+ limit = determine_row_limit(start, limit); // find the bottom of the next row
+ html.put_string("<tr valign=\"top\" align=\"left\">\n");
+ i=0;
+ start = page_contents->words.get_data();
+ while (i<indentation.no_of_columns) {
+ // reset the output position to the start of column
+ rewind_text_to(start);
+ output_vpos = start->minv;
+ output_hpos = indentation.columns[i].left;
+ // and display each column until limit
+ right = column_calculate_right_margin(indentation.columns[i].left,
+ indentation.columns[i].right);
+ left = column_calculate_left_margin(indentation.columns[i].left,
+ indentation.columns[i].right);
+
+ if (right>indentation.columns[i].right) {
+ if (debug_on) {
+ fprintf(stderr, "assert calculated right column edge is greater than column\n"); fflush(stderr);
+ // stop();
+ }
+ }
+
+ if (left<indentation.columns[i].left) {
+ if (debug_on) {
+ fprintf(stderr, "assert calculated left column edge is less than column\n"); fflush(stderr);
+ // stop();
+ }
+ }
+
+ if ((indentation.columns[i].right_hits == 1) &&
+ (indentation.columns[i].right != right_margin_indent)) {
+ indentation.wrap_margin = FALSE;
+ if (debug_on) {
+ fprintf(stderr, "turning auto wrap off during column %d for start word %s\n",
+ i, start->text_string);
+ fflush(stderr);
+ // stop();
+ }
+ } else {
+ indentation.wrap_margin = TRUE;
+ }
+
+ column_display_word(i, limit, left, right, indentation.columns[i].right);
+ i++;
+ }
+
+ if (page_contents->words.is_equal_to_tail()) {
+ start = 0;
+ } else {
+ page_contents->words.sub_move_right();
+ if (page_contents->words.is_empty()) {
+ start = 0;
+ } else {
+ start = page_contents->words.get_data();
+ }
+ }
+
+ html.put_string("</tr>\n");
+ } while (((limit < indentation.vertical_limit) && (start != 0) &&
+ (! page_contents->words.is_empty())) || (limit == -1));
+ end_table();
+
+ if (start == 0) {
+ // finished page remove all words
+ page_contents->words.start_from_head();
+ while (! page_contents->words.is_empty()) {
+ page_contents->words.sub_move_right();
+ }
+ } else if (! page_contents->words.is_empty()) {
+ page_contents->words.move_left();
+ }
+ }
+}
+
+/*
+ * write_centered_line - generates a line of centered text.
+ */
+
+void html_printer::write_centered_line (text_glob *g)
+{
+ int current_vpos=g->minv;
+
+ move_vertical(g, center_alignment);
+
+ header.written_header = FALSE;
+ supress_sub_sup = TRUE;
+ output_vpos = g->minv;
+ output_hpos = g->minh;
+ do {
+ char *postword=html_position_text(g, left_margin_indent, right_margin_indent);
+
+ if (! header.written_header) {
+ if (g->is_raw_command) {
+ html.put_string((char *)g->text_string);
+ } else {
+ translate_to_html(g);
+ }
+ if (postword != 0) {
+ html.put_string(postword);
+ }
+ need_one_newline = TRUE;
+ issued_newline = FALSE;
+ }
+ page_contents->words.move_right();
+ g = page_contents->words.get_data();
+ } while ((! page_contents->words.is_equal_to_head()) && (is_on_same_line(g, current_vpos)));
+ page_contents->words.move_left(); // so when we move right we land on the word following this centered line
+ need_one_newline = TRUE;
+}
+
+/*
+ * is_in_middle - returns TRUE if the text defn, t, is in the middle of the page.
+ */
+
+int html_printer::is_in_middle (int left, int right)
+{
+ return( abs(abs(left-left_margin_indent) - abs(right_margin_indent-right)) <= CENTER_TOLERANCE );
+}
+
+/*
+ * single_centered_line - returns TRUE if first is a centered line with a different
+ * margin to second.
+ */
+
+int html_printer::single_centered_line (text_defn *first, text_defn *second, text_glob *g)
+{
+ return(
+ ((count_columns(first) == 1) && (first[0].left != left_margin_indent) &&
+ (first[0].left != second[0].left) && is_in_middle(first->left, first->right))
+ );
+}
+
+/*
+ * check_able_to_use_center - returns TRUE if we can see a centered line.
+ */
+
+int html_printer::check_able_to_use_center (text_glob *g)
+{
+ if (auto_on && table_on && ((! is_on_same_line(g, output_vpos)) || issued_newline) && (! using_table_for_indent())) {
+ // we are allowed to check for centered line
+ // first check to see whether we might be looking at a set of columns
+ struct text_defn last_guess[MAX_WORDS_PER_LINE];
+ struct text_defn last_words[MAX_WORDS_PER_LINE];
+
+ collect_columns(last_words, last_guess, 0, 0, MAX_WORDS_PER_LINE);
+
+ rewind_text_to(g);
+ if ((count_columns(last_guess) == 1) && (is_in_middle(last_guess[0].left, last_guess[0].right))) {
+ write_centered_line(g);
+ return( TRUE );
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * check_able_to_use_table - examines forthcoming text to see whether we can
+ * better format it by using an html transparent table.
+ */
+
+int html_printer::check_able_to_use_table (text_glob *g)
+{
+ if (auto_on && ((! is_on_same_line(g, output_vpos)) || issued_newline) && (! using_table_for_indent())) {
+ // we are allowed to check for table
+
+ if ((output_hpos != right_margin_indent) && (found_use_for_table(g))) {
+ foreach_column_include_text(g);
+ return( TRUE );
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * move_vertical - if we are using html auto formatting then decide whether to
+ * break the line via a <br> or a </p><p> sequence.
+ */
+
+void html_printer::move_vertical (text_glob *g, paragraph_type p)
+{
+ int r = font::res;
+ int height = (g->text_style.point_size+2)*r/72; // --fixme-- we always assume VS is PS+2 (could do better)
+ int temp_vpos;
+
+ if (auto_on) {
+ if ((more_than_line_break(output_vpos, g->minv, height)) || (p != current_paragraph->para_type)) {
+ end_paragraph();
+ begin_paragraph(p);
+ } else {
+ html_newline();
+ }
+ } else {
+ if (output_vpos == -1) {
+ temp_vpos = g->minv;
+ } else {
+ temp_vpos = output_vpos;
+ }
+
+ force_begin_paragraph();
+ if (need_one_newline) {
+ html_newline();
+ temp_vpos += height;
+ } else {
+ need_one_newline = TRUE;
+ }
+
+ while ((temp_vpos < g->minv) && (more_than_line_break(temp_vpos, g->minv, height))) {
+ html_newline();
+ temp_vpos += height;
+ }
+ }
+}
+
+/*
+ * emit_space - emits a space within html, it checks for the font type and
+ * will change font depending upon, g. Courier spaces are larger
+ * than roman so we need consistancy when changing between them.
+ */
+
+void html_printer::emit_space (text_glob *g, int force_space)
+{
+ if (! current_paragraph->need_paragraph) {
+ // only generate a space if we have written a word - as html will ignore it otherwise
+ if ((output_style != g->text_style) && (g->text_style.f != 0)) {
+ terminate_current_font();
+ }
+ if (force_space || (g->minh > output_hpos)) {
+ html.put_string(" ");
+ }
+ change_font(g, TRUE);
+ }
+}
+
+/*
+ * html_position_text - determine whether the text is subscript/superscript/normal
+ * or a header.
+ */
+
+char *html_printer::html_position_text (text_glob *g, int left_margin, int right_margin)
+{
+ char *postword=0;
+
+ begin_paragraph(left_alignment);
+
+ if ((! header.written_header) &&
+ (is_on_same_line(g, output_vpos) ||
+ pretend_is_on_same_line(g, left_margin, right_margin))) {
+
+ /*
+ * check whether we should supress superscripts and subscripts.
+ * I guess we might be able to do better by examining text on this line
+ * --fixme--
+ */
+
+ if ((! is_on_same_line(g, output_vpos)) && (pretend_is_on_same_line(g, left_margin, right_margin))) {
+ supress_sub_sup = TRUE;
+ }
+ header.written_header = FALSE;
+ force_begin_paragraph();
+
+ // check whether we need to insert white space between words on 'same' line
+ if (pretend_is_on_same_line(g, left_margin, right_margin)) {
+ emit_space(g, TRUE);
+ }
+
+ // check whether the font was reset after generating an image
+ if (output_style.f == 0) {
+ change_font(g, TRUE);
+ }
+
+ if (looks_like_subscript(g)) {
+
+ g->text_style.point_size = output_style.point_size;
+ g->minv = output_vpos; // this ensures that output_vpos doesn't alter
+ // which allows multiple subscripted words
+ move_horizontal(g, left_margin);
+ html.put_string("<sub>");
+ postword = "</sub>";
+ } else if (looks_like_superscript(g)) {
+
+ g->text_style.point_size = output_style.point_size;
+ g->minv = output_vpos;
+
+ move_horizontal(g, left_margin);
+ html.put_string("<sup>");
+ postword = "</sup>";
+ } else {
+ move_horizontal(g, left_margin);
+ }
+ supress_sub_sup = FALSE;
+ } else {
+ // we have found a new line
+ if (! header.written_header) {
+ move_vertical(g, left_alignment);
+ }
+ header.written_header = FALSE;
+
+ if (processed_header(g)) {
+ // we must not alter output_vpos as we have peeped at the next word
+ // and set vpos to this - to ensure we do not generate a <br> after
+ // a heading. (The html heading automatically generates a line break)
+ output_hpos = left_margin;
+ return( postword );
+ } else {
+ force_begin_paragraph();
+ if (g->minh-left_margin != 0) {
+ make_html_indent(g->minh-left_margin);
+ }
+ change_font(g, TRUE);
+ supress_sub_sup = FALSE;
+ }
+ }
+ output_vpos = g->minv;
+ output_hpos = g->maxh;
+ return( postword );
+}
+
+
+int html_printer::html_position_region (void)
+{
+ int r = font::res;
+ int height = output_style.point_size*r/72;
+ int temp_vpos;
+ int is_center = FALSE;
+
+ if (output_style.point_size != 0) {
+ if (output_vpos != start_region_vpos) {
+
+ // graphic starts on a different line
+ if (output_vpos == -1) {
+ temp_vpos = start_region_vpos;
+ } else {
+ temp_vpos = output_vpos;
+ }
+ supress_sub_sup = TRUE;
+ if (need_one_newline) {
+ html_newline();
+ temp_vpos += height;
+ } else {
+ need_one_newline = TRUE;
+ }
+
+ while ((temp_vpos < start_region_vpos) &&
+ (more_than_line_break(temp_vpos, start_region_vpos, height))) {
+ html_newline();
+ temp_vpos += height;
+ }
+ }
+ }
+ if (auto_on && (is_in_middle(start_region_hpos, end_region_hpos))) {
+ is_center = TRUE;
+ } else {
+ if (start_region_hpos > get_left()) {
+ make_html_indent(start_region_hpos-get_left());
+ }
+ }
+ output_vpos = start_region_vpos;
+ output_hpos = start_region_hpos;
+ return( is_center );
+}
+
+/*
+ * gs_x - translate and scale the x axis
+ */
+
+int html_printer::gs_x (int x)
+{
+ x += IMAGE_BOARDER_PIXELS/2;
+ return((x-start_region_hpos)*postscript_res/font::res);
+}
+
+
+/*
+ * gs_y - translate and scale the y axis
+ */
+
+int html_printer::gs_y (int y)
+{
+ int yoffset=((int)(A4_PAGE_LENGTH*(double)font::res))-end_region_vpos;
+
+ y += IMAGE_BOARDER_PIXELS/2;
+ return( (y+yoffset)*postscript_res/font::res );
+}
+
+
+void html_printer::troff_position_text (text_glob *g)
+{
+ change_font(g, FALSE);
+
+ troff.put_string("V");
+ troff.put_number(gs_y(g->maxv));
+ troff.put_string("\n");
+
+ troff.put_string("H");
+ troff.put_number(gs_x(g->minh));
+ troff.put_string("\n");
+}
+
+void html_printer::troff_change_font (const char *fontname, int size, int font_no)
+{
+ troff.put_string("x font ");
+ troff.put_number(font_no);
+ troff.put_string(" ");
+ troff.put_string(fontname);
+ troff.put_string("\nf");
+ troff.put_number(font_no);
+ troff.put_string("\ns");
+ troff.put_number(size*1000);
+ troff.put_string("\n");
+}
+
+
+void html_printer::set_style(const style &sty)
+{
+#if 0
+ const char *fontname = sty.f->get_name();
+ if (fontname == 0)
+ fatal("no internalname specified for font");
+
+ change_font(fontname, (font::res/(72*font::sizescale))*sty.point_size);
+#endif
+}
+
+void html_printer::end_of_line()
+{
+ flush_sbuf();
+ output_hpos = -1;
+}
+
+void html_printer::html_display_word (text_glob *g)
+{
+#if 0
+ if (strcmp(g->text_string, "ot") == 0) {
+ stop();
+ }
+#endif
+ if (! check_able_to_use_table(g)) {
+ char *postword=html_position_text(g, left_margin_indent, right_margin_indent);
+
+ if (! header.written_header) {
+ if (g->is_raw_command) {
+ html.put_string((char *)g->text_string);
+ } else {
+ translate_to_html(g);
+ }
+ if (postword != 0) {
+ html.put_string(postword);
+ }
+ need_one_newline = TRUE;
+ issued_newline = FALSE;
+ }
+ }
+}
+
+void html_printer::troff_display_word (text_glob *g)
+{
+ troff_position_text(g);
+ if (g->is_raw_command) {
+ int l=strlen((char *)g->text_string);
+ if (l == 1) {
+ troff.put_string("c");
+ troff.put_string((char *)g->text_string);
+ troff.put_string("\n");
+ } else if (l > 1) {
+ troff.put_string("C");
+ troff.put_troffps_char((char *)g->text_string);
+ troff.put_string("\n");
+ }
+ } else {
+ troff_position_text(g);
+ troff.put_string("t");
+ troff.put_translated_string((const char *)g->text_string);
+ troff.put_string("\n");
+ }
+}
+
+void html_printer::display_word (text_glob *g, int is_to_html)
+{
+ if (is_to_html) {
+ html_display_word(g);
+ } else if ((g->is_raw_command) && (g->is_html_command)) {
+ // found a raw html command inside a graphic glob.
+ // We should emit the command to the html device, but of course we
+ // cannot place it correctly as we are dealing with troff words.
+ // Remember output_vpos will refer to troff and not html.
+ html.put_string((char *)g->text_string);
+ } else {
+ troff_display_word(g);
+ }
+}
+
+/*
+ * translate_to_html - translates a textual string into html text
+ */
+
+void html_printer::translate_to_html (text_glob *g)
+{
+ char buf[MAX_STRING_LENGTH];
+
+ str_translate_to_html(g->text_style.f, buf, MAX_STRING_LENGTH,
+ g->text_string, g->text_length, TRUE);
+ html.put_string(buf);
+}
+
+/*
+ * html_knows_about - given a character name, troff, return TRUE
+ * if we know how to display this character using
+ * html unicode.
+ */
+
+int html_printer::html_knows_about (char *troff)
+{
+ // --fixme-- needs to have similar code as above
+ return( FALSE );
+}
+
+/*
+ * display_fill - generates a troff format fill command
+ */
+
+void html_printer::display_fill (graphic_glob *g)
+{
+ troff.put_string("Df ") ;
+ troff.put_number(g->fill);
+ troff.put_string(" 0\n");
+}
+
+/*
+ * display_line - displays a line using troff format
+ */
+
+void html_printer::display_line (graphic_glob *g, int is_to_html)
+{
+ if (is_to_html) {
+ fatal("cannot emit lines in html");
+ }
+ if (g->code == 'l') {
+ // straight line
+
+ troff.put_string("V");
+ troff.put_number(gs_y(g->point[0].y));
+ troff.put_string("\n");
+
+ troff.put_string("H");
+ troff.put_number(gs_x(g->point[0].x));
+ troff.put_string("\n");
+
+ display_fill(g);
+
+ troff.put_string("Dl ");
+ troff.put_number((g->point[1].x-g->point[0].x)*postscript_res/font::res);
+ troff.put_string(" ");
+ troff.put_number((g->point[1].y-g->point[0].y)*postscript_res/font::res);
+ troff.put_string("\n");
+ // printf("line %c %d %d %d %d size %d\n", (char)g->code, g->point[0].x, g->point[0].y,
+ // g->point[1].x, g->point[1].y, g->size);
+ } else if ((g->code == 'c') || (g->code == 'C')) {
+ // circle
+
+ int xradius = (g->maxh - g->minh) / 2;
+ int yradius = (g->maxv - g->minv) / 2;
+ // center of circle or elipse
+
+ troff.put_string("V");
+ troff.put_number(gs_y(g->minv+yradius));
+ troff.put_string("\n");
+
+ troff.put_string("H");
+ troff.put_number(gs_x(g->minh));
+ troff.put_string("\n");
+
+ display_fill(g);
+
+ if (g->code == 'c') {
+ troff.put_string("Dc ");
+ } else {
+ troff.put_string("DC ");
+ }
+
+ troff.put_number(xradius*2*postscript_res/font::res);
+ troff.put_string("\n");
+
+ } else if ((g->code == 'e') || (g->code == 'E')) {
+ // ellipse
+
+ int xradius = (g->maxh - g->minh) / 2;
+ int yradius = (g->maxv - g->minv) / 2;
+ // center of elipse - this is untested
+
+ troff.put_string("V");
+ troff.put_number(gs_y(g->minv+yradius));
+ troff.put_string("\n");
+
+ troff.put_string("H");
+ troff.put_number(gs_x(g->minh));
+ troff.put_string("\n");
+
+ display_fill(g);
+
+ if (g->code == 'e') {
+ troff.put_string("De ");
+ } else {
+ troff.put_string("DE ");
+ }
+
+ troff.put_number(xradius*2*postscript_res/font::res);
+ troff.put_string(" ");
+ troff.put_number(yradius*2*postscript_res/font::res);
+ troff.put_string("\n");
+ } else if ((g->code == 'p') || (g->code == 'P')) {
+ // polygon
+ troff.put_string("V");
+ troff.put_number(gs_y(g->yc));
+ troff.put_string("\n");
+
+ troff.put_string("H");
+ troff.put_number(gs_x(g->xc));
+ troff.put_string("\n");
+
+ display_fill(g);
+
+ if (g->code == 'p') {
+ troff.put_string("Dp");
+ } else {
+ troff.put_string("DP");
+ }
+
+ int i;
+ int xc=g->xc;
+ int yc=g->yc;
+ for (i=0; i<g->nopoints; i++) {
+ troff.put_string(" ");
+ troff.put_number((g->point[i].x-xc)*postscript_res/font::res);
+ troff.put_string(" ");
+ troff.put_number((g->point[i].y-yc)*postscript_res/font::res);
+ xc = g->point[i].x;
+ yc = g->point[i].y;
+ }
+ troff.put_string("\n");
+ } else if (g->code == 'a') {
+ // arc
+ troff.put_string("V");
+ troff.put_number(gs_y(g->yc));
+ troff.put_string("\n");
+
+ troff.put_string("H");
+ troff.put_number(gs_x(g->xc));
+ troff.put_string("\n");
+
+ display_fill(g);
+
+ troff.put_string("Da");
+
+ int i;
+
+ for (i=0; i<g->nopoints; i++) {
+ troff.put_string(" ");
+ troff.put_number(g->point[i].x*postscript_res/font::res);
+ troff.put_string(" ");
+ troff.put_number(g->point[i].y*postscript_res/font::res);
+ }
+ troff.put_string("\n");
+ } else if (g->code == '~') {
+ // spline
+ troff.put_string("V");
+ troff.put_number(gs_y(g->yc));
+ troff.put_string("\n");
+
+ troff.put_string("H");
+ troff.put_number(gs_x(g->xc));
+ troff.put_string("\n");
+
+ display_fill(g);
+
+ troff.put_string("D~");
+
+ int i;
+ int xc=g->xc;
+ int yc=g->yc;
+ for (i=0; i<g->nopoints; i++) {
+ troff.put_string(" ");
+ troff.put_number((g->point[i].x-xc)*postscript_res/font::res);
+ troff.put_string(" ");
+ troff.put_number((g->point[i].y-yc)*postscript_res/font::res);
+ xc = g->point[i].x;
+ yc = g->point[i].y;
+ }
+ troff.put_string("\n");
+ }
+}
+
+
+/*
+ * flush_sbuf - flushes the current sbuf into the list of glyphs.
+ */
+
+void html_printer::flush_sbuf()
+{
+ if (sbuf_len > 0) {
+ int r=font::res; // resolution of the device
+ set_style(sbuf_style);
+
+ page_contents->add(&sbuf_style, sbuf, sbuf_len,
+ sbuf_vpos-sbuf_style.point_size*r/72, sbuf_start_hpos,
+ sbuf_vpos , sbuf_end_hpos);
+
+ output_hpos = sbuf_end_hpos;
+ output_vpos = sbuf_vpos;
+ sbuf_len = 0;
+ sbuf_dmark_hpos = -1;
+ }
+}
+
+
+void html_printer::set_line_thickness(const environment *env)
+{
+ line_thickness = env->size;
+ printf("line thickness = %d\n", line_thickness);
+}
+
+void html_printer::draw(int code, int *p, int np, const environment *env)
+{
+ switch (code) {
+
+ case 'l':
+ if (np == 2) {
+ page_contents->add_line(code,
+ env->hpos, env->vpos, env->hpos+p[0], env->vpos+p[1],
+ env->size, fill);
+ } else {
+ error("2 arguments required for line");
+ }
+ break;
+ case 't':
+ {
+ if (np == 0) {
+ line_thickness = -1;
+ } else {
+ // troff gratuitously adds an extra 0
+ if (np != 1 && np != 2) {
+ error("0 or 1 argument required for thickness");
+ break;
+ }
+ line_thickness = p[0];
+ }
+ break;
+ }
+
+ case 'P':
+ // fall through
+ case 'p':
+ {
+ if (np & 1) {
+ error("even number of arguments required for polygon");
+ break;
+ }
+ if (np == 0) {
+ error("no arguments for polygon");
+ break;
+ }
+ // firstly lets add our current position to polygon
+ int oh=env->hpos;
+ int ov=env->vpos;
+ int i=0;
+
+ while (i<np) {
+ p[i+0] += oh;
+ p[i+1] += ov;
+ oh = p[i+0];
+ ov = p[i+1];
+ i += 2;
+ }
+ // now store polygon in page
+ page_contents->add_polygon(code, np, p, env->hpos, env->vpos, env->size, fill);
+ }
+ break;
+ case 'E':
+ // fall through
+ case 'e':
+ if (np != 2) {
+ error("2 arguments required for ellipse");
+ break;
+ }
+ page_contents->add_line(code,
+ env->hpos, env->vpos-p[1]/2, env->hpos+p[0], env->vpos+p[1]/2,
+ env->size, fill);
+
+ break;
+ case 'C':
+ // fill circle
+
+ case 'c':
+ {
+ // troff adds an extra argument to C
+ if (np != 1 && !(code == 'C' && np == 2)) {
+ error("1 argument required for circle");
+ break;
+ }
+ page_contents->add_line(code,
+ env->hpos, env->vpos-p[0]/2, env->hpos+p[0], env->vpos+p[0]/2,
+ env->size, fill);
+ }
+ break;
+ case 'a':
+ {
+ if (np == 4) {
+ double c[2];
+
+ if (adjust_arc_center(p, c)) {
+ page_contents->add_arc('a', env->hpos, env->vpos, p, c, env->size, fill);
+ } else {
+ // a straignt line
+ page_contents->add_line('l', env->hpos, env->vpos, p[0]+p[2], p[1]+p[3], env->size, fill);
+ }
+ } else {
+ error("4 arguments required for arc");
+ }
+ }
+ break;
+ case '~':
+ {
+ if (np & 1) {
+ error("even number of arguments required for spline");
+ break;
+ }
+ if (np == 0) {
+ error("no arguments for spline");
+ break;
+ }
+ // firstly lets add our current position to spline
+ int oh=env->hpos;
+ int ov=env->vpos;
+ int i=0;
+
+ while (i<np) {
+ p[i+0] += oh;
+ p[i+1] += ov;
+ oh = p[i+0];
+ ov = p[i+1];
+ i += 2;
+ }
+ page_contents->add_spline('~', env->hpos, env->vpos, np, p, env->size, fill);
+ }
+ break;
+ case 'f':
+ {
+ if (np != 1 && np != 2) {
+ error("1 argument required for fill");
+ break;
+ }
+ fill = p[0];
+ if (fill < 0 || fill > FILL_MAX) {
+ // This means fill with the current color.
+ fill = FILL_MAX + 1;
+ }
+ break;
+ }
+
+ default:
+ error("unrecognised drawing command `%1'", char(code));
+ break;
+ }
+}
+
+
+void html_printer::begin_page(int n)
+{
+ page_number = n;
+ html.begin_comment("Page: ").comment_arg(itoa(page_number)).end_comment();;
+ no_of_printed_pages++;
+
+ output_style.f = 0;
+ output_space_code = 32;
+ output_draw_point_size = -1;
+ output_line_thickness = -1;
+ output_hpos = -1;
+ output_vpos = -1;
+}
+
+void testing (text_glob *g) {}
+
+void html_printer::flush_graphic (void)
+{
+ graphic_glob g;
+
+ graphic_level = 0;
+ page_contents->is_in_graphic = FALSE;
+
+ g.minv = -1;
+ g.maxv = -1;
+ calculate_region_range(&g);
+ if (g.minv != -1) {
+ page_contents->make_new_region(&g);
+ }
+ move_region_to_page();
+}
+
+void html_printer::end_page(int)
+{
+ flush_sbuf();
+ flush_graphic();
+ flush_page();
+}
+
+font *html_printer::make_font(const char *nm)
+{
+ return html_font::load_html_font(nm);
+}
+
+html_printer::~html_printer()
+{
+ if (fseek(tempfp, 0L, 0) < 0)
+ fatal("fseek on temporary file failed");
+ html.set_file(stdout);
+ fputs("<html>\n", stdout);
+ fputs("<head>\n", stdout);
+ fputs("<meta name=\"Content-Style\" content=\"text/css\">\n", stdout);
+ write_title(TRUE);
+ fputs("</head>\n", stdout);
+ fputs("<body>\n", stdout);
+ write_title(FALSE);
+ header.write_headings(stdout);
+ {
+ extern const char *Version_string;
+ html.begin_comment("Creator : ")
+ .comment_arg("groff ")
+ .comment_arg("version ")
+ .comment_arg(Version_string)
+ .end_comment();
+ }
+ {
+#ifdef LONG_FOR_TIME_T
+ long
+#else
+ time_t
+#endif
+ t = time(0);
+ html.begin_comment("CreationDate: ")
+ .comment_arg(ctime(&t))
+ .end_comment();
+ }
+ html.begin_comment("Total number of pages: ").comment_arg(itoa(no_of_printed_pages)).end_comment();
+ html.end_line();
+ html.copy_file(tempfp);
+ fputs("</body>\n", stdout);
+ fputs("</html>\n", stdout);
+ fclose(tempfp);
+}
+
+
+/*
+ * calculate_region_range - calculates the vertical range for words and lines
+ * within the region lists.
+ */
+
+void html_printer::calculate_region_range (graphic_glob *r)
+{
+ text_glob *w;
+ graphic_glob *g;
+
+ if (! page_contents->region_lines.is_empty()) {
+ page_contents->region_lines.start_from_head();
+ do {
+ g = page_contents->region_lines.get_data();
+ if ((r->minv == -1) || (g->minv < r->minv)) {
+ r->minv = g->minv;
+ }
+ if ((r->maxv == -1) || (g->maxv > r->maxv)) {
+ r->maxv = g->maxv;
+ }
+ page_contents->region_lines.move_right();
+ } while (! page_contents->region_lines.is_equal_to_head());
+ }
+ if (! page_contents->region_words.is_empty()) {
+ page_contents->region_words.start_from_head();
+ do {
+ w = page_contents->region_words.get_data();
+
+ if ((r->minv == -1) || (w->minv < r->minv)) {
+ r->minv = w->minv;
+ }
+ if ((r->maxv == -1) || (w->maxv > r->maxv)) {
+ r->maxv = w->maxv;
+ }
+ page_contents->region_words.move_right();
+ } while (! page_contents->region_words.is_equal_to_head());
+ }
+}
+
+
+/*
+ * move_region_to_page - moves lines and words held in the temporary region
+ * list to the page list.
+ */
+
+void html_printer::move_region_to_page (void)
+{
+ text_glob *w;
+ graphic_glob *g;
+
+ page_contents->region_lines.start_from_head();
+ while (! page_contents->region_lines.is_empty()) {
+ g = page_contents->region_lines.get_data(); // remove from our temporary region list
+ page_contents->lines.add(g); // and add to the page list
+ page_contents->region_lines.sub_move_right();
+ }
+ page_contents->region_words.start_from_head();
+ while (! page_contents->region_words.is_empty()) {
+ w = page_contents->region_words.get_data(); // remove from our temporary region list
+ page_contents->words.add(w); // and add to the page list
+ page_contents->region_words.sub_move_right();
+ }
+}
+
+/*
+ * is_graphic_start - returns TRUE if the start of table, pic, eqn was seen.
+ */
+
+int is_graphic_start (char *s)
+{
+ return( (strcmp(s, "graphic-start") == 0) ||
+ ((strcmp(s, "table-start") == 0) && (table_image_on)) );
+}
+
+/*
+ * is_graphic_end - return TRUE if the end of a table, pic, eqn was seen.
+ */
+
+int is_graphic_end (char *s)
+{
+ return( (strcmp(s, "graphic-end") == 0) ||
+ ((strcmp(s, "table-end") == 0) && (table_image_on)) );
+}
+
+/*
+ * special - handle all x X requests from troff. For grohtml they allow users
+ * to pass raw html commands, turn auto linked headings off/on and
+ * also allow tbl, eqn & pic say what commands they have generated.
+ */
+
+void html_printer::special(char *s, const environment *env)
+{
+ if (s != 0) {
+ if (is_graphic_start(s)) {
+ graphic_level++;
+ if (graphic_level == 1) {
+ page_contents->is_in_graphic = TRUE; // add words and lines to temporary region lists
+ }
+ } else if (is_graphic_end(s) && (graphic_level > 0)) {
+ graphic_level--;
+ if (graphic_level == 0) {
+ flush_graphic();
+ }
+ } else if (strncmp(s, "html:", 5) == 0) {
+ int r=font::res; // resolution of the device
+ char buf[MAX_STRING_LENGTH];
+ font *f=sbuf_style.f;
+
+ if (f == NULL) {
+ int found=FALSE;
+
+ f = font::load_font("TR", &found);
+ }
+ str_translate_to_html(f, buf, MAX_STRING_LENGTH,
+ &s[5], strlen(s)-5, FALSE);
+ page_contents->add_html_command(&sbuf_style, buf, strlen(buf),
+
+ // need to pass rest of string through to html output during flush
+
+ env->vpos-env->size*r/72, env->hpos,
+ env->vpos , env->hpos);
+ // assume that the html command has no width, if it does then we hopefully troff
+ // will have fudged this in a macro and requested that the formatting move right by
+ // the appropriate width
+ } else if (strncmp(s, "index:", 6) == 0) {
+ cutoff_heading = atoi(&s[6]);
+ }
+ }
+}
+
+void set_image_type (char *type)
+{
+ if (strcmp(type, "gif") == 0) {
+ image_type = gif;
+ } else if (strcmp(type, "png") == 0) {
+ image_type = png;
+ image_device = "png256";
+ } else if (strncmp(type, "png", 3) == 0) {
+ image_type = png;
+ image_device = type;
+ }
+}
+
+printer *make_printer()
+{
+ return new html_printer;
+}
+
+static void usage();
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int c;
+ while ((c = getopt(argc, argv, "F:atTvdgmx?I:r:")) != EOF)
+ switch(c) {
+ case 'v':
+ {
+ extern const char *Version_string;
+ fprintf(stderr, "grohtml version %s\n", Version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'a':
+ auto_on = FALSE;
+ break;
+ case 't':
+ table_on = FALSE;
+ break;
+ case 'T':
+ table_image_on = FALSE;
+ break;
+ case 'F':
+ font::command_line_font_dir(optarg);
+ break;
+ case 'I':
+ // user specifying the type of images we should generate
+ set_image_type(optarg);
+ break;
+ case 'r':
+ // resolution (dots per inch for an image)
+ image_res = atoi(optarg);
+ break;
+ case 'd':
+ // debugging on
+ debug_on = TRUE;
+ break;
+ case 'x':
+ debug_table_on = TRUE;
+ break;
+ case 'g':
+ // do not guess title and headings
+ guess_on = FALSE;
+ break;
+ case 'm':
+ // leave margins alone
+ margin_on = TRUE;
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ }
+ if (optind >= argc) {
+ do_file("-");
+ } else {
+ for (int i = optind; i < argc; i++)
+ do_file(argv[i]);
+ }
+ delete pr;
+ return 0;
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-avdgmt?] [-r resolution] [-F dir] [-I imagetype] [files ...]\n",
+ program_name);
+ exit(1);
+}
diff --git a/src/devices/grohtml/html.h b/src/devices/grohtml/html.h
new file mode 100644
index 00000000..37007751
--- /dev/null
+++ b/src/devices/grohtml/html.h
@@ -0,0 +1,57 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+class simple_output {
+public:
+ simple_output(FILE *, int max_line_length);
+ simple_output &put_string(const char *, int);
+ simple_output &put_string(const char *s);
+ simple_output &put_troffps_char (const char *s);
+ simple_output &put_translated_string(const char *s);
+ simple_output &put_number(int);
+ simple_output &put_float(double);
+ simple_output &put_symbol(const char *);
+ simple_output &put_literal_symbol(const char *);
+ simple_output &set_fixed_point(int);
+ simple_output &simple_comment(const char *);
+ simple_output &begin_comment(const char *);
+ simple_output &comment_arg(const char *);
+ simple_output &end_comment();
+ simple_output &set_file(FILE *);
+ simple_output &include_file(FILE *);
+ simple_output &copy_file(FILE *);
+ simple_output &end_line();
+ simple_output &put_raw_char(char);
+ simple_output &special(const char *);
+ simple_output &put_html_char (char);
+ FILE *get_file();
+private:
+ FILE *fp;
+ int max_line_length; // not including newline
+ int col;
+ int need_space;
+ int fixed_point;
+};
+
+inline FILE *simple_output::get_file()
+{
+ return fp;
+}
+
diff --git a/src/devices/grohtml/html_chars.h b/src/devices/grohtml/html_chars.h
new file mode 100755
index 00000000..76f094c8
--- /dev/null
+++ b/src/devices/grohtml/html_chars.h
@@ -0,0 +1,27 @@
+// -*- C++ -*-
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * Gaius Mulley (gaius@glam.ac.uk) wrote output.cc
+ * but it owes a huge amount of ideas and raw code from
+ * James Clark (jjc@jclark.com) grops/ps.cc.
+ *
+ * html_chars.h
+ *
+ * provides a diacritical character combination table for html
+ */
+
+
+
+struct diacritical_desc {
+ char *mark;
+ char *second_troff_char;
+ char translation;
+};
+
+
+static struct diacritical_desc diacritical_table[] = {
+ { "ad" , "aeiouyAEIOU" , ':' , }, /* */
+ { "ac" , "cC" , ',' , }, /* cedilla */
+ { "aa" , "aeiouyAEIOU" , '\'' , }, /* acute */
+ { NULL , NULL , (char)0, },
+};
diff --git a/src/devices/grohtml/ordered_list.h b/src/devices/grohtml/ordered_list.h
new file mode 100755
index 00000000..52fe1c9e
--- /dev/null
+++ b/src/devices/grohtml/ordered_list.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 1999 Free Software Foundation, Inc.
+ *
+ * Ordered list, a template module for simple ordered list manipulation.
+ *
+ * Gaius Mulley (gaius@glam.ac.uk)
+ */
+
+template <class T> class list_element
+{
+ public:
+ list_element *right;
+ list_element *left;
+
+ list_element (T *in);
+ T *data;
+};
+
+template <class T> class ordered_list
+{
+ private:
+ list_element<T> *head;
+ list_element<T> *tail;
+ list_element<T> *ptr;
+ public:
+ ordered_list (void);
+ ~ ordered_list (void);
+ void add (T* in);
+ void sub_move_right (void);
+ void move_right (void);
+ void move_left (void);
+ int is_empty (void);
+ int is_equal_to_tail (void);
+ int is_equal_to_head (void);
+ void start_from_head (void);
+ void start_from_tail (void);
+ T *move_right_get_data (void);
+ T *move_left_get_data (void);
+ T *get_data (void);
+};
+
+
+template <class T> ordered_list<T>::ordered_list()
+ : head(0), tail(0), ptr(0)
+{
+}
+
+template <class T> ordered_list<T>::~ordered_list()
+{
+ list_element<T> *temp=head;
+
+ do {
+ temp = head;
+ if (temp != 0) {
+ head = head->right;
+ delete temp;
+ }
+ } while ((head != 0) && (head != tail));
+}
+
+template <class T> list_element<T>::list_element(T *in)
+ : right(0), left(0)
+{
+ data = in;
+}
+
+template <class T> void ordered_list<T>::add(T *in)
+{
+ list_element<T> *t = new list_element<T>(in); // create a new list element with data field initialized
+ list_element<T> *last;
+
+ if (in == 0) {
+ fatal("cannot add NULL to ordered list");
+ }
+
+ if (head == 0) {
+ head = t;
+ tail = t;
+ t->left = t;
+ t->right = t;
+ } else {
+ last = tail;
+
+ while ((last != head) && (in->is_less(in, last->data))) {
+ last = last->left;
+ }
+
+ if (in->is_less(in, last->data)) {
+ t->right = last;
+ last->left->right = t;
+ t->left = last->left;
+ last->left = t;
+ // now check for a new head
+ if (last == head) {
+ head = t;
+ }
+ } else {
+ // add t onto beyond last
+ t->right = last->right;
+ t->left = last;
+ last->right->left = t;
+ last->right = t;
+ // now check for a new tail
+ if (last == tail) {
+ tail = t;
+ }
+ }
+ }
+}
+
+template <class T> void ordered_list<T>::sub_move_right (void)
+{
+ list_element<T> *t=ptr->right;
+
+ if (head == tail) {
+ head = 0;
+ if (tail != 0) {
+ delete tail;
+ }
+ tail = 0;
+ ptr = 0;
+ } else {
+ if (head == ptr) {
+ head = head->right;
+ }
+ if (tail == ptr) {
+ tail = tail->left;
+ }
+ ptr->left->right = ptr->right;
+ ptr->right->left = ptr->left;
+ ptr=t;
+ }
+}
+
+template <class T> void ordered_list<T>::start_from_head (void)
+{
+ ptr = head;
+}
+
+template <class T> void ordered_list<T>::start_from_tail (void)
+{
+ ptr = tail;
+}
+
+template <class T> int ordered_list<T>::is_empty (void)
+{
+ return( head == 0 );
+}
+
+template <class T> int ordered_list<T>::is_equal_to_tail (void)
+{
+ return( ptr == tail );
+}
+
+template <class T> int ordered_list<T>::is_equal_to_head (void)
+{
+ return( ptr == head );
+}
+
+template <class T> void ordered_list<T>::move_left (void)
+{
+ ptr = ptr->left;
+}
+
+template <class T> void ordered_list<T>::move_right (void)
+{
+ ptr = ptr->right;
+}
+
+template <class T> T* ordered_list<T>::get_data (void)
+{
+ return( ptr->data );
+}
+
+template <class T> T* ordered_list<T>::move_right_get_data (void)
+{
+ ptr = ptr->right;
+ if (ptr == head) {
+ return( 0 );
+ } else {
+ return( ptr->data );
+ }
+}
+
+template <class T> T* ordered_list<T>::move_left_get_data (void)
+{
+ ptr = ptr->left;
+ if (ptr == tail) {
+ return( 0 );
+ } else {
+ return( ptr->data );
+ }
+}
diff --git a/src/devices/grohtml/output.cc b/src/devices/grohtml/output.cc
new file mode 100644
index 00000000..48c85ee0
--- /dev/null
+++ b/src/devices/grohtml/output.cc
@@ -0,0 +1,257 @@
+// -*- C++ -*-
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * Gaius Mulley (gaius@glam.ac.uk) wrote output.cc
+ * but it owes a huge amount of ideas and raw code from
+ * James Clark (jjc@jclark.com) grops/ps.cc.
+ *
+ * output.cc
+ *
+ * provide the simple low level output routines needed by html.cc
+ */
+
+/*
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "driver.h"
+#include "stringclass.h"
+#include "cset.h"
+
+#include <time.h>
+#include "html.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if !defined(TRUE)
+# define TRUE (1==1)
+#endif
+#if !defined(FALSE)
+# define FALSE (1==0)
+#endif
+
+
+/*
+ * the classes and methods for simple_output manipulation
+ */
+
+simple_output::simple_output(FILE *f, int n)
+: fp(f), col(0), max_line_length(n), need_space(0), fixed_point(0)
+{
+}
+
+simple_output &simple_output::set_file(FILE *f)
+{
+ fp = f;
+ col = 0;
+ return *this;
+}
+
+simple_output &simple_output::copy_file(FILE *infp)
+{
+ int c;
+ while ((c = getc(infp)) != EOF)
+ putc(c, fp);
+ return *this;
+}
+
+simple_output &simple_output::end_line()
+{
+ if (col != 0) {
+ putc('\n', fp);
+ col = 0;
+ need_space = 0;
+ }
+ return *this;
+}
+
+simple_output &simple_output::special(const char *s)
+{
+ return *this;
+}
+
+simple_output &simple_output::simple_comment(const char *s)
+{
+ if (col != 0)
+ putc('\n', fp);
+ fputs("<!-- ", fp);
+ fputs(s, fp);
+ fputs(" -->\n", fp);
+ col = 0;
+ need_space = 0;
+ return *this;
+}
+
+simple_output &simple_output::begin_comment(const char *s)
+{
+ if (col != 0)
+ putc('\n', fp);
+ fputs("<!-- ", fp);
+ fputs(s, fp);
+ col = 5 + strlen(s);
+ return *this;
+}
+
+simple_output &simple_output::end_comment()
+{
+ if (need_space) {
+ putc(' ', fp);
+ }
+ fputs(" -->\n", fp);
+ col = 0;
+ need_space = 0;
+ return *this;
+}
+
+simple_output &simple_output::comment_arg(const char *s)
+{
+ int len = strlen(s);
+
+ if (col + len + 1 > max_line_length) {
+ fputs("\n ", fp);
+ col = 1;
+ }
+ fputs(s, fp);
+ col += len + 1;
+ return *this;
+}
+
+simple_output &simple_output::set_fixed_point(int n)
+{
+ assert(n >= 0 && n <= 10);
+ fixed_point = n;
+ return *this;
+}
+
+simple_output &simple_output::put_raw_char(char c)
+{
+ putc(c, fp);
+ col++;
+ need_space = 0;
+ return *this;
+}
+
+simple_output &simple_output::put_string(const char *s, int n)
+{
+ int i=0;
+
+ while (i<n) {
+ fputc(s[i], fp);
+ i++;
+ }
+ col += n;
+ return *this;
+}
+
+simple_output &simple_output::put_translated_string(const char *s)
+{
+ int i=0;
+
+ while (s[i] != (char)0) {
+ if ((s[i] & 0x7f) == s[i]) {
+ fputc(s[i], fp);
+ }
+ i++;
+ }
+ col += i;
+ return *this;
+}
+
+simple_output &simple_output::put_string(const char *s)
+{
+ int i=0;
+
+ while (s[i] != '\0') {
+ fputc(s[i], fp);
+ i++;
+ }
+ col += i;
+ return *this;
+}
+
+struct html_2_postscript {
+ char *html_char;
+ char *postscript_char;
+};
+
+static struct html_2_postscript ps_char_conversions[] = {
+ { "+-", "char177", },
+ { "eq", "=" , },
+ { "mu", "char215", },
+ { NULL, NULL , },
+};
+
+
+/*
+ * this is an aweful hack which attempts to translate html characters onto
+ * postscript characters. Can this be done inside the devhtml files?
+ *
+ * or should we read the devps files and find out the translations?
+ */
+
+simple_output &simple_output::put_troffps_char (const char *s)
+{
+ int i=0;
+
+ while (ps_char_conversions[i].html_char != NULL) {
+ if (strcmp(s, ps_char_conversions[i].html_char) == 0) {
+ put_string(ps_char_conversions[i].postscript_char);
+ return *this;
+ } else {
+ i++;
+ }
+ }
+ put_string(s);
+ return *this;
+}
+
+simple_output &simple_output::put_number(int n)
+{
+ char buf[1 + INT_DIGITS + 1];
+ sprintf(buf, "%d", n);
+ int len = strlen(buf);
+ put_string(buf, len);
+ need_space = 1;
+ return *this;
+}
+
+simple_output &simple_output::put_float(double d)
+{
+ char buf[128];
+
+ sprintf(buf, "%.4f", d);
+ int len = strlen(buf);
+ put_string(buf, len);
+ need_space = 1;
+ return *this;
+}
+
+
+simple_output &simple_output::put_symbol(const char *s)
+{
+ int len = strlen(s);
+
+ if (need_space) {
+ putc(' ', fp);
+ col++;
+ }
+ fputs(s, fp);
+ col += len;
+ need_space = 1;
+ return *this;
+}
diff --git a/src/devices/grolj4/Makefile.sub b/src/devices/grolj4/Makefile.sub
new file mode 100644
index 00000000..bbb0cff0
--- /dev/null
+++ b/src/devices/grolj4/Makefile.sub
@@ -0,0 +1,6 @@
+PROG=grolj4
+MAN1=grolj4.n
+XLIBS=$(LIBDRIVER) $(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=lj4.o
+CCSRCS=$(srcdir)/lj4.cc
diff --git a/src/devices/grolj4/grolj4.man b/src/devices/grolj4/grolj4.man
new file mode 100644
index 00000000..9a7c7fde
--- /dev/null
+++ b/src/devices/grolj4/grolj4.man
@@ -0,0 +1,119 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1994, 1995, 1999 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.TH GROLJ4 @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+grolj4 \- groff driver for HP Laserjet 4 family
+.SH SYNOPSIS
+.B grolj4
+[
+.B \-lv
+] [
+.B \-d
+[\c
+.IR n ]
+] [
+.BI \-c n
+] [
+.BI \-p paper_size
+] [
+.BI \-w n
+] [
+.BI \-F dir
+] [
+.IR files \|.\|.\|.
+]
+.SH DESCRIPTION
+.B grolj4
+is a driver for
+.B groff
+that produces output in PCL5 format suitable for an HP Laserjet 4 printer.
+.LP
+There is an additional drawing command available:
+.TP
+.BI \eD'R\ dh\ dv '
+Draw a rule (solid black rectangle), with one corner
+at the current position, and the diagonally opposite corner
+at the current position
+.RI +( dh , dv ).
+Afterwards the current position will be at the opposite corner. This
+generates a PCL fill rectangle command, and so will work on
+printers that do not support HPGL/2 unlike the other
+.B \eD
+commands.
+.SH OPTIONS
+.TP
+.BI \-c n
+Print
+.I n
+copies of each page.
+.TP
+.B \-l
+Print the document with a landscape orientation.
+.TP
+.BI "\-d [" n ]
+Use duplex mode
+.IR n :
+1\ is long-side binding; 2\ is short-side binding;
+default is\ 1.
+.TP
+.BI \-p size
+Set the paper size to
+.IR size ,
+which must be one of
+letter, legal, executive, a4, com10, monarch, c5, b5, dl.
+.TP
+.B \-v
+Print the version number.
+.TP
+.BI \-w n
+Set the default line thickness to
+.I n
+thousandths of an em.
+.TP
+.BI \-F dir
+Search directory
+.IB dir /devlj4
+for font and device description files.
+.SH FILES
+.TP
+.B @FONTDIR@/devlj4/DESC
+Device description file.
+.TP
+.B @FONTDIR@/devlj4/ F
+Font description file for font
+.IR F .
+.TP
+.B @MACRODIR@/tmac.lj4
+Macros for use with
+.BR grolj4 .
+.SH BUGS
+Small dots.
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@),
+.BR @g@eqn (@MAN1EXT@),
+.BR groff_out (@MAN5EXT@),
+.BR groff_font (@MAN5EXT@),
+.BR groff_char (@MAN7EXT@),
diff --git a/src/devices/grolj4/lj4.cc b/src/devices/grolj4/lj4.cc
new file mode 100644
index 00000000..163742a5
--- /dev/null
+++ b/src/devices/grolj4/lj4.cc
@@ -0,0 +1,695 @@
+// -*- C++ -*-
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+TODO
+
+option to use beziers for circle/ellipse/arc
+option to use lines for spline (for LJ3)
+left/top offset registration
+output bin selection option
+paper source option
+output non-integer parameters using fixed point numbers
+X command to insert contents of file
+X command to specify inline escape sequence (how to specify unprintable chars?)
+X command to include bitmap graphics
+*/
+
+#include "driver.h"
+
+static struct {
+ const char *name;
+ int code;
+ // at 300dpi
+ int x_offset_portrait;
+ int x_offset_landscape;
+} paper_table[] = {
+ { "letter", 2, 75, 60 },
+ { "legal", 3, 75, 60 },
+ { "executive", 1, 75, 60 },
+ { "a4", 26, 71, 59 },
+ { "com10", 81, 75, 60 },
+ { "monarch", 80, 75, 60 },
+ { "c5", 91, 71, 59 },
+ { "b5", 100, 71, 59 },
+ { "dl", 90, 71, 59 },
+};
+
+static int paper_size = -1;
+static int landscape_flag = 0;
+static int duplex_flag = 0;
+
+// An upper limit on the paper size in centipoints,
+// used for setting HPGL picture frame.
+#define MAX_PAPER_WIDTH (12*720)
+#define MAX_PAPER_HEIGHT (17*720)
+
+// Dotted lines that are thinner than this don't work right.
+#define MIN_DOT_PEN_WIDTH .351
+
+#ifndef DEFAULT_LINE_WIDTH_FACTOR
+// in ems/1000
+#define DEFAULT_LINE_WIDTH_FACTOR 40
+#endif
+
+const int DEFAULT_HPGL_UNITS = 1016;
+int line_width_factor = DEFAULT_LINE_WIDTH_FACTOR;
+unsigned ncopies = 0; // 0 means don't send ncopies command
+
+class lj4_font : public font {
+public:
+ ~lj4_font();
+ void handle_unknown_font_command(const char *command, const char *arg,
+ const char *filename, int lineno);
+ static lj4_font *load_lj4_font(const char *);
+ int weight;
+ int style;
+ int proportional;
+ int typeface;
+private:
+ lj4_font(const char *);
+};
+
+lj4_font::lj4_font(const char *nm)
+: font(nm), weight(0), style(0), proportional(0), typeface(0)
+{
+}
+
+lj4_font::~lj4_font()
+{
+}
+
+lj4_font *lj4_font::load_lj4_font(const char *s)
+{
+ lj4_font *f = new lj4_font(s);
+ if (!f->load()) {
+ delete f;
+ return 0;
+ }
+ return f;
+}
+
+static struct {
+ const char *s;
+ int lj4_font::*ptr;
+ int min;
+ int max;
+} command_table[] = {
+ { "pclweight", &lj4_font::weight, -7, 7 },
+ { "pclstyle", &lj4_font::style, 0, 32767 },
+ { "pclproportional", &lj4_font::proportional, 0, 1 },
+ { "pcltypeface", &lj4_font::typeface, 0, 65535 },
+};
+
+void lj4_font::handle_unknown_font_command(const char *command,
+ const char *arg,
+ const char *filename, int lineno)
+{
+ for (int i = 0; i < sizeof(command_table)/sizeof(command_table[0]); i++) {
+ if (strcmp(command, command_table[i].s) == 0) {
+ if (arg == 0)
+ fatal_with_file_and_line(filename, lineno,
+ "`%1' command requires an argument",
+ command);
+ char *ptr;
+ long n = strtol(arg, &ptr, 10);
+ if (n == 0 && ptr == arg)
+ fatal_with_file_and_line(filename, lineno,
+ "`%1' command requires numeric argument",
+ command);
+ if (n < command_table[i].min) {
+ error_with_file_and_line(filename, lineno,
+ "argument for `%1' command must not be less than %2",
+ command, command_table[i].min);
+ n = command_table[i].min;
+ }
+ else if (n > command_table[i].max) {
+ error_with_file_and_line(filename, lineno,
+ "argument for `%1' command must not be greater than %2",
+ command, command_table[i].max);
+ n = command_table[i].max;
+ }
+ this->*command_table[i].ptr = int(n);
+ break;
+ }
+ }
+}
+
+class lj4_printer : public printer {
+public:
+ lj4_printer();
+ ~lj4_printer();
+ void set_char(int, font *, const environment *, int, const char *name);
+ void draw(int code, int *p, int np, const environment *env);
+ void begin_page(int);
+ void end_page(int page_length);
+ font *make_font(const char *);
+ void end_of_line();
+private:
+ void set_line_thickness(int size, int dot = 0);
+ void hpgl_init();
+ void hpgl_start();
+ void hpgl_end();
+ int moveto(int hpos, int vpos);
+ int moveto1(int hpos, int vpos);
+
+ int cur_hpos;
+ int cur_vpos;
+ lj4_font *cur_font;
+ int cur_size;
+ unsigned short cur_symbol_set;
+ int x_offset;
+ int line_thickness;
+ double pen_width;
+ double hpgl_scale;
+ int hpgl_inited;
+};
+
+inline
+int lj4_printer::moveto(int hpos, int vpos)
+{
+ if (cur_hpos != hpos || cur_vpos != vpos || cur_hpos < 0)
+ return moveto1(hpos, vpos);
+ else
+ return 1;
+}
+
+inline
+void lj4_printer::hpgl_start()
+{
+ fputs("\033%1B", stdout);
+}
+
+inline
+void lj4_printer::hpgl_end()
+{
+ fputs(";\033%0A", stdout);
+}
+
+lj4_printer::lj4_printer()
+: cur_hpos(-1),
+ cur_font(0),
+ cur_size(0),
+ cur_symbol_set(0),
+ line_thickness(-1),
+ pen_width(-1.0),
+ hpgl_inited(0)
+{
+ if (7200 % font::res != 0)
+ fatal("invalid resolution %1: resolution must be a factor of 7200",
+ font::res);
+ fputs("\033E", stdout); // reset
+ if (font::res != 300)
+ printf("\033&u%dD", font::res); // unit of measure
+ if (ncopies > 0)
+ printf("\033&l%uX", ncopies);
+ if (paper_size < 0)
+ paper_size = 0; // default to letter
+ printf("\033&l%dA" // paper size
+ "\033&l%dO" // orientation
+ "\033&l0E", // no top margin
+ paper_table[paper_size].code,
+ landscape_flag != 0);
+ if (landscape_flag)
+ x_offset = paper_table[paper_size].x_offset_landscape;
+ else
+ x_offset = paper_table[paper_size].x_offset_portrait;
+ x_offset = (x_offset * font::res) / 300;
+ if (duplex_flag)
+ printf("\033&l%dS", duplex_flag);
+}
+
+lj4_printer::~lj4_printer()
+{
+ fputs("\033E", stdout);
+}
+
+void lj4_printer::begin_page(int)
+{
+}
+
+void lj4_printer::end_page(int)
+{
+ putchar('\f');
+ cur_hpos = -1;
+}
+
+void lj4_printer::end_of_line()
+{
+ cur_hpos = -1; // force absolute motion
+}
+
+inline
+int is_unprintable(unsigned char c)
+{
+ return c < 32 && (c == 0 || (7 <= c && c <= 15) || c == 27);
+}
+
+void lj4_printer::set_char(int index, font *f, const environment *env, int w, const char *name)
+{
+ int code = f->get_code(index);
+
+ unsigned char ch = code & 0xff;
+ unsigned short symbol_set = code >> 8;
+ if (symbol_set != cur_symbol_set) {
+ printf("\033(%d%c", symbol_set/32, (symbol_set & 31) + 64);
+ cur_symbol_set = symbol_set;
+ }
+ if (f != cur_font) {
+ lj4_font *psf = (lj4_font *)f;
+ // FIXME only output those that are needed
+ printf("\033(s%dp%ds%db%dT",
+ psf->proportional,
+ psf->style,
+ psf->weight,
+ psf->typeface);
+ if (!psf->proportional || !cur_font || !cur_font->proportional)
+ cur_size = 0;
+ cur_font = psf;
+ }
+ if (env->size != cur_size) {
+ if (cur_font->proportional) {
+ static const char *quarters[] = { "", ".25", ".5", ".75" };
+ printf("\033(s%d%sV", env->size/4, quarters[env->size & 3]);
+ }
+ else {
+ double pitch = double(font::res)/w;
+ // PCL uses the next largest pitch, so round it down.
+ pitch = floor(pitch*100.0)/100.0;
+ printf("\033(s%.2fH", pitch);
+ }
+ cur_size = env->size;
+ }
+ if (!moveto(env->hpos, env->vpos))
+ return;
+ if (is_unprintable(ch))
+ fputs("\033&p1X", stdout);
+ putchar(ch);
+ cur_hpos += w;
+}
+
+int lj4_printer::moveto1(int hpos, int vpos)
+{
+ if (hpos < x_offset || vpos < 0)
+ return 0;
+ fputs("\033*p", stdout);
+ if (cur_hpos < 0)
+ printf("%dx%dY", hpos - x_offset, vpos);
+ else {
+ if (cur_hpos != hpos)
+ printf("%s%d%c", hpos > cur_hpos ? "+" : "",
+ hpos - cur_hpos, vpos == cur_vpos ? 'X' : 'x');
+ if (cur_vpos != vpos)
+ printf("%s%dY", vpos > cur_vpos ? "+" : "", vpos - cur_vpos);
+ }
+ cur_hpos = hpos;
+ cur_vpos = vpos;
+ return 1;
+}
+
+void lj4_printer::draw(int code, int *p, int np, const environment *env)
+{
+ switch (code) {
+ case 'R':
+ {
+ if (np != 2) {
+ error("2 arguments required for rule");
+ break;
+ }
+ int hpos = env->hpos;
+ int vpos = env->vpos;
+ int hsize = p[0];
+ int vsize = p[1];
+ if (hsize < 0) {
+ hpos += hsize;
+ hsize = -hsize;
+ }
+ if (vsize < 0) {
+ vpos += vsize;
+ vsize = -vsize;
+ }
+ if (!moveto(hpos, vpos))
+ return;
+ printf("\033*c%da%db0P", hsize, vsize);
+ break;
+ }
+ case 'l':
+ if (np != 2) {
+ error("2 arguments required for line");
+ break;
+ }
+ hpgl_init();
+ if (!moveto(env->hpos, env->vpos))
+ return;
+ hpgl_start();
+ set_line_thickness(env->size, p[0] == 0 && p[1] == 0);
+ printf("PD%d,%d", p[0], p[1]);
+ hpgl_end();
+ break;
+ case 'p':
+ case 'P':
+ {
+ if (np & 1) {
+ error("even number of arguments required for polygon");
+ break;
+ }
+ if (np == 0) {
+ error("no arguments for polygon");
+ break;
+ }
+ hpgl_init();
+ if (!moveto(env->hpos, env->vpos))
+ return;
+ hpgl_start();
+ if (code == 'p')
+ set_line_thickness(env->size);
+ printf("PMPD%d", p[0]);
+ for (int i = 1; i < np; i++)
+ printf(",%d", p[i]);
+ printf("PM2%cP", code == 'p' ? 'E' : 'F');
+ hpgl_end();
+ break;
+ }
+ case '~':
+ {
+ if (np & 1) {
+ error("even number of arguments required for spline");
+ break;
+ }
+ if (np == 0) {
+ error("no arguments for spline");
+ break;
+ }
+ hpgl_init();
+ if (!moveto(env->hpos, env->vpos))
+ return;
+ hpgl_start();
+ set_line_thickness(env->size);
+ printf("PD%d,%d", p[0]/2, p[1]/2);
+ const int tnum = 2;
+ const int tden = 3;
+ if (np > 2) {
+ fputs("BR", stdout);
+ for (int i = 0; i < np - 2; i += 2) {
+ if (i != 0)
+ putchar(',');
+ printf("%d,%d,%d,%d,%d,%d",
+ (p[i]*tnum)/(2*tden),
+ (p[i + 1]*tnum)/(2*tden),
+ p[i]/2 + (p[i + 2]*(tden - tnum))/(2*tden),
+ p[i + 1]/2 + (p[i + 3]*(tden - tnum))/(2*tden),
+ (p[i] - p[i]/2) + p[i + 2]/2,
+ (p[i + 1] - p[i + 1]/2) + p[i + 3]/2);
+ }
+ }
+ printf("PR%d,%d", p[np - 2] - p[np - 2]/2, p[np - 1] - p[np - 1]/2);
+ hpgl_end();
+ break;
+ }
+ case 'c':
+ case 'C':
+ // troff adds an extra argument to C
+ if (np != 1 && !(code == 'C' && np == 2)) {
+ error("1 argument required for circle");
+ break;
+ }
+ hpgl_init();
+ if (!moveto(env->hpos + p[0]/2, env->vpos))
+ return;
+ hpgl_start();
+ if (code == 'c') {
+ set_line_thickness(env->size);
+ printf("CI%d", p[0]/2);
+ }
+ else
+ printf("WG%d,0,360", p[0]/2);
+ hpgl_end();
+ break;
+ case 'e':
+ case 'E':
+ if (np != 2) {
+ error("2 arguments required for ellipse");
+ break;
+ }
+ hpgl_init();
+ if (!moveto(env->hpos + p[0]/2, env->vpos))
+ return;
+ hpgl_start();
+ printf("SC0,%.4f,0,-%.4f,2", hpgl_scale * double(p[0])/p[1], hpgl_scale);
+ if (code == 'e') {
+ set_line_thickness(env->size);
+ printf("CI%d", p[1]/2);
+ }
+ else
+ printf("WG%d,0,360", p[1]/2);
+ printf("SC0,%.4f,0,-%.4f,2", hpgl_scale, hpgl_scale);
+ hpgl_end();
+ break;
+ case 'a':
+ {
+ if (np != 4) {
+ error("4 arguments required for arc");
+ break;
+ }
+ hpgl_init();
+ if (!moveto(env->hpos, env->vpos))
+ return;
+ hpgl_start();
+ set_line_thickness(env->size);
+ double c[2];
+ if (adjust_arc_center(p, c)) {
+ double sweep = ((atan2(p[1] + p[3] - c[1], p[0] + p[2] - c[0])
+ - atan2(-c[1], -c[0]))
+ * 180.0/PI);
+ if (sweep > 0.0)
+ sweep -= 360.0;
+ printf("PDAR%d,%d,%f", int(c[0]), int(c[1]), sweep);
+ }
+ else
+ printf("PD%d,%d", p[0] + p[2], p[1] + p[3]);
+ hpgl_end();
+ }
+ break;
+ case 'f':
+ if (np != 1 && np != 2) {
+ error("1 argument required for fill");
+ break;
+ }
+ hpgl_init();
+ hpgl_start();
+ if (p[0] >= 0 && p[0] <= 1000)
+ printf("FT10,%d", p[0]/10);
+ hpgl_end();
+ break;
+ case 't':
+ {
+ if (np == 0) {
+ line_thickness = -1;
+ }
+ else {
+ // troff gratuitously adds an extra 0
+ if (np != 1 && np != 2) {
+ error("0 or 1 argument required for thickness");
+ break;
+ }
+ line_thickness = p[0];
+ }
+ break;
+ }
+ default:
+ error("unrecognised drawing command `%1'", char(code));
+ break;
+ }
+}
+
+void lj4_printer::hpgl_init()
+{
+ if (hpgl_inited)
+ return;
+ hpgl_inited = 1;
+ hpgl_scale = double(DEFAULT_HPGL_UNITS)/font::res;
+ printf("\033&f0S" // push position
+ "\033*p0x0Y" // move to 0,0
+ "\033*c%dx%dy0T" // establish picture frame
+ "\033%%1B" // switch to HPGL
+ "SP1SC0,%.4f,0,-%.4f,2IR0,100,0,100" // set up scaling
+ "LA1,4,2,4" // round line ends and joins
+ "PR" // relative plotting
+ "TR0" // opaque
+ ";\033%%1A" // back to PCL
+ "\033&f1S", // pop position
+ MAX_PAPER_WIDTH, MAX_PAPER_HEIGHT,
+ hpgl_scale, hpgl_scale);
+}
+
+void lj4_printer::set_line_thickness(int size, int dot)
+{
+ double pw;
+ if (line_thickness < 0)
+ pw = (size * (line_width_factor * 25.4))/(font::sizescale * 72000.0);
+ else
+ pw = line_thickness*25.4/font::res;
+ if (dot && pw < MIN_DOT_PEN_WIDTH)
+ pw = MIN_DOT_PEN_WIDTH;
+ if (pw != pen_width) {
+ printf("PW%f", pw);
+ pen_width = pw;
+ }
+}
+
+font *lj4_printer::make_font(const char *nm)
+{
+ return lj4_font::load_lj4_font(nm);
+}
+
+printer *make_printer()
+{
+ return new lj4_printer;
+}
+
+static
+int lookup_paper_size(const char *s)
+{
+ for (int i = 0; i < sizeof(paper_table)/sizeof(paper_table[0]); i++) {
+ // FIXME Perhaps allow unique prefix.
+ if (strcasecmp(s, paper_table[i].name) == 0)
+ return i;
+ }
+ return -1;
+}
+
+static
+void handle_unknown_desc_command(const char *command, const char *arg,
+ const char *filename, int lineno)
+{
+ if (strcmp(command, "papersize") == 0) {
+ if (arg == 0)
+ error_with_file_and_line(filename, lineno,
+ "`papersize' command requires an argument");
+ else if (paper_size < 0) {
+ int n = lookup_paper_size(arg);
+ if (n < 0)
+ error_with_file_and_line(filename, lineno,
+ "unknown paper size `%1'", arg);
+ else
+ paper_size = n;
+ }
+ }
+}
+
+static void usage();
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ font::set_unknown_desc_command_handler(handle_unknown_desc_command);
+ int c;
+ extern int optopt, optind;
+ while ((c = getopt(argc, argv, ":F:p:d:lvw:c:")) != EOF)
+ switch(c) {
+ case 'l':
+ landscape_flag = 1;
+ break;
+ case ':':
+ if (optopt == 'd') {
+ fprintf(stderr, "duplex assumed to be long-side\n");
+ duplex_flag = 1;
+ } else
+ fprintf(stderr, "option -%c requires an operand\n", optopt);
+ fflush(stderr);
+ break;
+ case 'd':
+ if (!isdigit(*optarg)) // this ugly hack prevents -d without
+ optind--; // args from messing up the arg list
+ duplex_flag = atoi(optarg);
+ if (duplex_flag != 1 && duplex_flag != 2) {
+ fprintf(stderr, "odd value for duplex; assumed to be long-side\n");
+ duplex_flag = 1;
+ }
+ break;
+ case 'p':
+ {
+ int n = lookup_paper_size(optarg);
+ if (n < 0)
+ error("unknown paper size `%1'", optarg);
+ else
+ paper_size = n;
+ break;
+ }
+ case 'v':
+ {
+ extern const char *Version_string;
+ fprintf(stderr, "grolj4 version %s\n", Version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'F':
+ font::command_line_font_dir(optarg);
+ break;
+ case 'c':
+ {
+ char *ptr;
+ long n = strtol(optarg, &ptr, 10);
+ if (n == 0 && ptr == optarg)
+ error("argument for -c must be a positive integer");
+ else if (n <= 0 || n > 32767)
+ error("out of range argument for -c");
+ else
+ ncopies = unsigned(n);
+ break;
+ }
+ case 'w':
+ {
+ char *ptr;
+ long n = strtol(optarg, &ptr, 10);
+ if (n == 0 && ptr == optarg)
+ error("argument for -w must be a non-negative integer");
+ else if (n < 0 || n > INT_MAX)
+ error("out of range argument for -w");
+ else
+ line_width_factor = int(n);
+ break;
+ }
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ }
+ if (optind >= argc)
+ do_file("-");
+ else {
+ for (int i = optind; i < argc; i++)
+ do_file(argv[i]);
+ }
+ delete pr;
+ return 0;
+}
+
+static void usage()
+{
+ fprintf(stderr,
+ "usage: %s [-lv] [-d [n]] [-c n] [-p paper_size]\n"
+ " [-w n] [-F dir] [files ...]\n",
+ program_name);
+ exit(1);
+}
diff --git a/src/devices/grops/Makefile.sub b/src/devices/grops/Makefile.sub
new file mode 100644
index 00000000..4182527d
--- /dev/null
+++ b/src/devices/grops/Makefile.sub
@@ -0,0 +1,12 @@
+PROG=grops
+MAN1=grops.n
+XLIBS=$(LIBDRIVER) $(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=\
+ ps.o \
+ psrm.o
+CCSRCS=\
+ $(srcdir)/ps.cc \
+ $(srcdir)/psrm.cc
+HDRS=\
+ $(srcdir)/ps.h
diff --git a/src/devices/grops/TODO b/src/devices/grops/TODO
new file mode 100644
index 00000000..da67973a
--- /dev/null
+++ b/src/devices/grops/TODO
@@ -0,0 +1,29 @@
+Read PFB files directly.
+
+Generate %%DocumentMedia comment.
+
+Generate %%For comment.
+
+Generate %%Title comment.
+
+For efficiency it might be better to have the printer interface have
+support for the t and u commands.
+
+Angles in arc command: don't generate more digits after the decimal
+point than are necessary.
+
+Possibly generate BoundingBox comment.
+
+Per font composite character mechanism (sufficient for fractions).
+
+Consider whether we ought to do rounding of graphical objects other
+than lines. What's the point?
+
+Error messages should refer to output page number.
+
+Search for downloadable fonts using their PostScript names if not
+found in download file.
+
+Separate path for searching for downloadable font files.
+
+Clip to the BoundingBox when importing documents.
diff --git a/src/devices/grops/grops.man b/src/devices/grops/grops.man
new file mode 100644
index 00000000..9213c74e
--- /dev/null
+++ b/src/devices/grops/grops.man
@@ -0,0 +1,835 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.TH GROPS @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+grops \- PostScript driver for groff
+.SH SYNOPSIS
+.B grops
+[
+.B \-glmv
+] [
+.BI \-b n
+] [
+.BI \-c n
+] [
+.BI \-w n
+] [
+.BI \-F dir
+] [
+.IR files \|.\|.\|.
+]
+.SH DESCRIPTION
+.B grops
+translates the output of GNU
+.B troff
+to PostScript.
+Normally
+.B grops
+should be invoked by using the groff command
+with a
+.B \-Tps
+option.
+.if '@DEVICE@'ps' (Actually, this is the default for groff.)
+If no files are given,
+.B grops
+will read the standard input.
+A filename of
+.B \-
+will also cause
+.B grops
+to read the standard input.
+PostScript output is written to the standard output.
+When
+.B grops
+is run by
+.B groff
+options can be passed to
+.B grops
+using the
+.B groff
+.B \-P
+option.
+.SH OPTIONS
+.TP
+.BI \-b n
+Workaround broken spoolers and previewers.
+Normally
+.B grops
+produces output that conforms
+the Document Structuring Conventions version 3.0.
+Unfortunately some spoolers and previewers can't handle such output.
+The value of
+.I n
+controls what
+.B grops
+does to its output acceptable to such programs.
+A value of 0 will cause grops not to employ any workarounds.
+Add 1 if no
+.B %%BeginDocumentSetup
+and
+.B %%EndDocumentSetup
+comments should be generated;
+this is needed for early versions of TranScript that get confused by
+anything between the
+.B %%EndProlog
+comment and the first
+.B %%Page
+comment.
+Add 2 if lines in included files beginning with
+.B %!
+should be stripped out; this is needed for Sun's pageview previewer.
+Add 4 if
+.BR %%Page ,
+.BR %%Trailer
+and
+.B %%EndProlog
+comments should be
+stripped out of included files; this is needed for spoolers that
+don't understand the
+.B %%BeginDocument
+and
+.B %%EndDocument
+comments.
+Add 8 if the first line of the PostScript output should be
+.B %!PS-Adobe-2.0
+rather than
+.BR %!PS-Adobe-3.0 ;
+this is needed when using Sun's Newsprint with a printer that requires
+page reversal.
+The default value can be specified by a
+.RS
+.IP
+.BI broken\ n
+.LP
+command in the DESC file.
+Otherwise the default value is 0.
+.RE
+.TP
+.BI \-c n
+Print
+.I n
+copies of each page.
+.TP
+.BI \-g
+Guess the page length.
+This generates PostScript code that guesses the page length.
+The guess will be correct only if the imageable area is vertically
+centered on the page.
+This option allows you to generate documents that can be printed
+both on letter (8.5\(mu11) paper and on A4 paper without change.
+.TP
+.B \-l
+Print the document in landscape format.
+.TP
+.B \-m
+Turn manual feed on for the document.
+.TP
+.BI \-F dir
+Search the directory
+.IB dir /dev name
+for font and device description files;
+.I name
+is the name of the device, usually
+.BR ps .
+.TP
+.BI \-w n
+Lines should be drawn using a thickness of
+.I n
+thousandths of an em.
+.TP
+.B \-v
+Print the version number.
+.SH USAGE
+There are styles called
+.BR R ,
+.BR I ,
+.BR B ,
+and
+.B BI
+mounted at font positions 1 to 4.
+The fonts are grouped into families
+.BR A ,
+.BR BM ,
+.BR C ,
+.BR H ,
+.BR HN ,
+.BR N ,
+.B P
+and
+.B T
+having members in each of these styles:
+.de FT
+.if '\\*(.T'ps' .ft \\$1
+..
+.TP
+.B AR
+.FT AR
+AvantGarde-Book
+.FT
+.TP
+.B AI
+.FT AI
+AvantGarde-BookOblique
+.FT
+.TP
+.B AB
+.FT AB
+AvantGarde-Demi
+.FT
+.TP
+.B ABI
+.FT ABI
+AvantGarde-DemiOblique
+.FT
+.TP
+.B BMR
+.FT BMR
+Bookman-Light
+.FT
+.TP
+.B BMI
+.FT BMI
+Bookman-LightItalic
+.FT
+.TP
+.B BMB
+.FT BMB
+Bookman-Demi
+.FT
+.TP
+.B BMBI
+.FT BMBI
+Bookman-DemiItalic
+.FT
+.TP
+.B CR
+.FT CR
+Courier
+.FT
+.TP
+.B CI
+.FT CI
+Courier-Oblique
+.FT
+.TP
+.B CB
+.FT CB
+Courier-Bold
+.FT
+.TP
+.B CBI
+.FT CBI
+Courier-BoldOblique
+.FT
+.TP
+.B HR
+.FT HR
+Helvetica
+.FT
+.TP
+.B HI
+.FT HI
+Helvetica-Oblique
+.FT
+.TP
+.B HB
+.FT HB
+Helvetica-Bold
+.FT
+.TP
+.B HBI
+.FT HBI
+Helvetica-BoldOblique
+.FT
+.TP
+.B HNR
+.FT HNR
+Helvetica-Narrow
+.FT
+.TP
+.B HNI
+.FT HNI
+Helvetica-Narrow-Oblique
+.FT
+.TP
+.B HNB
+.FT HNB
+Helvetica-Narrow-Bold
+.FT
+.TP
+.B HNBI
+.FT HNBI
+Helvetica-Narrow-BoldOblique
+.FT
+.TP
+.B NR
+.FT NR
+NewCenturySchlbk-Roman
+.FT
+.TP
+.B NI
+.FT NI
+NewCenturySchlbk-Italic
+.FT
+.TP
+.B NB
+.FT NB
+NewCenturySchlbk-Bold
+.FT
+.TP
+.B NBI
+.FT NBI
+NewCenturySchlbk-BoldItalic
+.FT
+.TP
+.B PR
+.FT PR
+Palatino-Roman
+.FT
+.TP
+.B PI
+.FT PI
+Palatino-Italic
+.FT
+.TP
+.B PB
+.FT PB
+Palatino-Bold
+.FT
+.TP
+.B PBI
+.FT PBI
+Palatino-BoldItalic
+.FT
+.TP
+.B TR
+.FT TR
+Times-Roman
+.FT
+.TP
+.B TI
+.FT TI
+Times-Italic
+.FT
+.TP
+.B TB
+.FT TB
+Times-Bold
+.FT
+.TP
+.B TBI
+.FT TBI
+Times-BoldItalic
+.FT
+.LP
+There is also the following font which is not a member of a family:
+.TP
+.B ZCMI
+.FT ZCMI
+ZapfChancery-MediumItalic
+.FT
+.LP
+There are also some special fonts called
+.B SS
+and
+.BR S .
+Zapf Dingbats is available as
+.BR ZD
+and a reversed version of ZapfDingbats (with symbols pointing in the opposite
+direction) is available as
+.BR ZDR ;
+most characters in these fonts are unnamed and must be accessed using
+.BR \eN .
+.LP
+.B grops
+understands various X commands produced using the
+.B \eX
+escape sequence;
+.B grops
+will only interpret commands that begin with a
+.B ps:
+tag.
+.TP
+.BI \eX'ps:\ exec\ code '
+This executes the arbitrary PostScript commands in
+.IR code .
+The PostScript currentpoint will be set to the position of the
+.B \eX
+command before executing
+.IR code .
+The origin will be at the top left corner of the page,
+and y coordinates will increase down the page.
+A procedure
+.B u
+will be defined that converts groff units
+to the coordinate system in effect.
+For example,
+.RS
+.IP
+.B
+\&.nr x 1i
+.br
+.B
+\eX'ps: exec \enx u 0 rlineto stroke'
+.br
+.RE
+.IP
+will draw a horizontal line one inch long.
+.I code
+may make changes to the graphics state,
+but any changes will persist only to the
+end of the page.
+A dictionary containing the definitions specified by the
+.B def
+and
+.B mdef
+will be on top of the dictionary stack.
+If your code adds definitions to this dictionary,
+you should allocate space for them using
+.BI \eX'ps\ mdef \ n '\fR.
+Any definitions will persist only until the end of the page.
+If you use the
+.B \eY
+escape sequence with an argument that names a macro,
+.I code
+can extend over multiple lines.
+For example,
+.RS
+.IP
+.nf
+.ft B
+\&.nr x 1i
+\&.de y
+\&ps: exec
+\&\enx u 0 rlineto
+\&stroke
+\&..
+\&\eYy
+.fi
+.ft R
+.LP
+is another way to draw a horizontal line one inch long.
+.RE
+.TP
+.BI \eX'ps:\ file\ name '
+This is the same as the
+.B exec
+command except that the PostScript code is read from file
+.IR name .
+.TP
+.BI \eX'ps:\ def\ code '
+Place a PostScript definition contained in
+.I code
+in the prologue.
+There should be at most one definition per
+.B \eX
+command.
+Long definitions can be split over several
+.B \eX
+commands;
+all the
+.I code
+arguments are simply joined together separated by newlines.
+The definitions are placed in a dictionary which is automatically
+pushed on the dictionary stack when an
+.B exec
+command is executed.
+If you use the
+.B \eY
+escape sequence with an argument that names a macro,
+.I code
+can extend over multiple lines.
+.TP
+.BI \eX'ps:\ mdef\ n\ code '
+Like
+.BR def ,
+except that
+.I code
+may contain up to
+.I n
+definitions.
+.B grops
+needs to know how many definitions
+.I code
+contains
+so that it can create an appropriately sized PostScript dictionary
+to contain them.
+.TP
+.BI \eX'ps:\ import\ file\ llx\ lly\ urx\ ury\ width\ \fR[\fP\ height\ \fR]\fP '
+Import a PostScript graphic from
+.IR file .
+The arguments
+.IR llx ,
+.IR lly ,
+.IR urx ,
+and
+.I ury
+give the bounding box of the graphic in the default PostScript
+coordinate system; they should all be integers;
+.I llx
+and
+.I lly
+are the x and y coordinates of the lower left
+corner of the graphic;
+.I urx
+and
+.I ury
+are the x and y coordinates of the upper right corner of the graphic;
+.I width
+and
+.I height
+are integers that give the desired width and height in groff
+units of the graphic.
+The graphic will be scaled so that it has this width and height
+and translated so that the lower left corner of the graphic is
+located at the position associated with
+.B \eX
+command.
+If the height argument is omitted it will be scaled uniformly in the
+x and y directions so that it has the specified width.
+Note that the contents of the
+.B \eX
+command are not interpreted by
+.BR troff ;
+so vertical space for the graphic is not automatically added,
+and the
+.I width
+and
+.I height
+arguments are not allowed to have attached scaling indicators.
+If the PostScript file complies with the Adobe Document Structuring
+Conventions and contains a
+.B %%BoundingBox
+comment, then the bounding box can be automatically
+extracted from within groff by using the
+.B psbb
+request.
+.RS
+.LP
+The
+.B \-mps
+macros (which are automatically loaded when
+.B grops
+is run by the groff command) include a
+.B PSPIC
+macro which allows a picture to be easily imported.
+This has the format
+.IP
+\&\fB.PSPIC\fP [ \fB\-L\fP | \fB-R\fP | \fB\-I\fP \fIn\fP ]\ \"
+\fI\|file\fP [ \fIwidth\fP [ \fIheight\fP ]]
+.LP
+.I file
+is the name of the file containing the illustration;
+.I width
+and
+.I height
+give the desired width and height of the graphic.
+The
+.I width
+and
+.I height
+arguments may have scaling indicators attached;
+the default scaling indicator is
+.BR i .
+This macro will scale the graphic uniformly
+in the x and y directions so that it is no more than
+.I width
+wide
+and
+.I height
+high.
+By default, the graphic will be horizontally centered.
+The
+.BI \-L
+and
+.BI \-R
+cause the graphic to be left-aligned and right-aligned
+respectively.
+The
+.B \-I
+option causes the graphic to be indented by
+.IR n .
+.RE
+.TP
+.B \eX'ps:\ invis'
+.br
+.ns
+.TP
+.B \eX'ps:\ endinvis'
+No output will be generated for text and drawing commands
+that are bracketed with these
+.B \eX
+commands.
+These commands are intended for use when output from
+.B troff
+will be previewed before being processed with
+.BR grops ;
+if the previewer is unable to display certain characters
+or other constructs, then other substitute characters or constructs
+can be used for previewing by bracketing them with these
+.B \eX
+commands.
+.RS
+.LP
+For example,
+.B gxditview
+is not able to display a proper
+.B \e(em
+character because the standard X11 fonts do not provide it;
+this problem can be overcome by executing the following
+request
+.IP
+.ft B
+.nf
+\&.char \e(em \eX'ps: invis'\e
+\eZ'\ev'-.25m'\eh'.05m'\eD'l .9m 0'\eh'.05m''\e
+\eX'ps: endinvis'\e(em
+.ft
+.fi
+.LP
+In this case,
+.B gxditview
+will be unable to display the
+.B \e(em
+character and will draw the line,
+whereas
+.B grops
+will print the
+.B \e(em
+character
+and ignore the line.
+.RE
+.LP
+The input to
+.B grops
+must be in the format output by
+.BR @g@troff (@MAN1EXT@).
+This is described in
+.BR groff_out (@MAN1EXT@).
+In addition the device and font description files for the device used
+must meet certain requirements.
+The device and font description files supplied for
+.B ps
+device meet all these requirements.
+.BR afmtodit (@MAN1EXT@)
+can be used to create font files from AFM files.
+The resolution must be an integer multiple of 72 times the
+.BR sizescale .
+The
+.B ps
+device uses a resolution of 72000 and a sizescale of 1000.
+The device description file should contain a command
+.IP
+.BI paperlength\ n
+.LP
+which says that output should be generated which is suitable for
+printing on a page whose length is
+.I n
+machine units.
+Each font description file must contain a command
+.IP
+.BI internalname\ psname
+.LP
+which says that the PostScript name of the font is
+.IR psname .
+It may also contain a command
+.IP
+.BI encoding\ enc_file
+.LP
+which says that
+the PostScript font should be reencoded using the encoding described in
+.IR enc_file ;
+this file should consist of a sequence of lines of the form:
+.IP
+.I
+pschar code
+.LP
+where
+.I pschar
+is the PostScript name of the character,
+and
+.I code
+is its position in the encoding expressed as a decimal integer.
+The code for each character given in the font file must correspond
+to the code for the character in encoding file, or to the code in the default
+encoding for the font if the PostScript font is not to be reencoded.
+This code can be used with the
+.B \eN
+escape sequence in
+.B troff
+to select the character,
+even if the character does not have a groff name.
+Every character in the font file must exist in the PostScript font, and
+the widths given in the font file must match the widths used
+in the PostScript font.
+.B grops
+will assume that a character with a groff name of
+.B space
+is blank (makes no marks on the page);
+it can make use of such a character to generate more efficient and
+compact PostScript output.
+.LP
+.B grops
+can automatically include the downloadable fonts necessary
+to print the document.
+Any downloadable fonts which should, when required, be included by
+.B grops
+must be listed in the file
+.BR @FONTDIR@/devps/download ;
+this should consist of lines of the form
+.IP
+.I
+font filename
+.LP
+where
+.I font
+is the PostScript name of the font,
+and
+.I filename
+is the name of the file containing the font;
+lines beginning with
+.B #
+and blank lines are ignored;
+fields may be separated by tabs or spaces;
+.I filename
+will be searched for using the same mechanism that is used
+for groff font metric files.
+The
+.B download
+file itself will also be searched for using this mechanism.
+.LP
+If the file containing a downloadable font or imported document
+conforms to the Adobe Document Structuring Conventions,
+then
+.B grops
+will interpret any comments in the files sufficiently to ensure that its
+own output is conforming.
+It will also supply any needed font resources that are listed in the
+.B download
+file
+as well as any needed file resources.
+It is also able to handle inter-resource dependencies.
+For example, suppose that you have a downloadable font called Garamond,
+and also a downloadable font called Garamond-Outline
+which depends on Garamond
+(typically it would be defined to copy Garamond's font dictionary,
+and change the PaintType),
+then it is necessary for Garamond to be appear before Garamond-Outline
+in the PostScript document.
+.B grops
+will handle this automatically
+provided that the downloadable font file for Garamond-Outline
+indicates its dependence on Garamond by means of
+the Document Structuring Conventions,
+for example by beginning with the following lines
+.IP
+.B
+%!PS-Adobe-3.0 Resource-Font
+.br
+.B
+%%DocumentNeededResources: font Garamond
+.br
+.B
+%%EndComments
+.br
+.B
+%%IncludeResource: font Garamond
+.LP
+In this case both Garamond and Garamond-Outline would need to be listed
+in the
+.B download
+file.
+A downloadable font should not include its own name in a
+.B %%DocumentSuppliedResources
+comment.
+.LP
+.B grops
+will not interpret
+.B %%DocumentFonts
+comments.
+The
+.BR %%DocumentNeededResources ,
+.BR %%DocumentSuppliedResources ,
+.BR %%IncludeResource ,
+.BR %%BeginResource
+and
+.BR %%EndResource
+comments
+(or possibly the old
+.BR %%DocumentNeededFonts ,
+.BR %%DocumentSuppliedFonts ,
+.BR %%IncludeFont ,
+.BR %%BeginFont
+and
+.BR %%EndFont
+comments)
+should be used.
+.SH FILES
+.Tp \w'\fB@FONTDIR@/devps/download'u+2n
+.B @FONTDIR@/devps/DESC
+Device description file.
+.TP
+.BI @FONTDIR@/devps/ F
+Font description file for font
+.IR F .
+.TP
+.B @FONTDIR@/devps/download
+List of downloadable fonts.
+.TP
+.B @FONTDIR@/devps/text.enc
+Encoding used for text fonts.
+.TP
+.B @MACRODIR@/tmac.ps
+Macros for use with
+.BR grops ;
+automatically loaded by
+.BR troffrc
+.TP
+.B @MACRODIR@/tmac.pspic
+Definition of
+.B PSPIC
+macro,
+automatically loaded by
+.BR tmac.ps .
+.TP
+.B @MACRODIR@/tmac.psold
+Macros to disable use of characters not present in older
+PostScript printers; automatically loaded by
+.BR tmac.ps .
+.TP
+.B @MACRODIR@/tmac.psnew
+Macros to undo the effect of
+.BR tmac.psold .
+.TP
+.BI /tmp/grops XXXXXX
+Temporary file.
+.SH "SEE ALSO"
+.BR afmtodit (@MAN1EXT@),
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@),
+.BR psbb (@MAN1EXT@),
+.BR groff_out (@MAN5EXT@),
+.BR groff_font (@MAN5EXT@),
+.BR groff_char (@MAN7EXT@)
diff --git a/src/devices/grops/ps.cc b/src/devices/grops/ps.cc
new file mode 100644
index 00000000..0134c823
--- /dev/null
+++ b/src/devices/grops/ps.cc
@@ -0,0 +1,1532 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "driver.h"
+#include "stringclass.h"
+#include "cset.h"
+
+#include "ps.h"
+#include <time.h>
+
+static int landscape_flag = 0;
+static int manual_feed_flag = 0;
+static int ncopies = 1;
+static int linewidth = -1;
+// Non-zero means generate PostScript code that guesses the paper
+// length using the imageable area.
+static int guess_flag = 0;
+
+// Non-zero if -b was specified on the command line.
+static int bflag = 0;
+unsigned broken_flags = 0;
+
+#define DEFAULT_LINEWIDTH 40 /* in ems/1000 */
+#define MAX_LINE_LENGTH 72
+#define FILL_MAX 1000
+
+const char *const dict_name = "grops";
+const char *const defs_dict_name = "DEFS";
+const int DEFS_DICT_SPARE = 50;
+
+double degrees(double r)
+{
+ return r*180.0/PI;
+}
+
+double radians(double d)
+{
+ return d*PI/180.0;
+}
+
+inline double transform_fill(int fill)
+{
+ return 1 - fill/double(FILL_MAX);
+}
+
+// This is used for testing whether a character should be output in the
+// PostScript file using \nnn, so we really want the character to be
+// less than 0200.
+
+inline int is_ascii(char c)
+{
+ return (unsigned char)c < 0200;
+}
+
+ps_output::ps_output(FILE *f, int n)
+: fp(f), col(0), max_line_length(n), need_space(0), fixed_point(0)
+{
+}
+
+ps_output &ps_output::set_file(FILE *f)
+{
+ fp = f;
+ col = 0;
+ return *this;
+}
+
+ps_output &ps_output::copy_file(FILE *infp)
+{
+ int c;
+ while ((c = getc(infp)) != EOF)
+ putc(c, fp);
+ return *this;
+}
+
+ps_output &ps_output::end_line()
+{
+ if (col != 0) {
+ putc('\n', fp);
+ col = 0;
+ need_space = 0;
+ }
+ return *this;
+}
+
+ps_output &ps_output::special(const char *s)
+{
+ if (s == 0 || *s == '\0')
+ return *this;
+ if (col != 0) {
+ putc('\n', fp);
+ col = 0;
+ }
+ fputs(s, fp);
+ if (strchr(s, '\0')[-1] != '\n')
+ putc('\n', fp);
+ need_space = 0;
+ return *this;
+}
+
+ps_output &ps_output::simple_comment(const char *s)
+{
+ if (col != 0)
+ putc('\n', fp);
+ putc('%', fp);
+ putc('%', fp);
+ fputs(s, fp);
+ putc('\n', fp);
+ col = 0;
+ need_space = 0;
+ return *this;
+}
+
+ps_output &ps_output::begin_comment(const char *s)
+{
+ if (col != 0)
+ putc('\n', fp);
+ putc('%', fp);
+ putc('%', fp);
+ fputs(s, fp);
+ col = 2 + strlen(s);
+ return *this;
+}
+
+ps_output &ps_output::end_comment()
+{
+ if (col != 0) {
+ putc('\n', fp);
+ col = 0;
+ }
+ need_space = 0;
+ return *this;
+}
+
+ps_output &ps_output::comment_arg(const char *s)
+{
+ int len = strlen(s);
+ if (col + len + 1 > max_line_length) {
+ putc('\n', fp);
+ fputs("%%+", fp);
+ col = 3;
+ }
+ putc(' ', fp);
+ fputs(s, fp);
+ col += len + 1;
+ return *this;
+}
+
+ps_output &ps_output::set_fixed_point(int n)
+{
+ assert(n >= 0 && n <= 10);
+ fixed_point = n;
+ return *this;
+}
+
+ps_output &ps_output::put_delimiter(char c)
+{
+ if (col + 1 > max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ }
+ putc(c, fp);
+ col++;
+ need_space = 0;
+ return *this;
+}
+
+ps_output &ps_output::put_string(const char *s, int n)
+{
+ int len = 0;
+ int i;
+ for (i = 0; i < n; i++) {
+ char c = s[i];
+ if (is_ascii(c) && csprint(c)) {
+ if (c == '(' || c == ')' || c == '\\')
+ len += 2;
+ else
+ len += 1;
+ }
+ else
+ len += 4;
+ }
+ if (len > n*2) {
+ if (col + n*2 + 2 > max_line_length && n*2 + 2 <= max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ }
+ if (col + 1 > max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ }
+ putc('<', fp);
+ col++;
+ for (i = 0; i < n; i++) {
+ if (col + 2 > max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ }
+ fprintf(fp, "%02x", s[i] & 0377);
+ col += 2;
+ }
+ putc('>', fp);
+ col++;
+ }
+ else {
+ if (col + len + 2 > max_line_length && len + 2 <= max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ }
+ if (col + 2 > max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ }
+ putc('(', fp);
+ col++;
+ for (i = 0; i < n; i++) {
+ char c = s[i];
+ if (is_ascii(c) && csprint(c)) {
+ if (c == '(' || c == ')' || c == '\\')
+ len = 2;
+ else
+ len = 1;
+ }
+ else
+ len = 4;
+ if (col + len + 1 > max_line_length) {
+ putc('\\', fp);
+ putc('\n', fp);
+ col = 0;
+ }
+ switch (len) {
+ case 1:
+ putc(c, fp);
+ break;
+ case 2:
+ putc('\\', fp);
+ putc(c, fp);
+ break;
+ case 4:
+ fprintf(fp, "\\%03o", c & 0377);
+ break;
+ default:
+ assert(0);
+ }
+ col += len;
+ }
+ putc(')', fp);
+ col++;
+ }
+ need_space = 0;
+ return *this;
+}
+
+ps_output &ps_output::put_number(int n)
+{
+ char buf[1 + INT_DIGITS + 1];
+ sprintf(buf, "%d", n);
+ int len = strlen(buf);
+ if (col > 0 && col + len + need_space > max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ need_space = 0;
+ }
+ if (need_space) {
+ putc(' ', fp);
+ col++;
+ }
+ fputs(buf, fp);
+ col += len;
+ need_space = 1;
+ return *this;
+}
+
+ps_output &ps_output::put_fix_number(int i)
+{
+ const char *p = iftoa(i, fixed_point);
+ int len = strlen(p);
+ if (col > 0 && col + len + need_space > max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ need_space = 0;
+ }
+ if (need_space) {
+ putc(' ', fp);
+ col++;
+ }
+ fputs(p, fp);
+ col += len;
+ need_space = 1;
+ return *this;
+}
+
+ps_output &ps_output::put_float(double d)
+{
+ char buf[128];
+ sprintf(buf, "%.4f", d);
+ int len = strlen(buf);
+ if (col > 0 && col + len + need_space > max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ need_space = 0;
+ }
+ if (need_space) {
+ putc(' ', fp);
+ col++;
+ }
+ fputs(buf, fp);
+ col += len;
+ need_space = 1;
+ return *this;
+}
+
+ps_output &ps_output::put_symbol(const char *s)
+{
+ int len = strlen(s);
+ if (col > 0 && col + len + need_space > max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ need_space = 0;
+ }
+ if (need_space) {
+ putc(' ', fp);
+ col++;
+ }
+ fputs(s, fp);
+ col += len;
+ need_space = 1;
+ return *this;
+}
+
+ps_output &ps_output::put_literal_symbol(const char *s)
+{
+ int len = strlen(s);
+ if (col > 0 && col + len + 1 > max_line_length) {
+ putc('\n', fp);
+ col = 0;
+ }
+ putc('/', fp);
+ fputs(s, fp);
+ col += len + 1;
+ need_space = 1;
+ return *this;
+}
+
+class ps_font : public font {
+ ps_font(const char *);
+public:
+ int encoding_index;
+ char *encoding;
+ char *reencoded_name;
+ ~ps_font();
+ void handle_unknown_font_command(const char *command, const char *arg,
+ const char *filename, int lineno);
+ static ps_font *load_ps_font(const char *);
+};
+
+ps_font *ps_font::load_ps_font(const char *s)
+{
+ ps_font *f = new ps_font(s);
+ if (!f->load()) {
+ delete f;
+ return 0;
+ }
+ return f;
+}
+
+ps_font::ps_font(const char *nm)
+: font(nm), encoding_index(-1), encoding(0), reencoded_name(0)
+{
+}
+
+ps_font::~ps_font()
+{
+ a_delete encoding;
+ a_delete reencoded_name;
+}
+
+void ps_font::handle_unknown_font_command(const char *command, const char *arg,
+ const char *filename, int lineno)
+{
+ if (strcmp(command, "encoding") == 0) {
+ if (arg == 0)
+ error_with_file_and_line(filename, lineno,
+ "`encoding' command requires an argument");
+ else
+ encoding = strsave(arg);
+ }
+}
+
+static void handle_unknown_desc_command(const char *command, const char *arg,
+ const char *filename, int lineno)
+{
+ if (strcmp(command, "broken") == 0) {
+ if (arg == 0)
+ error_with_file_and_line(filename, lineno,
+ "`broken' command requires an argument");
+ else if (!bflag)
+ broken_flags = atoi(arg);
+ }
+}
+
+struct style {
+ font *f;
+ int point_size;
+ int height;
+ int slant;
+ style();
+ style(font *, int, int, int);
+ int operator==(const style &) const;
+ int operator!=(const style &) const;
+};
+
+style::style() : f(0)
+{
+}
+
+style::style(font *p, int sz, int h, int sl)
+: f(p), point_size(sz), height(h), slant(sl)
+{
+}
+
+int style::operator==(const style &s) const
+{
+ return (f == s.f && point_size == s.point_size
+ && height == s.height && slant == s.slant);
+}
+
+int style::operator!=(const style &s) const
+{
+ return !(*this == s);
+}
+
+class ps_printer : public printer {
+ FILE *tempfp;
+ ps_output out;
+ int res;
+ int space_char_index;
+ int pages_output;
+ int paper_length;
+ int equalise_spaces;
+ enum { SBUF_SIZE = 256 };
+ char sbuf[SBUF_SIZE];
+ int sbuf_len;
+ int sbuf_start_hpos;
+ int sbuf_vpos;
+ int sbuf_end_hpos;
+ int sbuf_space_width;
+ int sbuf_space_count;
+ int sbuf_space_diff_count;
+ int sbuf_space_code;
+ int sbuf_kern;
+ style sbuf_style;
+ style output_style;
+ int output_hpos;
+ int output_vpos;
+ int output_draw_point_size;
+ int line_thickness;
+ int output_line_thickness;
+ int fill;
+ unsigned char output_space_code;
+ enum { MAX_DEFINED_STYLES = 50 };
+ style defined_styles[MAX_DEFINED_STYLES];
+ int ndefined_styles;
+ int next_encoding_index;
+ string defs;
+ int ndefs;
+ resource_manager rm;
+ int invis_count;
+
+ void flush_sbuf();
+ void set_style(const style &);
+ void set_space_code(unsigned char c);
+ int set_encoding_index(ps_font *);
+ void do_exec(char *, const environment *);
+ void do_import(char *, const environment *);
+ void do_def(char *, const environment *);
+ void do_mdef(char *, const environment *);
+ void do_file(char *, const environment *);
+ void do_invis(char *, const environment *);
+ void do_endinvis(char *, const environment *);
+ void set_line_thickness(const environment *);
+ void fill_path();
+ void encode_fonts();
+ void define_encoding(const char *, int);
+ void reencode_font(ps_font *);
+public:
+ ps_printer();
+ ~ps_printer();
+ void set_char(int i, font *f, const environment *env, int w, const char *name);
+ void draw(int code, int *p, int np, const environment *env);
+ void begin_page(int);
+ void end_page(int);
+ void special(char *arg, const environment *env);
+ font *make_font(const char *);
+ void end_of_line();
+};
+
+ps_printer::ps_printer()
+: out(0, MAX_LINE_LENGTH),
+ pages_output(0),
+ sbuf_len(0),
+ output_hpos(-1),
+ output_vpos(-1),
+ line_thickness(-1),
+ fill(FILL_MAX + 1),
+ ndefined_styles(0),
+ next_encoding_index(0),
+ ndefs(0),
+ invis_count(0)
+{
+ tempfp = xtmpfile();
+ out.set_file(tempfp);
+ if (linewidth < 0)
+ linewidth = DEFAULT_LINEWIDTH;
+ if (font::hor != 1)
+ fatal("horizontal resolution must be 1");
+ if (font::vert != 1)
+ fatal("vertical resolution must be 1");
+ if (font::res % (font::sizescale*72) != 0)
+ fatal("res must be a multiple of 72*sizescale");
+ int r = font::res;
+ int point = 0;
+ while (r % 10 == 0) {
+ r /= 10;
+ point++;
+ }
+ res = r;
+ out.set_fixed_point(point);
+ space_char_index = font::name_to_index("space");
+ paper_length = font::paperlength;
+ if (paper_length == 0)
+ paper_length = 11*font::res;
+ equalise_spaces = font::res >= 72000;
+}
+
+int ps_printer::set_encoding_index(ps_font *f)
+{
+ if (f->encoding_index >= 0)
+ return f->encoding_index;
+ for (font_pointer_list *p = font_list; p; p = p->next)
+ if (p->p != f) {
+ char *encoding = ((ps_font *)p->p)->encoding;
+ int encoding_index = ((ps_font *)p->p)->encoding_index;
+ if (encoding != 0 && encoding_index >= 0
+ && strcmp(f->encoding, encoding) == 0) {
+ return f->encoding_index = encoding_index;
+ }
+ }
+ return f->encoding_index = next_encoding_index++;
+}
+
+void ps_printer::set_char(int i, font *f, const environment *env, int w, const char *name)
+{
+ if (i == space_char_index || invis_count > 0)
+ return;
+ unsigned char code = f->get_code(i);
+ style sty(f, env->size, env->height, env->slant);
+ if (sty.slant != 0) {
+ if (sty.slant > 80 || sty.slant < -80) {
+ error("silly slant `%1' degrees", sty.slant);
+ sty.slant = 0;
+ }
+ }
+ if (sbuf_len > 0) {
+ if (sbuf_len < SBUF_SIZE
+ && sty == sbuf_style
+ && sbuf_vpos == env->vpos) {
+ if (sbuf_end_hpos == env->hpos) {
+ sbuf[sbuf_len++] = code;
+ sbuf_end_hpos += w + sbuf_kern;
+ return;
+ }
+ if (sbuf_len == 1 && sbuf_kern == 0) {
+ sbuf_kern = env->hpos - sbuf_end_hpos;
+ sbuf_end_hpos = env->hpos + sbuf_kern + w;
+ sbuf[sbuf_len++] = code;
+ return;
+ }
+ /* If sbuf_end_hpos - sbuf_kern == env->hpos, we are better off
+ starting a new string. */
+ if (sbuf_len < SBUF_SIZE - 1 && env->hpos >= sbuf_end_hpos
+ && (sbuf_kern == 0 || sbuf_end_hpos - sbuf_kern != env->hpos)) {
+ if (sbuf_space_code < 0) {
+ if (f->contains(space_char_index)) {
+ sbuf_space_code = f->get_code(space_char_index);
+ sbuf_space_width = env->hpos - sbuf_end_hpos;
+ sbuf_end_hpos = env->hpos + w + sbuf_kern;
+ sbuf[sbuf_len++] = sbuf_space_code;
+ sbuf[sbuf_len++] = code;
+ sbuf_space_count++;
+ return;
+ }
+ }
+ else {
+ int diff = env->hpos - sbuf_end_hpos - sbuf_space_width;
+ if (diff == 0 || (equalise_spaces && (diff == 1 || diff == -1))) {
+ sbuf_end_hpos = env->hpos + w + sbuf_kern;
+ sbuf[sbuf_len++] = sbuf_space_code;
+ sbuf[sbuf_len++] = code;
+ sbuf_space_count++;
+ if (diff == 1)
+ sbuf_space_diff_count++;
+ else if (diff == -1)
+ sbuf_space_diff_count--;
+ return;
+ }
+ }
+ }
+ }
+ flush_sbuf();
+ }
+ sbuf_len = 1;
+ sbuf[0] = code;
+ sbuf_end_hpos = env->hpos + w;
+ sbuf_start_hpos = env->hpos;
+ sbuf_vpos = env->vpos;
+ sbuf_style = sty;
+ sbuf_space_code = -1;
+ sbuf_space_width = 0;
+ sbuf_space_count = sbuf_space_diff_count = 0;
+ sbuf_kern = 0;
+}
+
+static char *make_encoding_name(int encoding_index)
+{
+ static char buf[3 + INT_DIGITS + 1];
+ sprintf(buf, "ENC%d", encoding_index);
+ return buf;
+}
+
+const char *const WS = " \t\n\r";
+
+void ps_printer::define_encoding(const char *encoding, int encoding_index)
+{
+ char *vec[256];
+ int i;
+ for (i = 0; i < 256; i++)
+ vec[i] = 0;
+ char *path;
+ FILE *fp = font::open_file(encoding, &path);
+ if (fp == 0)
+ fatal("can't open encoding file `%1'", encoding);
+ int lineno = 1;
+ char buf[256];
+ while (fgets(buf, 512, fp) != 0) {
+ char *p = buf;
+ while (csspace(*p))
+ p++;
+ if (*p != '#' && *p != '\0' && (p = strtok(buf, WS)) != 0) {
+ char *q = strtok(0, WS);
+ int n;
+ if (q == 0 || sscanf(q, "%d", &n) != 1 || n < 0 || n >= 256)
+ fatal_with_file_and_line(path, lineno, "bad second field");
+ vec[n] = new char[strlen(p) + 1];
+ strcpy(vec[n], p);
+ }
+ lineno++;
+ }
+ a_delete path;
+ out.put_literal_symbol(make_encoding_name(encoding_index));
+ out.put_delimiter('[');
+ for (i = 0; i < 256; i++) {
+ if (vec[i] == 0)
+ out.put_literal_symbol(".notdef");
+ else {
+ out.put_literal_symbol(vec[i]);
+ a_delete vec[i];
+ }
+ }
+ out.put_delimiter(']').put_symbol("def");
+}
+
+void ps_printer::reencode_font(ps_font *f)
+{
+ out.put_literal_symbol(f->reencoded_name)
+ .put_symbol(make_encoding_name(f->encoding_index))
+ .put_literal_symbol(f->get_internal_name())
+ .put_symbol("RE");
+}
+
+void ps_printer::encode_fonts()
+{
+ if (next_encoding_index == 0)
+ return;
+ char *done_encoding = new char[next_encoding_index];
+ for (int i = 0; i < next_encoding_index; i++)
+ done_encoding[i] = 0;
+ for (font_pointer_list *f = font_list; f; f = f->next) {
+ int encoding_index = ((ps_font *)f->p)->encoding_index;
+ if (encoding_index >= 0) {
+ assert(encoding_index < next_encoding_index);
+ if (!done_encoding[encoding_index]) {
+ done_encoding[encoding_index] = 1;
+ define_encoding(((ps_font *)f->p)->encoding, encoding_index);
+ }
+ reencode_font((ps_font *)f->p);
+ }
+ }
+ a_delete done_encoding;
+}
+
+void ps_printer::set_style(const style &sty)
+{
+ char buf[1 + INT_DIGITS + 1];
+ for (int i = 0; i < ndefined_styles; i++)
+ if (sty == defined_styles[i]) {
+ sprintf(buf, "F%d", i);
+ out.put_symbol(buf);
+ return;
+ }
+ if (ndefined_styles >= MAX_DEFINED_STYLES)
+ ndefined_styles = 0;
+ sprintf(buf, "F%d", ndefined_styles);
+ out.put_literal_symbol(buf);
+ const char *psname = sty.f->get_internal_name();
+ if (psname == 0)
+ fatal("no internalname specified for font `%1'", sty.f->get_name());
+ char *encoding = ((ps_font *)sty.f)->encoding;
+ if (encoding != 0) {
+ char *s = ((ps_font *)sty.f)->reencoded_name;
+ if (s == 0) {
+ int ei = set_encoding_index((ps_font *)sty.f);
+ char *tem = new char[strlen(psname) + 1 + INT_DIGITS + 1];
+ sprintf(tem, "%s@%d", psname, ei);
+ psname = tem;
+ ((ps_font *)sty.f)->reencoded_name = tem;
+ }
+ else
+ psname = s;
+ }
+ out.put_fix_number((font::res/(72*font::sizescale))*sty.point_size);
+ if (sty.height != 0 || sty.slant != 0) {
+ int h = sty.height == 0 ? sty.point_size : sty.height;
+ h *= font::res/(72*font::sizescale);
+ int c = int(h*tan(radians(sty.slant)) + .5);
+ out.put_fix_number(c).put_fix_number(h).put_literal_symbol(psname)
+ .put_symbol("MF");
+ }
+ else {
+ out.put_literal_symbol(psname).put_symbol("SF");
+ }
+ defined_styles[ndefined_styles++] = sty;
+}
+
+void ps_printer::set_space_code(unsigned char c)
+{
+ out.put_literal_symbol("SC").put_number(c).put_symbol("def");
+}
+
+void ps_printer::end_of_line()
+{
+ flush_sbuf();
+ // this ensures that we do an absolute motion to the beginning of a line
+ output_vpos = output_hpos = -1;
+}
+
+void ps_printer::flush_sbuf()
+{
+ enum {
+ NONE,
+ RELATIVE_H,
+ RELATIVE_V,
+ RELATIVE_HV,
+ ABSOLUTE
+ } motion = NONE;
+ int space_flag = 0;
+ if (sbuf_len == 0)
+ return;
+ if (output_style != sbuf_style) {
+ set_style(sbuf_style);
+ output_style = sbuf_style;
+ }
+ int extra_space = 0;
+ if (output_hpos < 0 || output_vpos < 0)
+ motion = ABSOLUTE;
+ else {
+ if (output_hpos != sbuf_start_hpos)
+ motion = RELATIVE_H;
+ if (output_vpos != sbuf_vpos) {
+ if (motion != NONE)
+ motion = RELATIVE_HV;
+ else
+ motion = RELATIVE_V;
+ }
+ }
+ if (sbuf_space_code >= 0) {
+ int w = sbuf_style.f->get_width(space_char_index, sbuf_style.point_size);
+ if (w + sbuf_kern != sbuf_space_width) {
+ if (sbuf_space_code != output_space_code) {
+ set_space_code(sbuf_space_code);
+ output_space_code = sbuf_space_code;
+ }
+ space_flag = 1;
+ extra_space = sbuf_space_width - w - sbuf_kern;
+ if (sbuf_space_diff_count > sbuf_space_count/2)
+ extra_space++;
+ else if (sbuf_space_diff_count < -(sbuf_space_count/2))
+ extra_space--;
+ }
+ }
+ if (space_flag)
+ out.put_fix_number(extra_space);
+ if (sbuf_kern != 0)
+ out.put_fix_number(sbuf_kern);
+ out.put_string(sbuf, sbuf_len);
+ char sym[2];
+ sym[0] = 'A' + motion*4 + space_flag + 2*(sbuf_kern != 0);
+ sym[1] = '\0';
+ switch (motion) {
+ case NONE:
+ break;
+ case ABSOLUTE:
+ out.put_fix_number(sbuf_start_hpos)
+ .put_fix_number(sbuf_vpos);
+ break;
+ case RELATIVE_H:
+ out.put_fix_number(sbuf_start_hpos - output_hpos);
+ break;
+ case RELATIVE_V:
+ out.put_fix_number(sbuf_vpos - output_vpos);
+ break;
+ case RELATIVE_HV:
+ out.put_fix_number(sbuf_start_hpos - output_hpos)
+ .put_fix_number(sbuf_vpos - output_vpos);
+ break;
+ default:
+ assert(0);
+ }
+ out.put_symbol(sym);
+ output_hpos = sbuf_end_hpos;
+ output_vpos = sbuf_vpos;
+ sbuf_len = 0;
+}
+
+
+void ps_printer::set_line_thickness(const environment *env)
+{
+ if (line_thickness < 0) {
+ if (output_draw_point_size != env->size) {
+ // we ought to check for overflow here
+ int lw = ((font::res/(72*font::sizescale))*linewidth*env->size)/1000;
+ out.put_fix_number(lw).put_symbol("LW");
+ output_draw_point_size = env->size;
+ output_line_thickness = -1;
+ }
+ }
+ else {
+ if (output_line_thickness != line_thickness) {
+ out.put_fix_number(line_thickness).put_symbol("LW");
+ output_line_thickness = line_thickness;
+ output_draw_point_size = -1;
+ }
+ }
+}
+
+void ps_printer::fill_path()
+{
+ if (fill > FILL_MAX)
+ out.put_symbol("BL");
+ else
+ out.put_float(transform_fill(fill)).put_symbol("FL");
+}
+
+void ps_printer::draw(int code, int *p, int np, const environment *env)
+{
+ if (invis_count > 0)
+ return;
+ int fill_flag = 0;
+ switch (code) {
+ case 'C':
+ fill_flag = 1;
+ // fall through
+ case 'c':
+ // troff adds an extra argument to C
+ if (np != 1 && !(code == 'C' && np == 2)) {
+ error("1 argument required for circle");
+ break;
+ }
+ out.put_fix_number(env->hpos + p[0]/2)
+ .put_fix_number(env->vpos)
+ .put_fix_number(p[0]/2)
+ .put_symbol("DC");
+ if (fill_flag) {
+ fill_path();
+ }
+ else {
+ set_line_thickness(env);
+ out.put_symbol("ST");
+ }
+ break;
+ case 'l':
+ if (np != 2) {
+ error("2 arguments required for line");
+ break;
+ }
+ set_line_thickness(env);
+ out.put_fix_number(p[0] + env->hpos)
+ .put_fix_number(p[1] + env->vpos)
+ .put_fix_number(env->hpos)
+ .put_fix_number(env->vpos)
+ .put_symbol("DL");
+ break;
+ case 'E':
+ fill_flag = 1;
+ // fall through
+ case 'e':
+ if (np != 2) {
+ error("2 arguments required for ellipse");
+ break;
+ }
+ out.put_fix_number(p[0])
+ .put_fix_number(p[1])
+ .put_fix_number(env->hpos + p[0]/2)
+ .put_fix_number(env->vpos)
+ .put_symbol("DE");
+ if (fill_flag) {
+ fill_path();
+ }
+ else {
+ set_line_thickness(env);
+ out.put_symbol("ST");
+ }
+ break;
+ case 'P':
+ fill_flag = 1;
+ // fall through
+ case 'p':
+ {
+ if (np & 1) {
+ error("even number of arguments required for polygon");
+ break;
+ }
+ if (np == 0) {
+ error("no arguments for polygon");
+ break;
+ }
+ out.put_fix_number(env->hpos)
+ .put_fix_number(env->vpos)
+ .put_symbol("MT");
+ for (int i = 0; i < np; i += 2)
+ out.put_fix_number(p[i])
+ .put_fix_number(p[i+1])
+ .put_symbol("RL");
+ out.put_symbol("CL");
+ if (fill_flag) {
+ fill_path();
+ }
+ else {
+ set_line_thickness(env);
+ out.put_symbol("ST");
+ }
+ break;
+ }
+ case '~':
+ {
+ if (np & 1) {
+ error("even number of arguments required for spline");
+ break;
+ }
+ if (np == 0) {
+ error("no arguments for spline");
+ break;
+ }
+ out.put_fix_number(env->hpos)
+ .put_fix_number(env->vpos)
+ .put_symbol("MT");
+ out.put_fix_number(p[0]/2)
+ .put_fix_number(p[1]/2)
+ .put_symbol("RL");
+ /* tnum/tden should be between 0 and 1; the closer it is to 1
+ the tighter the curve will be to the guiding lines; 2/3
+ is the standard value */
+ const int tnum = 2;
+ const int tden = 3;
+ for (int i = 0; i < np - 2; i += 2) {
+ out.put_fix_number((p[i]*tnum)/(2*tden))
+ .put_fix_number((p[i + 1]*tnum)/(2*tden))
+ .put_fix_number(p[i]/2 + (p[i + 2]*(tden - tnum))/(2*tden))
+ .put_fix_number(p[i + 1]/2 + (p[i + 3]*(tden - tnum))/(2*tden))
+ .put_fix_number((p[i] - p[i]/2) + p[i + 2]/2)
+ .put_fix_number((p[i + 1] - p[i + 1]/2) + p[i + 3]/2)
+ .put_symbol("RC");
+ }
+ out.put_fix_number(p[np - 2] - p[np - 2]/2)
+ .put_fix_number(p[np - 1] - p[np - 1]/2)
+ .put_symbol("RL");
+ set_line_thickness(env);
+ out.put_symbol("ST");
+ }
+ break;
+ case 'a':
+ {
+ if (np != 4) {
+ error("4 arguments required for arc");
+ break;
+ }
+ set_line_thickness(env);
+ double c[2];
+ if (adjust_arc_center(p, c))
+ out.put_fix_number(env->hpos + int(c[0]))
+ .put_fix_number(env->vpos + int(c[1]))
+ .put_fix_number(int(sqrt(c[0]*c[0] + c[1]*c[1])))
+ .put_float(degrees(atan2(-c[1], -c[0])))
+ .put_float(degrees(atan2(p[1] + p[3] - c[1], p[0] + p[2] - c[0])))
+ .put_symbol("DA");
+ else
+ out.put_fix_number(p[0] + p[2] + env->hpos)
+ .put_fix_number(p[1] + p[3] + env->vpos)
+ .put_fix_number(env->hpos)
+ .put_fix_number(env->vpos)
+ .put_symbol("DL");
+ }
+ break;
+ case 't':
+ {
+ if (np == 0) {
+ line_thickness = -1;
+ }
+ else {
+ // troff gratuitously adds an extra 0
+ if (np != 1 && np != 2) {
+ error("0 or 1 argument required for thickness");
+ break;
+ }
+ line_thickness = p[0];
+ }
+ break;
+ }
+ case 'f':
+ {
+ if (np != 1 && np != 2) {
+ error("1 argument required for fill");
+ break;
+ }
+ fill = p[0];
+ if (fill < 0 || fill > FILL_MAX) {
+ // This means fill with the current color.
+ fill = FILL_MAX + 1;
+ }
+ break;
+ }
+ default:
+ error("unrecognised drawing command `%1'", char(code));
+ break;
+ }
+
+ output_hpos = output_vpos = -1;
+}
+
+
+void ps_printer::begin_page(int n)
+{
+ out.begin_comment("Page:").comment_arg(itoa(n));
+ out.comment_arg(itoa(++pages_output)).end_comment();
+ output_style.f = 0;
+ output_space_code = 32;
+ output_draw_point_size = -1;
+ output_line_thickness = -1;
+ output_hpos = output_vpos = -1;
+ ndefined_styles = 0;
+ out.simple_comment("BeginPageSetup");
+ out.put_symbol("BP");
+ out.simple_comment("EndPageSetup");
+}
+
+void ps_printer::end_page(int)
+{
+ flush_sbuf();
+ out.put_symbol("EP");
+ if (invis_count != 0) {
+ error("missing `endinvis' command");
+ invis_count = 0;
+ }
+}
+
+font *ps_printer::make_font(const char *nm)
+{
+ return ps_font::load_ps_font(nm);
+}
+
+ps_printer::~ps_printer()
+{
+ out.simple_comment("Trailer");
+ out.put_symbol("end");
+ out.simple_comment("EOF");
+ if (fseek(tempfp, 0L, 0) < 0)
+ fatal("fseek on temporary file failed");
+ fputs("%!PS-Adobe-", stdout);
+ fputs((broken_flags & USE_PS_ADOBE_2_0) ? "2.0" : "3.0", stdout);
+ putchar('\n');
+ out.set_file(stdout);
+ {
+ extern const char *Version_string;
+ out.begin_comment("Creator:")
+ .comment_arg("groff")
+ .comment_arg("version")
+ .comment_arg(Version_string)
+ .end_comment();
+ }
+ {
+ fputs("%%CreationDate: ", out.get_file());
+#ifdef LONG_FOR_TIME_T
+ long
+#else
+ time_t
+#endif
+ t = time(0);
+ fputs(ctime(&t), out.get_file());
+ }
+ for (font_pointer_list *f = font_list; f; f = f->next) {
+ ps_font *psf = (ps_font *)(f->p);
+ rm.need_font(psf->get_internal_name());
+ }
+ rm.print_header_comments(out);
+ out.begin_comment("Pages:").comment_arg(itoa(pages_output)).end_comment();
+ out.begin_comment("PageOrder:").comment_arg("Ascend").end_comment();
+#if 0
+ fprintf(out.get_file(), "%%%%DocumentMedia: () %g %g 0 () ()\n",
+ font::paperwidth*72.0/font::res,
+ paper_length*72.0/font::res);
+#endif
+ out.begin_comment("Orientation:")
+ .comment_arg(landscape_flag ? "Landscape" : "Portrait")
+ .end_comment();
+ if (ncopies != 1) {
+ out.end_line();
+ fprintf(out.get_file(), "%%%%Requirements: numcopies(%d)\n", ncopies);
+ }
+ out.simple_comment("EndComments");
+ out.simple_comment("BeginProlog");
+ rm.output_prolog(out);
+ if (!(broken_flags & NO_SETUP_SECTION)) {
+ out.simple_comment("EndProlog");
+ out.simple_comment("BeginSetup");
+ }
+ rm.document_setup(out);
+ out.put_symbol(dict_name).put_symbol("begin");
+ if (ndefs > 0)
+ ndefs += DEFS_DICT_SPARE;
+ out.put_literal_symbol(defs_dict_name)
+ .put_number(ndefs + 1)
+ .put_symbol("dict")
+ .put_symbol("def");
+ out.put_symbol(defs_dict_name)
+ .put_symbol("begin");
+ out.put_literal_symbol("u")
+ .put_delimiter('{')
+ .put_fix_number(1)
+ .put_symbol("mul")
+ .put_delimiter('}')
+ .put_symbol("bind")
+ .put_symbol("def");
+ defs += '\0';
+ out.special(defs.contents());
+ out.put_symbol("end");
+ if (ncopies != 1)
+ out.put_literal_symbol("#copies").put_number(ncopies).put_symbol("def");
+ out.put_literal_symbol("RES").put_number(res).put_symbol("def");
+ out.put_literal_symbol("PL");
+ if (guess_flag)
+ out.put_symbol("PLG");
+ else
+ out.put_fix_number(paper_length);
+ out.put_symbol("def");
+ out.put_literal_symbol("LS")
+ .put_symbol(landscape_flag ? "true" : "false")
+ .put_symbol("def");
+ if (manual_feed_flag) {
+ out.begin_comment("BeginFeature:")
+ .comment_arg("*ManualFeed")
+ .comment_arg("True")
+ .end_comment()
+ .put_symbol("MANUAL")
+ .simple_comment("EndFeature");
+ }
+ encode_fonts();
+ out.simple_comment((broken_flags & NO_SETUP_SECTION)
+ ? "EndProlog"
+ : "EndSetup");
+ out.end_line();
+ out.copy_file(tempfp);
+ fclose(tempfp);
+}
+
+void ps_printer::special(char *arg, const environment *env)
+{
+ typedef void (ps_printer::*SPECIAL_PROCP)(char *, const environment *);
+ static struct {
+ const char *name;
+ SPECIAL_PROCP proc;
+ } proc_table[] = {
+ { "exec", &ps_printer::do_exec },
+ { "def", &ps_printer::do_def },
+ { "mdef", &ps_printer::do_mdef },
+ { "import", &ps_printer::do_import },
+ { "file", &ps_printer::do_file },
+ { "invis", &ps_printer::do_invis },
+ { "endinvis", &ps_printer::do_endinvis },
+ };
+ char *p;
+ for (p = arg; *p == ' ' || *p == '\n'; p++)
+ ;
+ char *tag = p;
+ for (; *p != '\0' && *p != ':' && *p != ' ' && *p != '\n'; p++)
+ ;
+ if (*p == '\0' || strncmp(tag, "ps", p - tag) != 0) {
+ error("X command without `ps:' tag ignored");
+ return;
+ }
+ p++;
+ for (; *p == ' ' || *p == '\n'; p++)
+ ;
+ char *command = p;
+ for (; *p != '\0' && *p != ' ' && *p != '\n'; p++)
+ ;
+ if (*command == '\0') {
+ error("X command without `ps:' tag ignored");
+ return;
+ }
+ for (int i = 0; i < sizeof(proc_table)/sizeof(proc_table[0]); i++)
+ if (strncmp(command, proc_table[i].name, p - command) == 0) {
+ (this->*(proc_table[i].proc))(p, env);
+ return;
+ }
+ error("X command `%1' not recognised", command);
+}
+
+// A conforming PostScript document must not have lines longer
+// than 255 characters (excluding line termination characters).
+
+static int check_line_lengths(const char *p)
+{
+ for (;;) {
+ const char *end = strchr(p, '\n');
+ if (end == 0)
+ end = strchr(p, '\0');
+ if (end - p > 255)
+ return 0;
+ if (*end == '\0')
+ break;
+ p = end + 1;
+ }
+ return 1;
+}
+
+void ps_printer::do_exec(char *arg, const environment *env)
+{
+ flush_sbuf();
+ while (csspace(*arg))
+ arg++;
+ if (*arg == '\0') {
+ error("missing argument to X exec command");
+ return;
+ }
+ if (!check_line_lengths(arg)) {
+ error("lines in X exec command must not be more than 255 characters long");
+ return;
+ }
+ out.put_fix_number(env->hpos)
+ .put_fix_number(env->vpos)
+ .put_symbol("EBEGIN")
+ .special(arg)
+ .put_symbol("EEND");
+ output_hpos = output_vpos = -1;
+ output_style.f = 0;
+ output_draw_point_size = -1;
+ output_line_thickness = -1;
+ ndefined_styles = 0;
+ if (!ndefs)
+ ndefs = 1;
+}
+
+void ps_printer::do_file(char *arg, const environment *env)
+{
+ flush_sbuf();
+ while (csspace(*arg))
+ arg++;
+ if (*arg == '\0') {
+ error("missing argument to X file command");
+ return;
+ }
+ const char *filename = arg;
+ do {
+ ++arg;
+ } while (*arg != '\0' && *arg != ' ' && *arg != '\n');
+ out.put_fix_number(env->hpos)
+ .put_fix_number(env->vpos)
+ .put_symbol("EBEGIN");
+ rm.import_file(filename, out);
+ out.put_symbol("EEND");
+ output_hpos = output_vpos = -1;
+ output_style.f = 0;
+ output_draw_point_size = -1;
+ output_line_thickness = -1;
+ ndefined_styles = 0;
+ if (!ndefs)
+ ndefs = 1;
+}
+
+void ps_printer::do_def(char *arg, const environment *)
+{
+ flush_sbuf();
+ while (csspace(*arg))
+ arg++;
+ if (!check_line_lengths(arg)) {
+ error("lines in X def command must not be more than 255 characters long");
+ return;
+ }
+ defs += arg;
+ if (*arg != '\0' && strchr(arg, '\0')[-1] != '\n')
+ defs += '\n';
+ ndefs++;
+}
+
+// Like def, but the first argument says how many definitions it contains.
+
+void ps_printer::do_mdef(char *arg, const environment *)
+{
+ flush_sbuf();
+ char *p;
+ int n = (int)strtol(arg, &p, 10);
+ if (n == 0 && p == arg) {
+ error("first argument to X mdef must be an integer");
+ return;
+ }
+ if (n < 0) {
+ error("out of range argument `%1' to X mdef command", int(n));
+ return;
+ }
+ arg = p;
+ while (csspace(*arg))
+ arg++;
+ if (!check_line_lengths(arg)) {
+ error("lines in X mdef command must not be more than 255 characters long");
+ return;
+ }
+ defs += arg;
+ if (*arg != '\0' && strchr(arg, '\0')[-1] != '\n')
+ defs += '\n';
+ ndefs += n;
+}
+
+void ps_printer::do_import(char *arg, const environment *env)
+{
+ flush_sbuf();
+ while (*arg == ' ' || *arg == '\n')
+ arg++;
+ char *p;
+ for (p = arg; *p != '\0' && *p != ' ' && *p != '\n'; p++)
+ ;
+ if (*p != '\0')
+ *p++ = '\0';
+ int parms[6];
+ int nparms = 0;
+ while (nparms < 6) {
+ char *end;
+ long n = strtol(p, &end, 10);
+ if (n == 0 && end == p)
+ break;
+ parms[nparms++] = int(n);
+ p = end;
+ }
+ if (csalpha(*p) && (p[1] == '\0' || p[1] == ' ' || p[1] == '\n')) {
+ error("scaling indicators not allowed in arguments for X import command");
+ return;
+ }
+ while (*p == ' ' || *p == '\n')
+ p++;
+ if (nparms < 5) {
+ if (*p == '\0')
+ error("too few arguments for X import command");
+ else
+ error("invalid argument `%1' for X import command", p);
+ return;
+ }
+ if (*p != '\0') {
+ error("superflous argument `%1' for X import command", p);
+ return;
+ }
+ int llx = parms[0];
+ int lly = parms[1];
+ int urx = parms[2];
+ int ury = parms[3];
+ int desired_width = parms[4];
+ int desired_height = parms[5];
+ if (desired_width <= 0) {
+ error("bad width argument `%1' for X import command: must be > 0",
+ desired_width);
+ return;
+ }
+ if (nparms == 6 && desired_height <= 0) {
+ error("bad height argument `%1' for X import command: must be > 0",
+ desired_height);
+ return;
+ }
+ if (llx == urx) {
+ error("llx and urx arguments for X import command must not be equal");
+ return;
+ }
+ if (lly == ury) {
+ error("lly and ury arguments for X import command must not be equal");
+ return;
+ }
+ if (nparms == 5) {
+ int old_wid = urx - llx;
+ int old_ht = ury - lly;
+ if (old_wid < 0)
+ old_wid = -old_wid;
+ if (old_ht < 0)
+ old_ht = -old_ht;
+ desired_height = int(desired_width*(double(old_ht)/double(old_wid)) + .5);
+ }
+ if (env->vpos - desired_height < 0)
+ warning("top of imported graphic is above the top of the page");
+ out.put_number(llx)
+ .put_number(lly)
+ .put_fix_number(desired_width)
+ .put_number(urx - llx)
+ .put_fix_number(-desired_height)
+ .put_number(ury - lly)
+ .put_fix_number(env->hpos)
+ .put_fix_number(env->vpos)
+ .put_symbol("PBEGIN");
+ rm.import_file(arg, out);
+ // do this here just in case application defines PEND
+ out.put_symbol("end");
+ out.put_symbol("PEND");
+}
+
+void ps_printer::do_invis(char *, const environment *)
+{
+ invis_count++;
+}
+
+void ps_printer::do_endinvis(char *, const environment *)
+{
+ if (invis_count == 0)
+ error("unbalanced `endinvis' command");
+ else
+ --invis_count;
+}
+
+printer *make_printer()
+{
+ return new ps_printer;
+}
+
+static void usage();
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int c;
+ while ((c = getopt(argc, argv, "F:glmc:w:vb:")) != EOF)
+ switch(c) {
+ case 'v':
+ {
+ extern const char *Version_string;
+ fprintf(stderr, "grops version %s\n", Version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'c':
+ if (sscanf(optarg, "%d", &ncopies) != 1 || ncopies <= 0) {
+ error("bad number of copies `%s'", optarg);
+ ncopies = 1;
+ }
+ break;
+ case 'g':
+ guess_flag = 1;
+ break;
+ case 'l':
+ landscape_flag = 1;
+ break;
+ case 'm':
+ manual_feed_flag = 1;
+ break;
+ case 'F':
+ font::command_line_font_dir(optarg);
+ break;
+ case 'w':
+ if (sscanf(optarg, "%d", &linewidth) != 1 || linewidth < 0) {
+ error("bad linewidth `%1'", optarg);
+ linewidth = -1;
+ }
+ break;
+ case 'b':
+ // XXX check this
+ broken_flags = atoi(optarg);
+ bflag = 1;
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ }
+ font::set_unknown_desc_command_handler(handle_unknown_desc_command);
+ if (optind >= argc)
+ do_file("-");
+ else {
+ for (int i = optind; i < argc; i++)
+ do_file(argv[i]);
+ }
+ delete pr;
+ return 0;
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-glmv] [-b n] [-c n] [-w n] [-F dir] [files ...]\n",
+ program_name);
+ exit(1);
+}
diff --git a/src/devices/grops/ps.h b/src/devices/grops/ps.h
new file mode 100644
index 00000000..6e78597d
--- /dev/null
+++ b/src/devices/grops/ps.h
@@ -0,0 +1,122 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+class ps_output {
+public:
+ ps_output(FILE *, int max_line_length);
+ ps_output &put_string(const char *, int);
+ ps_output &put_number(int);
+ ps_output &put_fix_number(int);
+ ps_output &put_float(double);
+ ps_output &put_symbol(const char *);
+ ps_output &put_literal_symbol(const char *);
+ ps_output &set_fixed_point(int);
+ ps_output &simple_comment(const char *);
+ ps_output &begin_comment(const char *);
+ ps_output &comment_arg(const char *);
+ ps_output &end_comment();
+ ps_output &set_file(FILE *);
+ ps_output &include_file(FILE *);
+ ps_output &copy_file(FILE *);
+ ps_output &end_line();
+ ps_output &put_delimiter(char);
+ ps_output &special(const char *);
+ FILE *get_file();
+private:
+ FILE *fp;
+ int col;
+ int max_line_length; // not including newline
+ int need_space;
+ int fixed_point;
+};
+
+inline FILE *ps_output::get_file()
+{
+ return fp;
+}
+
+enum resource_type {
+ RESOURCE_FONT,
+ RESOURCE_PROCSET,
+ RESOURCE_FILE,
+ RESOURCE_ENCODING,
+ RESOURCE_FORM,
+ RESOURCE_PATTERN
+ };
+
+struct resource;
+
+extern string an_empty_string;
+
+class resource_manager {
+public:
+ resource_manager();
+ ~resource_manager();
+ void import_file(const char *filename, ps_output &);
+ void need_font(const char *name);
+ void print_header_comments(ps_output &);
+ void document_setup(ps_output &);
+ void output_prolog(ps_output &);
+private:
+ unsigned extensions;
+ unsigned language_level;
+ resource *procset_resource;
+ resource *resource_list;
+ resource *lookup_resource(resource_type type, string &name,
+ string &version = an_empty_string,
+ unsigned revision = 0);
+ resource *lookup_font(const char *name);
+ void read_download_file();
+ void supply_resource(resource *r, int rank, FILE *outfp,
+ int is_document = 0);
+ void process_file(int rank, FILE *fp, const char *filename, FILE *outfp);
+ resource *read_file_arg(const char **);
+ resource *read_procset_arg(const char **);
+ resource *read_font_arg(const char **);
+ resource *read_resource_arg(const char **);
+ void print_resources_comment(unsigned flag, FILE *outfp);
+ void print_extensions_comment(FILE *outfp);
+ void print_language_level_comment(FILE *outfp);
+ int do_begin_resource(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_include_resource(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_begin_document(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_include_document(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_begin_procset(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_include_procset(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_begin_font(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_include_font(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_begin_file(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_include_file(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int change_to_end_resource(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_begin_preview(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_begin_data(const char *ptr, int rank, FILE *fp, FILE *outfp);
+ int do_begin_binary(const char *ptr, int rank, FILE *fp, FILE *outfp);
+};
+
+extern unsigned broken_flags;
+
+// broken_flags is ored from these
+
+enum {
+ NO_SETUP_SECTION = 01,
+ STRIP_PERCENT_BANG = 02,
+ STRIP_STRUCTURE_COMMENTS = 04,
+ USE_PS_ADOBE_2_0 = 010
+};
diff --git a/src/devices/grops/psfig.diff b/src/devices/grops/psfig.diff
new file mode 100644
index 00000000..5be080dd
--- /dev/null
+++ b/src/devices/grops/psfig.diff
@@ -0,0 +1,106 @@
+These are patches to makes psfig work with groff. They apply to the
+version of psfig in comp.sources.unix/Volume11. After applying them,
+psfig should be recompiled with -DGROFF. The resulting psfig will
+work only with groff, so you might want to install it under a
+different name. The output of this psfig must be processed using the
+macros in the file ../tmac/tmac.psfig. These will automatically add
+the necessary PostScript code to the prologue output by grops. Use of
+the `global' feature in psfig will result in non-conformant PostScript
+which will fail if processed by a page reversal program. Note that
+psfig is unsupported by me (I'm not interested in hearing about psfig
+problems.) For new documents, I recommend using the PostScript
+inclusion features provided by grops.
+
+James Clark
+jjc@jclark.com
+
+*** cmds.c.~1~ Thu Feb 14 16:09:45 1991
+--- cmds.c Mon Mar 4 12:49:26 1991
+***************
+*** 245,253 ****
+--- 245,261 ----
+ (void) sprintf(x, "%.2fp", fx);
+ (void) sprintf(y, "%.2fp", fy);
+ } else if (!*x) {
++ #ifndef GROFF
+ (void) sprintf(x,"(%.2fp*%s/%.2fp)", fx, y, fy);
++ #else /* GROFF */
++ (void) sprintf(x,"(%.0fu*%s/%.0fu)", fx, y, fy);
++ #endif /* GROFF */
+ } else if (!*y) {
++ #ifndef GROFF
+ (void) sprintf(y,"(%.2fp*%s/%.2fp)", fy, x, fx);
++ #else /* GROFF */
++ (void) sprintf(y,"(%.0fu*%s/%.0fu)", fy, x, fx);
++ #endif /* GROFF */
+ }
+
+ /*
+*** troff.c.~1~ Thu Feb 14 16:09:48 1991
+--- troff.c Mon Mar 4 12:48:46 1991
+***************
+*** 26,32 ****
+--- 26,36 ----
+ }
+
+
++ #ifndef GROFF
+ char incl_file_s[] = "\\X'f%s'";
++ #else /* GROFF */
++ char incl_file_s[] = "\\X'ps: file %s'";
++ #endif /* GROFF */
+ includeFile(filenm)
+ char *filenm; {
+ printf(incl_file_s, filenm);
+***************
+*** 40,52 ****
+--- 44,64 ----
+ error("buffer overflow");
+ }
+
++ #ifndef GROFF
+ char endfig_s[] = "\\X'pendFig'";
++ #else /* GROFF */
++ char endfig_s[] = "\\X'ps: exec psfigend'";
++ #endif /* GROFF */
+ endfig() {
+ printf(endfig_s);
+ }
+
+ char startfig_s[] =
++ #ifndef GROFF
+ "\\X'p\\w@\\h@%s@@'\\X'p\\w@\\h@%s@@'\\X'p%.2f'\\X'p%.2f'\\X'p%.2f'\\X'p%.2f'\\X'pstartFig'";
++ #else /* GROFF */
++ "\\X'ps: exec \\w@\\h@%s@@ \\w@\\h@%s@@ %.2f %.2f %.2f %.2f psfigstart'";
++ #endif /* GROFF */
+
+ startfig(x, y, llx, lly, urx, ury)
+ char *x, *y;
+***************
+*** 57,63 ****
+--- 69,79 ----
+ }
+
+ emitDoClip() {
++ #ifndef GROFF
+ printf("\\X'pdoclip'");
++ #else /* GROFF */
++ printf("\\X'ps: exec psfigclip'");
++ #endif /* GROFF */
+ }
+
+ flushX()
+***************
+*** 116,122 ****
+--- 132,142 ----
+
+ #define isWhite(ch) ((ch) == ' ' || (ch) == '\t' || (ch) == '\n')
+
++ #ifndef GROFF
+ char literal_s[] = "\\X'p%s'";
++ #else /* GROFF */
++ char literal_s[] = "\\X'ps: exec %s'";
++ #endif /* GROFF */
+ emitLiteral(text)
+ char *text; {
+ static char litbuf[BUFSZ];
diff --git a/src/devices/grops/psrm.cc b/src/devices/grops/psrm.cc
new file mode 100644
index 00000000..91b7e6f1
--- /dev/null
+++ b/src/devices/grops/psrm.cc
@@ -0,0 +1,1103 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "driver.h"
+#include "stringclass.h"
+#include "cset.h"
+
+#include "ps.h"
+
+#define PROLOGUE "prologue"
+
+static void print_ps_string(const string &s, FILE *outfp);
+
+cset white_space("\n\r \t");
+string an_empty_string;
+
+const char *extension_table[] = {
+ "DPS",
+ "CMYK",
+ "Composite",
+ "FileSystem",
+};
+
+const int NEXTENSIONS = sizeof(extension_table)/sizeof(extension_table[0]);
+
+const char *resource_table[] = {
+ "font",
+ "procset",
+ "file",
+ "encoding",
+ "form",
+ "pattern",
+};
+
+const int NRESOURCES = sizeof(resource_table)/sizeof(resource_table[0]);
+
+static int read_uint_arg(const char **pp, unsigned *res)
+{
+ while (white_space(**pp))
+ *pp += 1;
+ if (**pp == '\0') {
+ error("missing argument");
+ return 0;
+ }
+ const char *start = *pp;
+ // XXX use strtoul
+ long n = strtol(start, (char **)pp, 10);
+ if (n == 0 && *pp == start) {
+ error("not an integer");
+ return 0;
+ }
+ if (n < 0) {
+ error("argument must not be negative");
+ return 0;
+ }
+ *res = unsigned(n);
+ return 1;
+}
+
+struct resource {
+ resource *next;
+ resource_type type;
+ string name;
+ enum { NEEDED = 01, SUPPLIED = 02, FONT_NEEDED = 04, BUSY = 010 };
+ unsigned flags;
+ string version;
+ unsigned revision;
+ char *filename;
+ int rank;
+ resource(resource_type, string &, string & = an_empty_string, unsigned = 0);
+ ~resource();
+ void print_type_and_name(FILE *outfp);
+};
+
+resource::resource(resource_type t, string &n, string &v, unsigned r)
+: next(0), type(t), flags(0), revision(r), filename(0), rank(-1)
+{
+ name.move(n);
+ version.move(v);
+ if (type == RESOURCE_FILE) {
+ if (name.search('\0') >= 0)
+ error("filename contains a character with code 0");
+ filename = name.extract();
+ }
+}
+
+resource::~resource()
+{
+ a_delete filename;
+}
+
+void resource::print_type_and_name(FILE *outfp)
+{
+ fputs(resource_table[type], outfp);
+ putc(' ', outfp);
+ print_ps_string(name, outfp);
+ if (type == RESOURCE_PROCSET) {
+ putc(' ', outfp);
+ print_ps_string(version, outfp);
+ fprintf(outfp, " %u", revision);
+ }
+}
+
+resource_manager::resource_manager()
+: extensions(0), language_level(0), resource_list(0)
+{
+ read_download_file();
+ string procset_name("grops");
+ extern const char *version_string;
+ extern const char *revision_string;
+ unsigned revision_uint;
+ if ( !read_uint_arg( &revision_string, &revision_uint) )
+ revision_uint = 0;
+ string procset_version(version_string);
+ procset_resource = lookup_resource(RESOURCE_PROCSET, procset_name,
+ procset_version, revision_uint);
+ procset_resource->flags |= resource::SUPPLIED;
+}
+
+resource_manager::~resource_manager()
+{
+ while (resource_list) {
+ resource *tem = resource_list;
+ resource_list = resource_list->next;
+ delete tem;
+ }
+}
+
+resource *resource_manager::lookup_resource(resource_type type,
+ string &name,
+ string &version,
+ unsigned revision)
+{
+ resource *r;
+ for (r = resource_list; r; r = r->next)
+ if (r->type == type
+ && r->name == name
+ && r->version == version
+ && r->revision == revision)
+ return r;
+ r = new resource(type, name, version, revision);
+ r->next = resource_list;
+ resource_list = r;
+ return r;
+}
+
+// Just a specialized version of lookup_resource().
+
+resource *resource_manager::lookup_font(const char *name)
+{
+ resource *r;
+ for (r = resource_list; r; r = r->next)
+ if (r->type == RESOURCE_FONT
+ && strlen(name) == r->name.length()
+ && memcmp(name, r->name.contents(), r->name.length()) == 0)
+ return r;
+ string s(name);
+ r = new resource(RESOURCE_FONT, s);
+ r->next = resource_list;
+ resource_list = r;
+ return r;
+}
+
+void resource_manager::need_font(const char *name)
+{
+ lookup_font(name)->flags |= resource::FONT_NEEDED;
+}
+
+typedef resource *Presource; // Work around g++ bug.
+
+void resource_manager::document_setup(ps_output &out)
+{
+ int nranks = 0;
+ resource *r;
+ for (r = resource_list; r; r = r->next)
+ if (r->rank >= nranks)
+ nranks = r->rank + 1;
+ if (nranks > 0) {
+ // Sort resource_list in reverse order of rank.
+ Presource *head = new Presource[nranks + 1];
+ Presource **tail = new Presource *[nranks + 1];
+ int i;
+ for (i = 0; i < nranks + 1; i++) {
+ head[i] = 0;
+ tail[i] = &head[i];
+ }
+ for (r = resource_list; r; r = r->next) {
+ i = r->rank < 0 ? 0 : r->rank + 1;
+ *tail[i] = r;
+ tail[i] = &(*tail[i])->next;
+ }
+ resource_list = 0;
+ for (i = 0; i < nranks + 1; i++)
+ if (head[i]) {
+ *tail[i] = resource_list;
+ resource_list = head[i];
+ }
+ a_delete head;
+ a_delete tail;
+ // check it
+ for (r = resource_list; r; r = r->next)
+ if (r->next)
+ assert(r->rank >= r->next->rank);
+ for (r = resource_list; r; r = r->next)
+ if (r->type == RESOURCE_FONT && r->rank >= 0)
+ supply_resource(r, -1, out.get_file());
+ }
+}
+
+void resource_manager::print_resources_comment(unsigned flag, FILE *outfp)
+{
+ int continued = 0;
+ for (resource *r = resource_list; r; r = r->next)
+ if (r->flags & flag) {
+ if (continued)
+ fputs("%%+ ", outfp);
+ else {
+ fputs(flag == resource::NEEDED
+ ? "%%DocumentNeededResources: "
+ : "%%DocumentSuppliedResources: ",
+ outfp);
+ continued = 1;
+ }
+ r->print_type_and_name(outfp);
+ putc('\n', outfp);
+ }
+}
+
+void resource_manager::print_header_comments(ps_output &out)
+{
+ for (resource *r = resource_list; r; r = r->next)
+ if (r->type == RESOURCE_FONT && (r->flags & resource::FONT_NEEDED))
+ supply_resource(r, 0, 0);
+ print_resources_comment(resource::NEEDED, out.get_file());
+ print_resources_comment(resource::SUPPLIED, out.get_file());
+ print_language_level_comment(out.get_file());
+ print_extensions_comment(out.get_file());
+}
+
+void resource_manager::output_prolog(ps_output &out)
+{
+ FILE *outfp = out.get_file();
+ out.end_line();
+ char *path;
+ FILE *fp = font::open_file(PROLOGUE, &path);
+ if (!fp)
+ fatal("can't find `%1'", PROLOGUE);
+ fputs("%%BeginResource: ", outfp);
+ procset_resource->print_type_and_name(outfp);
+ putc('\n', outfp);
+ process_file(-1, fp, path, outfp);
+ fclose(fp);
+ a_delete path;
+ fputs("%%EndResource\n", outfp);
+}
+
+void resource_manager::import_file(const char *filename, ps_output &out)
+{
+ out.end_line();
+ string name(filename);
+ resource *r = lookup_resource(RESOURCE_FILE, name);
+ supply_resource(r, -1, out.get_file(), 1);
+}
+
+void resource_manager::supply_resource(resource *r, int rank, FILE *outfp,
+ int is_document)
+{
+ if (r->flags & resource::BUSY) {
+ r->name += '\0';
+ fatal("loop detected in dependency graph for %1 `%2'",
+ resource_table[r->type],
+ r->name.contents());
+ }
+ r->flags |= resource::BUSY;
+ if (rank > r->rank)
+ r->rank = rank;
+ char *path;
+ FILE *fp = 0;
+ if (r->filename != 0) {
+ if (r->type == RESOURCE_FONT) {
+ fp = font::open_file(r->filename, &path);
+ if (!fp) {
+ error("can't find `%1'", r->filename);
+ a_delete r->filename;
+ r->filename = 0;
+ }
+ }
+ else {
+ errno = 0;
+ fp = fopen(r->filename, "r");
+ if (!fp) {
+ error("can't open `%1': %2", r->filename, strerror(errno));
+ a_delete r->filename;
+ r->filename = 0;
+ }
+ else
+ path = r->filename;
+ }
+ }
+ if (fp) {
+ if (outfp) {
+ if (r->type == RESOURCE_FILE && is_document) {
+ fputs("%%BeginDocument: ", outfp);
+ print_ps_string(r->name, outfp);
+ putc('\n', outfp);
+ }
+ else {
+ fputs("%%BeginResource: ", outfp);
+ r->print_type_and_name(outfp);
+ putc('\n', outfp);
+ }
+ }
+ process_file(rank, fp, path, outfp);
+ fclose(fp);
+ if (r->type == RESOURCE_FONT)
+ a_delete path;
+ if (outfp) {
+ if (r->type == RESOURCE_FILE && is_document)
+ fputs("%%EndDocument\n", outfp);
+ else
+ fputs("%%EndResource\n", outfp);
+ }
+ r->flags |= resource::SUPPLIED;
+ }
+ else {
+ if (outfp) {
+ if (r->type == RESOURCE_FILE && is_document) {
+ fputs("%%IncludeDocument: ", outfp);
+ print_ps_string(r->name, outfp);
+ putc('\n', outfp);
+ }
+ else {
+ fputs("%%IncludeResource: ", outfp);
+ r->print_type_and_name(outfp);
+ putc('\n', outfp);
+ }
+ }
+ r->flags |= resource::NEEDED;
+ }
+ r->flags &= ~resource::BUSY;
+}
+
+
+#define PS_LINE_MAX 255
+#define PS_MAGIC "%!PS-Adobe-"
+
+static int ps_get_line(char *buf, FILE *fp)
+{
+ int c = getc(fp);
+ if (c == EOF) {
+ buf[0] = '\0';
+ return 0;
+ }
+ current_lineno++;
+ int i = 0;
+ int err = 0;
+ while (c != '\r' && c != '\n' && c != EOF) {
+ if ((c < 0x1b && !white_space(c)) || c == 0x7f)
+ error("illegal input character code %1", int(c));
+ else if (i < PS_LINE_MAX)
+ buf[i++] = c;
+ else if (!err) {
+ err = 1;
+ error("PostScript file non-conforming "
+ "because length of line exceeds 255");
+ }
+ c = getc(fp);
+ }
+ buf[i++] = '\n';
+ buf[i] = '\0';
+ if (c == '\r') {
+ c = getc(fp);
+ if (c != EOF && c != '\n')
+ ungetc(c, fp);
+ }
+ return 1;
+}
+
+static int read_text_arg(const char **pp, string &res)
+{
+ res.clear();
+ while (white_space(**pp))
+ *pp += 1;
+ if (**pp == '\0') {
+ error("missing argument");
+ return 0;
+ }
+ if (**pp != '(') {
+ for (; **pp != '\0' && !white_space(**pp); *pp += 1)
+ res += **pp;
+ return 1;
+ }
+ *pp += 1;
+ res.clear();
+ int level = 0;
+ for (;;) {
+ if (**pp == '\0' || **pp == '\r' || **pp == '\n') {
+ error("missing ')'");
+ return 0;
+ }
+ if (**pp == ')') {
+ if (level == 0) {
+ *pp += 1;
+ break;
+ }
+ res += **pp;
+ level--;
+ }
+ else if (**pp == '(') {
+ level++;
+ res += **pp;
+ }
+ else if (**pp == '\\') {
+ *pp += 1;
+ switch (**pp) {
+ case 'n':
+ res += '\n';
+ break;
+ case 'r':
+ res += '\n';
+ break;
+ case 't':
+ res += '\t';
+ break;
+ case 'b':
+ res += '\b';
+ break;
+ case 'f':
+ res += '\f';
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ {
+ int val = **pp - '0';
+ if ((*pp)[1] >= '0' && (*pp)[1] <= '7') {
+ *pp += 1;
+ val = val*8 + (**pp - '0');
+ if ((*pp)[1] >= '0' && (*pp)[1] <= '7') {
+ *pp += 1;
+ val = val*8 + (**pp - '0');
+ }
+ }
+ }
+ break;
+ default:
+ res += **pp;
+ break;
+ }
+ }
+ else
+ res += **pp;
+ *pp += 1;
+ }
+ return 1;
+}
+
+resource *resource_manager::read_file_arg(const char **ptr)
+{
+ string arg;
+ if (!read_text_arg(ptr, arg))
+ return 0;
+ return lookup_resource(RESOURCE_FILE, arg);
+}
+
+resource *resource_manager::read_font_arg(const char **ptr)
+{
+ string arg;
+ if (!read_text_arg(ptr, arg))
+ return 0;
+ return lookup_resource(RESOURCE_FONT, arg);
+}
+
+resource *resource_manager::read_procset_arg(const char **ptr)
+{
+ string arg;
+ if (!read_text_arg(ptr, arg))
+ return 0;
+ string version;
+ if (!read_text_arg(ptr, version))
+ return 0;
+ unsigned revision;
+ if (!read_uint_arg(ptr, &revision))
+ return 0;
+ return lookup_resource(RESOURCE_PROCSET, arg, version, revision);
+}
+
+resource *resource_manager::read_resource_arg(const char **ptr)
+{
+ while (white_space(**ptr))
+ *ptr += 1;
+ const char *name = *ptr;
+ while (**ptr != '\0' && !white_space(**ptr))
+ *ptr += 1;
+ if (name == *ptr) {
+ error("missing resource type");
+ return 0;
+ }
+ int ri;
+ for (ri = 0; ri < NRESOURCES; ri++)
+ if (strlen(resource_table[ri]) == *ptr - name
+ && memcmp(resource_table[ri], name, *ptr - name) == 0)
+ break;
+ if (ri >= NRESOURCES) {
+ error("unknown resource type");
+ return 0;
+ }
+ if (ri == RESOURCE_PROCSET)
+ return read_procset_arg(ptr);
+ string arg;
+ if (!read_text_arg(ptr, arg))
+ return 0;
+ return lookup_resource(resource_type(ri), arg);
+}
+
+static const char *matches_comment(const char *buf, const char *comment)
+{
+ if (buf[0] != '%' || buf[1] != '%')
+ return 0;
+ for (buf += 2; *comment; comment++, buf++)
+ if (*buf != *comment)
+ return 0;
+ if (comment[-1] == ':')
+ return buf;
+ if (*buf == '\0' || white_space(*buf))
+ return buf;
+ return 0;
+}
+
+// Return 1 if the line should be copied out.
+
+int resource_manager::do_begin_resource(const char *ptr, int, FILE *,
+ FILE *)
+{
+ resource *r = read_resource_arg(&ptr);
+ if (r)
+ r->flags |= resource::SUPPLIED;
+ return 1;
+}
+
+int resource_manager::do_include_resource(const char *ptr, int rank, FILE *,
+ FILE *outfp)
+{
+ resource *r = read_resource_arg(&ptr);
+ if (r) {
+ if (r->type == RESOURCE_FONT) {
+ if (rank >= 0)
+ supply_resource(r, rank + 1, outfp);
+ else
+ r->flags |= resource::FONT_NEEDED;
+ }
+ else
+ supply_resource(r, rank, outfp);
+ }
+ return 0;
+}
+
+int resource_manager::do_begin_document(const char *ptr, int, FILE *,
+ FILE *)
+{
+ resource *r = read_file_arg(&ptr);
+ if (r)
+ r->flags |= resource::SUPPLIED;
+ return 1;
+}
+
+int resource_manager::do_include_document(const char *ptr, int rank, FILE *,
+ FILE *outfp)
+{
+ resource *r = read_file_arg(&ptr);
+ if (r)
+ supply_resource(r, rank, outfp, 1);
+ return 0;
+}
+
+int resource_manager::do_begin_procset(const char *ptr, int, FILE *,
+ FILE *outfp)
+{
+ resource *r = read_procset_arg(&ptr);
+ if (r) {
+ r->flags |= resource::SUPPLIED;
+ if (outfp) {
+ fputs("%%BeginResource: ", outfp);
+ r->print_type_and_name(outfp);
+ putc('\n', outfp);
+ }
+ }
+ return 0;
+}
+
+int resource_manager::do_include_procset(const char *ptr, int rank, FILE *,
+ FILE *outfp)
+{
+ resource *r = read_procset_arg(&ptr);
+ if (r)
+ supply_resource(r, rank, outfp);
+ return 0;
+}
+
+int resource_manager::do_begin_file(const char *ptr, int, FILE *,
+ FILE *outfp)
+{
+ resource *r = read_file_arg(&ptr);
+ if (r) {
+ r->flags |= resource::SUPPLIED;
+ if (outfp) {
+ fputs("%%BeginResource: ", outfp);
+ r->print_type_and_name(outfp);
+ putc('\n', outfp);
+ }
+ }
+ return 0;
+}
+
+int resource_manager::do_include_file(const char *ptr, int rank, FILE *,
+ FILE *outfp)
+{
+ resource *r = read_file_arg(&ptr);
+ if (r)
+ supply_resource(r, rank, outfp);
+ return 0;
+}
+
+int resource_manager::do_begin_font(const char *ptr, int, FILE *,
+ FILE *outfp)
+{
+ resource *r = read_font_arg(&ptr);
+ if (r) {
+ r->flags |= resource::SUPPLIED;
+ if (outfp) {
+ fputs("%%BeginResource: ", outfp);
+ r->print_type_and_name(outfp);
+ putc('\n', outfp);
+ }
+ }
+ return 0;
+}
+
+int resource_manager::do_include_font(const char *ptr, int rank, FILE *,
+ FILE *outfp)
+{
+ resource *r = read_font_arg(&ptr);
+ if (r) {
+ if (rank >= 0)
+ supply_resource(r, rank + 1, outfp);
+ else
+ r->flags |= resource::FONT_NEEDED;
+ }
+ return 0;
+}
+
+int resource_manager::change_to_end_resource(const char *, int, FILE *,
+ FILE *outfp)
+{
+ if (outfp)
+ fputs("%%EndResource\n", outfp);
+ return 0;
+}
+
+int resource_manager::do_begin_preview(const char *, int, FILE *fp, FILE *)
+{
+ char buf[PS_LINE_MAX + 2];
+ do {
+ if (!ps_get_line(buf, fp)) {
+ error("end of file in preview section");
+ break;
+ }
+ } while (!matches_comment(buf, "EndPreview"));
+ return 0;
+}
+
+int read_one_of(const char **ptr, const char **s, int n)
+{
+ while (white_space(**ptr))
+ *ptr += 1;
+ if (**ptr == '\0')
+ return -1;
+ const char *start = *ptr;
+ do {
+ ++(*ptr);
+ } while (**ptr != '\0' && !white_space(**ptr));
+ for (int i = 0; i < n; i++)
+ if (strlen(s[i]) == *ptr - start
+ && memcmp(s[i], start, *ptr - start) == 0)
+ return i;
+ return -1;
+}
+
+int resource_manager::do_begin_data(const char *ptr, int, FILE *fp,
+ FILE *outfp)
+{
+ while (white_space(*ptr))
+ ptr++;
+ const char *start = ptr;
+ unsigned numberof;
+ if (!read_uint_arg(&ptr, &numberof))
+ return 0;
+ static const char *types[] = { "Binary", "Hex", "ASCII" };
+ const int Binary = 0;
+ int type = 0;
+ static const char *units[] = { "Bytes", "Lines" };
+ const int Bytes = 0;
+ int unit = Bytes;
+ while (white_space(*ptr))
+ ptr++;
+ if (*ptr != '\0') {
+ type = read_one_of(&ptr, types, 3);
+ if (type < 0) {
+ error("bad data type");
+ return 0;
+ }
+ while (white_space(*ptr))
+ ptr++;
+ if (*ptr != '\0') {
+ unit = read_one_of(&ptr, units, 2);
+ if (unit < 0) {
+ error("expected `Bytes' or `Lines'");
+ return 0;
+ }
+ }
+ }
+ if (type != Binary)
+ return 1;
+ if (outfp) {
+ fputs("%%BeginData: ", outfp);
+ fputs(start, outfp);
+ }
+ if (numberof > 0) {
+ unsigned bytecount = 0;
+ unsigned linecount = 0;
+ do {
+ int c = getc(fp);
+ if (c == EOF) {
+ error("end of file within data section");
+ return 0;
+ }
+ if (outfp)
+ putc(c, outfp);
+ bytecount++;
+ if (c == '\r') {
+ int cc = getc(fp);
+ if (cc != '\n') {
+ linecount++;
+ current_lineno++;
+ }
+ if (cc != EOF)
+ ungetc(c, fp);
+ }
+ else if (c == '\n') {
+ linecount++;
+ current_lineno++;
+ }
+ } while ((unit == Bytes ? bytecount : linecount) < numberof);
+ }
+ char buf[PS_LINE_MAX + 2];
+ if (!ps_get_line(buf, fp)) {
+ error("missing %%%%EndData line");
+ return 0;
+ }
+ if (!matches_comment(buf, "EndData"))
+ error("bad %%%%EndData line");
+ if (outfp)
+ fputs(buf, outfp);
+ return 0;
+}
+
+int resource_manager::do_begin_binary(const char *ptr, int, FILE *fp,
+ FILE *outfp)
+{
+ if (!outfp)
+ return 0;
+ unsigned count;
+ if (!read_uint_arg(&ptr, &count))
+ return 0;
+ if (outfp)
+ fprintf(outfp, "%%%%BeginData: %u Binary Bytes\n", count);
+ while (count != 0) {
+ int c = getc(fp);
+ if (c == EOF) {
+ error("end of file within binary section");
+ return 0;
+ }
+ if (outfp)
+ putc(c, outfp);
+ --count;
+ if (c == '\r') {
+ int cc = getc(fp);
+ if (cc != '\n')
+ current_lineno++;
+ if (cc != EOF)
+ ungetc(c, fp);
+ }
+ else if (c == '\n')
+ current_lineno++;
+ }
+ char buf[PS_LINE_MAX + 2];
+ if (!ps_get_line(buf, fp)) {
+ error("missing %%%%EndBinary line");
+ return 0;
+ }
+ if (!matches_comment(buf, "EndBinary")) {
+ error("bad %%%%EndBinary line");
+ if (outfp)
+ fputs(buf, outfp);
+ }
+ else if (outfp)
+ fputs("%%EndData\n", outfp);
+ return 0;
+}
+
+static unsigned parse_extensions(const char *ptr)
+{
+ unsigned flags = 0;
+ for (;;) {
+ while (white_space(*ptr))
+ ptr++;
+ if (*ptr == '\0')
+ break;
+ const char *name = ptr;
+ do {
+ ++ptr;
+ } while (*ptr != '\0' && !white_space(*ptr));
+ int i;
+ for (i = 0; i < NEXTENSIONS; i++)
+ if (strlen(extension_table[i]) == ptr - name
+ && memcmp(extension_table[i], name, ptr - name) == 0) {
+ flags |= (1 << i);
+ break;
+ }
+ if (i >= NEXTENSIONS) {
+ string s(name, ptr - name);
+ s += '\0';
+ error("unknown extension `%1'", s.contents());
+ }
+ }
+ return flags;
+}
+
+// XXX if it has not been surrounded with {Begin,End}Document need to strip
+// out Page: Trailer {Begin,End}Prolog {Begin,End}Setup sections.
+
+// XXX Perhaps the decision whether to use BeginDocument or
+// BeginResource: file should be postponed till we have seen
+// the first line of the file.
+
+void resource_manager::process_file(int rank, FILE *fp, const char *filename,
+ FILE *outfp)
+{
+ // If none of these comments appear in the header section, and we are
+ // just analyzing the file (ie outfp is 0), then we can return immediately.
+ static const char *header_comment_table[] = {
+ "DocumentNeededResources:",
+ "DocumentSuppliedResources:",
+ "DocumentNeededFonts:",
+ "DocumentSuppliedFonts:",
+ "DocumentNeededProcSets:",
+ "DocumentSuppliedProcSets:",
+ "DocumentNeededFiles:",
+ "DocumentSuppliedFiles:",
+ };
+
+ const int NHEADER_COMMENTS = (sizeof(header_comment_table)
+ / sizeof(header_comment_table[0]));
+ struct comment_info {
+ const char *name;
+ int (resource_manager::*proc)(const char *, int, FILE *, FILE *);
+ };
+
+ static comment_info comment_table[] = {
+ { "BeginResource:", &resource_manager::do_begin_resource },
+ { "IncludeResource:", &resource_manager::do_include_resource },
+ { "BeginDocument:", &resource_manager::do_begin_document },
+ { "IncludeDocument:", &resource_manager::do_include_document },
+ { "BeginProcSet:", &resource_manager::do_begin_procset },
+ { "IncludeProcSet:", &resource_manager::do_include_procset },
+ { "BeginFont:", &resource_manager::do_begin_font },
+ { "IncludeFont:", &resource_manager::do_include_font },
+ { "BeginFile:", &resource_manager::do_begin_file },
+ { "IncludeFile:", &resource_manager::do_include_file },
+ { "EndProcSet", &resource_manager::change_to_end_resource },
+ { "EndFont", &resource_manager::change_to_end_resource },
+ { "EndFile", &resource_manager::change_to_end_resource },
+ { "BeginPreview:", &resource_manager::do_begin_preview },
+ { "BeginData:", &resource_manager::do_begin_data },
+ { "BeginBinary:", &resource_manager::do_begin_binary },
+ };
+
+ const int NCOMMENTS = sizeof(comment_table)/sizeof(comment_table[0]);
+ char buf[PS_LINE_MAX + 2];
+ int saved_lineno = current_lineno;
+ const char *saved_filename = current_filename;
+ current_filename = filename;
+ current_lineno = 0;
+ if (!ps_get_line(buf, fp)) {
+ current_filename = saved_filename;
+ current_lineno = saved_lineno;
+ return;
+ }
+ if (strlen(buf) < sizeof(PS_MAGIC) - 1
+ || memcmp(buf, PS_MAGIC, sizeof(PS_MAGIC) - 1) != 0) {
+ if (outfp) {
+ do {
+ if (!(broken_flags & STRIP_PERCENT_BANG)
+ || buf[0] != '%' || buf[1] != '!')
+ fputs(buf, outfp);
+ } while (ps_get_line(buf, fp));
+ }
+ }
+ else {
+ if (!(broken_flags & STRIP_PERCENT_BANG) && outfp)
+ fputs(buf, outfp);
+ int in_header = 1;
+ int interesting = 0;
+ int had_extensions_comment = 0;
+ int had_language_level_comment = 0;
+ for (;;) {
+ if (!ps_get_line(buf, fp))
+ break;
+ int copy_this_line = 1;
+ if (buf[0] == '%') {
+ if (buf[1] == '%') {
+ const char *ptr;
+ int i;
+ for (i = 0; i < NCOMMENTS; i++)
+ if ((ptr = matches_comment(buf, comment_table[i].name))) {
+ copy_this_line
+ = (this->*(comment_table[i].proc))(ptr, rank, fp, outfp);
+ break;
+ }
+ if (i >= NCOMMENTS && in_header) {
+ if ((ptr = matches_comment(buf, "EndComments")))
+ in_header = 0;
+ else if (!had_extensions_comment
+ && (ptr = matches_comment(buf, "Extensions:"))) {
+ extensions |= parse_extensions(ptr);
+ // XXX handle possibility that next line is %%+
+ had_extensions_comment = 1;
+ }
+ else if (!had_language_level_comment
+ && (ptr = matches_comment(buf, "LanguageLevel:"))) {
+ unsigned ll;
+ if (read_uint_arg(&ptr, &ll) && ll > language_level)
+ language_level = ll;
+ had_language_level_comment = 1;
+ }
+ else {
+ for (i = 0; i < NHEADER_COMMENTS; i++)
+ if (matches_comment(buf, header_comment_table[i])) {
+ interesting = 1;
+ break;
+ }
+ }
+ }
+ if ((broken_flags & STRIP_STRUCTURE_COMMENTS)
+ && (matches_comment(buf, "EndProlog")
+ || matches_comment(buf, "Page:")
+ || matches_comment(buf, "Trailer")))
+ copy_this_line = 0;
+ }
+ else if (buf[1] == '!') {
+ if (broken_flags & STRIP_PERCENT_BANG)
+ copy_this_line = 0;
+ }
+ }
+ else
+ in_header = 0;
+ if (!outfp && !in_header && !interesting)
+ break;
+ if (copy_this_line && outfp)
+ fputs(buf, outfp);
+ }
+ }
+ current_filename = saved_filename;
+ current_lineno = saved_lineno;
+}
+
+void resource_manager::read_download_file()
+{
+ char *path = 0;
+ FILE *fp = font::open_file("download", &path);
+ if (!fp)
+ fatal("can't find `download'");
+ char buf[512];
+ int lineno = 0;
+ while (fgets(buf, sizeof(buf), fp)) {
+ lineno++;
+ char *p = strtok(buf, " \t\r\n");
+ if (p == 0 || *p == '#')
+ continue;
+ char *q = strtok(0, " \t\r\n");
+ if (!q)
+ fatal_with_file_and_line(path, lineno, "missing filename");
+ lookup_font(p)->filename = strsave(q);
+ }
+ a_delete path;
+ fclose(fp);
+}
+
+// XXX Can we share some code with ps_output::put_string()?
+
+static void print_ps_string(const string &s, FILE *outfp)
+{
+ int len = s.length();
+ const char *str = s.contents();
+ int funny = 0;
+ if (str[0] == '(')
+ funny = 1;
+ else {
+ for (int i = 0; i < len; i++)
+ if (str[i] <= 040 || str[i] > 0176) {
+ funny = 1;
+ break;
+ }
+ }
+ if (!funny) {
+ put_string(s, outfp);
+ return;
+ }
+ int level = 0;
+ int i;
+ for (i = 0; i < len; i++)
+ if (str[i] == '(')
+ level++;
+ else if (str[i] == ')' && --level < 0)
+ break;
+ putc('(', outfp);
+ for (i = 0; i < len; i++)
+ switch (str[i]) {
+ case '(':
+ case ')':
+ if (level != 0)
+ putc('\\', outfp);
+ putc(str[i], outfp);
+ break;
+ case '\\':
+ fputs("\\\\", outfp);
+ break;
+ case '\n':
+ fputs("\\n", outfp);
+ break;
+ case '\r':
+ fputs("\\r", outfp);
+ break;
+ case '\t':
+ fputs("\\t", outfp);
+ break;
+ case '\b':
+ fputs("\\b", outfp);
+ break;
+ case '\f':
+ fputs("\\f", outfp);
+ break;
+ default:
+ if (str[i] < 040 || str[i] > 0176)
+ fprintf(outfp, "\\%03o", str[i] & 0377);
+ else
+ putc(str[i], outfp);
+ break;
+ }
+ putc(')', outfp);
+}
+
+void resource_manager::print_extensions_comment(FILE *outfp)
+{
+ if (extensions) {
+ fputs("%%Extensions:", outfp);
+ for (int i = 0; i < NEXTENSIONS; i++)
+ if (extensions & (1 << i)) {
+ putc(' ', outfp);
+ fputs(extension_table[i], outfp);
+ }
+ putc('\n', outfp);
+ }
+}
+
+void resource_manager::print_language_level_comment(FILE *outfp)
+{
+ if (language_level)
+ fprintf(outfp, "%%%%LanguageLevel: %u\n", language_level);
+}
+
diff --git a/src/devices/grotty/Makefile.sub b/src/devices/grotty/Makefile.sub
new file mode 100644
index 00000000..91d3908c
--- /dev/null
+++ b/src/devices/grotty/Makefile.sub
@@ -0,0 +1,6 @@
+PROG=grotty
+MAN1=grotty.n
+XLIBS=$(LIBDRIVER) $(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=tty.o
+CCSRCS=$(srcdir)/tty.cc
diff --git a/src/devices/grotty/TODO b/src/devices/grotty/TODO
new file mode 100644
index 00000000..3f23dc35
--- /dev/null
+++ b/src/devices/grotty/TODO
@@ -0,0 +1,3 @@
+Document font and device description file usage of grotty.
+
+With -h avoid using a tab when a single space will do.
diff --git a/src/devices/grotty/grotty.man b/src/devices/grotty/grotty.man
new file mode 100644
index 00000000..c189518a
--- /dev/null
+++ b/src/devices/grotty/grotty.man
@@ -0,0 +1,234 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-2000 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.TH GROTTY @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+grotty \- groff driver for typewriter-like devices
+.SH SYNOPSIS
+.B grotty
+[
+.B \-hfbuodBUv
+] [
+.BI \-F dir
+] [
+.IR files \|.\|.\|.
+]
+.SH DESCRIPTION
+.B grotty
+translates the output of GNU
+.B troff
+into a form suitable for typewriter-like devices.
+Normally
+.B grotty
+should invoked by using the
+.B groff
+command
+with a
+.BR \-Tascii ,
+.B \-Tlatin1
+or
+.B \-Tutf8
+option.
+If no files are given,
+.B grotty
+will read the standard input.
+A filename of
+.B \-
+will also cause
+.B grotty
+to read the standard input.
+Output is written to the standard output.
+.LP
+Normally
+.B grotty
+prints a bold character
+.I c
+using the sequence
+.RI ` c
+.SM BACKSPACE
+.IR c '
+and a italic character
+.I c
+by the sequence
+.RB ` _
+.SM BACKSPACE
+.IR c '.
+These sequences can be displayed on a terminal
+by piping through
+.BR ul (1).
+Pagers such as
+.BR more (1)
+or
+.BR less (1)
+are also able to display these sequences.
+Use either
+.B \-B
+or
+.B \-U
+when piping into
+.BR less (1);
+use
+.B \-b
+when piping into
+.BR more (1).
+There is no need to filter the output through
+.BR col (1)
+since
+.B grotty
+never outputs reverse line feeds.
+.LP
+The font description file may contain a command
+.IP
+.BI internalname\ n
+.LP
+where
+.I n
+is a decimal integer.
+If the 01 bit in
+.I n
+is set,
+then the font will be treated as an italic font;
+if the 02 bit is set,
+then it will be treated as a bold font.
+The code field in the font description field gives the
+code which will be used to output the character.
+This code can also be used in the
+.B \eN
+escape sequence in
+.BR troff .
+.SH OPTIONS
+.TP
+.BI \-F dir
+Search the directory
+.IB dir /dev name
+for font and device description files;
+.I name
+is the name of the device, usually
+.BR ascii ,
+.B latin1
+or
+.BR utf8 .
+.TP
+.B \-h
+Use horizontal tabs in the output.
+Tabs are assumed to be set every 8 columns.
+.TP
+.B \-f
+Use form feeds in the output.
+A form feed will be output at the end of each page that has no output
+on its last line.
+.TP
+.B \-b
+Suppress the use of overstriking for bold characters.
+.TP
+.B \-u
+Suppress the use of underlining for italic characters.
+.TP
+.B \-B
+Use only overstriking for bold-italic characters.
+.TP
+.B \-U
+Use only underlining for bold-italic characters.
+.TP
+.B \-o
+Suppress overstriking (other than for bold or underlined characters).
+.TP
+.B \-d
+Ignore all
+.B \eD
+commands.
+Without this
+.B grotty
+will render
+.B \eD'l\|.\|.\|.'
+commands that have at least at least one zero argument
+(and so are either horizontal or vertical)
+using
+.BR \- ,
+.B |
+and
+.B +
+characters.
+.TP
+.B \-v
+Print the version number.
+.SH FILES
+.TP
+.B @FONTDIR@/devascii/DESC
+Device description file for
+.B ascii
+device.
+.TP
+.B @FONTDIR@/devascii/ F
+Font description file for font
+.I F
+of
+.B ascii device.
+.TP
+.B @FONTDIR@/devlatin1/DESC
+Device description file for
+.B latin1
+device.
+.TP
+.B @FONTDIR@/devlatin1/ F
+Font description file for font
+.I F
+of
+.B latin1 device.
+.TP
+.B @FONTDIR@/devutf8/DESC
+Device description file for
+.B utf8
+device.
+.TP
+.B @FONTDIR@/devutf8/ F
+Font description file for font
+.I F
+of
+.B utf8 device.
+.TP
+.B @MACRODIR@/tmac.tty
+Macros for use with
+.BR grotty .
+.TP
+.B @MACRODIR@/tmac.tty-char
+Additional klugey character definitions for use with
+.BR grotty .
+.SH BUGS
+.LP
+.B grotty
+is intended only for simple documents.
+.LP
+There is no support for fractional horizontal or vertical motions.
+.LP
+There is no support for
+.B \eD
+commands
+other than horizontal and vertical lines.
+.LP
+Characters above the first line (ie with a vertical position of 0)
+cannot be printed.
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@),
+.BR groff_out (@MAN5EXT@),
+.BR groff_font (@MAN5EXT@),
+.BR groff_char (@MAN7EXT@),
+.BR ul (1),
+.BR more (1),
+.BR less (1)
diff --git a/src/devices/grotty/tty.cc b/src/devices/grotty/tty.cc
new file mode 100644
index 00000000..63d8fb8f
--- /dev/null
+++ b/src/devices/grotty/tty.cc
@@ -0,0 +1,474 @@
+// -*- C++ -*-
+/* Copyright (C) 1989-2000 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "driver.h"
+#include "device.h"
+
+#ifndef SHRT_MIN
+#define SHRT_MIN (-32768)
+#endif
+
+#ifndef SHRT_MAX
+#define SHRT_MAX 32767
+#endif
+
+#define TAB_WIDTH 8
+
+static int horizontal_tab_flag = 0;
+static int form_feed_flag = 0;
+static int bold_flag = 1;
+static int underline_flag = 1;
+static int overstrike_flag = 1;
+static int draw_flag = 1;
+
+enum {
+ UNDERLINE_MODE = 01,
+ BOLD_MODE = 02,
+ VDRAW_MODE = 04,
+ HDRAW_MODE = 010
+};
+
+// Mode to use for bold-underlining.
+static unsigned char bold_underline_mode = BOLD_MODE|UNDERLINE_MODE;
+
+class tty_font : public font {
+ tty_font(const char *);
+ unsigned char mode;
+public:
+ ~tty_font();
+ unsigned char get_mode() { return mode; }
+#if 0
+ void handle_x_command(int argc, const char **argv);
+#endif
+ static tty_font *load_tty_font(const char *);
+};
+
+tty_font *tty_font::load_tty_font(const char *s)
+{
+ tty_font *f = new tty_font(s);
+ if (!f->load()) {
+ delete f;
+ return 0;
+ }
+ const char *num = f->get_internal_name();
+ long n;
+ if (num != 0 && (n = strtol(num, 0, 0)) != 0)
+ f->mode = int(n & (BOLD_MODE|UNDERLINE_MODE));
+ if (!underline_flag)
+ f->mode &= ~UNDERLINE_MODE;
+ if (!bold_flag)
+ f->mode &= ~BOLD_MODE;
+ if ((f->mode & (BOLD_MODE|UNDERLINE_MODE)) == (BOLD_MODE|UNDERLINE_MODE))
+ f->mode = (f->mode & ~(BOLD_MODE|UNDERLINE_MODE)) | bold_underline_mode;
+ return f;
+}
+
+tty_font::tty_font(const char *nm)
+: font(nm), mode(0)
+{
+}
+
+tty_font::~tty_font()
+{
+}
+
+#if 0
+void tty_font::handle_x_command(int argc, const char **argv)
+{
+ if (argc >= 1 && strcmp(argv[0], "bold") == 0)
+ mode |= BOLD_MODE;
+ else if (argc >= 1 && strcmp(argv[0], "underline") == 0)
+ mode |= UNDERLINE_MODE;
+}
+#endif
+
+class glyph {
+ static glyph *free_list;
+public:
+ glyph *next;
+ short hpos;
+ unsigned int code;
+ unsigned char mode;
+ void *operator new(size_t);
+ void operator delete(void *);
+ inline int draw_mode() { return mode & (VDRAW_MODE|HDRAW_MODE); }
+};
+
+glyph *glyph::free_list = 0;
+
+void *glyph::operator new(size_t)
+{
+ if (!free_list) {
+ const int BLOCK = 1024;
+ free_list = (glyph *)new char[sizeof(glyph)*BLOCK];
+ for (int i = 0; i < BLOCK - 1; i++)
+ free_list[i].next = free_list + i + 1;
+ free_list[BLOCK - 1].next = 0;
+ }
+ glyph *p = free_list;
+ free_list = free_list->next;
+ p->next = 0;
+ return p;
+}
+
+void glyph::operator delete(void *p)
+{
+ if (p) {
+ ((glyph *)p)->next = free_list;
+ free_list = (glyph *)p;
+ }
+}
+
+class tty_printer : public printer {
+ int is_utf8;
+ glyph **lines;
+ int nlines;
+ int cached_v;
+ int cached_vpos;
+ void add_char(unsigned int, int, int, unsigned char);
+public:
+ tty_printer(const char *device);
+ ~tty_printer();
+ void set_char(int, font *, const environment *, int, const char *name);
+ void draw(int code, int *p, int np, const environment *env);
+ void put_char(unsigned int);
+ void begin_page(int) { }
+ void end_page(int page_length);
+ font *make_font(const char *);
+};
+
+tty_printer::tty_printer(const char *device) : cached_v(0)
+{
+ is_utf8 = !strcmp(device,"utf8");
+ nlines = 66;
+ lines = new glyph *[nlines];
+ for (int i = 0; i < nlines; i++)
+ lines[i] = 0;
+}
+
+tty_printer::~tty_printer()
+{
+ a_delete lines;
+}
+
+void tty_printer::set_char(int i, font *f, const environment *env, int w, const char *name)
+{
+ if (w != font::hor)
+ fatal("width of character not equal to horizontal resolution");
+ add_char(f->get_code(i), env->hpos, env->vpos, ((tty_font *)f)->get_mode());
+}
+
+void tty_printer::add_char(unsigned int c, int h, int v, unsigned char mode)
+{
+#if 0
+ // This is too expensive.
+ if (h % font::hor != 0)
+ fatal("horizontal position not a multiple of horizontal resolution");
+#endif
+ int hpos = h / font::hor;
+ if (hpos < SHRT_MIN || hpos > SHRT_MAX) {
+ error("character with ridiculous horizontal position discarded");
+ return;
+ }
+ int vpos;
+ if (v == cached_v && cached_v != 0)
+ vpos = cached_vpos;
+ else {
+ if (v % font::vert != 0)
+ fatal("vertical position not a multiple of vertical resolution");
+ vpos = v / font::vert;
+ if (vpos > nlines) {
+ glyph **old_lines = lines;
+ lines = new glyph *[vpos + 1];
+ memcpy(lines, old_lines, nlines*sizeof(glyph *));
+ for (int i = nlines; i <= vpos; i++)
+ lines[i] = 0;
+ a_delete old_lines;
+ nlines = vpos + 1;
+ }
+ // Note that the first output line corresponds to groff
+ // position font::vert.
+ if (vpos <= 0) {
+ error("character above first line discarded");
+ return;
+ }
+ cached_v = v;
+ cached_vpos = vpos;
+ }
+ glyph *g = new glyph;
+ g->hpos = hpos;
+ g->code = c;
+ g->mode = mode;
+
+ // The list will be reversed later. After reversal, it must be in
+ // increasing order of hpos, with HDRAW characters before VDRAW
+ // characters before normal characters at each hpos, and otherwise
+ // in order of occurrence.
+
+ glyph **pp;
+ for (pp = lines + (vpos - 1); *pp; pp = &(*pp)->next)
+ if ((*pp)->hpos < hpos
+ || ((*pp)->hpos == hpos && (*pp)->draw_mode() >= g->draw_mode()))
+ break;
+
+ g->next = *pp;
+ *pp = g;
+}
+
+void tty_printer::draw(int code, int *p, int np, const environment *env)
+{
+ if (code != 'l' || !draw_flag)
+ return;
+ if (np != 2) {
+ error("2 arguments required for line");
+ return;
+ }
+ if (p[0] == 0) {
+ // vertical line
+ int v = env->vpos;
+ int len = p[1];
+ if (len < 0) {
+ v += len;
+ len = -len;
+ }
+ while (len >= 0) {
+ add_char('|', env->hpos, v, VDRAW_MODE);
+ len -= font::vert;
+ v += font::vert;
+ }
+ }
+ if (p[1] == 0) {
+ // horizontal line
+ int h = env->hpos;
+ int len = p[0];
+ if (len < 0) {
+ h += len;
+ len = -len;
+ }
+ while (len >= 0) {
+ add_char('-', h, env->vpos, HDRAW_MODE);
+ len -= font::hor;
+ h += font::hor;
+ }
+ }
+}
+
+void tty_printer::put_char (unsigned int wc)
+{
+ if (is_utf8 && wc >= 0x80) {
+ char buf[6+1];
+ int count;
+ char *p = buf;
+ if (wc < 0x800)
+ count = 1, *p = (unsigned char) ((wc >> 6) | 0xC0);
+ else if (wc < 0x10000)
+ count = 2, *p = (unsigned char) ((wc >> 12) | 0xE0);
+ else if (wc < 0x200000)
+ count = 3, *p = (unsigned char) ((wc >> 18) | 0xF0);
+ else if (wc < 0x4000000)
+ count = 4, *p = (unsigned char) ((wc >> 24) | 0xF8);
+ else if (wc <= 0x7FFFFFFF)
+ count = 5, *p = (unsigned char) ((wc >> 30) | 0xFC);
+ else
+ return;
+ do *++p = (unsigned char)(((wc >> (6 * --count)) & 0x3F) | 0x80);
+ while (count > 0);
+ *++p = '\0';
+ fputs(buf,stdout);
+ } else {
+ putchar(wc);
+ }
+}
+
+void tty_printer::end_page(int page_length)
+{
+ if (page_length % font::vert != 0)
+ error("vertical position at end of page not multiple of vertical resolution");
+ int lines_per_page = page_length / font::vert;
+ int last_line;
+ for (last_line = nlines; last_line > 0; last_line--)
+ if (lines[last_line - 1])
+ break;
+#if 0
+ if (last_line > lines_per_page) {
+ error("characters past last line discarded");
+ do {
+ --last_line;
+ while (lines[last_line]) {
+ glyph *tem = lines[last_line];
+ lines[last_line] = tem->next;
+ delete tem;
+ }
+ } while (last_line > lines_per_page);
+ }
+#endif
+ for (int i = 0; i < last_line; i++) {
+ glyph *p = lines[i];
+ lines[i] = 0;
+ glyph *g = 0;
+ while (p) {
+ glyph *tem = p->next;
+ p->next = g;
+ g = p;
+ p = tem;
+ }
+ int hpos = 0;
+
+ glyph *nextp;
+ for (p = g; p; delete p, p = nextp) {
+ nextp = p->next;
+ if (nextp && p->hpos == nextp->hpos) {
+ if (p->draw_mode() == HDRAW_MODE && nextp->draw_mode() == VDRAW_MODE) {
+ nextp->code = '+';
+ continue;
+ }
+ if (p->draw_mode() != 0 && p->draw_mode() == nextp->draw_mode()) {
+ nextp->code = p->code;
+ continue;
+ }
+ if (!overstrike_flag)
+ continue;
+ }
+ if (hpos > p->hpos) {
+ do {
+ putchar('\b');
+ hpos--;
+ } while (hpos > p->hpos);
+ }
+ else {
+ if (horizontal_tab_flag) {
+ for (;;) {
+ int next_tab_pos = ((hpos + TAB_WIDTH) / TAB_WIDTH) * TAB_WIDTH;
+ if (next_tab_pos > p->hpos)
+ break;
+ putchar('\t');
+ hpos = next_tab_pos;
+ }
+ }
+ for (; hpos < p->hpos; hpos++)
+ putchar(' ');
+ }
+ assert(hpos == p->hpos);
+ if (p->mode & UNDERLINE_MODE) {
+ putchar('_');
+ putchar('\b');
+ }
+ if (p->mode & BOLD_MODE) {
+ put_char(p->code);
+ putchar('\b');
+ }
+ put_char(p->code);
+ hpos++;
+ }
+ putchar('\n');
+ }
+ if (form_feed_flag) {
+ if (last_line < lines_per_page)
+ putchar('\f');
+ }
+ else {
+ for (; last_line < lines_per_page; last_line++)
+ putchar('\n');
+ }
+}
+
+font *tty_printer::make_font(const char *nm)
+{
+ return tty_font::load_tty_font(nm);
+}
+
+printer *make_printer()
+{
+ return new tty_printer(device);
+}
+
+static void usage();
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int c;
+ while ((c = getopt(argc, argv, "F:vhfbuoBUd")) != EOF)
+ switch(c) {
+ case 'v':
+ {
+ extern const char *Version_string;
+ fprintf(stderr, "grotty version %s\n", Version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'b':
+ // Do not embolden by overstriking.
+ bold_flag = 0;
+ break;
+ case 'u':
+ // Do not underline.
+ underline_flag = 0;
+ break;
+ case 'o':
+ // Do not overstrike (other than emboldening and underlining).
+ overstrike_flag = 0;
+ break;
+ case 'B':
+ // Do bold-underlining as bold.
+ bold_underline_mode = BOLD_MODE;
+ break;
+ case 'U':
+ // Do bold-underlining as underlining.
+ bold_underline_mode = UNDERLINE_MODE;
+ break;
+ case 'h':
+ // Use horizontal tabs.
+ horizontal_tab_flag = 1;
+ break;
+ case 'f':
+ form_feed_flag = 1;
+ break;
+ case 'F':
+ font::command_line_font_dir(optarg);
+ break;
+ case 'd':
+ // Ignore \D commands.
+ draw_flag = 0;
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ }
+ if (optind >= argc)
+ do_file("-");
+ else {
+ for (int i = optind; i < argc; i++)
+ do_file(argv[i]);
+ }
+ delete pr;
+ return 0;
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-hfvbuodBU] [-F dir] [files ...]\n",
+ program_name);
+ exit(1);
+}
diff --git a/src/include/Makefile.sub b/src/include/Makefile.sub
new file mode 100644
index 00000000..191c4ccf
--- /dev/null
+++ b/src/include/Makefile.sub
@@ -0,0 +1,22 @@
+HDRS=\
+ assert.h cmap.h cset.h device.h driver.h errarg.h error.h font.h index.h \
+ lib.h macropath.h printer.h ptable.h refid.h search.h searchpath.h \
+ stringclass.h
+GENHDRS=defs.h
+CLEANADD=$(GENHDRS)
+
+all depend: $(GENHDRS)
+
+defs.h: FORCE
+ @$(SHELL) $(top_srcdir)/gendef.sh defs.h \
+ "PROG_PREFIX=\"$(g)\"" \
+ "DEVICE=\"$(DEVICE)\"" \
+ "FONTPATH=\"$(fontpath)\"" \
+ "MACROPATH=\"$(tmacpath)\"" \
+ "INDEX_SUFFIX=\"$(indexext)\"" \
+ "COMMON_WORDS_FILE=\"$(common_words_file)\"" \
+ "DEFAULT_INDEX_DIR=\"$(indexdir)\"" \
+ "DEFAULT_INDEX_NAME=\"$(indexname)\"" \
+ "DEFAULT_INDEX=\"$(indexdir)/$(indexname)\""
+
+FORCE:
diff --git a/src/include/assert.h b/src/include/assert.h
new file mode 100644
index 00000000..18d9c262
--- /dev/null
+++ b/src/include/assert.h
@@ -0,0 +1,39 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef ASSERT_H
+#define ASSERT_H
+
+void assertion_failed(int, const char *);
+
+inline void do_assert(int expr, int line, const char *file)
+{
+ if (!expr)
+ assertion_failed(line, file);
+}
+#endif /* ASSERT_H */
+
+#undef assert
+
+#ifdef NDEBUG
+#define assert(ignore) /* as nothing */
+#else
+#define assert(expr) do_assert(expr, __LINE__, __FILE__)
+#endif
diff --git a/src/include/cmap.h b/src/include/cmap.h
new file mode 100644
index 00000000..1537d462
--- /dev/null
+++ b/src/include/cmap.h
@@ -0,0 +1,56 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef UCHAR_MAX
+#define UCHAR_MAX 255
+#endif
+
+enum cmap_builtin { CMAP_BUILTIN };
+
+class cmap {
+public:
+ cmap();
+ cmap(cmap_builtin);
+ int operator()(unsigned char) const;
+ unsigned char &operator[](unsigned char);
+
+ friend class cmap_init;
+private:
+ unsigned char v[UCHAR_MAX+1];
+};
+
+inline int cmap::operator()(unsigned char c) const
+{
+ return v[c];
+}
+
+inline unsigned char &cmap::operator[](unsigned char c)
+{
+ return v[c];
+}
+
+extern cmap cmlower;
+extern cmap cmupper;
+
+static class cmap_init {
+ static int initialised;
+public:
+ cmap_init();
+} _cmap_init;
diff --git a/src/include/cset.h b/src/include/cset.h
new file mode 100644
index 00000000..b3a1a976
--- /dev/null
+++ b/src/include/cset.h
@@ -0,0 +1,75 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CC_LIMITS_H
+#include <limits.h>
+#else /* not HAVE_CC_LIMITS_H */
+#ifndef UCHAR_MAX
+#define UCHAR_MAX 255
+#endif
+#endif /* not HAVE_CC_LIMITS_H */
+
+enum cset_builtin { CSET_BUILTIN };
+
+class cset {
+public:
+ cset();
+ cset(cset_builtin);
+ cset(const char *);
+ cset(const unsigned char *);
+ int operator()(unsigned char) const;
+
+ cset &operator|=(const cset &);
+ cset &operator|=(unsigned char);
+
+ friend class cset_init;
+private:
+ char v[UCHAR_MAX+1];
+ void clear();
+};
+
+inline int cset::operator()(unsigned char c) const
+{
+ return v[c];
+}
+
+inline cset &cset::operator|=(unsigned char c)
+{
+ v[c] = 1;
+ return *this;
+}
+
+extern cset csalpha;
+extern cset csupper;
+extern cset cslower;
+extern cset csdigit;
+extern cset csxdigit;
+extern cset csspace;
+extern cset cspunct;
+extern cset csalnum;
+extern cset csprint;
+extern cset csgraph;
+extern cset cscntrl;
+
+static class cset_init {
+ static int initialised;
+public:
+ cset_init();
+} _cset_init;
diff --git a/src/include/device.h b/src/include/device.h
new file mode 100644
index 00000000..341af8d2
--- /dev/null
+++ b/src/include/device.h
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+extern const char *device;
diff --git a/src/include/driver.h b/src/include/driver.h
new file mode 100644
index 00000000..c18cdd42
--- /dev/null
+++ b/src/include/driver.h
@@ -0,0 +1,36 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <errno.h>
+#include <assert.h>
+#include <math.h>
+#include "errarg.h"
+#include "error.h"
+#include "font.h"
+#include "printer.h"
+#include "lib.h"
+
+void do_file(const char *);
+extern printer *pr;
diff --git a/src/include/errarg.h b/src/include/errarg.h
new file mode 100644
index 00000000..0c7957c8
--- /dev/null
+++ b/src/include/errarg.h
@@ -0,0 +1,46 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+class errarg {
+ enum { EMPTY, STRING, CHAR, INTEGER, DOUBLE } type;
+ union {
+ const char *s;
+ int n;
+ char c;
+ double d;
+ };
+ public:
+ errarg();
+ errarg(const char *);
+ errarg(char);
+ errarg(unsigned char);
+ errarg(int);
+ errarg(double);
+ int empty() const;
+ void print() const;
+};
+
+extern errarg empty_errarg;
+
+extern void errprint(const char *,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
diff --git a/src/include/error.h b/src/include/error.h
new file mode 100644
index 00000000..d26e2c70
--- /dev/null
+++ b/src/include/error.h
@@ -0,0 +1,58 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+extern void fatal_with_file_and_line(const char *filename, int lineno,
+ const char *format,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+extern void error_with_file_and_line(const char *filename, int lineno,
+ const char *format,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+extern void warning_with_file_and_line(const char *filename, int lineno,
+ const char *format,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+extern void fatal(const char *,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+extern void error(const char *,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+extern void warning(const char *,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+
+extern const char *program_name;
+extern int current_lineno;
+extern const char *current_filename;
+
diff --git a/src/include/font.h b/src/include/font.h
new file mode 100644
index 00000000..099f97be
--- /dev/null
+++ b/src/include/font.h
@@ -0,0 +1,116 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+typedef void (*FONT_COMMAND_HANDLER)(const char *, const char *,
+ const char *, int);
+
+struct font_kern_list;
+struct font_char_metric;
+struct font_widths_cache;
+
+class font {
+public:
+ enum {
+ LIG_ff = 1,
+ LIG_fi = 2,
+ LIG_fl = 4,
+ LIG_ffi = 8,
+ LIG_ffl = 16
+ };
+
+ virtual ~font();
+ int contains(int index);
+ int is_special();
+ int get_width(int index, int point_size);
+ int get_height(int index, int point_size);
+ int get_depth(int index, int point_size);
+ int get_space_width(int point_size);
+ int get_character_type(int index);
+ int get_kern(int index1, int index2, int point_size);
+ int get_skew(int index, int point_size, int slant);
+ int has_ligature(int);
+ int get_italic_correction(int index, int point_size);
+ int get_left_italic_correction(int index, int point_size);
+ int get_subscript_correction(int index, int point_size);
+ int get_code(int i);
+ const char *get_special_device_encoding(int index);
+ const char *get_name();
+ const char *get_internal_name();
+
+ static font *load_font(const char *, int *not_found = 0);
+ static void command_line_font_dir(const char *path);
+ static FILE *open_file(const char *name, char **pathp);
+ static int load_desc();
+ static int name_to_index(const char *);
+ static int number_to_index(int);
+ static FONT_COMMAND_HANDLER
+ set_unknown_desc_command_handler(FONT_COMMAND_HANDLER);
+
+ static int res;
+ static int hor;
+ static int vert;
+ static int unitwidth;
+ static int paperwidth;
+ static int paperlength;
+ static int biggestfont;
+ static int spare2;
+ static int sizescale;
+ static int tcommand;
+ static int pass_filenames;
+ static int use_charnames_in_special;
+
+ static const char **font_name_table;
+ static const char **style_table;
+ static const char *family;
+ static int *sizes;
+private:
+ unsigned ligatures;
+ font_kern_list **kern_hash_table;
+ int space_width;
+ short *ch_index;
+ int nindices;
+ font_char_metric *ch;
+ int ch_used;
+ int ch_size;
+ int special;
+ char *name;
+ char *internalname;
+ double slant;
+ font_widths_cache *widths_cache;
+ static FONT_COMMAND_HANDLER unknown_desc_command_handler;
+
+ enum { KERN_HASH_TABLE_SIZE = 503 };
+
+ void add_entry(int index, const font_char_metric &);
+ void copy_entry(int new_index, int old_index);
+ void add_kern(int index1, int index2, int amount);
+ static int hash_kern(int i1, int i2);
+ void alloc_ch_index(int);
+ void extend_ch();
+ void compact();
+
+ static int scale(int w, int pointsize);
+ virtual void handle_unknown_font_command(const char *command,
+ const char *arg,
+ const char *file, int lineno);
+protected:
+ font(const char *);
+ int load(int *not_found = 0);
+};
diff --git a/src/include/index.h b/src/include/index.h
new file mode 100644
index 00000000..7e608138
--- /dev/null
+++ b/src/include/index.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define INDEX_MAGIC 0x23021964
+#define INDEX_VERSION 1
+
+struct index_header {
+ int magic;
+ int version;
+ int tags_size;
+ int table_size;
+ int lists_size;
+ int strings_size;
+ int truncate;
+ int shortest;
+ int common;
+};
+
+struct tag {
+ int filename_index;
+ int start;
+ int length;
+};
+
+unsigned hash(const char *s, int len);
diff --git a/src/include/lib.h b/src/include/lib.h
new file mode 100644
index 00000000..b309a77b
--- /dev/null
+++ b/src/include/lib.h
@@ -0,0 +1,129 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+extern "C" {
+#ifndef strerror
+ char *strerror(int);
+#endif
+#ifndef __BORLANDC__
+ const char *itoa(int);
+ const char *iftoa(int, int);
+#endif /* __BORLANDC__ */
+}
+
+#ifdef STDLIB_H_DECLARES_GETOPT
+#include <stdlib.h>
+#else /* not STDLIB_H_DECLARES_GETOPT */
+#ifdef UNISTD_H_DECLARES_GETOPT
+#include <sys/types.h>
+#include <unistd.h>
+#else /* not UNISTD_H_DECLARES_GETOPT */
+extern "C" {
+ int getopt(int, char *const *, const char *);
+}
+#endif /* not UNISTD_H_DECLARES_GETOPT */
+
+extern "C" {
+ extern char *optarg;
+ extern int optind;
+ extern int opterr;
+}
+
+#endif /* not STDLIB_H_DECLARES_GETOPT */
+
+char *strsave(const char *s);
+int is_prime(unsigned);
+
+#include <stdio.h>
+
+FILE *xtmpfile();
+
+#ifndef STDIO_H_DECLARES_POPEN
+
+extern "C" { FILE *popen(const char *, const char *); }
+
+#endif /* not STDIO_H_DECLARES_POPEN */
+
+#ifndef STDIO_H_DECLARES_PCLOSE
+
+extern "C" { int pclose (FILE *); }
+
+#endif /* not STDIO_H_DECLARES_PCLOSE */
+
+int interpret_lf_args(const char *p);
+
+extern char illegal_char_table[];
+
+inline int illegal_input_char(int c)
+{
+ return c >= 0 && illegal_char_table[c];
+}
+
+#ifndef HAVE_STRCASECMP
+# define strcasecmp(a,b) strcmp((a),(b))
+#endif
+
+#ifdef HAVE_CC_LIMITS_H
+#include <limits.h>
+#else /* not HAVE_CC_LIMITS_H */
+#define INT_MAX 2147483647
+#endif /* not HAVE_CC_LIMITS_H */
+
+/* It's not safe to rely on people getting INT_MIN right (ie signed). */
+
+#ifdef INT_MIN
+#undef INT_MIN
+#endif
+
+#ifdef CFRONT_ANSI_BUG
+
+/* This works around a bug in cfront 2.0 used with ANSI C compilers. */
+
+#define INT_MIN ((long)(-INT_MAX-1))
+
+#else /* not CFRONT_ANSI_BUG */
+
+#define INT_MIN (-INT_MAX-1)
+
+#endif /* not CFRONT_ANSI_BUG */
+
+/* Maximum number of digits in the decimal representation of an int
+(not including the -). */
+
+#define INT_DIGITS 10
+
+#ifdef PI
+#undef PI
+#endif
+
+const double PI = 3.14159265358979323846;
+
+/* ad_delete deletes an array of objects with destructors;
+a_delete deletes an array of objects without destructors */
+
+#ifdef ARRAY_DELETE_NEEDS_SIZE
+/* for 2.0 systems */
+#define ad_delete(size) delete [size]
+#define a_delete delete
+#else /* not ARRAY_DELETE_NEEDS_SIZE */
+/* for ARM systems */
+#define ad_delete(size) delete []
+#define a_delete delete []
+#endif /* not ARRAY_DELETE_NEEDS_SIZE */
diff --git a/src/include/macropath.h b/src/include/macropath.h
new file mode 100644
index 00000000..4aa2f00c
--- /dev/null
+++ b/src/include/macropath.h
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+extern search_path macro_path;
diff --git a/src/include/posix.h b/src/include/posix.h
new file mode 100644
index 00000000..312e49b7
--- /dev/null
+++ b/src/include/posix.h
@@ -0,0 +1,49 @@
+// -*- C++ -*-
+/* Copyright (C) 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_CC_OSFCN_H
+#include <osfcn.h>
+#else
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+
+#ifndef S_IRUSR
+#define S_IRUSR 0400
+#endif
+
+#ifndef S_IRGRP
+#define S_IRGRP 0040
+#endif
+
+#ifndef S_IROTH
+#define S_IROTH 0004
+#endif
+
+#ifndef S_ISREG
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+
+#ifndef O_RDONLY
+#define O_RDONLY 0
+#endif
diff --git a/src/include/printer.h b/src/include/printer.h
new file mode 100644
index 00000000..974c9d5b
--- /dev/null
+++ b/src/include/printer.h
@@ -0,0 +1,76 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+struct environment {
+ int fontno;
+ int size;
+ int hpos;
+ int vpos;
+ int height;
+ int slant;
+};
+
+struct font;
+
+struct font_pointer_list {
+ font *p;
+ font_pointer_list *next;
+
+ font_pointer_list(font *, font_pointer_list *);
+};
+
+class printer {
+public:
+ printer();
+ virtual ~printer();
+ void load_font(int i, const char *name);
+ void set_ascii_char(unsigned char c, const environment *env,
+ int *widthp = 0);
+ void set_special_char(const char *nm, const environment *env,
+ int *widthp = 0);
+ void set_numbered_char(int n, const environment *env, int *widthp = 0);
+ int set_char_and_width(const char *nm, const environment *env,
+ int *widthp, font **f);
+ virtual void draw(int code, int *p, int np, const environment *env);
+ virtual void begin_page(int) = 0;
+ virtual void end_page(int page_length) = 0;
+ virtual font *make_font(const char *nm);
+ virtual void end_of_line();
+ virtual void special(char *arg, const environment *env);
+ static int adjust_arc_center(const int *, double *);
+protected:
+ font_pointer_list *font_list;
+
+ // information about named characters
+ int is_char_named;
+ int is_named_set;
+ char named_command;
+ const char *named_char_s;
+ int named_char_n;
+
+private:
+ font **font_table;
+ int nfonts;
+ font *find_font(const char *);
+ virtual void set_char(int index, font *f, const environment *env,
+ int w, const char *name) = 0;
+};
+
+printer *make_printer();
diff --git a/src/include/ptable.h b/src/include/ptable.h
new file mode 100644
index 00000000..dc56add0
--- /dev/null
+++ b/src/include/ptable.h
@@ -0,0 +1,168 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <assert.h>
+#include <string.h>
+
+#ifdef TRADITIONAL_CPP
+#define name2(a,b) a/**/b
+#else /* not TRADITIONAL_CPP */
+#define name2(a,b) name2x(a,b)
+#define name2x(a,b) a ## b
+#endif /* not TRADITIONAL_CPP */
+
+#define PTABLE(T) name2(T,_ptable)
+#define PASSOC(T) name2(T,_passoc)
+#define PTABLE_ITERATOR(T) name2(T,_ptable_iterator)
+
+extern unsigned next_ptable_size(unsigned);
+extern unsigned long hash_string(const char *);
+
+#define declare_ptable(T) \
+ \
+struct PASSOC(T) { \
+ char *key; \
+ T *val; \
+ PASSOC(T)(); \
+}; \
+ \
+struct PTABLE(T); \
+ \
+class PTABLE_ITERATOR(T) { \
+ PTABLE(T) *p; \
+ unsigned i; \
+public: \
+ PTABLE_ITERATOR(T)(PTABLE(T) *); \
+ int next(const char **, T **); \
+}; \
+ \
+class PTABLE(T) { \
+ PASSOC(T) *v; \
+ unsigned size; \
+ unsigned used; \
+ enum { FULL_NUM = 2, FULL_DEN = 3, INITIAL_SIZE = 17 }; \
+public: \
+ PTABLE(T)(); \
+ ~PTABLE(T)(); \
+ void define(const char *, T *); \
+ T *lookup(const char *); \
+ friend class PTABLE_ITERATOR(T); \
+};
+
+
+#define implement_ptable(T) \
+ \
+PASSOC(T)::PASSOC(T)() \
+: key(0), val(0) \
+{ \
+} \
+ \
+PTABLE(T)::PTABLE(T)() \
+{ \
+ v = new PASSOC(T)[size = INITIAL_SIZE]; \
+ used = 0; \
+} \
+ \
+PTABLE(T)::~PTABLE(T)() \
+{ \
+ for (unsigned i = 0; i < size; i++) { \
+ a_delete v[i].key; \
+ delete v[i].val; \
+ } \
+ a_delete v; \
+} \
+ \
+void PTABLE(T)::define(const char *key, T *val) \
+{ \
+ assert(key != 0); \
+ unsigned long h = hash_string(key); \
+ unsigned n; \
+ for (n = unsigned(h % size); \
+ v[n].key != 0; \
+ n = (n == 0 ? size - 1 : n - 1)) \
+ if (strcmp(v[n].key, key) == 0) { \
+ delete v[n].val; \
+ v[n].val = val; \
+ return; \
+ } \
+ if (val == 0) \
+ return; \
+ if (used*FULL_DEN >= size*FULL_NUM) { \
+ PASSOC(T) *oldv = v; \
+ unsigned old_size = size; \
+ size = next_ptable_size(size); \
+ v = new PASSOC(T)[size]; \
+ for (unsigned i = 0; i < old_size; i++) \
+ if (oldv[i].key != 0) { \
+ if (oldv[i].val == 0) \
+ a_delete oldv[i].key; \
+ else { \
+ unsigned j; \
+ for (j = unsigned(hash_string(oldv[i].key) % size); \
+ v[j].key != 0; \
+ j = (j == 0 ? size - 1 : j - 1)) \
+ ; \
+ v[j].key = oldv[i].key; \
+ v[j].val = oldv[i].val; \
+ } \
+ } \
+ for (n = unsigned(h % size); \
+ v[n].key != 0; \
+ n = (n == 0 ? size - 1 : n - 1)) \
+ ; \
+ a_delete oldv; \
+ } \
+ char *temp = new char[strlen(key)+1]; \
+ strcpy(temp, key); \
+ v[n].key = temp; \
+ v[n].val = val; \
+ used++; \
+} \
+ \
+T *PTABLE(T)::lookup(const char *key) \
+{ \
+ assert(key != 0); \
+ for (unsigned n = unsigned(hash_string(key) % size); \
+ v[n].key != 0; \
+ n = (n == 0 ? size - 1 : n - 1)) \
+ if (strcmp(v[n].key, key) == 0) \
+ return v[n].val; \
+ return 0; \
+} \
+ \
+PTABLE_ITERATOR(T)::PTABLE_ITERATOR(T)(PTABLE(T) *t) \
+: p(t), i(0) \
+{ \
+} \
+ \
+int PTABLE_ITERATOR(T)::next(const char **keyp, T **valp) \
+{ \
+ unsigned size = p->size; \
+ PASSOC(T) *v = p->v; \
+ for (; i < size; i++) \
+ if (v[i].key != 0) { \
+ *keyp = v[i].key; \
+ *valp = v[i].val; \
+ i++; \
+ return 1; \
+ } \
+ return 0; \
+}
+
diff --git a/src/include/refid.h b/src/include/refid.h
new file mode 100644
index 00000000..605427e9
--- /dev/null
+++ b/src/include/refid.h
@@ -0,0 +1,35 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+class reference_id {
+ int filename_id;
+ int pos;
+public:
+ reference_id() : filename_id(-1) { }
+ reference_id(int fid, int off) : filename_id(fid), pos(off) { }
+ unsigned hash() const { return (filename_id << 4) + pos; }
+ int is_null() const { return filename_id < 0; }
+ friend inline int operator==(const reference_id &, const reference_id &);
+};
+
+inline int operator==(const reference_id &r1, const reference_id &r2)
+{
+ return r1.filename_id == r2.filename_id && r1.pos == r2.pos;
+}
diff --git a/src/include/search.h b/src/include/search.h
new file mode 100644
index 00000000..260410e2
--- /dev/null
+++ b/src/include/search.h
@@ -0,0 +1,96 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+struct search_item;
+struct search_item_iterator;
+
+class search_list {
+public:
+ search_list();
+ ~search_list();
+ void add_file(const char *fn, int silent = 0);
+ int nfiles() const;
+private:
+ search_item *list;
+ int niterators;
+ int next_fid;
+ friend class search_list_iterator;
+};
+
+struct bmpattern;
+
+class linear_searcher {
+ const char *ignore_fields;
+ int truncate_len;
+ bmpattern **keys;
+ int nkeys;
+ const char *search_and_check(const bmpattern *key, const char *buf,
+ const char *bufend, const char **start = 0)
+ const;
+ int check_match(const char *buf, const char *bufend, const char *match,
+ int matchlen, const char **cont, const char **start)
+ const;
+public:
+ linear_searcher(const char *query, int query_len,
+ const char *ign, int trunc);
+ ~linear_searcher();
+ int search(const char *buf, const char *bufend,
+ const char **startp, int *lengthp) const;
+};
+
+class search_list_iterator {
+ search_list *list;
+ search_item *ptr;
+ search_item_iterator *iter;
+ char *query;
+ linear_searcher searcher;
+public:
+ search_list_iterator(search_list *, const char *query);
+ ~search_list_iterator();
+ int next(const char **, int *, reference_id * = 0);
+};
+
+class search_item {
+protected:
+ char *name;
+ int filename_id;
+public:
+ search_item *next;
+ search_item(const char *nm, int fid);
+ virtual search_item_iterator *make_search_item_iterator(const char *) = 0;
+ virtual ~search_item();
+ int is_named(const char *) const;
+ virtual int next_filename_id() const;
+};
+
+class search_item_iterator {
+ char shut_g_plus_plus_up;
+public:
+ virtual ~search_item_iterator();
+ virtual int next(const linear_searcher &, const char **ptr, int *lenp,
+ reference_id *) = 0;
+};
+
+search_item *make_index_search_item(const char *filename, int fid);
+search_item *make_linear_search_item(int fd, const char *filename, int fid);
+
+extern int linear_truncate_len;
+extern const char *linear_ignore_fields;
+extern int verify_flag;
diff --git a/src/include/searchpath.h b/src/include/searchpath.h
new file mode 100644
index 00000000..d1cb2eee
--- /dev/null
+++ b/src/include/searchpath.h
@@ -0,0 +1,29 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+class search_path {
+ char *dirs;
+ unsigned init_len;
+public:
+ search_path(const char *envvar, const char *standard);
+ ~search_path();
+ void command_line_dir(const char *);
+ FILE *open_file(const char *, char **);
+};
diff --git a/src/include/stringclass.h b/src/include/stringclass.h
new file mode 100644
index 00000000..be3a044f
--- /dev/null
+++ b/src/include/stringclass.h
@@ -0,0 +1,195 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+
+// Ensure that the first declaration of functions that are later
+// declared as inline declares them as inline.
+
+class string;
+
+inline string operator+(const string &, const string &);
+inline string operator+(const string &, const char *);
+inline string operator+(const char *, const string &);
+inline string operator+(const string &, char);
+inline string operator+(char, const string &);
+inline int operator==(const string &, const string &);
+inline int operator!=(const string &, const string &);
+
+class string {
+public:
+ string();
+ string(const string &);
+ string(const char *);
+ string(const char *, int);
+ string(char);
+
+ ~string();
+
+ string &operator=(const string &);
+ string &operator=(const char *);
+ string &operator=(char);
+
+ string &operator+=(const string &);
+ string &operator+=(const char *);
+ string &operator+=(char);
+ void append(const char *, int);
+
+ int length() const;
+ int empty() const;
+ int operator*() const;
+
+ string substring(int i, int n) const;
+
+ char &operator[](int);
+ char operator[](int) const;
+
+ void set_length(int i);
+ const char *contents() const;
+ int search(char) const;
+ char *extract() const;
+ void clear();
+ void move(string &);
+
+ friend string operator+(const string &, const string &);
+ friend string operator+(const string &, const char *);
+ friend string operator+(const char *, const string &);
+ friend string operator+(const string &, char);
+ friend string operator+(char, const string &);
+
+ friend int operator==(const string &, const string &);
+ friend int operator!=(const string &, const string &);
+ friend int operator<=(const string &, const string &);
+ friend int operator<(const string &, const string &);
+ friend int operator>=(const string &, const string &);
+ friend int operator>(const string &, const string &);
+
+private:
+ char *ptr;
+ int len;
+ int sz;
+
+ string(const char *, int, const char *, int); // for use by operator+
+ void grow1();
+};
+
+
+inline char &string::operator[](int i)
+{
+ assert(i >= 0 && i < len);
+ return ptr[i];
+}
+
+inline char string::operator[](int i) const
+{
+ assert(i >= 0 && i < len);
+ return ptr[i];
+}
+
+inline int string::length() const
+{
+ return len;
+}
+
+inline int string::empty() const
+{
+ return len == 0;
+}
+
+inline int string::operator*() const
+{
+ return len;
+}
+
+inline const char *string::contents() const
+{
+ return ptr;
+}
+
+inline string operator+(const string &s1, const string &s2)
+{
+ return string(s1.ptr, s1.len, s2.ptr, s2.len);
+}
+
+inline string operator+(const string &s1, const char *s2)
+{
+#ifdef __GNUG__
+ if (s2 == 0)
+ return s1;
+ else
+ return string(s1.ptr, s1.len, s2, strlen(s2));
+#else
+ return s2 == 0 ? s1 : string(s1.ptr, s1.len, s2, strlen(s2));
+#endif
+}
+
+inline string operator+(const char *s1, const string &s2)
+{
+#ifdef __GNUG__
+ if (s1 == 0)
+ return s2;
+ else
+ return string(s1, strlen(s1), s2.ptr, s2.len);
+#else
+ return s1 == 0 ? s2 : string(s1, strlen(s1), s2.ptr, s2.len);
+#endif
+}
+
+inline string operator+(const string &s, char c)
+{
+ return string(s.ptr, s.len, &c, 1);
+}
+
+inline string operator+(char c, const string &s)
+{
+ return string(&c, 1, s.ptr, s.len);
+}
+
+inline int operator==(const string &s1, const string &s2)
+{
+ return (s1.len == s2.len
+ && (s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) == 0));
+}
+
+inline int operator!=(const string &s1, const string &s2)
+{
+ return (s1.len != s2.len
+ || (s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) != 0));
+}
+
+inline string string::substring(int i, int n) const
+{
+ assert(i >= 0 && i + n <= len);
+ return string(ptr + i, n);
+}
+
+inline string &string::operator+=(char c)
+{
+ if (len >= sz)
+ grow1();
+ ptr[len++] = c;
+ return *this;
+}
+
+void put_string(const string &, FILE *);
+
+string as_string(int);
diff --git a/src/include/unix.h b/src/include/unix.h
new file mode 100755
index 00000000..e69de29b
--- /dev/null
+++ b/src/include/unix.h
diff --git a/src/libs/libbib/Makefile.sub b/src/libs/libbib/Makefile.sub
new file mode 100644
index 00000000..482f01ab
--- /dev/null
+++ b/src/libs/libbib/Makefile.sub
@@ -0,0 +1,14 @@
+LIB=bib
+OBJS=\
+ common.o \
+ index.o \
+ linear.o \
+ search.o \
+ map.o
+CCSRCS=\
+ $(srcdir)/common.cc \
+ $(srcdir)/index.cc \
+ $(srcdir)/linear.cc \
+ $(srcdir)/search.cc
+CSRCS=\
+ $(srcdir)/map.c
diff --git a/src/libs/libbib/common.cc b/src/libs/libbib/common.cc
new file mode 100644
index 00000000..4b2bcca2
--- /dev/null
+++ b/src/libs/libbib/common.cc
@@ -0,0 +1,38 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+unsigned hash(const char *s, int len)
+{
+#if 0
+ unsigned h = 0, g;
+ while (*s != '\0') {
+ h <<= 4;
+ h += *s++;
+ if ((g = h & 0xf0000000) != 0) {
+ h ^= g >> 24;
+ h ^= g;
+ }
+ }
+#endif
+ unsigned h = 0;
+ while (--len >= 0)
+ h = *s++ + 65587*h;
+ return h;
+}
+
diff --git a/src/libs/libbib/index.cc b/src/libs/libbib/index.cc
new file mode 100644
index 00000000..6717fcbd
--- /dev/null
+++ b/src/libs/libbib/index.cc
@@ -0,0 +1,624 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "posix.h"
+#include "lib.h"
+#include "cset.h"
+#include "cmap.h"
+#include "errarg.h"
+#include "error.h"
+
+#include "refid.h"
+#include "search.h"
+#include "index.h"
+#include "defs.h"
+
+// Interface to mmap.
+extern "C" {
+ void *mapread(int fd, int len);
+ int unmap(void *, int len);
+}
+
+#if 0
+const
+#endif
+int minus_one = -1;
+
+int verify_flag = 0;
+
+struct word_list;
+
+class index_search_item : public search_item {
+ search_item *out_of_date_files;
+ index_header header;
+ char *buffer;
+ void *map_addr;
+ int map_len;
+ tag *tags;
+ int *table;
+ int *lists;
+ char *pool;
+ char *key_buffer;
+ char *filename_buffer;
+ int filename_buflen;
+ char **common_words_table;
+ int common_words_table_size;
+ const char *ignore_fields;
+ time_t mtime;
+
+ const char *do_verify();
+ const int *search1(const char **pp, const char *end);
+ const int *search(const char *ptr, int length, int **temp_listp);
+ const char *munge_filename(const char *);
+ void read_common_words_file();
+ void add_out_of_date_file(int fd, const char *filename, int fid);
+public:
+ index_search_item(const char *, int);
+ ~index_search_item();
+ int load(int fd);
+ search_item_iterator *make_search_item_iterator(const char *);
+ int verify();
+ void check_files();
+ int next_filename_id() const;
+ friend class index_search_item_iterator;
+};
+
+class index_search_item_iterator : public search_item_iterator {
+ index_search_item *indx;
+ search_item_iterator *out_of_date_files_iter;
+ search_item *next_out_of_date_file;
+ const int *found_list;
+ int *temp_list;
+ char *buf;
+ int buflen;
+ linear_searcher searcher;
+ char *query;
+ int get_tag(int tagno, const linear_searcher &, const char **, int *,
+ reference_id *);
+public:
+ index_search_item_iterator(index_search_item *, const char *);
+ ~index_search_item_iterator();
+ int next(const linear_searcher &, const char **, int *, reference_id *);
+};
+
+
+index_search_item::index_search_item(const char *filename, int fid)
+: search_item(filename, fid), out_of_date_files(0), buffer(0), map_addr(0),
+ map_len(0), key_buffer(0), filename_buffer(0), filename_buflen(0),
+ common_words_table(0)
+{
+}
+
+index_search_item::~index_search_item()
+{
+ if (buffer)
+ free(buffer);
+ if (map_addr) {
+ if (unmap(map_addr, map_len) < 0)
+ error("unmap: %1", strerror(errno));
+ }
+ while (out_of_date_files) {
+ search_item *tem = out_of_date_files;
+ out_of_date_files = out_of_date_files->next;
+ delete tem;
+ }
+ a_delete filename_buffer;
+ a_delete key_buffer;
+ if (common_words_table) {
+ for (int i = 0; i < common_words_table_size; i++)
+ a_delete common_words_table[i];
+ a_delete common_words_table;
+ }
+}
+
+class file_closer {
+ int *fdp;
+public:
+ file_closer(int &fd) : fdp(&fd) { }
+ ~file_closer() { close(*fdp); }
+};
+
+// Tell the compiler that a variable is intentionally unused.
+inline void unused(void *) { }
+
+int index_search_item::load(int fd)
+{
+ file_closer fd_closer(fd); // close fd on return
+ unused(&fd_closer);
+ struct stat sb;
+ if (fstat(fd, &sb) < 0) {
+ error("can't fstat `%1': %2", name, strerror(errno));
+ return 0;
+ }
+ if (!S_ISREG(sb.st_mode)) {
+ error("`%1' is not a regular file", name);
+ return 0;
+ }
+ mtime = sb.st_mtime;
+ int size = int(sb.st_size);
+ char *addr;
+ map_addr = mapread(fd, size);
+ if (map_addr) {
+ addr = (char *)map_addr;
+ map_len = size;
+ }
+ else {
+ addr = buffer = (char *)malloc(size);
+ if (buffer == 0) {
+ error("can't allocate buffer for `%1'", name);
+ return 0;
+ }
+ char *ptr = buffer;
+ int bytes_to_read = size;
+ while (bytes_to_read > 0) {
+ int nread = read(fd, ptr, bytes_to_read);
+ if (nread == 0) {
+ error("unexpected EOF on `%1'", name);
+ return 0;
+ }
+ if (nread < 0) {
+ error("read error on `%1': %2", name, strerror(errno));
+ return 0;
+ }
+ bytes_to_read -= nread;
+ ptr += nread;
+ }
+ }
+ header = *(index_header *)addr;
+ if (header.magic != INDEX_MAGIC) {
+ error("`%1' is not an index file: wrong magic number", name);
+ return 0;
+ }
+ if (header.version != INDEX_VERSION) {
+ error("version number in `%1' is wrong: was %2, should be %3",
+ name, header.version, INDEX_VERSION);
+ return 0;
+ }
+ int sz = (header.tags_size * sizeof(tag)
+ + header.lists_size * sizeof(int)
+ + header.table_size * sizeof(int)
+ + header.strings_size
+ + sizeof(header));
+ if (sz != size) {
+ error("size of `%1' is wrong: was %2, should be %3",
+ name, size, sz);
+ return 0;
+ }
+ tags = (tag *)(addr + sizeof(header));
+ lists = (int *)(tags + header.tags_size);
+ table = (int *)(lists + header.lists_size);
+ pool = (char *)(table + header.table_size);
+ ignore_fields = strchr(strchr(pool, '\0') + 1, '\0') + 1;
+ key_buffer = new char[header.truncate];
+ read_common_words_file();
+ return 1;
+}
+
+const char *index_search_item::do_verify()
+{
+ if (tags == 0)
+ return "not loaded";
+ if (lists[header.lists_size - 1] >= 0)
+ return "last list element not negative";
+ int i;
+ for (i = 0; i < header.table_size; i++) {
+ int li = table[i];
+ if (li >= header.lists_size)
+ return "bad list index";
+ if (li >= 0) {
+ for (int *ptr = lists + li; *ptr >= 0; ptr++) {
+ if (*ptr >= header.tags_size)
+ return "bad tag index";
+ if (*ptr >= ptr[1] && ptr[1] >= 0)
+ return "list not ordered";
+ }
+ }
+ }
+ for (i = 0; i < header.tags_size; i++) {
+ if (tags[i].filename_index >= header.strings_size)
+ return "bad index in tags";
+ if (tags[i].length < 0)
+ return "bad length in tags";
+ if (tags[i].start < 0)
+ return "bad start in tags";
+ }
+ if (pool[header.strings_size - 1] != '\0')
+ return "last character in pool not nul";
+ return 0;
+}
+
+int index_search_item::verify()
+{
+ const char *reason = do_verify();
+ if (!reason)
+ return 1;
+ error("`%1' is bad: %2", name, reason);
+ return 0;
+}
+
+int index_search_item::next_filename_id() const
+{
+ return filename_id + header.strings_size + 1;
+}
+
+search_item_iterator *index_search_item::make_search_item_iterator(
+ const char *query)
+{
+ return new index_search_item_iterator(this, query);
+}
+
+search_item *make_index_search_item(const char *filename, int fid)
+{
+ char *index_filename = new char[strlen(filename) + sizeof(INDEX_SUFFIX)];
+ strcpy(index_filename, filename);
+ strcat(index_filename, INDEX_SUFFIX);
+ int fd = open(index_filename, O_RDONLY);
+ if (fd < 0)
+ return 0;
+ index_search_item *item = new index_search_item(index_filename, fid);
+ a_delete index_filename;
+ if (!item->load(fd)) {
+ close(fd);
+ delete item;
+ return 0;
+ }
+ else if (verify_flag && !item->verify()) {
+ delete item;
+ return 0;
+ }
+ else {
+ item->check_files();
+ return item;
+ }
+}
+
+
+index_search_item_iterator::index_search_item_iterator(index_search_item *ind,
+ const char *q)
+: indx(ind), out_of_date_files_iter(0), next_out_of_date_file(0), temp_list(0),
+ buf(0), buflen(0),
+ searcher(q, strlen(q), ind->ignore_fields, ind->header.truncate),
+ query(strsave(q))
+{
+ found_list = indx->search(q, strlen(q), &temp_list);
+ if (!found_list) {
+ found_list = &minus_one;
+ warning("all keys would have been discarded in constructing index `%1'",
+ indx->name);
+ }
+}
+
+index_search_item_iterator::~index_search_item_iterator()
+{
+ a_delete temp_list;
+ a_delete buf;
+ a_delete query;
+ delete out_of_date_files_iter;
+}
+
+int index_search_item_iterator::next(const linear_searcher &,
+ const char **pp, int *lenp,
+ reference_id *ridp)
+{
+ if (found_list) {
+ for (;;) {
+ int tagno = *found_list;
+ if (tagno == -1)
+ break;
+ found_list++;
+ if (get_tag(tagno, searcher, pp, lenp, ridp))
+ return 1;
+ }
+ found_list = 0;
+ next_out_of_date_file = indx->out_of_date_files;
+ }
+ while (next_out_of_date_file) {
+ if (out_of_date_files_iter == 0)
+ out_of_date_files_iter
+ = next_out_of_date_file->make_search_item_iterator(query);
+ if (out_of_date_files_iter->next(searcher, pp, lenp, ridp))
+ return 1;
+ delete out_of_date_files_iter;
+ out_of_date_files_iter = 0;
+ next_out_of_date_file = next_out_of_date_file->next;
+ }
+ return 0;
+}
+
+int index_search_item_iterator::get_tag(int tagno,
+ const linear_searcher &searcher,
+ const char **pp, int *lenp,
+ reference_id *ridp)
+{
+ if (tagno < 0 || tagno >= indx->header.tags_size) {
+ error("bad tag number");
+ return 0;
+ }
+ tag *tp = indx->tags + tagno;
+ const char *filename = indx->munge_filename(indx->pool + tp->filename_index);
+ int fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ error("can't open `%1': %2", filename, strerror(errno));
+ return 0;
+ }
+ struct stat sb;
+ if (fstat(fd, &sb) < 0) {
+ error("can't fstat: %1", strerror(errno));
+ close(fd);
+ return 0;
+ }
+ time_t mtime = sb.st_mtime;
+ if (mtime > indx->mtime) {
+ indx->add_out_of_date_file(fd, filename,
+ indx->filename_id + tp->filename_index);
+ return 0;
+ }
+ int res = 0;
+ FILE *fp = fdopen(fd, "r");
+ if (!fp) {
+ error("fdopen failed");
+ close(fd);
+ return 0;
+ }
+ if (tp->start != 0 && fseek(fp, long(tp->start), 0) < 0)
+ error("can't seek on `%1': %2", filename, strerror(errno));
+ else {
+ int length = tp->length;
+ int err = 0;
+ if (length == 0) {
+ struct stat sb;
+ if (fstat(fileno(fp), &sb) < 0) {
+ error("can't stat `%1': %2", filename, strerror(errno));
+ err = 1;
+ }
+ else if (!S_ISREG(sb.st_mode)) {
+ error("`%1' is not a regular file", filename);
+ err = 1;
+ }
+ else
+ length = int(sb.st_size);
+ }
+ if (!err) {
+ if (length + 2 > buflen) {
+ a_delete buf;
+ buflen = length + 2;
+ buf = new char[buflen];
+ }
+ if (fread(buf + 1, 1, length, fp) != length)
+ error("fread on `%1' failed: %2", filename, strerror(errno));
+ else {
+ buf[0] = '\n';
+ buf[length + 1] = '\n';
+ res = searcher.search(buf + 1, buf + 2 + length, pp, lenp);
+ if (res && ridp)
+ *ridp = reference_id(indx->filename_id + tp->filename_index,
+ tp->start);
+ }
+ }
+ }
+ fclose(fp);
+ return res;
+}
+
+const char *index_search_item::munge_filename(const char *filename)
+{
+ if (filename[0] == '/')
+ return filename;
+ const char *cwd = pool;
+ int need_slash = (cwd[0] != 0 && strchr(cwd, '\0')[-1] != '/');
+ int len = strlen(cwd) + strlen(filename) + need_slash + 1;
+ if (len > filename_buflen) {
+ a_delete filename_buffer;
+ filename_buflen = len;
+ filename_buffer = new char[len];
+ }
+ strcpy(filename_buffer, cwd);
+ if (need_slash)
+ strcat(filename_buffer, "/");
+ strcat(filename_buffer, filename);
+ return filename_buffer;
+}
+
+const int *index_search_item::search1(const char **pp, const char *end)
+{
+ while (*pp < end && !csalnum(**pp))
+ *pp += 1;
+ if (*pp >= end)
+ return 0;
+ const char *start = *pp;
+ while (*pp < end && csalnum(**pp))
+ *pp += 1;
+ int len = *pp - start;
+ if (len < header.shortest)
+ return 0;
+ if (len > header.truncate)
+ len = header.truncate;
+ int is_number = 1;
+ for (int i = 0; i < len; i++)
+ if (csdigit(start[i]))
+ key_buffer[i] = start[i];
+ else {
+ key_buffer[i] = cmlower(start[i]);
+ is_number = 0;
+ }
+ if (is_number && !(len == 4 && start[0] == '1' && start[1] == '9'))
+ return 0;
+ unsigned hc = hash(key_buffer, len);
+ if (common_words_table) {
+ for (int h = hc % common_words_table_size;
+ common_words_table[h];
+ --h) {
+ if (strlen(common_words_table[h]) == len
+ && memcmp(common_words_table[h], key_buffer, len) == 0)
+ return 0;
+ if (h == 0)
+ h = common_words_table_size;
+ }
+ }
+ int li = table[int(hc % header.table_size)];
+ return li < 0 ? &minus_one : lists + li;
+}
+
+static void merge(int *result, const int *s1, const int *s2)
+{
+ for (; *s1 >= 0; s1++) {
+ while (*s2 >= 0 && *s2 < *s1)
+ s2++;
+ if (*s2 == *s1)
+ *result++ = *s2;
+ }
+ *result++ = -1;
+}
+
+const int *index_search_item::search(const char *ptr, int length,
+ int **temp_listp)
+{
+ const char *end = ptr + length;
+ if (*temp_listp) {
+ a_delete *temp_listp;
+ *temp_listp = 0;
+ }
+ const int *first_list = 0;
+ while (ptr < end && (first_list = search1(&ptr, end)) == 0)
+ ;
+ if (!first_list)
+ return 0;
+ if (*first_list < 0)
+ return first_list;
+ const int *second_list = 0;
+ while (ptr < end && (second_list = search1(&ptr, end)) == 0)
+ ;
+ if (!second_list)
+ return first_list;
+ if (*second_list < 0)
+ return second_list;
+ const int *p;
+ for (p = first_list; *p >= 0; p++)
+ ;
+ int len = p - first_list;
+ for (p = second_list; *p >= 0; p++)
+ ;
+ if (p - second_list < len)
+ len = p - second_list;
+ int *matches = new int[len + 1];
+ merge(matches, first_list, second_list);
+ while (ptr < end) {
+ const int *list = search1(&ptr, end);
+ if (list != 0) {
+ if (*list < 0) {
+ a_delete matches;
+ return list;
+ }
+ merge(matches, matches, list);
+ if (*matches < 0) {
+ a_delete matches;
+ return &minus_one;
+ }
+ }
+ }
+ *temp_listp = matches;
+ return matches;
+}
+
+void index_search_item::read_common_words_file()
+{
+ if (header.common <= 0)
+ return;
+ const char *common_words_file = munge_filename(strchr(pool, '\0') + 1);
+ errno = 0;
+ FILE *fp = fopen(common_words_file, "r");
+ if (!fp) {
+ error("can't open `%1': %2", common_words_file, strerror(errno));
+ return;
+ }
+ common_words_table_size = 2*header.common + 1;
+ while (!is_prime(common_words_table_size))
+ common_words_table_size++;
+ common_words_table = new char *[common_words_table_size];
+ for (int i = 0; i < common_words_table_size; i++)
+ common_words_table[i] = 0;
+ int count = 0;
+ int key_len = 0;
+ for (;;) {
+ int c = getc(fp);
+ while (c != EOF && !csalnum(c))
+ c = getc(fp);
+ if (c == EOF)
+ break;
+ do {
+ if (key_len < header.truncate)
+ key_buffer[key_len++] = cmlower(c);
+ c = getc(fp);
+ } while (c != EOF && csalnum(c));
+ if (key_len >= header.shortest) {
+ int h = hash(key_buffer, key_len) % common_words_table_size;
+ while (common_words_table[h]) {
+ if (h == 0)
+ h = common_words_table_size;
+ --h;
+ }
+ common_words_table[h] = new char[key_len + 1];
+ memcpy(common_words_table[h], key_buffer, key_len);
+ common_words_table[h][key_len] = '\0';
+ }
+ if (++count >= header.common)
+ break;
+ key_len = 0;
+ if (c == EOF)
+ break;
+ }
+ fclose(fp);
+}
+
+void index_search_item::add_out_of_date_file(int fd, const char *filename,
+ int fid)
+{
+ search_item **pp;
+ for (pp = &out_of_date_files; *pp; pp = &(*pp)->next)
+ if ((*pp)->is_named(filename))
+ return;
+ *pp = make_linear_search_item(fd, filename, fid);
+ warning("`%1' modified since `%2' created", filename, name);
+}
+
+void index_search_item::check_files()
+{
+ const char *pool_end = pool + header.strings_size;
+ for (const char *ptr = strchr(ignore_fields, '\0') + 1;
+ ptr < pool_end;
+ ptr = strchr(ptr, '\0') + 1) {
+ const char *path = munge_filename(ptr);
+ struct stat sb;
+ if (stat(path, &sb) < 0)
+ error("can't stat `%1': %2", path, strerror(errno));
+ else if (sb.st_mtime > mtime) {
+ int fd = open(path, O_RDONLY);
+ if (fd < 0)
+ error("can't open `%1': %2", path, strerror(errno));
+ else
+ add_out_of_date_file(fd, path, filename_id + (ptr - pool));
+ }
+ }
+}
diff --git a/src/libs/libbib/linear.cc b/src/libs/libbib/linear.cc
new file mode 100644
index 00000000..77bd2312
--- /dev/null
+++ b/src/libs/libbib/linear.cc
@@ -0,0 +1,489 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "posix.h"
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+#include "cset.h"
+#include "cmap.h"
+
+#include "refid.h"
+#include "search.h"
+
+class file_buffer {
+ char *buffer;
+ char *bufend;
+public:
+ file_buffer();
+ ~file_buffer();
+ int load(int fd, const char *filename);
+ const char *get_start() const;
+ const char *get_end() const;
+};
+
+typedef unsigned char uchar;
+
+static uchar map[256];
+static uchar inv_map[256][3];
+
+struct map_init {
+ map_init();
+};
+
+static map_init the_map_init;
+
+map_init::map_init()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ map[i] = csalnum(i) ? cmlower(i) : '\0';
+ for (i = 0; i < 256; i++) {
+ if (cslower(i)) {
+ inv_map[i][0] = i;
+ inv_map[i][1] = cmupper(i);
+ inv_map[i][2] = '\0';
+ }
+ else if (csdigit(i)) {
+ inv_map[i][0] = i;
+ inv_map[i][1] = 0;
+ }
+ else
+ inv_map[i][0] = '\0';
+ }
+}
+
+
+class bmpattern {
+ char *pat;
+ int len;
+ int delta[256];
+public:
+ bmpattern(const char *pattern, int pattern_length);
+ ~bmpattern();
+ const char *search(const char *p, const char *end) const;
+ int length() const;
+};
+
+bmpattern::bmpattern(const char *pattern, int pattern_length)
+: len(pattern_length)
+{
+ pat = new char[len];
+ int i;
+ for (i = 0; i < len; i++)
+ pat[i] = map[uchar(pattern[i])];
+ for (i = 0; i < 256; i++)
+ delta[i] = len;
+ for (i = 0; i < len; i++)
+ for (const unsigned char *inv = inv_map[uchar(pat[i])]; *inv; inv++)
+ delta[*inv] = len - i - 1;
+}
+
+const char *bmpattern::search(const char *buf, const char *end) const
+{
+ int buflen = end - buf;
+ if (len > buflen)
+ return 0;
+ const char *strend;
+ if (buflen > len*4)
+ strend = end - len*4;
+ else
+ strend = buf;
+ const char *k = buf + len - 1;
+ const int *del = delta;
+ const char *pattern = pat;
+ for (;;) {
+ while (k < strend) {
+ int t = del[uchar(*k)];
+ if (!t)
+ break;
+ k += t;
+ k += del[uchar(*k)];
+ k += del[uchar(*k)];
+ }
+ while (k < end && del[uchar(*k)] != 0)
+ k++;
+ if (k == end)
+ break;
+ int j = len - 1;
+ const char *s = k;
+ for (;;) {
+ if (j == 0)
+ return s;
+ if (map[uchar(*--s)] != uchar(pattern[--j]))
+ break;
+ }
+ k++;
+ }
+ return 0;
+}
+
+bmpattern::~bmpattern()
+{
+ a_delete pat;
+}
+
+inline int bmpattern::length() const
+{
+ return len;
+}
+
+
+static const char *find_end(const char *bufend, const char *p);
+
+const char *linear_searcher::search_and_check(const bmpattern *key,
+ const char *buf, const char *bufend, const char **start) const
+{
+ assert(buf[-1] == '\n');
+ assert(bufend[-1] == '\n');
+ const char *ptr = buf;
+ for (;;) {
+ const char *found = key->search(ptr, bufend);
+ if (!found)
+ break;
+ if (check_match(buf, bufend, found, key->length(), &ptr, start))
+ return found;
+ }
+ return 0;
+}
+
+static const char *skip_field(const char *end, const char *p)
+{
+ for (;;)
+ if (*p++ == '\n') {
+ if (p == end || *p == '%')
+ break;
+ const char *q;
+ for (q = p; *q == ' ' || *q == '\t'; q++)
+ ;
+ if (*q == '\n')
+ break;
+ p = q + 1;
+ }
+ return p;
+}
+
+static const char *find_end(const char *bufend, const char *p)
+{
+ for (;;)
+ if (*p++ == '\n') {
+ if (p == bufend)
+ break;
+ const char *q;
+ for (q = p; *q == ' ' || *q == '\t'; q++)
+ ;
+ if (*q == '\n')
+ break;
+ p = q + 1;
+ }
+ return p;
+}
+
+
+int linear_searcher::check_match(const char *buf, const char *bufend,
+ const char *match, int matchlen,
+ const char **cont, const char **start) const
+{
+ *cont = match + 1;
+ // The user is required to supply only the first truncate_len characters
+ // of the key. If truncate_len <= 0, he must supply all the key.
+ if ((truncate_len <= 0 || matchlen < truncate_len)
+ && map[uchar(match[matchlen])] != '\0')
+ return 0;
+
+ // The character before the match must not be an alphanumeric
+ // character (unless the alphanumeric character follows one or two
+ // percent characters at the beginning of the line), nor must it be
+ // a percent character at the beginning of a line, nor a percent
+ // character following a percent character at the beginning of a
+ // line.
+
+ switch (match - buf) {
+ case 0:
+ break;
+ case 1:
+ if (match[-1] == '%' || map[uchar(match[-1])] != '\0')
+ return 0;
+ break;
+ case 2:
+ if (map[uchar(match[-1])] != '\0' && match[-2] != '%')
+ return 0;
+ if (match[-1] == '%'
+ && (match[-2] == '\n' || match[-2] == '%'))
+ return 0;
+ break;
+ default:
+ if (map[uchar(match[-1])] != '\0'
+ && !(match[-2] == '%'
+ && (match[-3] == '\n'
+ || (match[-3] == '%' && match[-4] == '\n'))))
+ return 0;
+ if (match[-1] == '%'
+ && (match[-2] == '\n'
+ || (match[-2] == '%' && match[-3] == '\n')))
+ return 0;
+ }
+
+ const char *p = match;
+ int had_percent = 0;
+ for (;;) {
+ if (*p == '\n') {
+ if (!had_percent && p[1] == '%') {
+ if (p[2] != '\0' && strchr(ignore_fields, p[2]) != 0) {
+ *cont = skip_field(bufend, match + matchlen);
+ return 0;
+ }
+ if (!start)
+ break;
+ had_percent = 1;
+ }
+ if (p <= buf) {
+ if (start)
+ *start = p + 1;
+ return 1;
+ }
+ const char *q;
+ for (q = p - 1; *q == ' ' || *q == '\t'; q--)
+ ;
+ if (*q == '\n') {
+ if (start)
+ *start = p + 1;
+ break;
+ }
+ p = q;
+ }
+ p--;
+ }
+ return 1;
+}
+
+file_buffer::file_buffer()
+: buffer(0), bufend(0)
+{
+}
+
+file_buffer::~file_buffer()
+{
+ a_delete buffer;
+}
+
+const char *file_buffer::get_start() const
+{
+ return buffer ? buffer + 4 : 0;
+}
+
+const char *file_buffer::get_end() const
+{
+ return bufend;
+}
+
+int file_buffer::load(int fd, const char *filename)
+{
+ struct stat sb;
+ if (fstat(fd, &sb) < 0)
+ error("can't fstat `%1': %2", filename, strerror(errno));
+ else if (!S_ISREG(sb.st_mode))
+ error("`%1' is not a regular file", filename);
+ else {
+ // We need one character extra at the beginning for an additional newline
+ // used as a sentinel. We get 4 instead so that the read buffer will be
+ // word-aligned. This seems to make the read slightly faster. We also
+ // need one character at the end also for an additional newline used as a
+ // sentinel.
+ int size = int(sb.st_size);
+ buffer = new char[size + 4 + 1];
+ int nread = read(fd, buffer + 4, size);
+ if (nread < 0)
+ error("error reading `%1': %2", filename, strerror(errno));
+ else if (nread != size)
+ error("size of `%1' decreased", filename);
+ else {
+ char c;
+ nread = read(fd, &c, 1);
+ if (nread != 0)
+ error("size of `%1' increased", filename);
+ else if (memchr(buffer + 4, '\0', size < 1024 ? size : 1024) != 0)
+ error("database `%1' is a binary file", filename);
+ else {
+ close(fd);
+ buffer[3] = '\n';
+ bufend = buffer + 4 + size;
+ if (bufend[-1] != '\n')
+ *bufend++ = '\n';
+ return 1;
+ }
+ }
+ a_delete buffer;
+ buffer = 0;
+ }
+ close(fd);
+ return 0;
+}
+
+linear_searcher::linear_searcher(const char *query, int query_len,
+ const char *ign, int trunc)
+: ignore_fields(ign), truncate_len(trunc), keys(0), nkeys(0)
+{
+ const char *query_end = query + query_len;
+ int nk = 0;
+ const char *p;
+ for (p = query; p < query_end; p++)
+ if (map[uchar(*p)] != '\0'
+ && (p[1] == '\0' || map[uchar(p[1])] == '\0'))
+ nk++;
+ if (nk == 0)
+ return;
+ keys = new bmpattern*[nk];
+ p = query;
+ for (;;) {
+ while (p < query_end && map[uchar(*p)] == '\0')
+ p++;
+ if (p == query_end)
+ break;
+ const char *start = p;
+ while (p < query_end && map[uchar(*p)] != '\0')
+ p++;
+ keys[nkeys++] = new bmpattern(start, p - start);
+ }
+ assert(nkeys <= nk);
+ if (nkeys == 0) {
+ a_delete keys;
+ keys = 0;
+ }
+}
+
+linear_searcher::~linear_searcher()
+{
+ for (int i = 0; i < nkeys; i++)
+ delete keys[i];
+ a_delete keys;
+}
+
+int linear_searcher::search(const char *buffer, const char *bufend,
+ const char **startp, int *lengthp) const
+{
+ assert(bufend - buffer > 0);
+ assert(buffer[-1] == '\n');
+ assert(bufend[-1] == '\n');
+ if (nkeys == 0)
+ return 0;
+ for (;;) {
+ const char *refstart;
+ const char *found = search_and_check(keys[0], buffer, bufend, &refstart);
+ if (!found)
+ break;
+ const char *refend = find_end(bufend, found + keys[0]->length());
+ int i;
+ for (i = 1; i < nkeys; i++)
+ if (!search_and_check(keys[i], refstart, refend))
+ break;
+ if (i >= nkeys) {
+ *startp = refstart;
+ *lengthp = refend - refstart;
+ return 1;
+ }
+ buffer = refend;
+ }
+ return 0;
+}
+
+class linear_search_item : public search_item {
+ file_buffer fbuf;
+public:
+ linear_search_item(const char *filename, int fid);
+ ~linear_search_item();
+ int load(int fd);
+ search_item_iterator *make_search_item_iterator(const char *);
+ friend class linear_search_item_iterator;
+};
+
+class linear_search_item_iterator : public search_item_iterator {
+ linear_search_item *lsi;
+ int pos;
+public:
+ linear_search_item_iterator(linear_search_item *, const char *query);
+ ~linear_search_item_iterator();
+ int next(const linear_searcher &, const char **ptr, int *lenp,
+ reference_id *ridp);
+};
+
+search_item *make_linear_search_item(int fd, const char *filename, int fid)
+{
+ linear_search_item *item = new linear_search_item(filename, fid);
+ if (!item->load(fd)) {
+ delete item;
+ return 0;
+ }
+ else
+ return item;
+}
+
+linear_search_item::linear_search_item(const char *filename, int fid)
+: search_item(filename, fid)
+{
+}
+
+linear_search_item::~linear_search_item()
+{
+}
+
+int linear_search_item::load(int fd)
+{
+ return fbuf.load(fd, name);
+}
+
+search_item_iterator *linear_search_item::make_search_item_iterator(
+ const char *query)
+{
+ return new linear_search_item_iterator(this, query);
+}
+
+linear_search_item_iterator::linear_search_item_iterator(
+ linear_search_item *p, const char *)
+: lsi(p), pos(0)
+{
+}
+
+linear_search_item_iterator::~linear_search_item_iterator()
+{
+}
+
+int linear_search_item_iterator::next(const linear_searcher &searcher,
+ const char **startp, int *lengthp,
+ reference_id *ridp)
+{
+ const char *bufstart = lsi->fbuf.get_start();
+ const char *bufend = lsi->fbuf.get_end();
+ const char *ptr = bufstart + pos;
+ if (ptr < bufend && searcher.search(ptr, bufend, startp, lengthp)) {
+ pos = *startp + *lengthp - bufstart;
+ if (ridp)
+ *ridp = reference_id(lsi->filename_id, *startp - bufstart);
+ return 1;
+ }
+ else
+ return 0;
+}
diff --git a/src/libs/libbib/map.c b/src/libs/libbib/map.c
new file mode 100644
index 00000000..3632a11e
--- /dev/null
+++ b/src/libs/libbib/map.c
@@ -0,0 +1,75 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_MMAP
+
+#include <sys/types.h>
+#include <sys/mman.h>
+
+/* The Net-2 man pages says that a MAP_FILE flag is required. */
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+
+char *mapread(fd, nbytes)
+ int fd;
+ int nbytes;
+{
+ char *p = (char *)mmap((caddr_t)0, (size_t)nbytes, PROT_READ,
+ MAP_FILE|MAP_PRIVATE, fd, (off_t)0);
+ if (p == (char *)-1)
+ return 0;
+ /* mmap() shouldn't return 0 since MAP_FIXED wasn't specified. */
+ if (p == 0)
+ abort();
+ return p;
+}
+
+int unmap(p, len)
+ char *p;
+ int len;
+{
+ return munmap((caddr_t)p, len);
+}
+
+#else /* not HAVE_MMAP */
+
+#include <errno.h>
+
+#ifndef errno
+extern int errno;
+#endif
+
+char *mapread(fd, nbytes)
+ int fd;
+ int nbytes;
+{
+ errno = ENODEV;
+ return 0;
+}
+
+int unmap(p, len)
+ char *p;
+ int len;
+{
+ errno = EINVAL;
+ return -1;
+}
+
+#endif /* not HAVE_MMAP */
diff --git a/src/libs/libbib/search.cc b/src/libs/libbib/search.cc
new file mode 100644
index 00000000..8c7b3e16
--- /dev/null
+++ b/src/libs/libbib/search.cc
@@ -0,0 +1,131 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "posix.h"
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+
+#include "refid.h"
+#include "search.h"
+
+int linear_truncate_len = 6;
+const char *linear_ignore_fields = "XYZ";
+
+search_list::search_list()
+: list(0), niterators(0), next_fid(1)
+{
+}
+
+search_list::~search_list()
+{
+ assert(niterators == 0);
+ while (list) {
+ search_item *tem = list->next;
+ delete list;
+ list = tem;
+ }
+}
+
+void search_list::add_file(const char *filename, int silent)
+{
+ search_item *p = make_index_search_item(filename, next_fid);
+ if (!p) {
+ int fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ if (!silent)
+ error("can't open `%1': %2", filename, strerror(errno));
+ }
+ else
+ p = make_linear_search_item(fd, filename, next_fid);
+ }
+ if (p) {
+ search_item **pp;
+ for (pp = &list; *pp; pp = &(*pp)->next)
+ ;
+ *pp = p;
+ next_fid = p->next_filename_id();
+ }
+}
+
+int search_list::nfiles() const
+{
+ int n = 0;
+ for (search_item *ptr = list; ptr; ptr = ptr->next)
+ n++;
+ return n;
+}
+
+search_list_iterator::search_list_iterator(search_list *p, const char *q)
+: list(p), ptr(p->list), iter(0), query(strsave(q)),
+ searcher(q, strlen(q), linear_ignore_fields, linear_truncate_len)
+{
+ list->niterators += 1;
+}
+
+search_list_iterator::~search_list_iterator()
+{
+ list->niterators -= 1;
+ a_delete query;
+ delete iter;
+}
+
+int search_list_iterator::next(const char **pp, int *lenp, reference_id *ridp)
+{
+ while (ptr) {
+ if (iter == 0)
+ iter = ptr->make_search_item_iterator(query);
+ if (iter->next(searcher, pp, lenp, ridp))
+ return 1;
+ delete iter;
+ iter = 0;
+ ptr = ptr->next;
+ }
+ return 0;
+}
+
+search_item::search_item(const char *nm, int fid)
+: name(strsave(nm)), filename_id(fid), next(0)
+{
+}
+
+search_item::~search_item()
+{
+ a_delete name;
+}
+
+int search_item::is_named(const char *nm) const
+{
+ return strcmp(name, nm) == 0;
+}
+
+int search_item::next_filename_id() const
+{
+ return filename_id + 1;
+}
+
+search_item_iterator::~search_item_iterator()
+{
+}
diff --git a/src/libs/libdriver/Makefile.sub b/src/libs/libdriver/Makefile.sub
new file mode 100644
index 00000000..d50f060b
--- /dev/null
+++ b/src/libs/libdriver/Makefile.sub
@@ -0,0 +1,7 @@
+LIB=driver
+OBJS=\
+ input.o \
+ printer.o
+CCSRCS=\
+ $(srcdir)/input.cc \
+ $(srcdir)/printer.cc
diff --git a/src/libs/libdriver/input.cc b/src/libs/libdriver/input.cc
new file mode 100644
index 00000000..ba71a5b3
--- /dev/null
+++ b/src/libs/libdriver/input.cc
@@ -0,0 +1,501 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "driver.h"
+#include "device.h"
+#include "cset.h"
+
+const char *current_filename=0;
+int current_lineno;
+const char *device = 0;
+FILE *current_file;
+
+int get_integer(); // don't read the newline
+int possibly_get_integer(int *);
+char *get_string(int is_long = 0);
+void skip_line();
+
+struct environment_list {
+ environment env;
+ environment_list *next;
+
+ environment_list(const environment &, environment_list *);
+};
+
+environment_list::environment_list(const environment &e, environment_list *p)
+: env(e), next(p)
+{
+}
+
+inline int get_char()
+{
+ return getc(current_file);
+}
+
+/*
+ * remember_filename - is needed as get_string might overwrite the
+ * filename eventually.
+ */
+
+void remember_filename (const char *filename)
+{
+ if (current_filename != 0) {
+ free((char *)current_filename);
+ }
+ if (strcmp(filename, "-") == 0) {
+ filename = "<standard input>";
+ }
+ current_filename = (const char *)malloc(strlen(filename)+1);
+ if (current_filename == 0) {
+ fatal("can't malloc space for filename");
+ }
+ strcpy((char *)current_filename, (char *)filename);
+}
+
+void do_file(const char *filename)
+{
+ int npages = 0;
+ if (filename[0] == '-' && filename[1] == '\0') {
+ remember_filename(filename);
+ current_file = stdin;
+ }
+ else {
+ errno = 0;
+ current_file = fopen(filename, "r");
+ if (current_file == 0) {
+ error("can't open `%1'", filename);
+ return;
+ }
+ remember_filename(filename);
+ }
+ environment env;
+ env.vpos = -1;
+ env.hpos = -1;
+ env.fontno = -1;
+ env.height = 0;
+ env.slant = 0;
+ environment_list *env_list = 0;
+ current_lineno = 1;
+ int command;
+ char *s;
+ command = get_char();
+ if (command == EOF)
+ return;
+ if (command != 'x')
+ fatal("the first command must be `x T'");
+ s = get_string();
+ if (s[0] != 'T')
+ fatal("the first command must be `x T'");
+ char *dev = get_string();
+ if (pr == 0) {
+ device = strsave(dev);
+ if (!font::load_desc())
+ fatal("sorry, I can't continue");
+ }
+ else {
+ if (device == 0 || strcmp(device, dev) != 0)
+ fatal("all files must use the same device");
+ }
+ skip_line();
+ env.size = 10*font::sizescale;
+ command = get_char();
+ if (command != 'x')
+ fatal("the second command must be `x res'");
+ s = get_string();
+ if (s[0] != 'r')
+ fatal("the second command must be `x res'");
+ int n = get_integer();
+ if (n != font::res)
+ fatal("resolution does not match");
+ n = get_integer();
+ if (n != font::hor)
+ fatal("horizontal resolution does not match");
+ n = get_integer();
+ if (n != font::vert)
+ fatal("vertical resolution does not match");
+ skip_line();
+ command = get_char();
+ if (command != 'x')
+ fatal("the third command must be `x init'");
+ s = get_string();
+ if (s[0] != 'i')
+ fatal("the third command must be `x init'");
+ skip_line();
+ if (pr == 0)
+ pr = make_printer();
+ while ((command = get_char()) != EOF) {
+ switch (command) {
+ case 's':
+ env.size = get_integer();
+ if (env.height == env.size)
+ env.height = 0;
+ break;
+ case 'f':
+ env.fontno = get_integer();
+ break;
+ case 'F':
+ remember_filename(get_string());
+ break;
+ case 'C':
+ {
+ if (npages == 0)
+ fatal("`C' command illegal before first `p' command");
+ char *s = get_string();
+ pr->set_special_char(s, &env);
+ }
+ break;
+ case 'N':
+ {
+ if (npages == 0)
+ fatal("`N' command illegal before first `p' command");
+ pr->set_numbered_char(get_integer(), &env);
+ }
+ break;
+ case 'H':
+ env.hpos = get_integer();
+ break;
+ case 'h':
+ env.hpos += get_integer();
+ break;
+ case 'V':
+ env.vpos = get_integer();
+ break;
+ case 'v':
+ env.vpos += get_integer();
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ int c = get_char();
+ if (!csdigit(c))
+ fatal("digit expected");
+ env.hpos += (command - '0')*10 + (c - '0');
+ }
+ // fall through
+ case 'c':
+ {
+ if (npages == 0)
+ fatal("`c' command illegal before first `p' command");
+ int c = get_char();
+ if (c == EOF)
+ fatal("missing argument to `c' command");
+ pr->set_ascii_char(c, &env);
+ }
+ break;
+ case 'n':
+ if (npages == 0)
+ fatal("`n' command illegal before first `p' command");
+ pr->end_of_line();
+ (void)get_integer();
+ (void)get_integer();
+ break;
+ case 'w':
+ case ' ':
+ break;
+ case '\n':
+ current_lineno++;
+ break;
+ case 'p':
+ if (npages)
+ pr->end_page(env.vpos);
+ npages++;
+ pr->begin_page(get_integer());
+ env.vpos = 0;
+ break;
+ case '{':
+ env_list = new environment_list(env, env_list);
+ break;
+ case '}':
+ if (!env_list) {
+ fatal("can't pop");
+ }
+ else {
+ env = env_list->env;
+ environment_list *tem = env_list;
+ env_list = env_list->next;
+ delete tem;
+ }
+ break;
+ case 'u':
+ {
+ if (npages == 0)
+ fatal("`u' command illegal before first `p' command");
+ int kern = get_integer();
+ int c = get_char();
+ while (c == ' ')
+ c = get_char();
+ while (c != EOF) {
+ if (c == '\n') {
+ current_lineno++;
+ break;
+ }
+ int w;
+ pr->set_ascii_char(c, &env, &w);
+ env.hpos += w + kern;
+ c = get_char();
+ if (c == ' ')
+ break;
+ }
+ }
+ break;
+ case 't':
+ {
+ if (npages == 0)
+ fatal("`t' command illegal before first `p' command");
+ int c;
+ while ((c = get_char()) != EOF && c != ' ') {
+ if (c == '\n') {
+ current_lineno++;
+ break;
+ }
+ int w;
+ pr->set_ascii_char(c, &env, &w);
+ env.hpos += w;
+ }
+ }
+ break;
+ case '#':
+ skip_line();
+ break;
+ case 'D':
+ {
+ if (npages == 0)
+ fatal("`D' command illegal before first `p' command");
+ int c;
+ while ((c = get_char()) == ' ')
+ ;
+ int n;
+ int *p = 0;
+ int szp = 0;
+ int np;
+ for (np = 0; possibly_get_integer(&n); np++) {
+ if (np >= szp) {
+ if (szp == 0) {
+ szp = 16;
+ p = new int[szp];
+ }
+ else {
+ int *oldp = p;
+ p = new int[szp*2];
+ memcpy(p, oldp, szp*sizeof(int));
+ szp *= 2;
+ a_delete oldp;
+ }
+ }
+ p[np] = n;
+ }
+ pr->draw(c, p, np, &env);
+ if (c == 'e') {
+ if (np > 0)
+ env.hpos += p[0];
+ }
+ else if (c == 'f' || c == 't')
+ ;
+ else {
+ int i;
+ for (i = 0; i < np/2; i++) {
+ env.hpos += p[i*2];
+ env.vpos += p[i*2 + 1];
+ }
+ // there might be an odd number of characters
+ if (i*2 < np)
+ env.hpos += p[i*2];
+ }
+ a_delete p;
+ skip_line();
+ }
+ break;
+ case 'x':
+ {
+ char *s = get_string();
+ int suppress_skip = 0;
+ switch (s[0]) {
+ case 'i':
+ error("duplicate `x init' command");
+ break;
+ case 'T':
+ error("duplicate `x T' command");
+ break;
+ case 'r':
+ error("duplicate `x res' command");
+ break;
+ case 'p':
+ break;
+ case 's':
+ break;
+ case 't':
+ break;
+ case 'f':
+ {
+ int n = get_integer();
+ char *name = get_string();
+ pr->load_font(n, name);
+ }
+ break;
+ case 'H':
+ env.height = get_integer();
+ if (env.height == env.size)
+ env.height = 0;
+ break;
+ case 'S':
+ env.slant = get_integer();
+ break;
+ case 'X':
+ if (npages == 0)
+ fatal("`x X' command illegal before first `p' command");
+ pr->special(get_string(1), &env);
+ suppress_skip = 1;
+ break;
+ default:
+ error("unrecognised x command `%1'", s);
+ }
+ if (!suppress_skip)
+ skip_line();
+ }
+ break;
+ default:
+ error("unrecognised command code %1", int(command));
+ skip_line();
+ break;
+ }
+ }
+ if (npages)
+ pr->end_page(env.vpos);
+}
+
+int get_integer()
+{
+ int c = get_char();
+ while (c == ' ')
+ c = get_char();
+ int neg = 0;
+ if (c == '-') {
+ neg = 1;
+ c = get_char();
+ }
+ if (!csdigit(c))
+ fatal("integer expected");
+ int total = 0;
+ do {
+ total = total*10;
+ if (neg)
+ total -= c - '0';
+ else
+ total += c - '0';
+ c = get_char();
+ } while (csdigit(c));
+ if (c != EOF)
+ ungetc(c, current_file);
+ return total;
+}
+
+int possibly_get_integer(int *res)
+{
+ int c = get_char();
+ while (c == ' ')
+ c = get_char();
+ int neg = 0;
+ if (c == '-') {
+ neg = 1;
+ c = get_char();
+ }
+ if (!csdigit(c)) {
+ if (c != EOF)
+ ungetc(c, current_file);
+ return 0;
+ }
+ int total = 0;
+ do {
+ total = total*10;
+ if (neg)
+ total -= c - '0';
+ else
+ total += c - '0';
+ c = get_char();
+ } while (csdigit(c));
+ if (c != EOF)
+ ungetc(c, current_file);
+ *res = total;
+ return 1;
+}
+
+
+char *get_string(int is_long)
+{
+ static char *buf;
+ static int buf_size;
+ int c = get_char();
+ while (c == ' ')
+ c = get_char();
+ for (int i = 0;; i++) {
+ if (i >= buf_size) {
+ if (buf_size == 0) {
+ buf_size = 16;
+ buf = new char[buf_size];
+ }
+ else {
+ char *old_buf = buf;
+ int old_size = buf_size;
+ buf_size *= 2;
+ buf = new char[buf_size];
+ memcpy(buf, old_buf, old_size);
+ a_delete old_buf;
+ }
+ }
+ if ((!is_long && (c == ' ' || c == '\n')) || c == EOF) {
+ buf[i] = '\0';
+ break;
+ }
+ if (is_long && c == '\n') {
+ current_lineno++;
+ c = get_char();
+ if (c == '+')
+ c = '\n';
+ else {
+ buf[i] = '\0';
+ break;
+ }
+ }
+ buf[i] = c;
+ c = get_char();
+ }
+ if (c != EOF)
+ ungetc(c, current_file);
+ return buf;
+}
+
+void skip_line()
+{
+ int c;
+ while ((c = get_char()) != EOF)
+ if (c == '\n') {
+ current_lineno++;
+ break;
+ }
+}
+
diff --git a/src/libs/libdriver/printer.cc b/src/libs/libdriver/printer.cc
new file mode 100644
index 00000000..770aa507
--- /dev/null
+++ b/src/libs/libdriver/printer.cc
@@ -0,0 +1,263 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "driver.h"
+
+printer *pr = 0;
+
+font_pointer_list::font_pointer_list(font *f, font_pointer_list *fp)
+: p(f), next(fp)
+{
+}
+
+printer::printer()
+: font_list(0), font_table(0), nfonts(0)
+{
+}
+
+printer::~printer()
+{
+ a_delete font_table;
+ while (font_list) {
+ font_pointer_list *tem = font_list;
+ font_list = font_list->next;
+ delete tem->p;
+ delete tem;
+ }
+ if (ferror(stdout) || fflush(stdout) < 0)
+ fatal("output error");
+}
+
+void printer::load_font(int n, const char *nm)
+{
+ assert(n >= 0);
+ if (n >= nfonts) {
+ if (nfonts == 0) {
+ nfonts = 10;
+ if (nfonts <= n)
+ nfonts = n + 1;
+ font_table = new font *[nfonts];
+ for (int i = 0; i < nfonts; i++)
+ font_table[i] = 0;
+ }
+ else {
+ font **old_font_table = font_table;
+ int old_nfonts = nfonts;
+ nfonts *= 2;
+ if (n >= nfonts)
+ nfonts = n + 1;
+ font_table = new font *[nfonts];
+ int i;
+ for (i = 0; i < old_nfonts; i++)
+ font_table[i] = old_font_table[i];
+ for (i = old_nfonts; i < nfonts; i++)
+ font_table[i] = 0;
+ a_delete old_font_table;
+ }
+ }
+ font *f = find_font(nm);
+ font_table[n] = f;
+}
+
+font *printer::find_font(const char *nm)
+{
+ for (font_pointer_list *p = font_list; p; p = p->next)
+ if (strcmp(p->p->get_name(), nm) == 0)
+ return p->p;
+ font *f = make_font(nm);
+ if (!f)
+ fatal("sorry, I can't continue");
+ font_list = new font_pointer_list(f, font_list);
+ return f;
+}
+
+font *printer::make_font(const char *nm)
+{
+ return font::load_font(nm);
+}
+
+void printer::end_of_line()
+{
+}
+
+void printer::special(char *, const environment *)
+{
+}
+
+void printer::draw(int, int *, int, const environment *)
+{
+}
+
+void printer::set_ascii_char(unsigned char c, const environment *env,
+ int *widthp)
+{
+ char buf[2];
+ int w;
+ font *f;
+
+ buf[0] = c;
+ buf[1] = '\0';
+
+ int i = set_char_and_width(buf, env, &w, &f);
+ set_char(i, f, env, w, 0);
+ if (widthp) {
+ *widthp = w;
+ }
+}
+
+void printer::set_special_char(const char *nm, const environment *env,
+ int *widthp)
+{
+ font *f;
+ int w;
+ int i = set_char_and_width(nm, env, &w, &f);
+ if (i != -1) {
+ set_char(i, f, env, w, nm);
+ if (widthp) {
+ *widthp = w;
+ }
+ }
+}
+
+int printer::set_char_and_width(const char *nm, const environment *env,
+ int *widthp, font **f)
+{
+ int i = font::name_to_index(nm);
+ int fn = env->fontno;
+ if (fn < 0 || fn >= nfonts) {
+ error("bad font position `%1'", fn);
+ return(-1);
+ }
+ *f = font_table[fn];
+ if (*f == 0) {
+ error("no font mounted at `%1'", fn);
+ return(-1);
+ }
+ if (!(*f)->contains(i)) {
+ if (nm[0] != '\0' && nm[1] == '\0')
+ error("font `%1' does not contain ascii character `%2'",
+ (*f)->get_name(),
+ nm[0]);
+ else
+ error("font `%1' does not contain special character `%2'",
+ (*f)->get_name(),
+ nm);
+ return(-1);
+ }
+ int w = (*f)->get_width(i, env->size);
+ if (widthp)
+ *widthp = w;
+ return( i );
+}
+
+void printer::set_numbered_char(int num, const environment *env, int *widthp)
+{
+ int i = font::number_to_index(num);
+ int fn = env->fontno;
+ if (fn < 0 || fn >= nfonts) {
+ error("bad font position `%1'", fn);
+ return;
+ }
+ font *f = font_table[fn];
+ if (f == 0) {
+ error("no font mounted at `%1'", fn);
+ return;
+ }
+ if (!f->contains(i)) {
+ error("font `%1' does not contain numbered character %2",
+ f->get_name(),
+ num);
+ return;
+ }
+ int w = f->get_width(i, env->size);
+ if (widthp)
+ *widthp = w;
+ set_char(i, f, env, w, 0);
+}
+
+// This utility function adjusts the specified center of the
+// arc so that it is equidistant between the specified start
+// and end points. (p[0], p[1]) is a vector from the current
+// point to the center; (p[2], p[3]) is a vector from the
+// center to the end point. If the center can be adjusted,
+// a vector from the current point to the adjusted center is
+// stored in c[0], c[1] and 1 is returned. Otherwise 0 is
+// returned.
+
+#if 1
+int printer::adjust_arc_center(const int *p, double *c)
+{
+ // We move the center along a line parallel to the line between
+ // the specified start point and end point so that the center
+ // is equidistant between the start and end point.
+ // It can be proved (using Lagrange multipliers) that this will
+ // give the point nearest to the specified center that is equidistant
+ // between the start and end point.
+
+ double x = p[0] + p[2]; // (x, y) is the end point
+ double y = p[1] + p[3];
+ double n = x*x + y*y;
+ if (n != 0) {
+ c[0]= double(p[0]);
+ c[1] = double(p[1]);
+ double k = .5 - (c[0]*x + c[1]*y)/n;
+ c[0] += k*x;
+ c[1] += k*y;
+ return 1;
+ }
+ else
+ return 0;
+}
+#else
+int printer::adjust_arc_center(const int *p, double *c)
+{
+ int x = p[0] + p[2]; // (x, y) is the end point
+ int y = p[1] + p[3];
+ // Start at the current point; go in the direction of the specified
+ // center point until we reach a point that is equidistant between
+ // the specified starting point and the specified end point. Place
+ // the center of the arc there.
+ double n = p[0]*double(x) + p[1]*double(y);
+ if (n > 0) {
+ double k = (double(x)*x + double(y)*y)/(2.0*n);
+ // (cx, cy) is our chosen center
+ c[0] = k*p[0];
+ c[1] = k*p[1];
+ return 1;
+ }
+ else {
+ // We would never reach such a point. So instead start at the
+ // specified end point of the arc. Go towards the specified
+ // center point until we reach a point that is equidistant between
+ // the specified start point and specified end point. Place
+ // the center of the arc there.
+ n = p[2]*double(x) + p[3]*double(y);
+ if (n > 0) {
+ double k = 1 - (double(x)*x + double(y)*y)/(2.0*n);
+ // (c[0], c[1]) is our chosen center
+ c[0] = p[0] + k*p[2];
+ c[1] = p[1] + k*p[3];
+ return 1;
+ }
+ else
+ return 0;
+ }
+}
+#endif
diff --git a/src/libs/libgroff/Makefile.sub b/src/libs/libgroff/Makefile.sub
new file mode 100644
index 00000000..d854f4c7
--- /dev/null
+++ b/src/libs/libgroff/Makefile.sub
@@ -0,0 +1,78 @@
+LIB=groff
+OBJS=\
+ assert.o \
+ change_lf.o \
+ cmap.o \
+ cset.o \
+ device.o \
+ errarg.o \
+ error.o \
+ fatal.o \
+ filename.o \
+ font.o \
+ fontfile.o \
+ lf.o \
+ lineno.o \
+ macropath.o \
+ nametoindex.o \
+ new.o \
+ prime.o \
+ progname.o \
+ ptable.o \
+ searchpath.o \
+ string.o \
+ strsave.o \
+ tmpfile.o \
+ iftoa.o \
+ itoa.o \
+ matherr.o \
+ version.o \
+ illegal.o \
+ $(LIBOBJS)
+CCSRCS=\
+ $(srcdir)/assert.cc \
+ $(srcdir)/change_lf.cc \
+ $(srcdir)/cmap.cc \
+ $(srcdir)/cset.cc \
+ $(srcdir)/device.cc \
+ $(srcdir)/errarg.cc \
+ $(srcdir)/error.cc \
+ $(srcdir)/fatal.cc \
+ $(srcdir)/filename.cc \
+ $(srcdir)/font.cc \
+ $(srcdir)/fontfile.cc \
+ $(srcdir)/lf.cc \
+ $(srcdir)/lineno.cc \
+ $(srcdir)/macropath.cc \
+ $(srcdir)/nametoindex.cc \
+ $(srcdir)/new.cc \
+ $(srcdir)/prime.cc \
+ $(srcdir)/progname.cc \
+ $(srcdir)/ptable.cc \
+ $(srcdir)/searchpath.cc \
+ $(srcdir)/string.cc \
+ $(srcdir)/strsave.cc \
+ $(srcdir)/tmpfile.cc \
+ version.cc \
+ $(srcdir)/illegal.cc
+CSRCS=\
+ $(srcdir)/fmod.c \
+ $(srcdir)/getcwd.c \
+ $(srcdir)/iftoa.c \
+ $(srcdir)/itoa.c \
+ $(srcdir)/matherr.c \
+ $(srcdir)/strerror.c \
+ $(srcdir)/strtol.c \
+ $(srcdir)/putenv.c
+GENSRCS=\
+ version.cc
+
+version=`cat $(top_srcdir)/VERSION`
+revision=`cat $(top_srcdir)/REVISION`
+
+version.cc: $(top_srcdir)/VERSION $(top_srcdir)/REVISION
+ @echo Making version.cc
+ @echo const char \*version_string = \"$(version)\"\; >$@
+ @echo const char \*revision_string = \"$(revision)\"\; >>$@
+ @echo const char \*Version_string = \"$(version).$(revision)\"\; | \
+ sed -e 's/\.0\"/\"/' >>$@
diff --git a/src/libs/libgroff/assert.cc b/src/libs/libgroff/assert.cc
new file mode 100644
index 00000000..89742e32
--- /dev/null
+++ b/src/libs/libgroff/assert.cc
@@ -0,0 +1,34 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "assert.h"
+
+extern const char *program_name;
+
+void assertion_failed(int lineno, const char *filename)
+{
+ if (program_name != 0)
+ fprintf(stderr, "%s: ", program_name);
+ fprintf(stderr, "Failed assertion at line %d, file `%s'.\n",
+ lineno, filename);
+ fflush(stderr);
+ abort();
+}
diff --git a/src/libs/libgroff/change_lf.cc b/src/libs/libgroff/change_lf.cc
new file mode 100644
index 00000000..2e44af1d
--- /dev/null
+++ b/src/libs/libgroff/change_lf.cc
@@ -0,0 +1,37 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <string.h>
+
+extern char *strsave(const char *);
+
+extern const char *current_filename;
+extern int current_lineno;
+
+void change_filename(const char *f)
+{
+ if (current_filename != 0 && strcmp(current_filename, f) == 0)
+ return;
+ current_filename = strsave(f);
+}
+
+void change_lineno(int ln)
+{
+ current_lineno = ln;
+}
diff --git a/src/libs/libgroff/cmap.cc b/src/libs/libgroff/cmap.cc
new file mode 100644
index 00000000..4b75d06f
--- /dev/null
+++ b/src/libs/libgroff/cmap.cc
@@ -0,0 +1,56 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <ctype.h>
+#include "cmap.h"
+
+cmap cmlower(CMAP_BUILTIN);
+cmap cmupper(CMAP_BUILTIN);
+
+#ifdef isascii
+#define ISASCII(c) isascii(c)
+#else
+#define ISASCII(c) (1)
+#endif
+
+cmap::cmap()
+{
+ unsigned char *p = v;
+ for (int i = 0; i <= UCHAR_MAX; i++)
+ p[i] = i;
+}
+
+cmap::cmap(cmap_builtin)
+{
+ // these are initialised by cmap_init::cmap_init()
+}
+
+int cmap_init::initialised = 0;
+
+cmap_init::cmap_init()
+{
+ if (initialised)
+ return;
+ initialised = 1;
+ for (int i = 0; i <= UCHAR_MAX; i++) {
+ cmupper.v[i] = ISASCII(i) && islower(i) ? toupper(i) : i;
+ cmlower.v[i] = ISASCII(i) && isupper(i) ? tolower(i) : i;
+ }
+}
diff --git a/src/libs/libgroff/cset.cc b/src/libs/libgroff/cset.cc
new file mode 100644
index 00000000..e4845c11
--- /dev/null
+++ b/src/libs/libgroff/cset.cc
@@ -0,0 +1,102 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <ctype.h>
+#include "cset.h"
+
+cset csalpha(CSET_BUILTIN);
+cset csupper(CSET_BUILTIN);
+cset cslower(CSET_BUILTIN);
+cset csdigit(CSET_BUILTIN);
+cset csxdigit(CSET_BUILTIN);
+cset csspace(CSET_BUILTIN);
+cset cspunct(CSET_BUILTIN);
+cset csalnum(CSET_BUILTIN);
+cset csprint(CSET_BUILTIN);
+cset csgraph(CSET_BUILTIN);
+cset cscntrl(CSET_BUILTIN);
+
+#ifdef isascii
+#define ISASCII(c) isascii(c)
+#else
+#define ISASCII(c) (1)
+#endif
+
+void cset::clear()
+{
+ char *p = v;
+ for (int i = 0; i <= UCHAR_MAX; i++)
+ p[i] = 0;
+}
+
+cset::cset()
+{
+ clear();
+}
+
+cset::cset(const char *s)
+{
+ clear();
+ while (*s)
+ v[(unsigned char)*s++] = 1;
+}
+
+cset::cset(const unsigned char *s)
+{
+ clear();
+ while (*s)
+ v[*s++] = 1;
+}
+
+cset::cset(cset_builtin)
+{
+ // these are initialised by cset_init::cset_init()
+}
+
+cset &cset::operator|=(const cset &cs)
+{
+ for (int i = 0; i <= UCHAR_MAX; i++)
+ if (cs.v[i])
+ v[i] = 1;
+ return *this;
+}
+
+
+int cset_init::initialised = 0;
+
+cset_init::cset_init()
+{
+ if (initialised)
+ return;
+ initialised = 1;
+ for (int i = 0; i <= UCHAR_MAX; i++) {
+ csalpha.v[i] = ISASCII(i) && isalpha(i);
+ csupper.v[i] = ISASCII(i) && isupper(i);
+ cslower.v[i] = ISASCII(i) && islower(i);
+ csdigit.v[i] = ISASCII(i) && isdigit(i);
+ csxdigit.v[i] = ISASCII(i) && isxdigit(i);
+ csspace.v[i] = ISASCII(i) && isspace(i);
+ cspunct.v[i] = ISASCII(i) && ispunct(i);
+ csalnum.v[i] = ISASCII(i) && isalnum(i);
+ csprint.v[i] = ISASCII(i) && isprint(i);
+ csgraph.v[i] = ISASCII(i) && isgraph(i);
+ cscntrl.v[i] = ISASCII(i) && iscntrl(i);
+ }
+}
diff --git a/src/libs/libgroff/device.cc b/src/libs/libgroff/device.cc
new file mode 100644
index 00000000..7efbfef2
--- /dev/null
+++ b/src/libs/libgroff/device.cc
@@ -0,0 +1,36 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdlib.h>
+#include "device.h"
+#include "defs.h"
+
+const char *device = DEVICE;
+
+struct device_init {
+ device_init();
+} _device_init;
+
+device_init::device_init()
+{
+ char *tem = getenv("GROFF_TYPESETTER");
+ if (tem)
+ device = tem;
+}
diff --git a/src/libs/libgroff/errarg.cc b/src/libs/libgroff/errarg.cc
new file mode 100644
index 00000000..ea30c370
--- /dev/null
+++ b/src/libs/libgroff/errarg.cc
@@ -0,0 +1,118 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "assert.h"
+#include "errarg.h"
+
+errarg::errarg(const char *p) : type(STRING)
+{
+ s = p ? p : "(null)";
+}
+
+errarg::errarg() : type(EMPTY)
+{
+}
+
+errarg::errarg(unsigned char cc) : type(CHAR)
+{
+ c = cc;
+}
+
+errarg::errarg(int nn) : type(INTEGER)
+{
+ n = nn;
+}
+
+errarg::errarg(char cc) : type(CHAR)
+{
+ c = cc;
+}
+
+errarg::errarg(double dd) : type(DOUBLE)
+{
+ d = dd;
+}
+
+int errarg::empty() const
+{
+ return type == EMPTY;
+}
+
+extern "C" {
+ const char *itoa(int);
+}
+
+void errarg::print() const
+{
+ switch (type) {
+ case INTEGER:
+ fputs(itoa(n), stderr);
+ break;
+ case CHAR:
+ putc(c, stderr);
+ break;
+ case STRING:
+ fputs(s, stderr);
+ break;
+ case DOUBLE:
+ fprintf(stderr, "%g", d);
+ break;
+ case EMPTY:
+ break;
+ }
+}
+
+errarg empty_errarg;
+
+void errprint(const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ assert(format != 0);
+ char c;
+ while ((c = *format++) != '\0') {
+ if (c == '%') {
+ c = *format++;
+ switch(c) {
+ case '%':
+ fputc('%', stderr);
+ break;
+ case '1':
+ assert(!arg1.empty());
+ arg1.print();
+ break;
+ case '2':
+ assert(!arg2.empty());
+ arg2.print();
+ break;
+ case '3':
+ assert(!arg3.empty());
+ arg3.print();
+ break;
+ default:
+ assert(0);
+ }
+ }
+ else
+ putc(c, stderr);
+ }
+}
diff --git a/src/libs/libgroff/error.cc b/src/libs/libgroff/error.cc
new file mode 100644
index 00000000..53fd6298
--- /dev/null
+++ b/src/libs/libgroff/error.cc
@@ -0,0 +1,137 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "errarg.h"
+#include "error.h"
+
+extern void fatal_error_exit();
+
+enum error_type { WARNING, ERROR, FATAL };
+
+static void do_error_with_file_and_line(const char *filename, int lineno,
+ error_type type,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ int need_space = 0;
+ if (program_name) {
+ fprintf(stderr, "%s:", program_name);
+ need_space = 1;
+ }
+ if (lineno >= 0 && filename != 0) {
+ if (strcmp(filename, "-") == 0)
+ filename = "<standard input>";
+ fprintf(stderr, "%s:%d:", filename, lineno);
+ need_space = 1;
+ }
+ switch (type) {
+ case FATAL:
+ fputs("fatal error:", stderr);
+ need_space = 1;
+ break;
+ case ERROR:
+ break;
+ case WARNING:
+ fputs("warning:", stderr);
+ need_space = 1;
+ break;
+ }
+ if (need_space)
+ fputc(' ', stderr);
+ errprint(format, arg1, arg2, arg3);
+ fputc('\n', stderr);
+ fflush(stderr);
+ if (type == FATAL)
+ fatal_error_exit();
+}
+
+
+static void do_error(error_type type,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ do_error_with_file_and_line(current_filename, current_lineno,
+ type, format, arg1, arg2, arg3);
+}
+
+
+void error(const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ do_error(ERROR, format, arg1, arg2, arg3);
+}
+
+void warning(const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ do_error(WARNING, format, arg1, arg2, arg3);
+}
+
+void fatal(const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ do_error(FATAL, format, arg1, arg2, arg3);
+}
+
+void error_with_file_and_line(const char *filename,
+ int lineno,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ do_error_with_file_and_line(filename, lineno,
+ ERROR, format, arg1, arg2, arg3);
+}
+
+void warning_with_file_and_line(const char *filename,
+ int lineno,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ do_error_with_file_and_line(filename, lineno,
+ WARNING, format, arg1, arg2, arg3);
+}
+
+void fatal_with_file_and_line(const char *filename,
+ int lineno,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ do_error_with_file_and_line(filename, lineno,
+ FATAL, format, arg1, arg2, arg3);
+}
diff --git a/src/libs/libgroff/fatal.cc b/src/libs/libgroff/fatal.cc
new file mode 100644
index 00000000..42560dca
--- /dev/null
+++ b/src/libs/libgroff/fatal.cc
@@ -0,0 +1,27 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdlib.h>
+
+#define FATAL_ERROR_EXIT_CODE 3
+
+void fatal_error_exit()
+{
+ exit(FATAL_ERROR_EXIT_CODE);
+}
diff --git a/src/libs/libgroff/filename.cc b/src/libs/libgroff/filename.cc
new file mode 100644
index 00000000..1cbaa93d
--- /dev/null
+++ b/src/libs/libgroff/filename.cc
@@ -0,0 +1 @@
+const char *current_filename = 0;
diff --git a/src/libs/libgroff/fmod.c b/src/libs/libgroff/fmod.c
new file mode 100644
index 00000000..818f946e
--- /dev/null
+++ b/src/libs/libgroff/fmod.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <math.h>
+
+double fmod(x, y)
+ double x, y;
+{
+ double quot = x/y;
+ return x - (quot < 0.0 ? ceil(quot) : floor(quot)) * y;
+}
+
diff --git a/src/libs/libgroff/font.cc b/src/libs/libgroff/font.cc
new file mode 100644
index 00000000..bc830693
--- /dev/null
+++ b/src/libs/libgroff/font.cc
@@ -0,0 +1,938 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <math.h>
+#include <stdlib.h>
+#include "errarg.h"
+#include "error.h"
+#include "cset.h"
+#include "font.h"
+#include "lib.h"
+
+const char *const WS = " \t\n\r";
+
+struct font_char_metric {
+ char type;
+ int code;
+ int width;
+ int height;
+ int depth;
+ int pre_math_space;
+ int italic_correction;
+ int subscript_correction;
+ char *special_device_coding;
+};
+
+struct font_kern_list {
+ int i1;
+ int i2;
+ int amount;
+ font_kern_list *next;
+
+ font_kern_list(int, int, int, font_kern_list * = 0);
+};
+
+struct font_widths_cache {
+ font_widths_cache *next;
+ int point_size;
+ int *width;
+
+ font_widths_cache(int, int, font_widths_cache *);
+ ~font_widths_cache();
+};
+
+/* text_file */
+
+struct text_file {
+ FILE *fp;
+ char *path;
+ int lineno;
+ int size;
+ int skip_comments;
+ char *buf;
+ text_file(FILE *fp, char *p);
+ ~text_file();
+ int next();
+ void error(const char *format,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+};
+
+text_file::text_file(FILE *p, char *s)
+: fp(p), path(s), lineno(0), size(0), skip_comments(1), buf(0)
+{
+}
+
+text_file::~text_file()
+{
+ a_delete buf;
+ a_delete path;
+ if (fp)
+ fclose(fp);
+}
+
+
+int text_file::next()
+{
+ if (fp == 0)
+ return 0;
+ if (buf == 0) {
+ buf = new char [128];
+ size = 128;
+ }
+ for (;;) {
+ int i = 0;
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ if (illegal_input_char(c))
+ error("illegal input character code `%1'", int(c));
+ else {
+ if (i + 1 >= size) {
+ char *old_buf = buf;
+ buf = new char[size*2];
+ memcpy(buf, old_buf, size);
+ a_delete old_buf;
+ size *= 2;
+ }
+ buf[i++] = c;
+ if (c == '\n')
+ break;
+ }
+ }
+ if (i == 0)
+ break;
+ buf[i] = '\0';
+ lineno++;
+ char *ptr = buf;
+ while (csspace(*ptr))
+ ptr++;
+ if (*ptr != 0 && (!skip_comments || *ptr != '#'))
+ return 1;
+ }
+ return 0;
+}
+
+void text_file::error(const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ error_with_file_and_line(path, lineno, format, arg1, arg2, arg3);
+}
+
+
+/* font functions */
+
+font::font(const char *s)
+: ligatures(0), kern_hash_table(0), space_width(0), ch_index(0), nindices(0),
+ ch(0), ch_used(0), ch_size(0), special(0), widths_cache(0)
+{
+ name = new char[strlen(s) + 1];
+ strcpy(name, s);
+ internalname = 0;
+ slant = 0.0;
+ // load(); // for testing
+}
+
+font::~font()
+{
+ a_delete ch;
+ a_delete ch_index;
+ if (kern_hash_table) {
+ for (int i = 0; i < KERN_HASH_TABLE_SIZE; i++) {
+ font_kern_list *kerns = kern_hash_table[i];
+ while (kerns) {
+ font_kern_list *tem = kerns;
+ kerns = kerns->next;
+ delete tem;
+ }
+ }
+ a_delete kern_hash_table;
+ }
+ a_delete name;
+ a_delete internalname;
+ while (widths_cache) {
+ font_widths_cache *tem = widths_cache;
+ widths_cache = widths_cache->next;
+ delete tem;
+ }
+}
+
+static int scale_round(int n, int x, int y)
+{
+ assert(x >= 0 && y > 0);
+ int y2 = y/2;
+ if (x == 0)
+ return 0;
+ if (n >= 0) {
+ if (n <= (INT_MAX - y2)/x)
+ return (n*x + y2)/y;
+ return int(n*double(x)/double(y) + .5);
+ }
+ else {
+ if (-(unsigned)n <= (-(unsigned)INT_MIN - y2)/x)
+ return (n*x - y2)/y;
+ return int(n*double(x)/double(y) - .5);
+ }
+}
+
+inline int font::scale(int w, int sz)
+{
+ return sz == unitwidth ? w : scale_round(w, sz, unitwidth);
+}
+
+int font::get_skew(int c, int point_size, int sl)
+{
+ int h = get_height(c, point_size);
+ return int(h*tan((slant+sl)*PI/180.0) + .5);
+}
+
+int font::contains(int c)
+{
+ return c >= 0 && c < nindices && ch_index[c] >= 0;
+}
+
+int font::is_special()
+{
+ return special;
+}
+
+font_widths_cache::font_widths_cache(int ps, int ch_size,
+ font_widths_cache *p = 0)
+: next(p), point_size(ps)
+{
+ width = new int[ch_size];
+ for (int i = 0; i < ch_size; i++)
+ width[i] = -1;
+}
+
+font_widths_cache::~font_widths_cache()
+{
+ a_delete width;
+}
+
+int font::get_width(int c, int point_size)
+{
+ assert(c >= 0 && c < nindices);
+ int i = ch_index[c];
+ assert(i >= 0);
+
+ if (point_size == unitwidth)
+ return ch[i].width;
+
+ if (!widths_cache)
+ widths_cache = new font_widths_cache(point_size, ch_size);
+ else if (widths_cache->point_size != point_size) {
+ font_widths_cache **p;
+ for (p = &widths_cache; *p; p = &(*p)->next)
+ if ((*p)->point_size == point_size)
+ break;
+ if (*p) {
+ font_widths_cache *tem = *p;
+ *p = (*p)->next;
+ tem->next = widths_cache;
+ widths_cache = tem;
+ }
+ else
+ widths_cache = new font_widths_cache(point_size, ch_size, widths_cache);
+ }
+ int &w = widths_cache->width[i];
+ if (w < 0)
+ w = scale(ch[i].width, point_size);
+ return w;
+}
+
+int font::get_height(int c, int point_size)
+{
+ assert(c >= 0 && c < nindices && ch_index[c] >= 0);
+ return scale(ch[ch_index[c]].height, point_size);
+}
+
+int font::get_depth(int c, int point_size)
+{
+ assert(c >= 0 && c < nindices && ch_index[c] >= 0);
+ return scale(ch[ch_index[c]].depth, point_size);
+}
+
+int font::get_italic_correction(int c, int point_size)
+{
+ assert(c >= 0 && c < nindices && ch_index[c] >= 0);
+ return scale(ch[ch_index[c]].italic_correction, point_size);
+}
+
+int font::get_left_italic_correction(int c, int point_size)
+{
+ assert(c >= 0 && c < nindices && ch_index[c] >= 0);
+ return scale(ch[ch_index[c]].pre_math_space, point_size);
+}
+
+int font::get_subscript_correction(int c, int point_size)
+{
+ assert(c >= 0 && c < nindices && ch_index[c] >= 0);
+ return scale(ch[ch_index[c]].subscript_correction, point_size);
+}
+
+int font::get_space_width(int point_size)
+{
+ return scale(space_width, point_size);
+}
+
+font_kern_list::font_kern_list(int c1, int c2, int n, font_kern_list *p)
+ : i1(c1), i2(c2), amount(n), next(p)
+{
+}
+
+inline int font::hash_kern(int i1, int i2)
+{
+ int n = ((i1 << 10) + i2) % KERN_HASH_TABLE_SIZE;
+ return n < 0 ? -n : n;
+}
+
+void font::add_kern(int i1, int i2, int amount)
+{
+ if (!kern_hash_table) {
+ kern_hash_table = new font_kern_list *[KERN_HASH_TABLE_SIZE];
+ for (int i = 0; i < KERN_HASH_TABLE_SIZE; i++)
+ kern_hash_table[i] = 0;
+ }
+ font_kern_list **p = kern_hash_table + hash_kern(i1, i2);
+ *p = new font_kern_list(i1, i2, amount, *p);
+}
+
+int font::get_kern(int i1, int i2, int point_size)
+{
+ if (kern_hash_table) {
+ for (font_kern_list *p = kern_hash_table[hash_kern(i1, i2)]; p; p = p->next)
+ if (i1 == p->i1 && i2 == p->i2)
+ return scale(p->amount, point_size);
+ }
+ return 0;
+}
+
+int font::has_ligature(int mask)
+{
+ return mask & ligatures;
+}
+
+int font::get_character_type(int c)
+{
+ assert(c >= 0 && c < nindices && ch_index[c] >= 0);
+ return ch[ch_index[c]].type;
+}
+
+int font::get_code(int c)
+{
+ assert(c >= 0 && c < nindices && ch_index[c] >= 0);
+ return ch[ch_index[c]].code;
+}
+
+const char *font::get_name()
+{
+ return name;
+}
+
+const char *font::get_internal_name()
+{
+ return internalname;
+}
+
+const char *font::get_special_device_encoding(int c)
+{
+ assert(c >= 0 && c < nindices && ch_index[c] >= 0);
+ return( ch[ch_index[c]].special_device_coding );
+}
+
+void font::alloc_ch_index(int index)
+{
+ if (nindices == 0) {
+ nindices = 128;
+ if (index >= nindices)
+ nindices = index + 10;
+ ch_index = new short[nindices];
+ for (int i = 0; i < nindices; i++)
+ ch_index[i] = -1;
+ }
+ else {
+ int old_nindices = nindices;
+ nindices *= 2;
+ if (index >= nindices)
+ nindices = index + 10;
+ short *old_ch_index = ch_index;
+ ch_index = new short[nindices];
+ memcpy(ch_index, old_ch_index, sizeof(short)*old_nindices);
+ for (int i = old_nindices; i < nindices; i++)
+ ch_index[i] = -1;
+ a_delete old_ch_index;
+ }
+}
+
+void font::extend_ch()
+{
+ if (ch == 0)
+ ch = new font_char_metric[ch_size = 16];
+ else {
+ int old_ch_size = ch_size;
+ ch_size *= 2;
+ font_char_metric *old_ch = ch;
+ ch = new font_char_metric[ch_size];
+ memcpy(ch, old_ch, old_ch_size*sizeof(font_char_metric));
+ a_delete old_ch;
+ }
+}
+
+void font::compact()
+{
+ int i;
+ for (i = nindices - 1; i >= 0; i--)
+ if (ch_index[i] >= 0)
+ break;
+ i++;
+ if (i < nindices) {
+ short *old_ch_index = ch_index;
+ ch_index = new short[i];
+ memcpy(ch_index, old_ch_index, i*sizeof(short));
+ a_delete old_ch_index;
+ nindices = i;
+ }
+ if (ch_used < ch_size) {
+ font_char_metric *old_ch = ch;
+ ch = new font_char_metric[ch_used];
+ memcpy(ch, old_ch, ch_used*sizeof(font_char_metric));
+ a_delete old_ch;
+ ch_size = ch_used;
+ }
+}
+
+void font::add_entry(int index, const font_char_metric &metric)
+{
+ assert(index >= 0);
+ if (index >= nindices)
+ alloc_ch_index(index);
+ assert(index < nindices);
+ if (ch_used + 1 >= ch_size)
+ extend_ch();
+ assert(ch_used + 1 < ch_size);
+ ch_index[index] = ch_used;
+ ch[ch_used++] = metric;
+}
+
+void font::copy_entry(int new_index, int old_index)
+{
+ assert(new_index >= 0 && old_index >= 0 && old_index < nindices);
+ if (new_index >= nindices)
+ alloc_ch_index(new_index);
+ ch_index[new_index] = ch_index[old_index];
+}
+
+font *font::load_font(const char *s, int *not_found)
+{
+ font *f = new font(s);
+ if (!f->load(not_found)) {
+ delete f;
+ return 0;
+ }
+ return f;
+}
+
+static char *trim_arg(char *p)
+{
+ if (!p)
+ return 0;
+ while (csspace(*p))
+ p++;
+ char *q = strchr(p, '\0');
+ while (q > p && csspace(q[-1]))
+ q--;
+ *q = '\0';
+ return p;
+}
+
+// If the font can't be found, then if not_found is NULL it will be set
+// to 1 otherwise a message will be printed.
+
+int font::load(int *not_found)
+{
+ char *path;
+ FILE *fp;
+ if ((fp = open_file(name, &path)) == NULL) {
+ if (not_found)
+ *not_found = 1;
+ else
+ error("can't find font file `%1'", name);
+ return 0;
+ }
+ text_file t(fp, path);
+ t.skip_comments = 1;
+ char *p;
+ for (;;) {
+ if (!t.next()) {
+ t.error("missing charset command");
+ return 0;
+ }
+ p = strtok(t.buf, WS);
+ if (strcmp(p, "name") == 0) {
+ }
+ else if (strcmp(p, "spacewidth") == 0) {
+ p = strtok(0, WS);
+ int n;
+ if (p == 0 || sscanf(p, "%d", &n) != 1 || n <= 0) {
+ t.error("bad argument for spacewidth command");
+ return 0;
+ }
+ space_width = n;
+ }
+ else if (strcmp(p, "slant") == 0) {
+ p = strtok(0, WS);
+ double n;
+ if (p == 0 || sscanf(p, "%lf", &n) != 1 || n >= 90.0 || n <= -90.0) {
+ t.error("bad argument for slant command", p);
+ return 0;
+ }
+ slant = n;
+ }
+ else if (strcmp(p, "ligatures") == 0) {
+ for (;;) {
+ p = strtok(0, WS);
+ if (p == 0 || strcmp(p, "0") == 0)
+ break;
+ if (strcmp(p, "ff") == 0)
+ ligatures |= LIG_ff;
+ else if (strcmp(p, "fi") == 0)
+ ligatures |= LIG_fi;
+ else if (strcmp(p, "fl") == 0)
+ ligatures |= LIG_fl;
+ else if (strcmp(p, "ffi") == 0)
+ ligatures |= LIG_ffi;
+ else if (strcmp(p, "ffl") == 0)
+ ligatures |= LIG_ffl;
+ else {
+ t.error("unrecognised ligature `%1'", p);
+ return 0;
+ }
+ }
+ }
+ else if (strcmp(p, "internalname") == 0) {
+ p = strtok(0, WS);
+ if (!p) {
+ t.error("`internalname command requires argument");
+ return 0;
+ }
+ internalname = new char[strlen(p) + 1];
+ strcpy(internalname, p);
+ }
+ else if (strcmp(p, "special") == 0) {
+ special = 1;
+ }
+ else if (strcmp(p, "kernpairs") != 0 && strcmp(p, "charset") != 0) {
+ char *command = p;
+ p = strtok(0, "\n");
+ handle_unknown_font_command(command, trim_arg(p), t.path, t.lineno);
+ }
+ else
+ break;
+ }
+ char *command = p;
+ int had_charset = 0;
+ t.skip_comments = 0;
+ while (command) {
+ if (strcmp(command, "kernpairs") == 0) {
+ for (;;) {
+ if (!t.next()) {
+ command = 0;
+ break;
+ }
+ char *c1 = strtok(t.buf, WS);
+ if (c1 == 0)
+ continue;
+ char *c2 = strtok(0, WS);
+ if (c2 == 0) {
+ command = c1;
+ break;
+ }
+ p = strtok(0, WS);
+ if (p == 0) {
+ t.error("missing kern amount");
+ return 0;
+ }
+ int n;
+ if (sscanf(p, "%d", &n) != 1) {
+ t.error("bad kern amount `%1'", p);
+ return 0;
+ }
+ int i1 = name_to_index(c1);
+ if (i1 < 0) {
+ t.error("illegal character `%1'", c1);
+ return 0;
+ }
+ int i2 = name_to_index(c2);
+ if (i2 < 0) {
+ t.error("illegal character `%1'", c2);
+ return 0;
+ }
+ add_kern(i1, i2, n);
+ }
+ }
+ else if (strcmp(command, "charset") == 0) {
+ had_charset = 1;
+ int last_index = -1;
+ for (;;) {
+ if (!t.next()) {
+ command = 0;
+ break;
+ }
+ char *nm = strtok(t.buf, WS);
+ if (nm == 0)
+ continue; // I dont think this should happen
+ p = strtok(0, WS);
+ if (p == 0) {
+ command = nm;
+ break;
+ }
+ if (p[0] == '"') {
+ if (last_index == -1) {
+ t.error("first charset entry is duplicate");
+ return 0;
+ }
+ if (strcmp(nm, "---") == 0) {
+ t.error("unnamed character cannot be duplicate");
+ return 0;
+ }
+ int index = name_to_index(nm);
+ if (index < 0) {
+ t.error("illegal character `%1'", nm);
+ return 0;
+ }
+ copy_entry(index, last_index);
+ }
+ else {
+ font_char_metric metric;
+ metric.height = 0;
+ metric.depth = 0;
+ metric.pre_math_space = 0;
+ metric.italic_correction = 0;
+ metric.subscript_correction = 0;
+ int nparms = sscanf(p, "%d,%d,%d,%d,%d,%d",
+ &metric.width, &metric.height, &metric.depth,
+ &metric.italic_correction,
+ &metric.pre_math_space,
+ &metric.subscript_correction);
+ if (nparms < 1) {
+ t.error("bad width for `%1'", nm);
+ return 0;
+ }
+ p = strtok(0, WS);
+ if (p == 0) {
+ t.error("missing character type for `%1'", nm);
+ return 0;
+ }
+ int type;
+ if (sscanf(p, "%d", &type) != 1) {
+ t.error("bad character type for `%1'", nm);
+ return 0;
+ }
+ if (type < 0 || type > 255) {
+ t.error("character code `%1' out of range", type);
+ return 0;
+ }
+ metric.type = type;
+ p = strtok(0, WS);
+ if (p == 0) {
+ t.error("missing code for `%1'", nm);
+ return 0;
+ }
+ char *ptr;
+ metric.code = (int)strtol(p, &ptr, 0);
+ if (metric.code == 0 && ptr == p) {
+ t.error("bad code `%1' for character `%2'", p, nm);
+ return 0;
+ }
+
+ p = strtok(0, WS);
+ if ((p == NULL) || (strcmp(p, "--") == 0)) {
+ metric.special_device_coding = NULL;
+ } else {
+ char *name=(char *)malloc(strlen(p)+1);
+
+ if (name == NULL) {
+ fatal("malloc failed while reading character encoding");
+ }
+ strcpy(name, p);
+ metric.special_device_coding = name;
+ }
+
+ if (strcmp(nm, "---") == 0) {
+ last_index = number_to_index(metric.code);
+ add_entry(last_index, metric);
+ }
+ else {
+ last_index = name_to_index(nm);
+ if (last_index < 0) {
+ t.error("illegal character `%1'", nm);
+ return 0;
+ }
+ add_entry(last_index, metric);
+ copy_entry(number_to_index(metric.code), last_index);
+ }
+ }
+ }
+ if (last_index == -1) {
+ t.error("I didn't seem to find any characters");
+ return 0;
+ }
+ }
+ else {
+ t.error("unrecognised command `%1' after `kernpairs' or `charset' command", command);
+ return 0;
+ }
+ }
+ if (!had_charset) {
+ t.error("missing charset command");
+ return 0;
+ }
+ if (space_width == 0)
+ space_width = scale_round(unitwidth, res, 72*3*sizescale);
+ compact();
+ return 1;
+}
+
+static struct {
+ const char *command;
+ int *ptr;
+} table[] = {
+ { "res", &font::res },
+ { "hor", &font::hor },
+ { "vert", &font::vert },
+ { "unitwidth", &font::unitwidth },
+ { "paperwidth", &font::paperwidth },
+ { "paperlength", &font::paperlength },
+ { "spare1", &font::biggestfont },
+ { "biggestfont", &font::biggestfont },
+ { "spare2", &font::spare2 },
+ { "sizescale", &font::sizescale }
+ };
+
+
+int font::load_desc()
+{
+ int nfonts = 0;
+ FILE *fp;
+ char *path;
+ if ((fp = open_file("DESC", &path)) == 0) {
+ error("can't find `DESC' file");
+ return 0;
+ }
+ text_file t(fp, path);
+ t.skip_comments = 1;
+ res = 0;
+ while (t.next()) {
+ char *p = strtok(t.buf, WS);
+ int found = 0;
+ int idx;
+ for (idx = 0; !found && idx < sizeof(table)/sizeof(table[0]); idx++)
+ if (strcmp(table[idx].command, p) == 0)
+ found = 1;
+ if (found) {
+ char *q = strtok(0, WS);
+ if (!q) {
+ t.error("missing value for command `%1'", p);
+ return 0;
+ }
+ //int *ptr = &(this->*(table[idx-1].ptr));
+ int *ptr = table[idx-1].ptr;
+ if (sscanf(q, "%d", ptr) != 1) {
+ t.error("bad number `%1'", q);
+ return 0;
+ }
+ }
+ else if (strcmp("tcommand", p) == 0) {
+ tcommand = 1;
+ }
+ else if (strcmp("pass_filenames", p) == 0) {
+ pass_filenames = 1;
+ }
+ else if (strcmp("use_charnames_in_special", p) == 0) {
+ use_charnames_in_special = 1;
+ }
+ else if (strcmp("family", p) == 0) {
+ p = strtok(0, WS);
+ if (!p) {
+ t.error("family command requires an argument");
+ return 0;
+ }
+ char *tem = new char[strlen(p)+1];
+ strcpy(tem, p);
+ family = tem;
+ }
+ else if (strcmp("fonts", p) == 0) {
+ p = strtok(0, WS);
+ if (!p || sscanf(p, "%d", &nfonts) != 1 || nfonts <= 0) {
+ t.error("bad number of fonts `%1'", p);
+ return 0;
+ }
+ font_name_table = (const char **)new char *[nfonts+1];
+ for (int i = 0; i < nfonts; i++) {
+ p = strtok(0, WS);
+ while (p == 0) {
+ if (!t.next()) {
+ t.error("end of file while reading list of fonts");
+ return 0;
+ }
+ p = strtok(t.buf, WS);
+ }
+ char *temp = new char[strlen(p)+1];
+ strcpy(temp, p);
+ font_name_table[i] = temp;
+ }
+ p = strtok(0, WS);
+ if (p != 0) {
+ t.error("font count does not match number of fonts");
+ return 0;
+ }
+ font_name_table[nfonts] = 0;
+ }
+ else if (strcmp("sizes", p) == 0) {
+ int n = 16;
+ sizes = new int[n];
+ int i = 0;
+ for (;;) {
+ p = strtok(0, WS);
+ while (p == 0) {
+ if (!t.next()) {
+ t.error("list of sizes must be terminated by `0'");
+ return 0;
+ }
+ p = strtok(t.buf, WS);
+ }
+ int lower, upper;
+ switch (sscanf(p, "%d-%d", &lower, &upper)) {
+ case 1:
+ upper = lower;
+ // fall through
+ case 2:
+ if (lower <= upper && lower >= 0)
+ break;
+ // fall through
+ default:
+ t.error("bad size range `%1'", p);
+ return 0;
+ }
+ if (i + 2 > n) {
+ int *old_sizes = sizes;
+ sizes = new int[n*2];
+ memcpy(sizes, old_sizes, n*sizeof(int));
+ n *= 2;
+ a_delete old_sizes;
+ }
+ sizes[i++] = lower;
+ if (lower == 0)
+ break;
+ sizes[i++] = upper;
+ }
+ if (i == 1) {
+ t.error("must have some sizes");
+ return 0;
+ }
+ }
+ else if (strcmp("styles", p) == 0) {
+ int style_table_size = 5;
+ style_table = (const char **)new char *[style_table_size];
+ int j;
+ for (j = 0; j < style_table_size; j++)
+ style_table[j] = 0;
+ int i = 0;
+ for (;;) {
+ p = strtok(0, WS);
+ if (p == 0)
+ break;
+ // leave room for terminating 0
+ if (i + 1 >= style_table_size) {
+ const char **old_style_table = style_table;
+ style_table_size *= 2;
+ style_table = (const char **)new char*[style_table_size];
+ for (j = 0; j < i; j++)
+ style_table[j] = old_style_table[j];
+ for (; j < style_table_size; j++)
+ style_table[j] = 0;
+ a_delete old_style_table;
+ }
+ char *tem = new char[strlen(p) + 1];
+ strcpy(tem, p);
+ style_table[i++] = tem;
+ }
+ }
+ else if (strcmp("charset", p) == 0)
+ break;
+ else if (unknown_desc_command_handler) {
+ char *command = p;
+ p = strtok(0, "\n");
+ (*unknown_desc_command_handler)(command, trim_arg(p), t.path, t.lineno);
+ }
+ }
+ if (res == 0) {
+ t.error("missing `res' command");
+ return 0;
+ }
+ if (unitwidth == 0) {
+ t.error("missing `unitwidth' command");
+ return 0;
+ }
+ if (font_name_table == 0) {
+ t.error("missing `fonts' command");
+ return 0;
+ }
+ if (sizes == 0) {
+ t.error("missing `sizes' command");
+ return 0;
+ }
+ if (sizescale < 1) {
+ t.error("bad `sizescale' value");
+ return 0;
+ }
+ if (hor < 1) {
+ t.error("bad `hor' value");
+ return 0;
+ }
+ if (vert < 1) {
+ t.error("bad `vert' value");
+ return 0;
+ }
+ return 1;
+}
+
+void font::handle_unknown_font_command(const char *, const char *,
+ const char *, int)
+{
+}
+
+FONT_COMMAND_HANDLER
+font::set_unknown_desc_command_handler(FONT_COMMAND_HANDLER func)
+{
+ FONT_COMMAND_HANDLER prev = unknown_desc_command_handler;
+ unknown_desc_command_handler = func;
+ return prev;
+}
+
diff --git a/src/libs/libgroff/fontfile.cc b/src/libs/libgroff/fontfile.cc
new file mode 100644
index 00000000..fa87b861
--- /dev/null
+++ b/src/libs/libgroff/fontfile.cc
@@ -0,0 +1,66 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "font.h"
+#include "lib.h"
+#include "searchpath.h"
+#include "device.h"
+#include "defs.h"
+
+const char *const FONT_ENV_VAR = "GROFF_FONT_PATH";
+
+static search_path font_path(FONT_ENV_VAR, FONTPATH);
+
+int font::res = 0;
+int font::hor = 1;
+int font::vert = 1;
+int font::unitwidth = 0;
+int font::paperwidth = 0;
+int font::paperlength = 0;
+int font::biggestfont = 0;
+int font::spare2 = 0;
+int font::sizescale = 1;
+int font::tcommand = 0;
+int font::pass_filenames = 0;
+int font::use_charnames_in_special = 0;
+const char **font::font_name_table = 0;
+int *font::sizes = 0;
+const char *font::family = 0;
+const char **font::style_table = 0;
+FONT_COMMAND_HANDLER font::unknown_desc_command_handler = 0;
+
+void font::command_line_font_dir(const char *dir)
+{
+ font_path.command_line_dir(dir);
+}
+
+FILE *font::open_file(const char *name, char **pathp)
+{
+ char *filename = new char[strlen(name) + strlen(device) + 5];
+ sprintf(filename, "dev%s/%s", device, name);
+ FILE *fp = font_path.open_file(filename, pathp);
+ a_delete filename;
+ return fp;
+}
diff --git a/src/libs/libgroff/getcwd.c b/src/libs/libgroff/getcwd.c
new file mode 100644
index 00000000..208e8111
--- /dev/null
+++ b/src/libs/libgroff/getcwd.c
@@ -0,0 +1,38 @@
+/* Partial emulation of getcwd in terms of getwd. */
+
+#include <sys/param.h>
+#include <string.h>
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+char *getwd();
+
+char *getcwd(buf, size)
+ char *buf;
+ int size; /* POSIX says this should be size_t */
+{
+ if (size <= 0) {
+ errno = EINVAL;
+ return 0;
+ }
+ else {
+ char mybuf[MAXPATHLEN];
+ int saved_errno = errno;
+
+ errno = 0;
+ if (!getwd(mybuf)) {
+ if (errno == 0)
+ ; /* what to do? */
+ return 0;
+ }
+ errno = saved_errno;
+ if (strlen(mybuf) + 1 > size) {
+ errno = ERANGE;
+ return 0;
+ }
+ strcpy(buf, mybuf);
+ return buf;
+ }
+}
diff --git a/src/libs/libgroff/iftoa.c b/src/libs/libgroff/iftoa.c
new file mode 100644
index 00000000..75cd5e44
--- /dev/null
+++ b/src/libs/libgroff/iftoa.c
@@ -0,0 +1,65 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define INT_DIGITS 19 /* enough for 64-bit integer */
+
+char *iftoa(i, decimal_point)
+ int i, decimal_point;
+{
+ /* room for a -, INT_DIGITS digits, a decimal point, and a terminating '\0' */
+ static char buf[INT_DIGITS + 3];
+ char *p = buf + INT_DIGITS + 2;
+ int point = 0;
+ buf[INT_DIGITS + 2] = '\0';
+ /* assert(decimal_point <= INT_DIGITS); */
+ if (i >= 0) {
+ do {
+ *--p = '0' + (i % 10);
+ i /= 10;
+ if (++point == decimal_point)
+ *--p = '.';
+ } while (i != 0 || point < decimal_point);
+ }
+ else { /* i < 0 */
+ do {
+ *--p = '0' - (i % 10);
+ i /= 10;
+ if (++point == decimal_point)
+ *--p = '.';
+ } while (i != 0 || point < decimal_point);
+ *--p = '-';
+ }
+ if (decimal_point > 0) {
+ char *q;
+ /* there must be a dot, so this will terminate */
+ for (q = buf + INT_DIGITS + 2; q[-1] == '0'; --q)
+ ;
+ if (q[-1] == '.') {
+ if (q - 1 == p) {
+ q[-1] = '0';
+ q[0] = '\0';
+ }
+ else
+ q[-1] = '\0';
+ }
+ else
+ *q = '\0';
+ }
+ return p;
+}
diff --git a/src/libs/libgroff/illegal.cc b/src/libs/libgroff/illegal.cc
new file mode 100755
index 00000000..10f4d5bd
--- /dev/null
+++ b/src/libs/libgroff/illegal.cc
@@ -0,0 +1,22 @@
+#include "lib.h"
+
+// Table of illegal input characters.
+
+char illegal_char_table[256]= {
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 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, 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,
+ 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,
+ 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, 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,
+};
diff --git a/src/libs/libgroff/itoa.c b/src/libs/libgroff/itoa.c
new file mode 100644
index 00000000..69f21cc8
--- /dev/null
+++ b/src/libs/libgroff/itoa.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define INT_DIGITS 19 /* enough for 64 bit integer */
+
+char *itoa(i)
+ int i;
+{
+ /* Room for INT_DIGITS digits, - and '\0' */
+ static char buf[INT_DIGITS + 2];
+ char *p = buf + INT_DIGITS + 1; /* points to terminating '\0' */
+ if (i >= 0) {
+ do {
+ *--p = '0' + (i % 10);
+ i /= 10;
+ } while (i != 0);
+ return p;
+ }
+ else { /* i < 0 */
+ do {
+ *--p = '0' - (i % 10);
+ i /= 10;
+ } while (i != 0);
+ *--p = '-';
+ }
+ return p;
+}
diff --git a/src/libs/libgroff/lf.cc b/src/libs/libgroff/lf.cc
new file mode 100644
index 00000000..34272c7d
--- /dev/null
+++ b/src/libs/libgroff/lf.cc
@@ -0,0 +1,62 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <string.h>
+#include <ctype.h>
+#include "cset.h"
+#include "stringclass.h"
+
+extern void change_filename(const char *);
+extern void change_lineno(int);
+
+int interpret_lf_args(const char *p)
+{
+ while (*p == ' ')
+ p++;
+ if (!csdigit(*p))
+ return 0;
+ int ln = 0;
+ do {
+ ln *= 10;
+ ln += *p++ - '0';
+ } while (csdigit(*p));
+ if (*p != ' ' && *p != '\n' && *p != '\0')
+ return 0;
+ while (*p == ' ')
+ p++;
+ if (*p == '\0' || *p == '\n') {
+ change_lineno(ln);
+ return 1;
+ }
+ const char *q;
+ for (q = p;
+ *q != '\0' && *q != ' ' && *q != '\n' && *q != '\\';
+ q++)
+ ;
+ string tem(p, q - p);
+ while (*q == ' ')
+ q++;
+ if (*q != '\n' && *q != '\0')
+ return 0;
+ tem += '\0';
+ change_filename(tem.contents());
+ change_lineno(ln);
+ return 1;
+}
diff --git a/src/libs/libgroff/lineno.cc b/src/libs/libgroff/lineno.cc
new file mode 100644
index 00000000..f7138dba
--- /dev/null
+++ b/src/libs/libgroff/lineno.cc
@@ -0,0 +1 @@
+int current_lineno = 0;
diff --git a/src/libs/libgroff/macropath.cc b/src/libs/libgroff/macropath.cc
new file mode 100644
index 00000000..4fd22a30
--- /dev/null
+++ b/src/libs/libgroff/macropath.cc
@@ -0,0 +1,28 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "lib.h"
+#include "searchpath.h"
+#include "macropath.h"
+#include "defs.h"
+
+#define MACROPATH_ENVVAR "GROFF_TMAC_PATH"
+
+search_path macro_path(MACROPATH_ENVVAR, MACROPATH);
diff --git a/src/libs/libgroff/matherr.c b/src/libs/libgroff/matherr.c
new file mode 100644
index 00000000..b0097b8b
--- /dev/null
+++ b/src/libs/libgroff/matherr.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <math.h>
+#include <errno.h>
+
+#ifdef HAVE_STRUCT_EXCEPTION
+#ifdef TLOSS
+
+int matherr(exc)
+struct exception *exc;
+{
+ switch (exc->type) {
+ case SING:
+ case DOMAIN:
+ errno = EDOM;
+ break;
+ case OVERFLOW:
+ case UNDERFLOW:
+ case TLOSS:
+ case PLOSS:
+ errno = ERANGE;
+ break;
+ }
+ return 1;
+}
+
+#endif /* TLOSS */
+#endif /* HAVE_STRUCT_EXCEPTION */
diff --git a/src/libs/libgroff/nametoindex.cc b/src/libs/libgroff/nametoindex.cc
new file mode 100644
index 00000000..694cab94
--- /dev/null
+++ b/src/libs/libgroff/nametoindex.cc
@@ -0,0 +1,118 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <stdlib.h>
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+#include "font.h"
+#include "ptable.h"
+
+declare_ptable(int)
+implement_ptable(int)
+
+class character_indexer {
+public:
+ character_indexer();
+ ~character_indexer();
+ int ascii_char_index(unsigned char);
+ int named_char_index(const char *);
+ int numbered_char_index(int);
+private:
+ enum { NSMALL = 256 };
+ int next_index;
+ int ascii_index[256];
+ int small_number_index[NSMALL];
+ PTABLE(int) table;
+ int lookup_char(const char *, int);
+};
+
+character_indexer::character_indexer()
+: next_index(0)
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ ascii_index[i] = -1;
+ for (i = 0; i < NSMALL; i++)
+ small_number_index[i] = -1;
+}
+
+character_indexer::~character_indexer()
+{
+}
+
+int character_indexer::ascii_char_index(unsigned char c)
+{
+ if (ascii_index[c] < 0)
+ ascii_index[c] = next_index++;
+ return ascii_index[c];
+}
+
+int character_indexer::numbered_char_index(int n)
+{
+ if (n >= 0 && n < NSMALL) {
+ if (small_number_index[n] < 0)
+ small_number_index[n] = next_index++;
+ return small_number_index[n];
+ }
+ // Not the most efficient possible implementation.
+ char buf[INT_DIGITS + 3];
+ buf[0] = ' ';
+ strcpy(buf + 1, itoa(n));
+ return named_char_index(buf);
+}
+
+int character_indexer::named_char_index(const char *s)
+{
+ int *np = table.lookup(s);
+ if (!np) {
+ np = new int;
+ *np = next_index++;
+ table.define(s, np);
+ }
+ return *np;
+}
+
+static character_indexer indexer;
+
+int font::number_to_index(int n)
+{
+ return indexer.numbered_char_index(n);
+}
+
+int font::name_to_index(const char *s)
+{
+ assert(s != 0 && s[0] != '\0' && s[0] != ' ');
+ if (s[1] == '\0')
+ return indexer.ascii_char_index(s[0]);
+ /* char128 and \200 are synonyms */
+ if (s[0] == 'c' && s[1] == 'h' && s[2] == 'a' && s[3] == 'r') {
+ char *res;
+ long n = strtol(s + 4, &res, 10);
+ if (res != s + 4 && *res == '\0' && n >= 0 && n < 256)
+ return indexer.ascii_char_index((unsigned char)n);
+ }
+ return indexer.named_char_index(s);
+}
+
diff --git a/src/libs/libgroff/new.cc b/src/libs/libgroff/new.cc
new file mode 100644
index 00000000..d26db2f5
--- /dev/null
+++ b/src/libs/libgroff/new.cc
@@ -0,0 +1,67 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "posix.h"
+
+extern const char *program_name;
+
+static void ewrite(const char *s)
+{
+ write(2, s, strlen(s));
+}
+
+void *operator new(size_t size)
+{
+ // Avoid relying on the behaviour of malloc(0).
+ if (size == 0)
+ size++;
+#ifdef COOKIE_BUG
+ char *p = (char *)malloc(unsigned(size + 8));
+#else /* not COOKIE_BUG */
+ char *p = (char *)malloc(unsigned(size));
+#endif /* not COOKIE_BUG */
+ if (p == 0) {
+ if (program_name) {
+ ewrite(program_name);
+ ewrite(": ");
+ }
+ ewrite("out of memory\n");
+ _exit(-1);
+ }
+#ifdef COOKIE_BUG
+ ((unsigned *)p)[1] = 0;
+ return p + 8;
+#else /* not COOKIE_BUG */
+ return p;
+#endif /* not COOKIE_BUG */
+}
+
+#ifdef COOKIE_BUG
+
+void operator delete(void *p)
+{
+ if (p)
+ free((void *)((char *)p - 8));
+}
+
+#endif /* COOKIE_BUG */
diff --git a/src/libs/libgroff/prime.cc b/src/libs/libgroff/prime.cc
new file mode 100644
index 00000000..f0b1eadc
--- /dev/null
+++ b/src/libs/libgroff/prime.cc
@@ -0,0 +1,26 @@
+#include <math.h>
+
+int is_prime(unsigned n)
+{
+ if (n <= 3)
+ return 1;
+ if (!(n & 1))
+ return 0;
+ if (n % 3 == 0)
+ return 0;
+ unsigned lim = unsigned(sqrt((double)n));
+ unsigned d = 5;
+ for (;;) {
+ if (d > lim)
+ break;
+ if (n % d == 0)
+ return 0;
+ d += 2;
+ if (d > lim)
+ break;
+ if (n % d == 0)
+ return 0;
+ d += 4;
+ }
+ return 1;
+}
diff --git a/src/libs/libgroff/progname.cc b/src/libs/libgroff/progname.cc
new file mode 100644
index 00000000..a70e3419
--- /dev/null
+++ b/src/libs/libgroff/progname.cc
@@ -0,0 +1 @@
+const char *program_name = 0;
diff --git a/src/libs/libgroff/ptable.cc b/src/libs/libgroff/ptable.cc
new file mode 100644
index 00000000..76735c24
--- /dev/null
+++ b/src/libs/libgroff/ptable.cc
@@ -0,0 +1,52 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "ptable.h"
+#include "errarg.h"
+#include "error.h"
+
+unsigned long hash_string(const char *s)
+{
+ assert(s != 0);
+ unsigned long h = 0, g;
+ while (*s != 0) {
+ h <<= 4;
+ h += *s++;
+ if ((g = h & 0xf0000000) != 0) {
+ h ^= g >> 24;
+ h ^= g;
+ }
+ }
+ return h;
+}
+
+static const unsigned table_sizes[] = {
+101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009,
+80021, 160001, 500009, 1000003, 2000003, 4000037, 8000009,
+16000057, 32000011, 64000031, 128000003, 0
+};
+
+unsigned next_ptable_size(unsigned n)
+{
+ const unsigned *p;
+ for (p = table_sizes; *p <= n; p++)
+ if (*p == 0)
+ fatal("cannot expand table");
+ return *p;
+}
diff --git a/src/libs/libgroff/putenv.c b/src/libs/libgroff/putenv.c
new file mode 100644
index 00000000..c1ca671a
--- /dev/null
+++ b/src/libs/libgroff/putenv.c
@@ -0,0 +1,95 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C 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.
+
+The GNU C 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 the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* Hacked slightly by jjc@jclark.com for groff. */
+
+#include <string.h>
+
+#ifdef __STDC__
+#include <stddef.h>
+typedef void *PTR;
+typedef size_t SIZE_T;
+#else /* not __STDC__ */
+typedef char *PTR;
+typedef int SIZE_T;
+#endif /* not __STDC__ */
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#else /* not HAVE_STDLIB_H */
+PTR malloc();
+#endif /* not HAVE_STDLIB_H */
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+extern char **environ;
+
+/* Put STRING, which is of the form "NAME=VALUE", in the environment. */
+
+int putenv(const char *string)
+{
+ char *name_end = strchr(string, '=');
+ SIZE_T size;
+ char **ep;
+
+ if (name_end == NULL)
+ {
+ /* Remove the variable from the environment. */
+ size = strlen(string);
+ for (ep = environ; *ep != NULL; ++ep)
+ if (!strncmp(*ep, string, size) && (*ep)[size] == '=')
+ {
+ while (ep[1] != NULL)
+ {
+ ep[0] = ep[1];
+ ++ep;
+ }
+ *ep = NULL;
+ return 0;
+ }
+ }
+
+ size = 0;
+ for (ep = environ; *ep != NULL; ++ep)
+ if (!strncmp(*ep, string, name_end - string)
+ && (*ep)[name_end - string] == '=')
+ break;
+ else
+ ++size;
+
+ if (*ep == NULL)
+ {
+ static char **last_environ = NULL;
+ char **new_environ = (char **) malloc((size + 2) * sizeof(char *));
+ if (new_environ == NULL)
+ return -1;
+ (void) memcpy((PTR) new_environ, (PTR) environ, size * sizeof(char *));
+ new_environ[size] = (char *) string;
+ new_environ[size + 1] = NULL;
+ if (last_environ != NULL)
+ free((PTR) last_environ);
+ last_environ = new_environ;
+ environ = new_environ;
+ }
+ else
+ *ep = (char *) string;
+
+ return 0;
+}
diff --git a/src/libs/libgroff/searchpath.cc b/src/libs/libgroff/searchpath.cc
new file mode 100644
index 00000000..730b5d99
--- /dev/null
+++ b/src/libs/libgroff/searchpath.cc
@@ -0,0 +1,117 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "lib.h"
+#include "searchpath.h"
+
+search_path::search_path(const char *envvar, const char *standard)
+{
+ char *e = envvar ? getenv(envvar) : 0;
+ if (e && standard) {
+ dirs = new char[strlen(e) + strlen(standard) + 2];
+ strcpy(dirs, e);
+ strcat(dirs, ":");
+ strcat(dirs, standard);
+ }
+ else
+ dirs = strsave(e ? e : standard);
+ init_len = dirs ? strlen(dirs) : 0;
+}
+
+search_path::~search_path()
+{
+ if (dirs)
+ a_delete dirs;
+}
+
+void search_path::command_line_dir(const char *s)
+{
+ if (!dirs)
+ dirs = strsave(s);
+ else {
+ char *old = dirs;
+ unsigned old_len = strlen(old);
+ unsigned slen = strlen(s);
+ dirs = new char[old_len + 1 + slen + 1];
+ memcpy(dirs, old, old_len - init_len);
+ char *p = dirs;
+ p += old_len - init_len;
+ if (init_len == 0)
+ *p++ = ':';
+ memcpy(p, s, slen);
+ p += slen;
+ if (init_len > 0) {
+ *p++ = ':';
+ memcpy(p, old + old_len - init_len, init_len);
+ p += init_len;
+ }
+ *p++ = '\0';
+ a_delete old;
+ }
+}
+
+FILE *search_path::open_file(const char *name, char **pathp)
+{
+ assert(name != 0);
+ if (*name == '/' || dirs == 0 || *dirs == '\0') {
+ FILE *fp = fopen(name, "r");
+ if (fp) {
+ if (pathp)
+ *pathp = strsave(name);
+ return fp;
+ }
+ else
+ return 0;
+ }
+ unsigned namelen = strlen(name);
+ char *p = dirs;
+ for (;;) {
+ char *end = strchr(p, ':');
+ if (!end)
+ end = strchr(p, '\0');
+ int need_slash = end > p && end[-1] != '/';
+ char *path = new char[(end - p) + need_slash + namelen + 1];
+ memcpy(path, p, end - p);
+ if (need_slash)
+ path[end - p] = '/';
+ strcpy(path + (end - p) + need_slash, name);
+#if 0
+ fprintf(stderr, "trying `%s'\n", path);
+#endif
+ FILE *fp = fopen(path, "r");
+ if (fp) {
+ if (pathp)
+ *pathp = path;
+ else
+ a_delete path;
+ return fp;
+ }
+ a_delete path;
+ if (*end == '\0')
+ break;
+ p = end + 1;
+ }
+ return 0;
+}
diff --git a/src/libs/libgroff/strerror.c b/src/libs/libgroff/strerror.c
new file mode 100644
index 00000000..69089f13
--- /dev/null
+++ b/src/libs/libgroff/strerror.c
@@ -0,0 +1,41 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+
+#define INT_DIGITS 19 /* enough for 64 bit integer */
+
+#ifndef HAVE_SYS_NERR
+extern int sys_nerr;
+#endif
+#ifndef HAVE_SYS_ERRLIST
+extern char *sys_errlist[];
+#endif
+
+char *strerror(n)
+ int n;
+{
+ static char buf[sizeof("Error ") + 1 + INT_DIGITS];
+ if (n >= 0 && n < sys_nerr && sys_errlist[n] != 0)
+ return sys_errlist[n];
+ else {
+ sprintf(buf, "Error %d", n);
+ return buf;
+ }
+}
diff --git a/src/libs/libgroff/string.cc b/src/libs/libgroff/string.cc
new file mode 100644
index 00000000..4bcd4ccc
--- /dev/null
+++ b/src/libs/libgroff/string.cc
@@ -0,0 +1,311 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "stringclass.h"
+#include "lib.h"
+
+static char *salloc(int len, int *sizep);
+static void sfree(char *ptr, int size);
+static char *sfree_alloc(char *ptr, int size, int len, int *sizep);
+static char *srealloc(char *ptr, int size, int oldlen, int newlen, int *sizep);
+
+static char *salloc(int len, int *sizep)
+{
+ if (len == 0) {
+ *sizep = 0;
+ return 0;
+ }
+ else
+ return new char[*sizep = len*2];
+}
+
+static void sfree(char *ptr, int)
+{
+ a_delete ptr;
+}
+
+static char *sfree_alloc(char *ptr, int oldsz, int len, int *sizep)
+{
+ if (oldsz >= len) {
+ *sizep = oldsz;
+ return ptr;
+ }
+ a_delete ptr;
+ if (len == 0) {
+ *sizep = 0;
+ return 0;
+ }
+ else
+ return new char[*sizep = len*2];
+}
+
+static char *srealloc(char *ptr, int oldsz, int oldlen, int newlen, int *sizep)
+{
+ if (oldsz >= newlen) {
+ *sizep = oldsz;
+ return ptr;
+ }
+ if (newlen == 0) {
+ a_delete ptr;
+ *sizep = 0;
+ return 0;
+ }
+ else {
+ char *p = new char[*sizep = newlen*2];
+ if (oldlen < newlen && oldlen != 0)
+ memcpy(p, ptr, oldlen);
+ a_delete ptr;
+ return p;
+ }
+}
+
+string::string() : ptr(0), len(0), sz(0)
+{
+}
+
+string::string(const char *p, int n) : len(n)
+{
+ assert(n >= 0);
+ ptr = salloc(n, &sz);
+ if (n != 0)
+ memcpy(ptr, p, n);
+}
+
+string::string(const char *p)
+{
+ if (p == 0) {
+ len = 0;
+ ptr = 0;
+ sz = 0;
+ }
+ else {
+ len = strlen(p);
+ ptr = salloc(len, &sz);
+ memcpy(ptr, p, len);
+ }
+}
+
+string::string(char c) : len(1)
+{
+ ptr = salloc(1, &sz);
+ *ptr = c;
+}
+
+string::string(const string &s) : len(s.len)
+{
+ ptr = salloc(len, &sz);
+ if (len != 0)
+ memcpy(ptr, s.ptr, len);
+}
+
+string::~string()
+{
+ sfree(ptr, sz);
+}
+
+string &string::operator=(const string &s)
+{
+ ptr = sfree_alloc(ptr, sz, s.len, &sz);
+ len = s.len;
+ if (len != 0)
+ memcpy(ptr, s.ptr, len);
+ return *this;
+}
+
+string &string::operator=(const char *p)
+{
+ if (p == 0) {
+ sfree(ptr, len);
+ len = 0;
+ ptr = 0;
+ sz = 0;
+ }
+ else {
+ int slen = strlen(p);
+ ptr = sfree_alloc(ptr, sz, slen, &sz);
+ len = slen;
+ memcpy(ptr, p, len);
+ }
+ return *this;
+}
+
+string &string::operator=(char c)
+{
+ ptr = sfree_alloc(ptr, sz, 1, &sz);
+ len = 1;
+ *ptr = c;
+ return *this;
+}
+
+void string::move(string &s)
+{
+ sfree(ptr, sz);
+ ptr = s.ptr;
+ len = s.len;
+ sz = s.sz;
+ s.ptr = 0;
+ s.len = 0;
+ s.sz = 0;
+}
+
+void string::grow1()
+{
+ ptr = srealloc(ptr, sz, len, len + 1, &sz);
+}
+
+string &string::operator+=(const char *p)
+{
+ if (p != 0) {
+ int n = strlen(p);
+ int newlen = len + n;
+ if (newlen > sz)
+ ptr = srealloc(ptr, sz, len, newlen, &sz);
+ memcpy(ptr + len, p, n);
+ len = newlen;
+ }
+ return *this;
+}
+
+string &string::operator+=(const string &s)
+{
+ if (s.len != 0) {
+ int newlen = len + s.len;
+ if (newlen > sz)
+ ptr = srealloc(ptr, sz, len, newlen, &sz);
+ memcpy(ptr + len, s.ptr, s.len);
+ len = newlen;
+ }
+ return *this;
+}
+
+void string::append(const char *p, int n)
+{
+ if (n > 0) {
+ int newlen = len + n;
+ if (newlen > sz)
+ ptr = srealloc(ptr, sz, len, newlen, &sz);
+ memcpy(ptr + len, p, n);
+ len = newlen;
+ }
+}
+
+string::string(const char *s1, int n1, const char *s2, int n2)
+{
+ assert(n1 >= 0 && n2 >= 0);
+ len = n1 + n2;
+ if (len == 0) {
+ sz = 0;
+ ptr = 0;
+ }
+ else {
+ ptr = salloc(len, &sz);
+ if (n1 == 0)
+ memcpy(ptr, s2, n2);
+ else {
+ memcpy(ptr, s1, n1);
+ if (n2 != 0)
+ memcpy(ptr + n1, s2, n2);
+ }
+ }
+}
+
+int operator<=(const string &s1, const string &s2)
+{
+ return (s1.len <= s2.len
+ ? s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) <= 0
+ : s2.len != 0 && memcmp(s1.ptr, s2.ptr, s2.len) < 0);
+}
+
+int operator<(const string &s1, const string &s2)
+{
+ return (s1.len < s2.len
+ ? s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) <= 0
+ : s2.len != 0 && memcmp(s1.ptr, s2.ptr, s2.len) < 0);
+}
+
+int operator>=(const string &s1, const string &s2)
+{
+ return (s1.len >= s2.len
+ ? s2.len == 0 || memcmp(s1.ptr, s2.ptr, s2.len) >= 0
+ : s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) > 0);
+}
+
+int operator>(const string &s1, const string &s2)
+{
+ return (s1.len > s2.len
+ ? s2.len == 0 || memcmp(s1.ptr, s2.ptr, s2.len) >= 0
+ : s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) > 0);
+}
+
+void string::set_length(int i)
+{
+ assert(i >= 0);
+ if (i > sz)
+ ptr = srealloc(ptr, sz, len, i, &sz);
+ len = i;
+}
+
+void string::clear()
+{
+ len = 0;
+}
+
+int string::search(char c) const
+{
+ char *p = ptr ? (char *)memchr(ptr, c, len) : NULL;
+ return p ? p - ptr : -1;
+}
+
+// we silently strip nuls
+
+char *string::extract() const
+{
+ char *p = ptr;
+ int n = len;
+ int nnuls = 0;
+ int i;
+ for (i = 0; i < n; i++)
+ if (p[i] == '\0')
+ nnuls++;
+ char *q = new char[n + 1 - nnuls];
+ char *r = q;
+ for (i = 0; i < n; i++)
+ if (p[i] != '\0')
+ *r++ = p[i];
+ q[n] = '\0';
+ return q;
+}
+
+void put_string(const string &s, FILE *fp)
+{
+ int len = s.length();
+ const char *ptr = s.contents();
+ for (int i = 0; i < len; i++)
+ putc(ptr[i], fp);
+}
+
+string as_string(int i)
+{
+ static char buf[INT_DIGITS + 2];
+ sprintf(buf, "%d", i);
+ return string(buf);
+}
+
diff --git a/src/libs/libgroff/strsave.cc b/src/libs/libgroff/strsave.cc
new file mode 100644
index 00000000..dfd2b6f4
--- /dev/null
+++ b/src/libs/libgroff/strsave.cc
@@ -0,0 +1,31 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <string.h>
+
+char *strsave(const char *s)
+{
+ if (s == 0)
+ return 0;
+ char *p = new char[strlen(s) + 1];
+ strcpy(p, s);
+ return p;
+}
+
diff --git a/src/libs/libgroff/strtol.c b/src/libs/libgroff/strtol.c
new file mode 100644
index 00000000..071bade8
--- /dev/null
+++ b/src/libs/libgroff/strtol.c
@@ -0,0 +1,131 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#ifndef LONG_MAX
+#define LONG_MAX 2147483647
+#endif
+
+#ifndef LONG_MIN
+#define LONG_MIN (-LONG_MAX-1)
+#endif
+
+#ifdef isascii
+#define ISASCII(c) isascii(c)
+#else
+#define ISASCII(c) (1)
+#endif
+
+long strtol(str, ptr, base)
+ char *str, **ptr;
+ int base;
+{
+ char *start = str;
+ int neg = 0;
+ long val;
+ char *p;
+ static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+
+ while (ISASCII((unsigned char)*str) && isspace((unsigned char)*str))
+ str++;
+
+ if (*str == '-') {
+ neg = 1;
+ str++;
+ }
+ if (base == 0) {
+ if (*str == '0') {
+ if (str[1] == 'x' || str[1] == 'X') {
+ str += 2;
+ base = 16;
+ }
+ else
+ base = 8;
+ }
+ else
+ base = 10;
+ }
+ if (base < 2 || base > 36)
+ base = 10;
+ else if (base == 16 && *str == '0' && (str[1] == 'x' || str[1] == 'X'))
+ str += 2;
+
+ p = strchr(digits, (ISASCII((unsigned char)*str)
+ && isupper((unsigned char)*str)
+ ? tolower((unsigned char)*str)
+ : *str));
+ if (p == 0 || (val = (p - digits)) >= base) {
+ if (base == 16 && str > start && (str[-1] == 'x' || str[-1] == 'X')) {
+ if (ptr)
+ *ptr = str - 1;
+ }
+ else {
+ if (ptr)
+ *ptr = start;
+ errno = ERANGE;
+ }
+ return 0;
+ }
+ if (neg)
+ val = -val;
+
+ while (*++str != '\0') {
+ int n;
+
+ p = strchr(digits, (ISASCII((unsigned char)*str)
+ && isupper((unsigned char)*str)
+ ? tolower((unsigned char)*str) : *str));
+ if (p == 0)
+ break;
+ n = p - digits;
+ if (n >= base)
+ break;
+ if (neg) {
+ if (-(unsigned long)val > (-(unsigned long)LONG_MIN - n)/base) {
+ val = LONG_MIN;
+ errno = ERANGE;
+ }
+ else
+ val = val*base - n;
+ }
+ else {
+ if (val > (LONG_MAX - n)/base) {
+ val = LONG_MAX;
+ errno = ERANGE;
+ }
+ else
+ val = val*base + n;
+ }
+ }
+
+ if (ptr)
+ *ptr = str;
+
+ return val;
+}
diff --git a/src/libs/libgroff/tmpfile.cc b/src/libs/libgroff/tmpfile.cc
new file mode 100644
index 00000000..280d87c5
--- /dev/null
+++ b/src/libs/libgroff/tmpfile.cc
@@ -0,0 +1,99 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "posix.h"
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+
+extern "C" {
+ // Sun's stdlib.h fails to declare this.
+ char *mktemp(char *);
+ int mkstemp(char *);
+}
+
+// If this is set, create temporary files there
+#define GROFF_TMPDIR_ENVVAR "GROFF_TMPDIR"
+// otherwise if this is set, create temporary files there
+#define TMPDIR_ENVVAR "TMPDIR"
+// otherwise create temporary files here.
+#define DEFAULT_TMPDIR "/tmp"
+// Use this as the prefix for temporary filenames.
+#define TMPFILE_PREFIX "groff"
+
+// Open a temporary file with fatal error on failure.
+
+FILE *xtmpfile()
+{
+ const char *dir = getenv(GROFF_TMPDIR_ENVVAR);
+ if (!dir) {
+ dir = getenv(TMPDIR_ENVVAR);
+ if (!dir)
+ dir = DEFAULT_TMPDIR;
+ }
+
+ const char *p = strrchr(dir, '/');
+ int needs_slash = (!p || p[1]);
+ char *templ = new char[strlen(dir) + needs_slash
+ + sizeof(TMPFILE_PREFIX) - 1 + 6 + 1];
+ strcpy(templ, dir);
+ if (needs_slash)
+ strcat(templ, "/");
+ strcat(templ, TMPFILE_PREFIX);
+ strcat(templ, "XXXXXX");
+
+#ifdef HAVE_MKSTEMP
+ errno = 0;
+ int fd = mkstemp(templ);
+ if (fd < 0)
+ fatal("cannot create temporary file: %1", strerror(errno));
+ errno = 0;
+ FILE *fp = fdopen(fd, "w+");
+ if (!fp)
+ fatal("fdopen: %1", strerror(errno));
+#else /* not HAVE_MKSTEMP */
+ if (!mktemp(templ) || !templ[0])
+ fatal("cannot create file name for temporary file");
+ errno = 0;
+ FILE *fp = fopen(templ, "w+");
+ if (!fp)
+ fatal("cannot open `%1': %2", templ, strerror(errno));
+#endif /* not HAVE_MKSTEMP */
+ if (unlink(templ) < 0)
+ error("cannot unlink `%1': %2", templ, strerror(errno));
+ a_delete templ;
+ return fp;
+}
+
+#if 0
+// If you're not running Unix, the following will do:
+FILE *xtmpfile()
+{
+ FILE *fp = tmpfile();
+ if (!fp)
+ fatal("couldn't create temporary file");
+ return fp;
+}
+#endif
diff --git a/src/preproc/eqn/Makefile.sub b/src/preproc/eqn/Makefile.sub
new file mode 100644
index 00000000..eaafe2dd
--- /dev/null
+++ b/src/preproc/eqn/Makefile.sub
@@ -0,0 +1,57 @@
+PROG=eqn
+MAN1=eqn.n
+XLIBS=$(LIBGROFF)
+OBJS=\
+ eqn.o \
+ main.o \
+ lex.o \
+ box.o \
+ limit.o \
+ list.o \
+ over.o \
+ text.o \
+ script.o \
+ mark.o \
+ other.o \
+ delim.o \
+ sqrt.o \
+ pile.o \
+ special.o
+CCSRCS=\
+ $(srcdir)/main.cc \
+ $(srcdir)/lex.cc \
+ $(srcdir)/box.cc \
+ $(srcdir)/limit.cc \
+ $(srcdir)/list.cc \
+ $(srcdir)/over.cc \
+ $(srcdir)/text.cc \
+ $(srcdir)/script.cc \
+ $(srcdir)/mark.cc \
+ $(srcdir)/other.cc \
+ $(srcdir)/delim.cc \
+ $(srcdir)/sqrt.cc \
+ $(srcdir)/pile.cc \
+ $(srcdir)/special.cc
+HDRS=\
+ $(srcdir)/box.h \
+ $(srcdir)/eqn.h \
+ $(srcdir)/pbox.h
+GRAM=$(srcdir)/eqn.y
+YTABC=$(srcdir)/eqn.cc
+YTABH=$(srcdir)/eqn.tab.h
+NAMEPREFIX=$(g)
+CLEANADD=neqn
+
+all: neqn
+
+neqn: neqn.sh
+ -rm -f neqn
+ sed -e 's/@g@/$(g)/g' -e "$(SH_SCRIPT_SED_CMD)" $(srcdir)/neqn.sh >neqn
+ chmod +x neqn
+
+install_data: neqn
+ -rm -f $(bindir)/$(NAMEPREFIX)neqn
+ $(INSTALL_PROGRAM) neqn $(bindir)/$(NAMEPREFIX)neqn
+
+uninstall_sub:
+ -rm -f $(bindir)/$(NAMEPREFIX)neqn
diff --git a/src/preproc/eqn/TODO b/src/preproc/eqn/TODO
new file mode 100644
index 00000000..210d0ab0
--- /dev/null
+++ b/src/preproc/eqn/TODO
@@ -0,0 +1,49 @@
+Use the same size increases for sum prod int as eqn does.
+
+Perhaps chartype should be renamed.
+
+TeX makes {sub,super}script on a single character with an accent
+into an accent onto the (character with the script). Should we do this?
+
+Implement mark and lineups within scripts, matrices and piles, and accents.
+(Why would this be useful?)
+
+Perhaps push hmotions down through lists to avoid upsetting spacing
+adjustments.
+
+Possibly generate .lf commands during compute_metrics phase.
+
+Consider whether there should be extra space at the side of piles.
+
+Provide scriptstyle displaystyle etc.
+
+Provide a nicer matrix syntax, eg
+matrix ccc {
+a then b then c above
+e then f then g above
+h then i then k
+}
+
+Perhaps generate syntax error messages using the style of gpic.
+
+Wide accents.
+
+More use of \Z.
+
+Extensible square roots.
+
+Vphantom
+
+Smash.
+
+Provide a variant of vec that extends over the length of the accentee.
+
+Support vertical arrow delimiters.
+
+Make the following work:
+.EQ
+delim @@
+.EN
+.EQ @<-@
+some equation
+.EN
diff --git a/src/preproc/eqn/box.cc b/src/preproc/eqn/box.cc
new file mode 100644
index 00000000..4e61b5dc
--- /dev/null
+++ b/src/preproc/eqn/box.cc
@@ -0,0 +1,611 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+const char *current_roman_font;
+
+char *gfont = 0;
+char *grfont = 0;
+char *gbfont = 0;
+int gsize = 0;
+
+int script_size_reduction = -1; // negative means reduce by a percentage
+
+int positive_space = -1;
+int negative_space = -1;
+
+int minimum_size = 5;
+
+int fat_offset = 4;
+int body_height = 85;
+int body_depth = 35;
+
+int over_hang = 0;
+int accent_width = 31;
+int delimiter_factor = 900;
+int delimiter_shortfall = 50;
+
+int null_delimiter_space = 12;
+int script_space = 5;
+int thin_space = 17;
+int medium_space = 22;
+int thick_space = 28;
+
+int num1 = 70;
+int num2 = 40;
+// we don't use num3, because we don't have \atop
+int denom1 = 70;
+int denom2 = 36;
+int axis_height = 26; // in 100ths of an em
+int sup1 = 42;
+int sup2 = 37;
+int sup3 = 28;
+int default_rule_thickness = 4;
+int sub1 = 20;
+int sub2 = 23;
+int sup_drop = 38;
+int sub_drop = 5;
+int x_height = 45;
+int big_op_spacing1 = 11;
+int big_op_spacing2 = 17;
+int big_op_spacing3 = 20;
+int big_op_spacing4 = 60;
+int big_op_spacing5 = 10;
+
+// These are for piles and matrices.
+
+int baseline_sep = 140; // = num1 + denom1
+int shift_down = 26; // = axis_height
+int column_sep = 100; // = em space
+int matrix_side_sep = 17; // = thin space
+
+int nroff = 0; // should we grok ndefine or tdefine?
+
+struct {
+ const char *name;
+ int *ptr;
+} param_table[] = {
+ { "fat_offset", &fat_offset },
+ { "over_hang", &over_hang },
+ { "accent_width", &accent_width },
+ { "delimiter_factor", &delimiter_factor },
+ { "delimiter_shortfall", &delimiter_shortfall },
+ { "null_delimiter_space", &null_delimiter_space },
+ { "script_space", &script_space },
+ { "thin_space", &thin_space },
+ { "medium_space", &medium_space },
+ { "thick_space", &thick_space },
+ { "num1", &num1 },
+ { "num2", &num2 },
+ { "denom1", &denom1 },
+ { "denom2", &denom2 },
+ { "axis_height", &axis_height },
+ { "sup1", &sup1 },
+ { "sup2", &sup2 },
+ { "sup3", &sup3 },
+ { "default_rule_thickness", &default_rule_thickness },
+ { "sub1", &sub1 },
+ { "sub2", &sub2 },
+ { "sup_drop", &sup_drop },
+ { "sub_drop", &sub_drop },
+ { "x_height", &x_height },
+ { "big_op_spacing1", &big_op_spacing1 },
+ { "big_op_spacing2", &big_op_spacing2 },
+ { "big_op_spacing3", &big_op_spacing3 },
+ { "big_op_spacing4", &big_op_spacing4 },
+ { "big_op_spacing5", &big_op_spacing5 },
+ { "minimum_size", &minimum_size },
+ { "baseline_sep", &baseline_sep },
+ { "shift_down", &shift_down },
+ { "column_sep", &column_sep },
+ { "matrix_side_sep", &matrix_side_sep },
+ { "draw_lines", &draw_flag },
+ { "body_height", &body_height },
+ { "body_depth", &body_depth },
+ { "nroff", &nroff },
+ { 0, 0 }
+};
+
+void set_param(const char *name, int value)
+{
+ for (int i = 0; param_table[i].name != 0; i++)
+ if (strcmp(param_table[i].name, name) == 0) {
+ *param_table[i].ptr = value;
+ return;
+ }
+ error("unrecognised parameter `%1'", name);
+}
+
+int script_style(int style)
+{
+ return style > SCRIPT_STYLE ? style - 2 : style;
+}
+
+int cramped_style(int style)
+{
+ return (style & 1) ? style - 1 : style;
+}
+
+void set_space(int n)
+{
+ if (n < 0)
+ negative_space = -n;
+ else
+ positive_space = n;
+}
+
+// Return 0 if the specified size is bad.
+// The caller is responsible for giving the error message.
+
+int set_gsize(const char *s)
+{
+ const char *p = (*s == '+' || *s == '-') ? s + 1 : s;
+ char *end;
+ long n = strtol(p, &end, 10);
+ if (n <= 0 || *end != '\0' || n > INT_MAX)
+ return 0;
+ if (p > s) {
+ if (!gsize)
+ gsize = 10;
+ if (*s == '+') {
+ if (gsize > INT_MAX - n)
+ return 0;
+ gsize += int(n);
+ }
+ else {
+ if (gsize - n <= 0)
+ return 0;
+ gsize -= int(n);
+ }
+ }
+ else
+ gsize = int(n);
+ return 1;
+}
+
+void set_script_reduction(int n)
+{
+ script_size_reduction = n;
+}
+
+const char *get_gfont()
+{
+ return gfont ? gfont : "I";
+}
+
+const char *get_grfont()
+{
+ return grfont ? grfont : "R";
+}
+
+const char *get_gbfont()
+{
+ return gbfont ? gbfont : "B";
+}
+
+void set_gfont(const char *s)
+{
+ a_delete gfont;
+ gfont = strsave(s);
+}
+
+void set_grfont(const char *s)
+{
+ a_delete grfont;
+ grfont = strsave(s);
+}
+
+void set_gbfont(const char *s)
+{
+ a_delete gbfont;
+ gbfont = strsave(s);
+}
+
+// this must be precisely 2 characters in length
+#define COMPATIBLE_REG "0C"
+
+void start_string()
+{
+ printf(".nr " COMPATIBLE_REG " \\n(.C\n");
+ printf(".cp 0\n");
+ printf(".ds " LINE_STRING "\n");
+}
+
+void output_string()
+{
+ printf("\\*[" LINE_STRING "]\n");
+}
+
+void restore_compatibility()
+{
+ printf(".cp \\n(" COMPATIBLE_REG "\n");
+}
+
+void do_text(const char *s)
+{
+ printf(".eo\n");
+ printf(".as " LINE_STRING " \"%s\n", s);
+ printf(".ec\n");
+}
+
+void set_minimum_size(int n)
+{
+ minimum_size = n;
+}
+
+void set_script_size()
+{
+ if (minimum_size < 0)
+ minimum_size = 0;
+ if (script_size_reduction >= 0)
+ printf(".ps \\n[.s]-%d>?%d\n", script_size_reduction, minimum_size);
+ else
+ printf(".ps (u;\\n[.s]*7+5/10>?%d)*1z\n", minimum_size);
+}
+
+int box::next_uid = 0;
+
+box::box() : spacing_type(ORDINARY_TYPE), uid(next_uid++)
+{
+}
+
+box::~box()
+{
+}
+
+void box::top_level()
+{
+ // debug_print();
+ // putc('\n', stderr);
+ box *b = this;
+ printf(".nr " SAVED_FONT_REG " \\n[.f]\n");
+ printf(".ft\n");
+ printf(".nr " SAVED_PREV_FONT_REG " \\n[.f]\n");
+ printf(".ft %s\n", get_gfont());
+ printf(".nr " SAVED_SIZE_REG " \\n[.s]z\n");
+ if (gsize > 0) {
+ char buf[INT_DIGITS + 1];
+ sprintf(buf, "%d", gsize);
+ b = new size_box(strsave(buf), b);
+ }
+ current_roman_font = get_grfont();
+ // This catches tabs used within \Z (which aren't allowed).
+ b->check_tabs(0);
+ int r = b->compute_metrics(DISPLAY_STYLE);
+ printf(".ft \\n[" SAVED_PREV_FONT_REG "]\n");
+ printf(".ft \\n[" SAVED_FONT_REG "]\n");
+ printf(".nr " MARK_OR_LINEUP_FLAG_REG " %d\n", r);
+ if (r == FOUND_MARK) {
+ printf(".nr " SAVED_MARK_REG " \\n[" MARK_REG "]\n");
+ printf(".nr " MARK_WIDTH_REG " 0\\n[" WIDTH_FORMAT "]\n", b->uid);
+ }
+ else if (r == FOUND_LINEUP)
+ printf(".if r" SAVED_MARK_REG " .as " LINE_STRING " \\h'\\n["
+ SAVED_MARK_REG "]u-\\n[" MARK_REG "]u'\n");
+ else
+ assert(r == FOUND_NOTHING);
+ // The problem here is that the argument to \f is read in copy mode,
+ // so we cannot use \E there; so we hide it in a string instead.
+ // Another problem is that if we use \R directly, then the space will
+ // prevent it working in a macro argument.
+ printf(".ds " SAVE_FONT_STRING " "
+ "\\R'" SAVED_INLINE_FONT_REG " \\\\n[.f]'"
+ "\\fP"
+ "\\R'" SAVED_INLINE_PREV_FONT_REG " \\\\n[.f]'"
+ "\\R'" SAVED_INLINE_SIZE_REG " \\\\n[.s]z'"
+ "\\s0"
+ "\\R'" SAVED_INLINE_PREV_SIZE_REG " \\\\n[.s]z'"
+ "\n"
+ ".ds " RESTORE_FONT_STRING " "
+ "\\f[\\\\n[" SAVED_INLINE_PREV_FONT_REG "]]"
+ "\\f[\\\\n[" SAVED_INLINE_FONT_REG "]]"
+ "\\s'\\\\n[" SAVED_INLINE_PREV_SIZE_REG "]u'"
+ "\\s'\\\\n[" SAVED_INLINE_SIZE_REG "]u'"
+ "\n");
+ printf(".as " LINE_STRING " \\&\\E*[" SAVE_FONT_STRING "]");
+ printf("\\f[%s]", get_gfont());
+ printf("\\s'\\En[" SAVED_SIZE_REG "]u'");
+ current_roman_font = get_grfont();
+ b->output();
+ printf("\\E*[" RESTORE_FONT_STRING "]\n");
+ if (r == FOUND_LINEUP)
+ printf(".if r" SAVED_MARK_REG " .as " LINE_STRING " \\h'\\n["
+ MARK_WIDTH_REG "]u-\\n[" SAVED_MARK_REG "]u-(\\n["
+ WIDTH_FORMAT "]u-\\n[" MARK_REG "]u)'\n",
+ b->uid);
+ b->extra_space();
+ if (!inline_flag)
+ printf(".ne \\n[" HEIGHT_FORMAT "]u-%dM>?0+(\\n["
+ DEPTH_FORMAT "]u-%dM>?0)\n",
+ b->uid, body_height, b->uid, body_depth);
+ delete b;
+ next_uid = 0;
+}
+
+// gpic defines this register so as to make geqn not produce `\x's
+#define EQN_NO_EXTRA_SPACE_REG "0x"
+
+void box::extra_space()
+{
+ printf(".if !r" EQN_NO_EXTRA_SPACE_REG " "
+ ".nr " EQN_NO_EXTRA_SPACE_REG " 0\n");
+ if (positive_space >= 0 || negative_space >= 0) {
+ if (positive_space > 0)
+ printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] "
+ ".as " LINE_STRING " \\x'-%dM'\n", positive_space);
+ if (negative_space > 0)
+ printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] "
+ ".as " LINE_STRING " \\x'%dM'\n", negative_space);
+ positive_space = negative_space = -1;
+ }
+ else {
+ printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] "
+ ".if \\n[" HEIGHT_FORMAT "]>%dM .as " LINE_STRING
+ " \\x'-(\\n[" HEIGHT_FORMAT
+ "]u-%dM)'\n",
+ uid, body_height, uid, body_height);
+ printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] "
+ ".if \\n[" DEPTH_FORMAT "]>%dM .as " LINE_STRING
+ " \\x'\\n[" DEPTH_FORMAT
+ "]u-%dM'\n",
+ uid, body_depth, uid, body_depth);
+ }
+}
+
+int box::compute_metrics(int)
+{
+ printf(".nr " WIDTH_FORMAT " 0\n", uid);
+ printf(".nr " HEIGHT_FORMAT " 0\n", uid);
+ printf(".nr " DEPTH_FORMAT " 0\n", uid);
+ return FOUND_NOTHING;
+}
+
+void box::compute_subscript_kern()
+{
+ printf(".nr " SUB_KERN_FORMAT " 0\n", uid);
+}
+
+void box::compute_skew()
+{
+ printf(".nr " SKEW_FORMAT " 0\n", uid);
+}
+
+void box::output()
+{
+}
+
+void box::check_tabs(int)
+{
+}
+
+int box::is_char()
+{
+ return 0;
+}
+
+int box::left_is_italic()
+{
+ return 0;
+}
+
+int box::right_is_italic()
+{
+ return 0;
+}
+
+void box::hint(unsigned)
+{
+}
+
+void box::handle_char_type(int, int)
+{
+}
+
+
+box_list::box_list(box *pp)
+{
+ p = new box*[10];
+ for (int i = 0; i < 10; i++)
+ p[i] = 0;
+ maxlen = 10;
+ len = 1;
+ p[0] = pp;
+}
+
+void box_list::append(box *pp)
+{
+ if (len + 1 > maxlen) {
+ box **oldp = p;
+ maxlen *= 2;
+ p = new box*[maxlen];
+ memcpy(p, oldp, sizeof(box*)*len);
+ a_delete oldp;
+ }
+ p[len++] = pp;
+}
+
+box_list::~box_list()
+{
+ for (int i = 0; i < len; i++)
+ delete p[i];
+ a_delete p;
+}
+
+void box_list::list_check_tabs(int level)
+{
+ for (int i = 0; i < len; i++)
+ p[i]->check_tabs(level);
+}
+
+
+pointer_box::pointer_box(box *pp) : p(pp)
+{
+ spacing_type = p->spacing_type;
+}
+
+pointer_box::~pointer_box()
+{
+ delete p;
+}
+
+int pointer_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ return r;
+}
+
+void pointer_box::compute_subscript_kern()
+{
+ p->compute_subscript_kern();
+ printf(".nr " SUB_KERN_FORMAT " \\n[" SUB_KERN_FORMAT "]\n", uid, p->uid);
+}
+
+void pointer_box::compute_skew()
+{
+ p->compute_skew();
+ printf(".nr " SKEW_FORMAT " 0\\n[" SKEW_FORMAT "]\n",
+ uid, p->uid);
+}
+
+void pointer_box::check_tabs(int level)
+{
+ p->check_tabs(level);
+}
+
+int simple_box::compute_metrics(int)
+{
+ printf(".nr " WIDTH_FORMAT " 0\\w" DELIMITER_CHAR, uid);
+ output();
+ printf(DELIMITER_CHAR "\n");
+ printf(".nr " HEIGHT_FORMAT " 0>?\\n[rst]\n", uid);
+ printf(".nr " DEPTH_FORMAT " 0-\\n[rsb]>?0\n", uid);
+ printf(".nr " SUB_KERN_FORMAT " 0-\\n[ssc]>?0\n", uid);
+ printf(".nr " SKEW_FORMAT " 0\\n[skw]\n", uid);
+ return FOUND_NOTHING;
+}
+
+void simple_box::compute_subscript_kern()
+{
+ // do nothing, we already computed it in do_metrics
+}
+
+void simple_box::compute_skew()
+{
+ // do nothing, we already computed it in do_metrics
+}
+
+int box::is_simple()
+{
+ return 0;
+}
+
+int simple_box::is_simple()
+{
+ return 1;
+}
+
+quoted_text_box::quoted_text_box(char *s) : text(s)
+{
+}
+
+quoted_text_box::~quoted_text_box()
+{
+ a_delete text;
+}
+
+void quoted_text_box::output()
+{
+ if (text)
+ fputs(text, stdout);
+}
+
+tab_box::tab_box() : disabled(0)
+{
+}
+
+// We treat a tab_box as having width 0 for width computations.
+
+void tab_box::output()
+{
+ if (!disabled)
+ printf("\\t");
+}
+
+void tab_box::check_tabs(int level)
+{
+ if (level > 0) {
+ error("tabs allowed only at outermost level");
+ disabled = 1;
+ }
+}
+
+space_box::space_box()
+{
+ spacing_type = SUPPRESS_TYPE;
+}
+
+void space_box::output()
+{
+ printf("\\h'%dM'", thick_space);
+}
+
+half_space_box::half_space_box()
+{
+ spacing_type = SUPPRESS_TYPE;
+}
+
+void half_space_box::output()
+{
+ printf("\\h'%dM'", thin_space);
+}
+
+void box_list::list_debug_print(const char *sep)
+{
+ p[0]->debug_print();
+ for (int i = 1; i < len; i++) {
+ fprintf(stderr, "%s", sep);
+ p[i]->debug_print();
+ }
+}
+
+void quoted_text_box::debug_print()
+{
+ fprintf(stderr, "\"%s\"", (text ? text : ""));
+}
+
+void half_space_box::debug_print()
+{
+ fprintf(stderr, "^");
+}
+
+void space_box::debug_print()
+{
+ fprintf(stderr, "~");
+}
+
+void tab_box::debug_print()
+{
+ fprintf(stderr, "<tab>");
+}
diff --git a/src/preproc/eqn/box.h b/src/preproc/eqn/box.h
new file mode 100644
index 00000000..01bfe96a
--- /dev/null
+++ b/src/preproc/eqn/box.h
@@ -0,0 +1,277 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+struct list_box;
+
+class box {
+private:
+ static int next_uid;
+public:
+ int spacing_type;
+ const int uid;
+ box();
+ virtual void debug_print() = 0;
+ virtual ~box();
+ void top_level();
+ virtual int compute_metrics(int);
+ virtual void compute_subscript_kern();
+ virtual void compute_skew();
+ virtual void output();
+ void extra_space();
+ virtual list_box *to_list_box();
+ virtual int is_simple();
+ virtual int is_char();
+ virtual int left_is_italic();
+ virtual int right_is_italic();
+ virtual void handle_char_type(int, int);
+ enum { FOUND_NOTHING = 0, FOUND_MARK = 1, FOUND_LINEUP = 2 };
+ void set_spacing_type(char *type);
+ virtual void hint(unsigned);
+ virtual void check_tabs(int);
+};
+
+class box_list {
+private:
+ int maxlen;
+public:
+ box **p;
+ int len;
+
+ box_list(box *);
+ ~box_list();
+ void append(box *);
+ void list_check_tabs(int);
+ void list_debug_print(const char *sep);
+ friend class list_box;
+};
+
+class list_box : public box {
+ int is_script;
+ box_list list;
+ int sty;
+public:
+ list_box(box *);
+ void debug_print();
+ int compute_metrics(int);
+ void compute_subscript_kern();
+ void output();
+ void check_tabs(int);
+ void append(box *);
+ list_box *to_list_box();
+ void handle_char_type(int, int);
+ void compute_sublist_width(int n);
+ friend box *make_script_box(box *, box *, box *);
+ friend box *make_mark_box(box *);
+ friend box *make_lineup_box(box *);
+};
+
+enum alignment { LEFT_ALIGN, RIGHT_ALIGN, CENTER_ALIGN };
+
+class column : public box_list {
+ alignment align;
+ int space;
+public:
+ column(box *);
+ void set_alignment(alignment);
+ void set_space(int);
+ void debug_print(const char *);
+
+ friend class matrix_box;
+ friend class pile_box;
+};
+
+class pile_box : public box {
+ column col;
+public:
+ pile_box(box *);
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+ void check_tabs(int);
+ void set_alignment(alignment a) { col.set_alignment(a); }
+ void set_space(int n) { col.set_space(n); }
+ void append(box *p) { col.append(p); }
+};
+
+class matrix_box : public box {
+private:
+ int len;
+ int maxlen;
+ column **p;
+public:
+ matrix_box(column *);
+ ~matrix_box();
+ void append(column *);
+ int compute_metrics(int);
+ void output();
+ void check_tabs(int);
+ void debug_print();
+};
+
+class pointer_box : public box {
+protected:
+ box *p;
+public:
+ pointer_box(box *);
+ ~pointer_box();
+ int compute_metrics(int);
+ void compute_subscript_kern();
+ void compute_skew();
+ void debug_print() = 0;
+ void check_tabs(int);
+};
+
+class vcenter_box : public pointer_box {
+public:
+ vcenter_box(box *);
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+};
+
+class simple_box : public box {
+public:
+ int compute_metrics(int);
+ void compute_subscript_kern();
+ void compute_skew();
+ void output() = 0;
+ void debug_print() = 0;
+ int is_simple();
+};
+
+class quoted_text_box : public simple_box {
+ char *text;
+public:
+ quoted_text_box(char *);
+ ~quoted_text_box();
+ void debug_print();
+ void output();
+};
+
+class half_space_box : public simple_box {
+public:
+ half_space_box();
+ void output();
+ void debug_print();
+};
+
+class space_box : public simple_box {
+public:
+ space_box();
+ void output();
+ void debug_print();
+};
+
+class tab_box : public box {
+ int disabled;
+public:
+ tab_box();
+ void output();
+ void debug_print();
+ void check_tabs(int);
+};
+
+class size_box : public pointer_box {
+private:
+ char *size;
+public:
+ size_box(char *, box *);
+ ~size_box();
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+};
+
+class font_box : public pointer_box {
+private:
+ char *f;
+public:
+ font_box(char *, box *);
+ ~font_box();
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+};
+
+class fat_box : public pointer_box {
+public:
+ fat_box(box *);
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+};
+
+class vmotion_box : public pointer_box {
+private:
+ int n; // up is >= 0
+public:
+ vmotion_box(int, box *);
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+};
+
+class hmotion_box : public pointer_box {
+ int n;
+public:
+ hmotion_box(int, box *);
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+};
+
+box *split_text(char *);
+box *make_script_box(box *, box *, box *);
+box *make_mark_box(box *);
+box *make_lineup_box(box *);
+box *make_delim_box(char *, box *, char *);
+box *make_sqrt_box(box *);
+box *make_prime_box(box *);
+box *make_over_box(box *, box *);
+box *make_small_over_box(box *, box *);
+box *make_limit_box(box *, box *, box *);
+box *make_accent_box(box *, box *);
+box *make_uaccent_box(box *, box *);
+box *make_overline_box(box *);
+box *make_underline_box(box *);
+box *make_special_box(char *, box *);
+
+void set_space(int);
+int set_gsize(const char *);
+void set_gfont(const char *);
+void set_grfont(const char *);
+void set_gbfont(const char *);
+const char *get_gfont();
+const char *get_grfont();
+const char *get_gbfont();
+void start_string();
+void output_string();
+void do_text(const char *);
+void restore_compatibility();
+void set_script_reduction(int n);
+void set_minimum_size(int n);
+void set_param(const char *name, int value);
+
+void set_char_type(const char *type, char *ch);
+
+void init_char_table();
+void init_extensible();
+void define_extensible(const char *name, const char *ext, const char *top = 0,
+ const char *mid = 0, const char *bot = 0);
diff --git a/src/preproc/eqn/delim.cc b/src/preproc/eqn/delim.cc
new file mode 100644
index 00000000..29deded3
--- /dev/null
+++ b/src/preproc/eqn/delim.cc
@@ -0,0 +1,381 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+enum left_or_right_t { LEFT_DELIM = 01, RIGHT_DELIM = 02 };
+
+// Small must be none-zero and must exist in each device.
+// Small will be put in the roman font, others are assumed to be
+// on the special font (so no font change will be necessary.)
+
+struct delimiter {
+ const char *name;
+ int flags;
+ const char *small;
+ const char *chain_format;
+ const char *ext;
+ const char *top;
+ const char *mid;
+ const char *bot;
+} delim_table[] = {
+ {
+ "(", LEFT_DELIM|RIGHT_DELIM, "(", "\\[parenleft%s]",
+ "\\[parenleftex]",
+ "\\[parenlefttp]",
+ 0,
+ "\\[parenleftbt]",
+ },
+ {
+ ")", LEFT_DELIM|RIGHT_DELIM, ")", "\\[parenright%s]",
+ "\\[parenrightex]",
+ "\\[parenrighttp]",
+ 0,
+ "\\[parenrightbt]",
+ },
+ {
+ "[", LEFT_DELIM|RIGHT_DELIM, "[", "\\[bracketleft%s]",
+ "\\[bracketleftex]",
+ "\\[bracketlefttp]",
+ 0,
+ "\\[bracketleftbt]",
+ },
+ {
+ "]", LEFT_DELIM|RIGHT_DELIM, "]", "\\[bracketright%s]",
+ "\\[bracketrightex]",
+ "\\[bracketrighttp]",
+ 0,
+ "\\[bracketrightbt]",
+ },
+ {
+ "{", LEFT_DELIM|RIGHT_DELIM, "{", "\\[braceleft%s]",
+ "\\[braceleftex]",
+ "\\[bracelefttp]",
+ "\\[braceleftmid]",
+ "\\[braceleftbt]",
+ },
+ {
+ "}", LEFT_DELIM|RIGHT_DELIM, "}", "\\[braceright%s]",
+ "\\[bracerightex]",
+ "\\[bracerighttp]",
+ "\\[bracerightmid]",
+ "\\[bracerightbt]",
+ },
+ {
+ "|", LEFT_DELIM|RIGHT_DELIM, "|", "\\[bar%s]",
+ "\\[barex]",
+ },
+ {
+ "floor", LEFT_DELIM, "\\(lf", "\\[floorleft%s]",
+ "\\[bracketleftex]",
+ 0,
+ 0,
+ "\\[bracketleftbt]",
+ },
+ {
+ "floor", RIGHT_DELIM, "\\(rf", "\\[floorright%s]",
+ "\\[bracketrightex]",
+ 0,
+ 0,
+ "\\[bracketrightbt]",
+ },
+ {
+ "ceiling", LEFT_DELIM, "\\(lc", "\\[ceilingleft%s]",
+ "\\[bracketleftex]",
+ "\\[bracketlefttp]",
+ },
+ {
+ "ceiling", RIGHT_DELIM, "\\(rc", "\\[ceilingright%s]",
+ "\\[bracketrightex]",
+ "\\[bracketrighttp]",
+ },
+ {
+ "||", LEFT_DELIM|RIGHT_DELIM, "|", "\\[bar%s]",
+ "\\[bardblex]",
+ },
+ {
+ "<", LEFT_DELIM|RIGHT_DELIM, "\\(la", "\\[angleleft%s]",
+ },
+ {
+ ">", LEFT_DELIM|RIGHT_DELIM, "\\(ra", "\\[angleright%s]",
+ },
+ {
+ "uparrow", LEFT_DELIM|RIGHT_DELIM, "\\(ua", "\\[arrowup%s]",
+ "\\[arrowvertex]",
+ "\\[arrowverttp]",
+ },
+ {
+ "downarrow", LEFT_DELIM|RIGHT_DELIM, "\\(da", "\\[arrowdown%s]",
+ "\\[arrowvertex]",
+ 0,
+ 0,
+ "\\[arrowvertbt]",
+ },
+ {
+ "updownarrow", LEFT_DELIM|RIGHT_DELIM, "\\(va", "\\[arrowupdown%s]",
+ "\\[arrowvertex]",
+ "\\[arrowverttp]",
+ 0,
+ "\\[arrowvertbt]",
+ },
+};
+
+const int DELIM_TABLE_SIZE = int(sizeof(delim_table)/sizeof(delim_table[0]));
+
+class delim_box : public box {
+private:
+ char *left;
+ char *right;
+ box *p;
+public:
+ delim_box(char *, box *, char *);
+ ~delim_box();
+ int compute_metrics(int);
+ void output();
+ void check_tabs(int);
+ void debug_print();
+};
+
+box *make_delim_box(char *l, box *pp, char *r)
+{
+ if (l != 0 && *l == '\0') {
+ a_delete l;
+ l = 0;
+ }
+ if (r != 0 && *r == '\0') {
+ a_delete r;
+ r = 0;
+ }
+ return new delim_box(l, pp, r);
+}
+
+delim_box::delim_box(char *l, box *pp, char *r)
+: left(l), right(r), p(pp)
+{
+}
+
+delim_box::~delim_box()
+{
+ a_delete left;
+ a_delete right;
+ delete p;
+}
+
+static void build_extensible(const char *ext, const char *top, const char *mid,
+ const char *bot)
+{
+ assert(ext != 0);
+ printf(".nr " DELIM_WIDTH_REG " 0\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n",
+ ext);
+ printf(".nr " EXT_HEIGHT_REG " 0\\n[rst]\n");
+ printf(".nr " EXT_DEPTH_REG " 0-\\n[rsb]\n");
+ if (top) {
+ printf(".nr " DELIM_WIDTH_REG " 0\\n[" DELIM_WIDTH_REG "]"
+ ">?\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n",
+ top);
+ printf(".nr " TOP_HEIGHT_REG " 0\\n[rst]\n");
+ printf(".nr " TOP_DEPTH_REG " 0-\\n[rsb]\n");
+ }
+ if (mid) {
+ printf(".nr " DELIM_WIDTH_REG " 0\\n[" DELIM_WIDTH_REG "]"
+ ">?\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n",
+ mid);
+ printf(".nr " MID_HEIGHT_REG " 0\\n[rst]\n");
+ printf(".nr " MID_DEPTH_REG " 0-\\n[rsb]\n");
+ }
+ if (bot) {
+ printf(".nr " DELIM_WIDTH_REG " 0\\n[" DELIM_WIDTH_REG "]"
+ ">?\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n",
+ bot);
+ printf(".nr " BOT_HEIGHT_REG " 0\\n[rst]\n");
+ printf(".nr " BOT_DEPTH_REG " 0-\\n[rsb]\n");
+ }
+ printf(".nr " TOTAL_HEIGHT_REG " 0");
+ if (top)
+ printf("+\\n[" TOP_HEIGHT_REG "]+\\n[" TOP_DEPTH_REG "]");
+ if (bot)
+ printf("+\\n[" BOT_HEIGHT_REG "]+\\n[" BOT_DEPTH_REG "]");
+ if (mid)
+ printf("+\\n[" MID_HEIGHT_REG "]+\\n[" MID_DEPTH_REG "]");
+ printf("\n");
+ // determine how many extensible characters we need
+ printf(".nr " TEMP_REG " \\n[" DELTA_REG "]-\\n[" TOTAL_HEIGHT_REG "]");
+ if (mid)
+ printf("/2");
+ printf(">?0+\\n[" EXT_HEIGHT_REG "]+\\n[" EXT_DEPTH_REG "]-1/(\\n["
+ EXT_HEIGHT_REG "]+\\n[" EXT_DEPTH_REG "])\n");
+
+ printf(".nr " TOTAL_HEIGHT_REG " +(\\n[" EXT_HEIGHT_REG "]+\\n["
+ EXT_DEPTH_REG "]*\\n[" TEMP_REG "]");
+ if (mid)
+ printf("*2");
+ printf(")\n");
+ printf(".ds " DELIM_STRING " \\Z" DELIMITER_CHAR
+ "\\v'-%dM-(\\n[" TOTAL_HEIGHT_REG "]u/2u)'\n",
+ axis_height);
+ if (top)
+ printf(".as " DELIM_STRING " \\v'\\n[" TOP_HEIGHT_REG "]u'"
+ "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR
+ "\\v'\\n[" TOP_DEPTH_REG "]u'\n",
+ top);
+
+ // this macro appends $2 copies of $3 to string $1
+ printf(".de " REPEAT_APPEND_STRING_MACRO "\n"
+ ".if \\\\$2 \\{.as \\\\$1 \"\\\\$3\n"
+ "." REPEAT_APPEND_STRING_MACRO " \\\\$1 \\\\$2-1 \"\\\\$3\"\n"
+ ".\\}\n"
+ "..\n");
+
+ printf("." REPEAT_APPEND_STRING_MACRO " " DELIM_STRING " \\n[" TEMP_REG "] "
+ "\\v'\\n[" EXT_HEIGHT_REG "]u'"
+ "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR
+ "\\v'\\n[" EXT_DEPTH_REG "]u'\n",
+ ext);
+
+ if (mid) {
+ printf(".as " DELIM_STRING " \\v'\\n[" MID_HEIGHT_REG "]u'"
+ "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR
+ "\\v'\\n[" MID_DEPTH_REG "]u'\n",
+ mid);
+ printf("." REPEAT_APPEND_STRING_MACRO " " DELIM_STRING
+ " \\n[" TEMP_REG "] "
+ "\\v'\\n[" EXT_HEIGHT_REG "]u'"
+ "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR
+ "\\v'\\n[" EXT_DEPTH_REG "]u'\n",
+ ext);
+ }
+ if (bot)
+ printf(".as " DELIM_STRING " \\v'\\n[" BOT_HEIGHT_REG "]u'"
+ "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR
+ "\\v'\\n[" BOT_DEPTH_REG "]u'\n",
+ bot);
+ printf(".as " DELIM_STRING " " DELIMITER_CHAR "\n");
+}
+
+static void define_extensible_string(char *delim, int uid,
+ left_or_right_t left_or_right)
+{
+ printf(".ds " DELIM_STRING "\n");
+ delimiter *d = delim_table;
+ int delim_len = strlen(delim);
+ int i;
+ for (i = 0; i < DELIM_TABLE_SIZE; i++, d++)
+ if (strncmp(delim, d->name, delim_len) == 0
+ && (left_or_right & d->flags) != 0)
+ break;
+ if (i >= DELIM_TABLE_SIZE) {
+ error("there is no `%1' delimiter", delim);
+ printf(".nr " DELIM_WIDTH_REG " 0\n");
+ return;
+ }
+
+ printf(".nr " DELIM_WIDTH_REG " 0\\w" DELIMITER_CHAR "\\f[%s]%s\\fP" DELIMITER_CHAR "\n"
+ ".ds " DELIM_STRING " \\Z" DELIMITER_CHAR
+ "\\v'\\n[rsb]u+\\n[rst]u/2u-%dM'\\f[%s]%s\\fP" DELIMITER_CHAR "\n"
+ ".nr " TOTAL_HEIGHT_REG " \\n[rst]-\\n[rsb]\n"
+ ".if \\n[" TOTAL_HEIGHT_REG "]<\\n[" DELTA_REG "] "
+ "\\{",
+ current_roman_font, d->small, axis_height,
+ current_roman_font, d->small);
+
+ char buf[256];
+ sprintf(buf, d->chain_format, "\\\\n[" INDEX_REG "]");
+ printf(".nr " INDEX_REG " 0\n"
+ ".de " TEMP_MACRO "\n"
+ ".ie c%s \\{\\\n"
+ ".nr " DELIM_WIDTH_REG " 0\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n"
+ ".ds " DELIM_STRING " \\Z" DELIMITER_CHAR
+ "\\v'\\\\n[rsb]u+\\\\n[rst]u/2u-%dM'%s" DELIMITER_CHAR "\n"
+ ".nr " TOTAL_HEIGHT_REG " \\\\n[rst]-\\\\n[rsb]\n"
+ ".if \\\\n[" TOTAL_HEIGHT_REG "]<\\n[" DELTA_REG "] "
+ "\\{.nr " INDEX_REG " +1\n"
+ "." TEMP_MACRO "\n"
+ ".\\}\\}\n"
+ ".el .nr " INDEX_REG " 0-1\n"
+ "..\n"
+ "." TEMP_MACRO "\n",
+ buf, buf, axis_height, buf);
+ if (d->ext) {
+ printf(".if \\n[" INDEX_REG "]<0 \\{.if c%s \\{\\\n", d->ext);
+ build_extensible(d->ext, d->top, d->mid, d->bot);
+ printf(".\\}\\}\n");
+ }
+ printf(".\\}\n");
+ printf(".as " DELIM_STRING " \\h'\\n[" DELIM_WIDTH_REG "]u'\n");
+ printf(".nr " WIDTH_FORMAT " +\\n[" DELIM_WIDTH_REG "]\n", uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
+ ">?(\\n[" TOTAL_HEIGHT_REG "]/2+%dM)\n",
+ uid, uid, axis_height);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
+ ">?(\\n[" TOTAL_HEIGHT_REG "]/2-%dM)\n",
+ uid, uid, axis_height);
+}
+
+int delim_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DELTA_REG " \\n[" HEIGHT_FORMAT "]-%dM"
+ ">?(\\n[" DEPTH_FORMAT "]+%dM)\n",
+ p->uid, axis_height, p->uid, axis_height);
+ printf(".nr " DELTA_REG " 0\\n[" DELTA_REG "]*%d/500"
+ ">?(\\n[" DELTA_REG "]*2-%dM)\n",
+ delimiter_factor, delimiter_shortfall);
+ if (left) {
+ define_extensible_string(left, uid, LEFT_DELIM);
+ printf(".rn " DELIM_STRING " " LEFT_DELIM_STRING_FORMAT "\n",
+ uid);
+ if (r)
+ printf(".nr " MARK_REG " +\\n[" DELIM_WIDTH_REG "]\n");
+ }
+ if (right) {
+ define_extensible_string(right, uid, RIGHT_DELIM);
+ printf(".rn " DELIM_STRING " " RIGHT_DELIM_STRING_FORMAT "\n",
+ uid);
+ }
+ return r;
+}
+
+void delim_box::output()
+{
+ if (left)
+ printf("\\*[" LEFT_DELIM_STRING_FORMAT "]", uid);
+ p->output();
+ if (right)
+ printf("\\*[" RIGHT_DELIM_STRING_FORMAT "]", uid);
+}
+
+void delim_box::check_tabs(int level)
+{
+ p->check_tabs(level);
+}
+
+void delim_box::debug_print()
+{
+ fprintf(stderr, "left \"%s\" { ", left ? left : "");
+ p->debug_print();
+ fprintf(stderr, " }");
+ if (right)
+ fprintf(stderr, " right \"%s\"", right);
+}
+
diff --git a/src/preproc/eqn/eqn.cc b/src/preproc/eqn/eqn.cc
new file mode 100755
index 00000000..1fdda611
--- /dev/null
+++ b/src/preproc/eqn/eqn.cc
@@ -0,0 +1,1277 @@
+#if defined(__STDC__) || defined(__cplusplus)
+#define YYCONST const
+#define YYPARAMS(x) x
+#define YYDEFUN(name, arglist, args) name(args)
+#define YYAND ,
+#define YYPTR void *
+#else
+#define YYCONST
+#define YYPARAMS(x) ()
+#define YYDEFUN(name, arglist, args) name arglist args;
+#define YYAND ;
+#define YYPTR char *
+#endif
+#ifndef lint
+YYCONST static char yysccsid[] = "@(#)yaccpar 1.8 (Berkeley +Cygnus.28) 01/20/91";
+#endif
+#define YYBYACC 1
+#ifndef YYDONT_INCLUDE_STDIO
+#include <stdio.h>
+#endif
+#ifdef __cplusplus
+#include <stdlib.h> /* for malloc/realloc/free */
+#endif
+#line 20 "eqn.y"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "lib.h"
+#include "box.h"
+extern int non_empty_flag;
+char *strsave(const char *);
+int yylex();
+void yyerror(const char *);
+#line 32 "eqn.y"
+typedef union {
+ char *str;
+ box *b;
+ pile_box *pb;
+ matrix_box *mb;
+ int n;
+ column *col;
+} YYSTYPE;
+#line 45 "y.tab.c"
+#define OVER 257
+#define SMALLOVER 258
+#define SQRT 259
+#define SUB 260
+#define SUP 261
+#define LPILE 262
+#define RPILE 263
+#define CPILE 264
+#define PILE 265
+#define LEFT 266
+#define RIGHT 267
+#define TO 268
+#define FROM 269
+#define SIZE 270
+#define FONT 271
+#define ROMAN 272
+#define BOLD 273
+#define ITALIC 274
+#define FAT 275
+#define ACCENT 276
+#define BAR 277
+#define UNDER 278
+#define ABOVE 279
+#define TEXT 280
+#define QUOTED_TEXT 281
+#define FWD 282
+#define BACK 283
+#define DOWN 284
+#define UP 285
+#define MATRIX 286
+#define COL 287
+#define LCOL 288
+#define RCOL 289
+#define CCOL 290
+#define MARK 291
+#define LINEUP 292
+#define TYPE 293
+#define VCENTER 294
+#define PRIME 295
+#define SPLIT 296
+#define NOSPLIT 297
+#define UACCENT 298
+#define SPECIAL 299
+#define SPACE 300
+#define GFONT 301
+#define GSIZE 302
+#define DEFINE 303
+#define NDEFINE 304
+#define TDEFINE 305
+#define SDEFINE 306
+#define UNDEF 307
+#define IFDEF 308
+#define INCLUDE 309
+#define DELIM 310
+#define CHARTYPE 311
+#define SET 312
+#define GRFONT 313
+#define GBFONT 314
+#define YYERRCODE 256
+static YYCONST short yylhs[] = { -1,
+ 0, 0, 6, 6, 1, 1, 1, 2, 2, 2,
+ 2, 2, 3, 3, 3, 3, 4, 4, 7, 7,
+ 7, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 8, 11, 11, 12, 12, 13,
+ 13, 16, 16, 15, 15, 14, 14, 14, 14, 9,
+ 9, 10, 10, 10,
+};
+static YYCONST short yylen[] = { 2,
+ 0, 1, 1, 2, 1, 2, 2, 1, 3, 3,
+ 5, 5, 1, 2, 3, 3, 1, 3, 1, 3,
+ 5, 1, 1, 2, 2, 1, 1, 1, 3, 2,
+ 2, 2, 2, 4, 5, 3, 2, 2, 2, 3,
+ 3, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ 3, 3, 2, 3, 1, 1, 3, 3, 4, 1,
+ 2, 1, 3, 3, 4, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1,
+};
+static YYCONST short yydefred[] = { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 22, 23, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 26, 27, 28, 0,
+ 0, 3, 5, 0, 13, 0, 0, 17, 14, 70,
+ 71, 0, 0, 55, 31, 32, 33, 30, 73, 74,
+ 72, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 6, 7, 0, 0, 24, 25, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 37, 38,
+ 39, 0, 4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 60, 0,
+ 0, 29, 15, 16, 9, 0, 0, 20, 18, 40,
+ 41, 0, 58, 0, 0, 0, 0, 66, 67, 68,
+ 69, 34, 61, 0, 0, 0, 0, 59, 35, 0,
+ 0, 0, 11, 12, 21, 0, 64, 0, 0, 65,
+};
+static YYCONST short yydgoto[] = { 31,
+ 32, 33, 34, 35, 36, 84, 38, 43, 44, 52,
+ 85, 45, 98, 99, 118, 131,
+};
+static YYCONST short yysindex[] = { 1488,
+ 1527, -120, -120, -120, -120, -123, -249, -249, 1566, 1566,
+ 1566, 1566, 0, 0, -249, -249, -249, -249, -115, 1488,
+ 1488, -249, 1566, -256, -251, -249, 0, 0, 0, 1488,
+ 0, 0, 0, -221, 0, -233, 1488, 0, 0, 0,
+ 0, 1488, -85, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1488, 1566, 1566, -195, -195, -195, -195, 1566, 1566,
+ 1566, 1566, -272, 0, 0, 1566, -195, 0, 0, 1566,
+ 1402, 1527, 1527, 1527, 1527, 1566, 1566, 1566, 0, 0,
+ 0, 1566, 0, 1488, -113, 1488, 1444, -195, -195, -195,
+ -195, -195, -195, -117, -117, -117, -117, -118, 0, -195,
+ -195, 0, 0, 0, 0, -167, -189, 0, 0, 0,
+ 0, 1488, 0, -106, -123, 1488, -83, 0, 0, 0,
+ 0, 0, 0, 1527, 1527, 1566, 1488, 0, 0, 1488,
+ -105, 1488, 0, 0, 0, 1488, 0, -104, 1488, 0,
+};
+static YYCONST short yyrindex[] = { 41,
+ 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, 1, 0, 1220, 46, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 85, 128, 363, 406, 0, 0,
+ 0, 0, 0, 0, 0, 0, 449, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, -103, 0, 0, 185, 492, 727, 770,
+ 813, 856, 1091, 0, 0, 0, 0, 0, 0, 1134,
+ 1177, 0, 0, 0, 0, 42, 1220, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -102, 0, 0, -101,
+ 0, 0, 0, 0, 0, 0, 0, 0, -99, 0,
+};
+static YYCONST short yygindex[] = { 0,
+ -7, -69, 3, -66, 458, 9, -26, 52, 27, -63,
+ -32, 54, 0, -35, 2, -59,
+};
+#define YYTABLESIZE 1865
+static YYCONST short yytable[] = { 49,
+ 8, 50, 42, 39, 105, 116, 122, 63, 37, 8,
+ 109, 113, 64, 65, 94, 95, 96, 97, 128, 137,
+ 140, 56, 57, 62, 68, 63, 76, 77, 69, 83,
+ 40, 41, 51, 53, 54, 72, 73, 86, 71, 132,
+ 1, 10, 78, 79, 80, 2, 74, 75, 66, 108,
+ 10, 129, 70, 114, 133, 134, 46, 47, 48, 135,
+ 87, 81, 123, 83, 82, 0, 59, 60, 61, 62,
+ 76, 126, 138, 0, 103, 104, 83, 106, 0, 83,
+ 78, 79, 80, 0, 42, 0, 78, 79, 80, 72,
+ 73, 0, 0, 42, 8, 0, 119, 120, 121, 81,
+ 124, 125, 82, 0, 0, 81, 0, 0, 82, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,
+ 127, 0, 83, 8, 130, 8, 8, 43, 0, 0,
+ 0, 83, 0, 0, 0, 10, 43, 0, 0, 0,
+ 130, 51, 0, 0, 139, 117, 117, 117, 117, 0,
+ 0, 0, 0, 0, 0, 0, 40, 41, 0, 40,
+ 41, 0, 40, 41, 10, 112, 10, 10, 94, 95,
+ 96, 97, 112, 136, 136, 56, 57, 62, 42, 63,
+ 0, 0, 0, 0, 36, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 42, 0, 42,
+ 42, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 43, 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,
+ 43, 0, 43, 43, 0, 0, 0, 0, 0, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 0, 0, 0,
+ 0, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 36,
+ 0, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 0, 0,
+ 0, 0, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 0, 0, 44, 42, 42, 42, 42, 42, 42, 42,
+ 42, 44, 0, 0, 0, 42, 42, 42, 42, 0,
+ 42, 42, 0, 42, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 0, 0, 45, 43, 43, 43, 43,
+ 43, 43, 43, 43, 45, 0, 0, 0, 43, 43,
+ 43, 43, 0, 43, 43, 0, 43, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 36, 36, 0, 36, 36, 0, 0, 53, 0,
+ 0, 0, 36, 36, 0, 0, 44, 53, 0, 0,
+ 36, 36, 36, 36, 0, 0, 55, 56, 57, 58,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 36,
+ 67, 0, 36, 0, 0, 44, 0, 44, 44, 0,
+ 0, 47, 0, 0, 0, 0, 0, 0, 0, 45,
+ 47, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 88, 89, 0, 0, 0, 0, 90, 91, 92, 93,
+ 0, 0, 0, 100, 0, 0, 0, 101, 45, 0,
+ 45, 45, 0, 107, 0, 110, 0, 0, 0, 111,
+ 0, 0, 53, 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, 53, 0, 53, 53, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 47, 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, 47, 0, 47, 47, 0, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 0, 0,
+ 0, 44, 44, 44, 44, 44, 44, 44, 44, 0,
+ 0, 0, 0, 44, 44, 44, 44, 0, 44, 44,
+ 0, 44, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 0, 0, 0, 45, 45, 45, 45, 45, 45,
+ 45, 45, 0, 0, 0, 0, 45, 45, 45, 45,
+ 0, 45, 45, 0, 45, 53, 53, 53, 53, 53,
+ 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+ 53, 53, 53, 53, 0, 0, 46, 53, 53, 53,
+ 53, 53, 53, 53, 53, 46, 0, 0, 0, 53,
+ 53, 53, 53, 0, 53, 53, 0, 53, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 0, 0, 48,
+ 47, 47, 47, 47, 47, 47, 47, 47, 48, 0,
+ 0, 0, 47, 47, 47, 47, 0, 47, 47, 0,
+ 47, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 49, 0, 0, 0, 0, 0, 0, 0,
+ 46, 49, 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, 46,
+ 0, 46, 46, 0, 0, 51, 0, 0, 0, 0,
+ 0, 0, 0, 48, 51, 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, 48, 0, 48, 48, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 49, 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, 49, 0, 49, 49, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 51,
+ 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, 51, 0,
+ 51, 51, 0, 46, 46, 46, 46, 46, 46, 46,
+ 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
+ 46, 46, 0, 0, 0, 46, 46, 46, 46, 46,
+ 46, 46, 46, 0, 0, 0, 0, 46, 46, 46,
+ 46, 0, 46, 46, 0, 46, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 0, 0, 0, 48, 48,
+ 48, 48, 48, 48, 48, 48, 0, 0, 0, 0,
+ 48, 48, 48, 48, 0, 48, 48, 0, 48, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 0, 0,
+ 50, 49, 49, 49, 49, 49, 49, 49, 49, 50,
+ 0, 0, 0, 49, 49, 49, 49, 0, 49, 49,
+ 0, 49, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 0, 0, 52, 51, 51, 51, 51, 51, 51,
+ 51, 51, 52, 0, 0, 0, 51, 51, 51, 51,
+ 0, 51, 51, 0, 51, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 54, 0, 0, 0,
+ 0, 0, 0, 0, 50, 54, 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, 50, 0, 50, 50, 0, 0, 19,
+ 0, 0, 0, 0, 0, 0, 0, 52, 19, 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, 52, 0, 52, 52,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 54, 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, 54,
+ 0, 54, 54, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 19, 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, 19, 0, 19, 19, 0, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 0, 0, 0, 50,
+ 50, 50, 50, 50, 50, 50, 50, 0, 0, 0,
+ 0, 50, 50, 50, 50, 0, 50, 50, 0, 50,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 0,
+ 29, 0, 52, 52, 52, 52, 52, 52, 52, 52,
+ 0, 0, 0, 0, 52, 52, 52, 52, 0, 52,
+ 52, 0, 52, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 29, 0, 0, 54, 54, 54, 54, 54,
+ 54, 54, 54, 0, 0, 0, 0, 54, 54, 54,
+ 54, 0, 54, 54, 0, 54, 19, 19, 19, 0,
+ 0, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 27, 29, 0, 19, 19,
+ 19, 19, 19, 19, 19, 19, 0, 0, 0, 0,
+ 19, 19, 19, 19, 0, 19, 19, 0, 19, 0,
+ 0, 0, 0, 0, 30, 0, 102, 28, 0, 0,
+ 0, 0, 0, 0, 0, 29, 0, 27, 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, 30, 0, 0, 28,
+ 0, 0, 0, 0, 29, 0, 0, 0, 0, 0,
+ 0, 27, 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,
+ 30, 0, 0, 28, 0, 0, 0, 0, 0, 0,
+ 27, 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, 30,
+ 0, 0, 28, 0, 0, 0, 0, 0, 0, 27,
+ 1, 0, 0, 2, 3, 4, 5, 6, 0, 0,
+ 0, 7, 8, 9, 10, 11, 12, 0, 0, 0,
+ 0, 13, 14, 15, 16, 17, 18, 19, 30, 0,
+ 0, 28, 20, 21, 22, 23, 0, 24, 25, 0,
+ 26, 0, 1, 0, 0, 2, 3, 4, 5, 6,
+ 115, 0, 0, 7, 8, 9, 10, 11, 12, 0,
+ 0, 0, 0, 13, 14, 15, 16, 17, 18, 19,
+ 0, 0, 0, 0, 20, 21, 22, 23, 0, 24,
+ 25, 0, 26, 0, 0, 0, 1, 0, 0, 2,
+ 3, 4, 5, 6, 0, 0, 0, 7, 8, 9,
+ 10, 11, 12, 0, 0, 0, 0, 13, 14, 15,
+ 16, 17, 18, 19, 0, 0, 0, 0, 20, 21,
+ 22, 23, 0, 24, 25, 1, 26, 0, 2, 3,
+ 4, 5, 6, 0, 0, 0, 7, 8, 9, 10,
+ 11, 12, 0, 0, 0, 0, 13, 14, 15, 16,
+ 17, 18, 19, 0, 0, 0, 0, 0, 0, 22,
+ 23, 0, 24, 25, 0, 26, 0, 2, 3, 4,
+ 5, 6, 0, 0, 0, 7, 8, 9, 10, 11,
+ 12, 0, 0, 0, 0, 13, 14, 15, 16, 17,
+ 18, 19, 0, 0, 0, 0, 0, 0, 22, 23,
+ 0, 24, 25, 0, 26,
+};
+static YYCONST short yycheck[] = { 123,
+ 0, 125, 123, 1, 74, 123, 125, 123, 0, 9,
+ 77, 125, 20, 21, 287, 288, 289, 290, 125, 125,
+ 125, 125, 125, 125, 281, 125, 260, 261, 280, 37,
+ 280, 281, 6, 7, 8, 257, 258, 123, 30, 123,
+ 0, 0, 276, 277, 278, 0, 268, 269, 22, 76,
+ 9, 115, 26, 86, 124, 125, 3, 4, 5, 126,
+ 52, 295, 98, 71, 298, -1, 15, 16, 17, 18,
+ 260, 261, 132, -1, 72, 73, 84, 75, -1, 87,
+ 276, 277, 278, -1, 0, -1, 276, 277, 278, 257,
+ 258, -1, -1, 9, 94, -1, 95, 96, 97, 295,
+ 268, 269, 298, -1, -1, 295, -1, -1, 298, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 127,
+ 112, -1, 130, 123, 116, 125, 126, 0, -1, -1,
+ -1, 139, -1, -1, -1, 94, 9, -1, -1, -1,
+ 132, 115, -1, -1, 136, 94, 95, 96, 97, -1,
+ -1, -1, -1, -1, -1, -1, 280, 281, -1, 280,
+ 281, -1, 280, 281, 123, 279, 125, 126, 287, 288,
+ 289, 290, 279, 279, 279, 279, 279, 279, 94, 279,
+ -1, -1, -1, -1, 0, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 123, -1, 125,
+ 126, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 94, -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,
+ 123, -1, 125, 126, -1, -1, -1, -1, -1, 259,
+ 260, 261, 262, 263, 264, 265, 266, 267, -1, -1,
+ 270, 271, 272, 273, 274, 275, 276, 277, 278, 279,
+ 280, 281, 282, 283, 284, 285, 286, -1, -1, -1,
+ -1, 291, 292, 293, 294, 295, 296, 297, 298, 299,
+ 259, 260, 261, 262, 263, 264, 265, 266, 267, 125,
+ -1, 270, 271, 272, 273, 274, 275, 276, 277, 278,
+ 279, 280, 281, 282, 283, 284, 285, 286, -1, -1,
+ -1, -1, 291, 292, 293, 294, 295, 296, 297, 298,
+ 299, 257, 258, 259, 260, 261, 262, 263, 264, 265,
+ 266, 267, 268, 269, 270, 271, 272, 273, 274, 275,
+ -1, -1, 0, 279, 280, 281, 282, 283, 284, 285,
+ 286, 9, -1, -1, -1, 291, 292, 293, 294, -1,
+ 296, 297, -1, 299, 257, 258, 259, 260, 261, 262,
+ 263, 264, 265, 266, 267, 268, 269, 270, 271, 272,
+ 273, 274, 275, -1, -1, 0, 279, 280, 281, 282,
+ 283, 284, 285, 286, 9, -1, -1, -1, 291, 292,
+ 293, 294, -1, 296, 297, -1, 299, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 257, 258, -1, 260, 261, -1, -1, 0, -1,
+ -1, -1, 268, 269, -1, -1, 94, 9, -1, -1,
+ 276, 277, 278, 279, -1, -1, 9, 10, 11, 12,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 295,
+ 23, -1, 298, -1, -1, 123, -1, 125, 126, -1,
+ -1, 0, -1, -1, -1, -1, -1, -1, -1, 94,
+ 9, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 53, 54, -1, -1, -1, -1, 59, 60, 61, 62,
+ -1, -1, -1, 66, -1, -1, -1, 70, 123, -1,
+ 125, 126, -1, 76, -1, 78, -1, -1, -1, 82,
+ -1, -1, 94, -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, 123, -1, 125, 126, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 94, -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, 123, -1, 125, 126, -1, 257,
+ 258, 259, 260, 261, 262, 263, 264, 265, 266, 267,
+ 268, 269, 270, 271, 272, 273, 274, 275, -1, -1,
+ -1, 279, 280, 281, 282, 283, 284, 285, 286, -1,
+ -1, -1, -1, 291, 292, 293, 294, -1, 296, 297,
+ -1, 299, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, -1, -1, -1, 279, 280, 281, 282, 283, 284,
+ 285, 286, -1, -1, -1, -1, 291, 292, 293, 294,
+ -1, 296, 297, -1, 299, 257, 258, 259, 260, 261,
+ 262, 263, 264, 265, 266, 267, 268, 269, 270, 271,
+ 272, 273, 274, 275, -1, -1, 0, 279, 280, 281,
+ 282, 283, 284, 285, 286, 9, -1, -1, -1, 291,
+ 292, 293, 294, -1, 296, 297, -1, 299, 257, 258,
+ 259, 260, 261, 262, 263, 264, 265, 266, 267, 268,
+ 269, 270, 271, 272, 273, 274, 275, -1, -1, 0,
+ 279, 280, 281, 282, 283, 284, 285, 286, 9, -1,
+ -1, -1, 291, 292, 293, 294, -1, 296, 297, -1,
+ 299, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 0, -1, -1, -1, -1, -1, -1, -1,
+ 94, 9, -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, 123,
+ -1, 125, 126, -1, -1, 0, -1, -1, -1, -1,
+ -1, -1, -1, 94, 9, -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, 123, -1, 125, 126, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 94, -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, 123, -1, 125, 126, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 94,
+ -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, 123, -1,
+ 125, 126, -1, 257, 258, 259, 260, 261, 262, 263,
+ 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
+ 274, 275, -1, -1, -1, 279, 280, 281, 282, 283,
+ 284, 285, 286, -1, -1, -1, -1, 291, 292, 293,
+ 294, -1, 296, 297, -1, 299, 257, 258, 259, 260,
+ 261, 262, 263, 264, 265, 266, 267, 268, 269, 270,
+ 271, 272, 273, 274, 275, -1, -1, -1, 279, 280,
+ 281, 282, 283, 284, 285, 286, -1, -1, -1, -1,
+ 291, 292, 293, 294, -1, 296, 297, -1, 299, 257,
+ 258, 259, 260, 261, 262, 263, 264, 265, 266, 267,
+ 268, 269, 270, 271, 272, 273, 274, 275, -1, -1,
+ 0, 279, 280, 281, 282, 283, 284, 285, 286, 9,
+ -1, -1, -1, 291, 292, 293, 294, -1, 296, 297,
+ -1, 299, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, -1, -1, 0, 279, 280, 281, 282, 283, 284,
+ 285, 286, 9, -1, -1, -1, 291, 292, 293, 294,
+ -1, 296, 297, -1, 299, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 0, -1, -1, -1,
+ -1, -1, -1, -1, 94, 9, -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, 123, -1, 125, 126, -1, -1, 0,
+ -1, -1, -1, -1, -1, -1, -1, 94, 9, -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, 123, -1, 125, 126,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 94, -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, 123,
+ -1, 125, 126, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 94, -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, 123, -1, 125, 126, -1, 257, 258, 259,
+ 260, 261, 262, 263, 264, 265, 266, 267, 268, 269,
+ 270, 271, 272, 273, 274, 275, -1, -1, -1, 279,
+ 280, 281, 282, 283, 284, 285, 286, -1, -1, -1,
+ -1, 291, 292, 293, 294, -1, 296, 297, -1, 299,
+ 257, 258, 259, 260, 261, 262, 263, 264, 265, 266,
+ 267, 268, 269, 270, 271, 272, 273, 274, 275, -1,
+ 9, -1, 279, 280, 281, 282, 283, 284, 285, 286,
+ -1, -1, -1, -1, 291, 292, 293, 294, -1, 296,
+ 297, -1, 299, 257, 258, 259, 260, 261, 262, 263,
+ 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
+ 274, 275, 9, -1, -1, 279, 280, 281, 282, 283,
+ 284, 285, 286, -1, -1, -1, -1, 291, 292, 293,
+ 294, -1, 296, 297, -1, 299, 257, 258, 259, -1,
+ -1, 262, 263, 264, 265, 266, 267, 268, 269, 270,
+ 271, 272, 273, 274, 275, 94, 9, -1, 279, 280,
+ 281, 282, 283, 284, 285, 286, -1, -1, -1, -1,
+ 291, 292, 293, 294, -1, 296, 297, -1, 299, -1,
+ -1, -1, -1, -1, 123, -1, 125, 126, -1, -1,
+ -1, -1, -1, -1, -1, 9, -1, 94, -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, 123, -1, -1, 126,
+ -1, -1, -1, -1, 9, -1, -1, -1, -1, -1,
+ -1, 94, -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,
+ 123, -1, -1, 126, -1, -1, -1, -1, -1, -1,
+ 94, -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, 123,
+ -1, -1, 126, -1, -1, -1, -1, -1, -1, 94,
+ 259, -1, -1, 262, 263, 264, 265, 266, -1, -1,
+ -1, 270, 271, 272, 273, 274, 275, -1, -1, -1,
+ -1, 280, 281, 282, 283, 284, 285, 286, 123, -1,
+ -1, 126, 291, 292, 293, 294, -1, 296, 297, -1,
+ 299, -1, 259, -1, -1, 262, 263, 264, 265, 266,
+ 267, -1, -1, 270, 271, 272, 273, 274, 275, -1,
+ -1, -1, -1, 280, 281, 282, 283, 284, 285, 286,
+ -1, -1, -1, -1, 291, 292, 293, 294, -1, 296,
+ 297, -1, 299, -1, -1, -1, 259, -1, -1, 262,
+ 263, 264, 265, 266, -1, -1, -1, 270, 271, 272,
+ 273, 274, 275, -1, -1, -1, -1, 280, 281, 282,
+ 283, 284, 285, 286, -1, -1, -1, -1, 291, 292,
+ 293, 294, -1, 296, 297, 259, 299, -1, 262, 263,
+ 264, 265, 266, -1, -1, -1, 270, 271, 272, 273,
+ 274, 275, -1, -1, -1, -1, 280, 281, 282, 283,
+ 284, 285, 286, -1, -1, -1, -1, -1, -1, 293,
+ 294, -1, 296, 297, -1, 299, -1, 262, 263, 264,
+ 265, 266, -1, -1, -1, 270, 271, 272, 273, 274,
+ 275, -1, -1, -1, -1, 280, 281, 282, 283, 284,
+ 285, 286, -1, -1, -1, -1, -1, -1, 293, 294,
+ -1, 296, 297, -1, 299,
+};
+#define YYFINAL 31
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#define YYMAXTOKEN 314
+#if YYDEBUG
+static YYCONST char *YYCONST yyname[] = {
+"end-of-file",0,0,0,0,0,0,0,0,"'\\t'",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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"OVER",
+"SMALLOVER","SQRT","SUB","SUP","LPILE","RPILE","CPILE","PILE","LEFT","RIGHT",
+"TO","FROM","SIZE","FONT","ROMAN","BOLD","ITALIC","FAT","ACCENT","BAR","UNDER",
+"ABOVE","TEXT","QUOTED_TEXT","FWD","BACK","DOWN","UP","MATRIX","COL","LCOL",
+"RCOL","CCOL","MARK","LINEUP","TYPE","VCENTER","PRIME","SPLIT","NOSPLIT",
+"UACCENT","SPECIAL","SPACE","GFONT","GSIZE","DEFINE","NDEFINE","TDEFINE",
+"SDEFINE","UNDEF","IFDEF","INCLUDE","DELIM","CHARTYPE","SET","GRFONT","GBFONT",
+};
+static YYCONST char *YYCONST yyrule[] = {
+"$accept : top",
+"top :",
+"top : equation",
+"equation : mark",
+"equation : equation mark",
+"mark : from_to",
+"mark : MARK mark",
+"mark : LINEUP mark",
+"from_to : sqrt_over",
+"from_to : sqrt_over TO from_to",
+"from_to : sqrt_over FROM sqrt_over",
+"from_to : sqrt_over FROM sqrt_over TO from_to",
+"from_to : sqrt_over FROM sqrt_over FROM from_to",
+"sqrt_over : script",
+"sqrt_over : SQRT sqrt_over",
+"sqrt_over : sqrt_over OVER sqrt_over",
+"sqrt_over : sqrt_over SMALLOVER sqrt_over",
+"script : nonsup",
+"script : simple SUP script",
+"nonsup : simple",
+"nonsup : simple SUB nonsup",
+"nonsup : simple SUB simple SUP script",
+"simple : TEXT",
+"simple : QUOTED_TEXT",
+"simple : SPLIT QUOTED_TEXT",
+"simple : NOSPLIT TEXT",
+"simple : '^'",
+"simple : '~'",
+"simple : '\\t'",
+"simple : '{' equation '}'",
+"simple : PILE pile_arg",
+"simple : LPILE pile_arg",
+"simple : RPILE pile_arg",
+"simple : CPILE pile_arg",
+"simple : MATRIX '{' column_list '}'",
+"simple : LEFT delim equation RIGHT delim",
+"simple : LEFT delim equation",
+"simple : simple BAR",
+"simple : simple UNDER",
+"simple : simple PRIME",
+"simple : simple ACCENT simple",
+"simple : simple UACCENT simple",
+"simple : ROMAN simple",
+"simple : BOLD simple",
+"simple : ITALIC simple",
+"simple : FAT simple",
+"simple : FONT text simple",
+"simple : SIZE text simple",
+"simple : FWD number simple",
+"simple : BACK number simple",
+"simple : UP number simple",
+"simple : DOWN number simple",
+"simple : TYPE text simple",
+"simple : VCENTER simple",
+"simple : SPECIAL text simple",
+"number : text",
+"pile_element_list : equation",
+"pile_element_list : pile_element_list ABOVE equation",
+"pile_arg : '{' pile_element_list '}'",
+"pile_arg : number '{' pile_element_list '}'",
+"column_list : column",
+"column_list : column_list column",
+"column_element_list : equation",
+"column_element_list : column_element_list ABOVE equation",
+"column_arg : '{' column_element_list '}'",
+"column_arg : number '{' column_element_list '}'",
+"column : COL column_arg",
+"column : LCOL column_arg",
+"column : RCOL column_arg",
+"column : CCOL column_arg",
+"text : TEXT",
+"text : QUOTED_TEXT",
+"delim : text",
+"delim : '{'",
+"delim : '}'",
+};
+#endif
+#define YYLEX yylex()
+#define YYEMPTY -1
+#define yyclearin (yychar=(YYEMPTY))
+#define yyerrok (yyerrflag=0)
+#ifndef YYINITDEPTH
+#define YYINITDEPTH 200
+#endif
+#ifdef YYSTACKSIZE
+#undef YYMAXDEPTH
+#define YYMAXDEPTH YYSTACKSIZE
+#else
+#ifdef YYMAXDEPTH
+#define YYSTACKSIZE YYMAXDEPTH
+#else
+#define YYSTACKSIZE 10000
+#define YYMAXDEPTH 10000
+#endif
+#endif
+int yydebug;
+int yynerrs;
+int yyerrflag;
+int yychar;
+YYSTYPE yyval;
+YYSTYPE yylval;
+static short *yyss;
+static YYSTYPE *yyvs;
+static int yystacksize;
+static int yygrow ();
+static YYPTR yymalloc YYPARAMS((unsigned));
+static YYPTR yyrealloc YYPARAMS((YYPTR, unsigned));
+#define yyfree(x) free(x)
+#define YYABORT goto yyabort
+#define YYACCEPT goto yyaccept
+#define YYERROR goto yyerrlab
+
+#if YYDEBUG
+#ifdef __cplusplus
+extern "C" char *getenv();
+#else
+extern char *getenv();
+#endif
+#endif
+
+int
+yyparse()
+{
+ register int yym, yyn, yystate;
+ register YYSTYPE *yyvsp;
+ register short *yyssp;
+ short *yysse;
+#if YYDEBUG
+ register YYCONST char *yys;
+
+ if (yys = getenv("YYDEBUG"))
+ {
+ yyn = *yys;
+ if (yyn >= '0' && yyn <= '9')
+ yydebug = yyn - '0';
+ }
+#endif
+
+ yynerrs = 0;
+ yyerrflag = 0;
+ yychar = (-1);
+
+ if (yyss == 0)
+ {
+ yyss = (short *) yymalloc (YYINITDEPTH * sizeof (short));
+ if (yyss == 0)
+ goto yyabort;
+ yyvs = (YYSTYPE *) yymalloc (YYINITDEPTH * sizeof (YYSTYPE));
+ if (yyvs == 0)
+ {
+ yyfree (yyss);
+ goto yyabort;
+ }
+ yystacksize = YYINITDEPTH;
+ }
+ yysse = yyss + yystacksize - 1;
+ yyssp = yyss;
+ yyvsp = yyvs;
+ *yyssp = yystate = 0;
+
+yyloop:
+ if (yyn = yydefred[yystate]) goto yyreduce;
+ if (yychar < 0)
+ {
+ if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+ if (!yys) yys = "illegal-symbol";
+ printf("yydebug: state %d, reading %d (%s)\n", yystate,
+ yychar, yys);
+ }
+#endif
+ }
+ if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("yydebug: state %d, shifting to state %d\n",
+ yystate, yytable[yyn]);
+#endif
+ if (yyssp >= yysse)
+ {
+ /* FIXME: Rework so there's only one of these. */
+ int depth = yyssp - yyss;
+ if (yygrow () != 0)
+ goto yyoverflow;
+ yysse = yyss + yystacksize - 1;
+ yyssp = yyss + depth;
+ yyvsp = yyvs + depth;
+ }
+ *++yyssp = yystate = yytable[yyn];
+ *++yyvsp = yylval;
+ yychar = (-1);
+ if (yyerrflag > 0) --yyerrflag;
+ goto yyloop;
+ }
+ if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+ {
+ yyn = yytable[yyn];
+ goto yyreduce;
+ }
+ if (yyerrflag) goto yyinrecovery;
+#ifdef lint
+ goto yynewerror;
+#endif
+yynewerror:
+ yyerror("syntax error");
+#ifdef lint
+ goto yyerrlab;
+#endif
+yyerrlab:
+ ++yynerrs;
+yyinrecovery:
+ if (yyerrflag < 3)
+ {
+ yyerrflag = 3;
+ for (;;)
+ {
+ if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("yydebug: state %d, error recovery shifting\
+ to state %d\n", *yyssp, yytable[yyn]);
+#endif
+ if (yyssp >= yysse)
+ {
+ int depth = yyssp - yyss;
+ if (yygrow () != 0)
+ goto yyoverflow;
+ yysse = yyss + yystacksize - 1;
+ yyssp = yyss + depth;
+ yyvsp = yyvs + depth;
+ }
+ *++yyssp = yystate = yytable[yyn];
+ *++yyvsp = yylval;
+ goto yyloop;
+ }
+ else
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("yydebug: error recovery discarding state %d\n",
+ *yyssp);
+#endif
+ if (yyssp <= yyss) goto yyabort;
+ --yyssp;
+ --yyvsp;
+ }
+ }
+ }
+ else
+ {
+ if (yychar == 0) goto yyabort;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+ if (!yys) yys = "illegal-symbol";
+ printf("yydebug: state %d, error recovery discards token %d (%s)\n",
+ yystate, yychar, yys);
+ }
+#endif
+ yychar = (-1);
+ goto yyloop;
+ }
+yyreduce:
+#if YYDEBUG
+ if (yydebug)
+ printf("yydebug: state %d, reducing by rule %d (%s)\n",
+ yystate, yyn, yyrule[yyn]);
+#endif
+ yym = yylen[yyn];
+ yyval = yyvsp[1-yym];
+ switch (yyn)
+ {
+case 2:
+#line 126 "eqn.y"
+{ yyvsp[0].b->top_level(); non_empty_flag = 1; }
+break;
+case 3:
+#line 131 "eqn.y"
+{ yyval.b = yyvsp[0].b; }
+break;
+case 4:
+#line 133 "eqn.y"
+{
+ list_box *lb = yyvsp[-1].b->to_list_box();
+ if (!lb)
+ lb = new list_box(yyvsp[-1].b);
+ lb->append(yyvsp[0].b);
+ yyval.b = lb;
+ }
+break;
+case 5:
+#line 144 "eqn.y"
+{ yyval.b = yyvsp[0].b; }
+break;
+case 6:
+#line 146 "eqn.y"
+{ yyval.b = make_mark_box(yyvsp[0].b); }
+break;
+case 7:
+#line 148 "eqn.y"
+{ yyval.b = make_lineup_box(yyvsp[0].b); }
+break;
+case 8:
+#line 153 "eqn.y"
+{ yyval.b = yyvsp[0].b; }
+break;
+case 9:
+#line 155 "eqn.y"
+{ yyval.b = make_limit_box(yyvsp[-2].b, 0, yyvsp[0].b); }
+break;
+case 10:
+#line 157 "eqn.y"
+{ yyval.b = make_limit_box(yyvsp[-2].b, yyvsp[0].b, 0); }
+break;
+case 11:
+#line 159 "eqn.y"
+{ yyval.b = make_limit_box(yyvsp[-4].b, yyvsp[-2].b, yyvsp[0].b); }
+break;
+case 12:
+#line 161 "eqn.y"
+{ yyval.b = make_limit_box(yyvsp[-4].b, make_limit_box(yyvsp[-2].b, yyvsp[0].b, 0), 0); }
+break;
+case 13:
+#line 166 "eqn.y"
+{ yyval.b = yyvsp[0].b; }
+break;
+case 14:
+#line 168 "eqn.y"
+{ yyval.b = make_sqrt_box(yyvsp[0].b); }
+break;
+case 15:
+#line 170 "eqn.y"
+{ yyval.b = make_over_box(yyvsp[-2].b, yyvsp[0].b); }
+break;
+case 16:
+#line 172 "eqn.y"
+{ yyval.b = make_small_over_box(yyvsp[-2].b, yyvsp[0].b); }
+break;
+case 17:
+#line 177 "eqn.y"
+{ yyval.b = yyvsp[0].b; }
+break;
+case 18:
+#line 179 "eqn.y"
+{ yyval.b = make_script_box(yyvsp[-2].b, 0, yyvsp[0].b); }
+break;
+case 19:
+#line 184 "eqn.y"
+{ yyval.b = yyvsp[0].b; }
+break;
+case 20:
+#line 186 "eqn.y"
+{ yyval.b = make_script_box(yyvsp[-2].b, yyvsp[0].b, 0); }
+break;
+case 21:
+#line 188 "eqn.y"
+{ yyval.b = make_script_box(yyvsp[-4].b, yyvsp[-2].b, yyvsp[0].b); }
+break;
+case 22:
+#line 193 "eqn.y"
+{ yyval.b = split_text(yyvsp[0].str); }
+break;
+case 23:
+#line 195 "eqn.y"
+{ yyval.b = new quoted_text_box(yyvsp[0].str); }
+break;
+case 24:
+#line 197 "eqn.y"
+{ yyval.b = split_text(yyvsp[0].str); }
+break;
+case 25:
+#line 199 "eqn.y"
+{ yyval.b = new quoted_text_box(yyvsp[0].str); }
+break;
+case 26:
+#line 201 "eqn.y"
+{ yyval.b = new half_space_box; }
+break;
+case 27:
+#line 203 "eqn.y"
+{ yyval.b = new space_box; }
+break;
+case 28:
+#line 205 "eqn.y"
+{ yyval.b = new tab_box; }
+break;
+case 29:
+#line 207 "eqn.y"
+{ yyval.b = yyvsp[-1].b; }
+break;
+case 30:
+#line 209 "eqn.y"
+{ yyvsp[0].pb->set_alignment(CENTER_ALIGN); yyval.b = yyvsp[0].pb; }
+break;
+case 31:
+#line 211 "eqn.y"
+{ yyvsp[0].pb->set_alignment(LEFT_ALIGN); yyval.b = yyvsp[0].pb; }
+break;
+case 32:
+#line 213 "eqn.y"
+{ yyvsp[0].pb->set_alignment(RIGHT_ALIGN); yyval.b = yyvsp[0].pb; }
+break;
+case 33:
+#line 215 "eqn.y"
+{ yyvsp[0].pb->set_alignment(CENTER_ALIGN); yyval.b = yyvsp[0].pb; }
+break;
+case 34:
+#line 217 "eqn.y"
+{ yyval.b = yyvsp[-1].mb; }
+break;
+case 35:
+#line 219 "eqn.y"
+{ yyval.b = make_delim_box(yyvsp[-3].str, yyvsp[-2].b, yyvsp[0].str); }
+break;
+case 36:
+#line 221 "eqn.y"
+{ yyval.b = make_delim_box(yyvsp[-1].str, yyvsp[0].b, 0); }
+break;
+case 37:
+#line 223 "eqn.y"
+{ yyval.b = make_overline_box(yyvsp[-1].b); }
+break;
+case 38:
+#line 225 "eqn.y"
+{ yyval.b = make_underline_box(yyvsp[-1].b); }
+break;
+case 39:
+#line 227 "eqn.y"
+{ yyval.b = make_prime_box(yyvsp[-1].b); }
+break;
+case 40:
+#line 229 "eqn.y"
+{ yyval.b = make_accent_box(yyvsp[-2].b, yyvsp[0].b); }
+break;
+case 41:
+#line 231 "eqn.y"
+{ yyval.b = make_uaccent_box(yyvsp[-2].b, yyvsp[0].b); }
+break;
+case 42:
+#line 233 "eqn.y"
+{ yyval.b = new font_box(strsave(get_grfont()), yyvsp[0].b); }
+break;
+case 43:
+#line 235 "eqn.y"
+{ yyval.b = new font_box(strsave(get_gbfont()), yyvsp[0].b); }
+break;
+case 44:
+#line 237 "eqn.y"
+{ yyval.b = new font_box(strsave(get_gfont()), yyvsp[0].b); }
+break;
+case 45:
+#line 239 "eqn.y"
+{ yyval.b = new fat_box(yyvsp[0].b); }
+break;
+case 46:
+#line 241 "eqn.y"
+{ yyval.b = new font_box(yyvsp[-1].str, yyvsp[0].b); }
+break;
+case 47:
+#line 243 "eqn.y"
+{ yyval.b = new size_box(yyvsp[-1].str, yyvsp[0].b); }
+break;
+case 48:
+#line 245 "eqn.y"
+{ yyval.b = new hmotion_box(yyvsp[-1].n, yyvsp[0].b); }
+break;
+case 49:
+#line 247 "eqn.y"
+{ yyval.b = new hmotion_box(-yyvsp[-1].n, yyvsp[0].b); }
+break;
+case 50:
+#line 249 "eqn.y"
+{ yyval.b = new vmotion_box(yyvsp[-1].n, yyvsp[0].b); }
+break;
+case 51:
+#line 251 "eqn.y"
+{ yyval.b = new vmotion_box(-yyvsp[-1].n, yyvsp[0].b); }
+break;
+case 52:
+#line 253 "eqn.y"
+{ yyvsp[0].b->set_spacing_type(yyvsp[-1].str); yyval.b = yyvsp[0].b; }
+break;
+case 53:
+#line 255 "eqn.y"
+{ yyval.b = new vcenter_box(yyvsp[0].b); }
+break;
+case 54:
+#line 257 "eqn.y"
+{ yyval.b = make_special_box(yyvsp[-1].str, yyvsp[0].b); }
+break;
+case 55:
+#line 262 "eqn.y"
+{
+ int n;
+ if (sscanf(yyvsp[0].str, "%d", &n) == 1)
+ yyval.n = n;
+ a_delete yyvsp[0].str;
+ }
+break;
+case 56:
+#line 272 "eqn.y"
+{ yyval.pb = new pile_box(yyvsp[0].b); }
+break;
+case 57:
+#line 274 "eqn.y"
+{ yyvsp[-2].pb->append(yyvsp[0].b); yyval.pb = yyvsp[-2].pb; }
+break;
+case 58:
+#line 279 "eqn.y"
+{ yyval.pb = yyvsp[-1].pb; }
+break;
+case 59:
+#line 281 "eqn.y"
+{ yyvsp[-1].pb->set_space(yyvsp[-3].n); yyval.pb = yyvsp[-1].pb; }
+break;
+case 60:
+#line 286 "eqn.y"
+{ yyval.mb = new matrix_box(yyvsp[0].col); }
+break;
+case 61:
+#line 288 "eqn.y"
+{ yyvsp[-1].mb->append(yyvsp[0].col); yyval.mb = yyvsp[-1].mb; }
+break;
+case 62:
+#line 293 "eqn.y"
+{ yyval.col = new column(yyvsp[0].b); }
+break;
+case 63:
+#line 295 "eqn.y"
+{ yyvsp[-2].col->append(yyvsp[0].b); yyval.col = yyvsp[-2].col; }
+break;
+case 64:
+#line 300 "eqn.y"
+{ yyval.col = yyvsp[-1].col; }
+break;
+case 65:
+#line 302 "eqn.y"
+{ yyvsp[-1].col->set_space(yyvsp[-3].n); yyval.col = yyvsp[-1].col; }
+break;
+case 66:
+#line 307 "eqn.y"
+{ yyvsp[0].col->set_alignment(CENTER_ALIGN); yyval.col = yyvsp[0].col; }
+break;
+case 67:
+#line 309 "eqn.y"
+{ yyvsp[0].col->set_alignment(LEFT_ALIGN); yyval.col = yyvsp[0].col; }
+break;
+case 68:
+#line 311 "eqn.y"
+{ yyvsp[0].col->set_alignment(RIGHT_ALIGN); yyval.col = yyvsp[0].col; }
+break;
+case 69:
+#line 313 "eqn.y"
+{ yyvsp[0].col->set_alignment(CENTER_ALIGN); yyval.col = yyvsp[0].col; }
+break;
+case 70:
+#line 317 "eqn.y"
+{ yyval.str = yyvsp[0].str; }
+break;
+case 71:
+#line 319 "eqn.y"
+{ yyval.str = yyvsp[0].str; }
+break;
+case 72:
+#line 324 "eqn.y"
+{ yyval.str = yyvsp[0].str; }
+break;
+case 73:
+#line 326 "eqn.y"
+{ yyval.str = strsave("{"); }
+break;
+case 74:
+#line 328 "eqn.y"
+{ yyval.str = strsave("}"); }
+break;
+#line 1168 "y.tab.c"
+ }
+ yyssp -= yym;
+ yystate = *yyssp;
+ yyvsp -= yym;
+ yym = yylhs[yyn];
+ if (yystate == 0 && yym == 0)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("yydebug: after reduction, shifting from state 0 to\
+ state %d\n", YYFINAL);
+#endif
+ yystate = YYFINAL;
+ *++yyssp = YYFINAL;
+ *++yyvsp = yyval;
+ if (yychar < 0)
+ {
+ if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+ if (!yys) yys = "illegal-symbol";
+ printf("yydebug: state %d, reading %d (%s)\n",
+ YYFINAL, yychar, yys);
+ }
+#endif
+ }
+ if (yychar == 0) goto yyaccept;
+ goto yyloop;
+ }
+ if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
+ yystate = yytable[yyn];
+ else
+ yystate = yydgoto[yym];
+#if YYDEBUG
+ if (yydebug)
+ printf("yydebug: after reduction, shifting from state %d \
+to state %d\n", *yyssp, yystate);
+#endif
+ if (yyssp >= yysse)
+ {
+ int depth = yyssp - yyss;
+ if (yygrow () != 0)
+ goto yyoverflow;
+ yysse = yyss + yystacksize - 1;
+ yyssp = yyss + depth;
+ yyvsp = yyvs + depth;
+ }
+ *++yyssp = yystate;
+ *++yyvsp = yyval;
+ goto yyloop;
+yyoverflow:
+ yyerror("yacc stack overflow");
+yyabort:
+ return (1);
+yyaccept:
+ return (0);
+}
+
+static int
+yygrow ()
+{
+ int old_stacksize = yystacksize;
+ short *new_yyss;
+ YYSTYPE *new_yyvs;
+
+ if (yystacksize >= YYMAXDEPTH)
+ return (1);
+ yystacksize *= 2;
+ if (yystacksize > YYMAXDEPTH)
+ yystacksize = YYMAXDEPTH;
+#if YYDEBUG
+ if (yydebug)
+ printf("yydebug: growing stack size from %d to %d\n",
+ old_stacksize, yystacksize);
+#endif
+ new_yyss = (short *) yyrealloc (yyss, yystacksize * sizeof (short));
+ if (new_yyss == 0)
+ return (1);
+ new_yyvs = (YYSTYPE *) yyrealloc (yyvs, yystacksize * sizeof (YYSTYPE));
+ if (new_yyvs == 0)
+ {
+ yyfree (new_yyss);
+ return (1);
+ }
+ yyss = new_yyss;
+ yyvs = new_yyvs;
+ return (0);
+}
+
+static YYPTR
+YYDEFUN (yymalloc, (bytes), unsigned bytes)
+{
+ YYPTR ptr = (YYPTR) malloc (bytes);
+ if (ptr != 0) return (ptr);
+ yyerror ("yyparse: memory exhausted");
+ return (0);
+}
+
+static YYPTR
+YYDEFUN (yyrealloc, (old, bytes), YYPTR old YYAND unsigned bytes)
+{
+ YYPTR ptr = (YYPTR) realloc (old, bytes);
+ if (ptr != 0) return (ptr);
+ yyerror ("yyparse: memory exhausted");
+ return (0);
+}
diff --git a/src/preproc/eqn/eqn.h b/src/preproc/eqn/eqn.h
new file mode 100644
index 00000000..70b19271
--- /dev/null
+++ b/src/preproc/eqn/eqn.h
@@ -0,0 +1,51 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "cset.h"
+#include "errarg.h"
+#include "error.h"
+#include "lib.h"
+
+#include "box.h"
+
+extern char start_delim;
+extern char end_delim;
+extern int non_empty_flag;
+extern int inline_flag;
+extern int draw_flag;
+extern int one_size_reduction_flag;
+extern int compatible_flag;
+extern int nroff;
+
+void init_lex(const char *str, const char *filename, int lineno);
+void lex_error(const char *message,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+void init_table(const char *device);
+
+// prefix for all registers, strings, macros
+#define PREFIX "0"
diff --git a/src/preproc/eqn/eqn.man b/src/preproc/eqn/eqn.man
new file mode 100644
index 00000000..e49078a0
--- /dev/null
+++ b/src/preproc/eqn/eqn.man
@@ -0,0 +1,880 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-2000 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.ie \n(.V<\n(.v .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X
+.el .ds tx TeX
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.\" The BSD man macros can't handle " in arguments to font change macros,
+.\" so use \(ts instead of ".
+.tr \(ts"
+.TH @G@EQN @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+@g@eqn \- format equations for troff
+.SH SYNOPSIS
+.B @g@eqn
+[
+.B \-rvCNR
+]
+[
+.BI \-d cc
+]
+[
+.BI \-T name
+]
+[
+.BI \-M dir
+]
+[
+.BI \-f F
+]
+[
+.BI \-s n
+]
+[
+.BI \-p n
+]
+[
+.BI \-m n
+]
+[
+.IR files \|.\|.\|.
+]
+.SH DESCRIPTION
+This manual page describes the GNU version of
+.BR eqn ,
+which is part of the groff document formatting system.
+.B eqn
+compiles descriptions of equations embedded within
+.B troff
+input files into commands that are understood by
+.BR troff .
+Normally, it should be invoked using the
+.B \-e
+option of
+.BR groff .
+The syntax is quite compatible with Unix eqn.
+The output of GNU eqn cannot be processed with Unix troff;
+it must be processed with GNU troff.
+If no files are given on the command line, the standard input
+will be read.
+A filename of
+.B \-
+will cause the standard input to be read.
+.LP
+.B eqn
+searches for the file
+.B eqnrc
+using the path
+.BR @MACROPATH@ .
+If it exists, eqn will process it before the other input files.
+The
+.B \-R
+option prevents this.
+.LP
+GNU eqn does not provide the functionality of neqn:
+it does not support low-resolution, typewriter-like devices
+(although it may work adequately for very simple input).
+.SH OPTIONS
+.TP
+.B \-C
+Recognize
+.B .EQ
+and
+.B .EN
+even when followed by a character other than space or newline.
+.TP
+.B \-N
+Don't allow newlines within delimiters.
+This option allows
+.B eqn
+to recover better from missing closing delimiters.
+.TP
+.B \-v
+Print the version number.
+.TP
+.B \-r
+Only one size reduction.
+.TP
+.BI \-m n
+The minimum point-size is
+.IR n .
+eqn will not reduce the size of subscripts or superscripts to
+a smaller size than
+.IR n .
+.TP
+.BI \-T name
+The output is for device
+.IR name .
+The only effect of this is to define a macro
+.I name
+with a value of
+.BR 1 .
+Typically
+.B eqnrc
+will use this to provide definitions appropriate for the output device.
+The default output device is
+.BR @DEVICE@ .
+.TP
+.BI \-M dir
+Search
+.I dir
+for
+.B eqnrc
+before the default directories.
+.TP
+.B \-R
+Don't load
+.BR eqnrc .
+.TP
+.BI \-f F
+This is equivalent to a
+.BI gfont\ F
+command.
+.TP
+.BI \-s n
+This is equivalent to a
+.BI gsize\ n
+command.
+This option is deprecated.
+eqn will normally set equations at whatever the current point size
+is when the equation is encountered.
+.TP
+.BI \-p n
+This says that subscripts and superscripts should be
+.I n
+points smaller than the surrounding text.
+This option is deprecated.
+Normally eqn makes sets subscripts and superscripts at 70%
+of the size of the surrounding text.
+.SH USAGE
+Only the differences between GNU eqn and Unix eqn are described here.
+.LP
+Most of the new features of GNU eqn
+are based on \*(tx.
+There are some references to the differences between \*(tx and GNU eqn below;
+these may safely be ignored if you do not know \*(tx.
+.SS Automatic spacing
+.LP
+.B eqn
+gives each component of an equation a type, and adjusts the spacing
+between components using that type.
+Possible types are:
+.TP \w'punctuation'u+2n
+ordinary
+an ordinary character such as 1 or
+.IR x ;
+.TP
+operator
+a large operator such as
+.ds Su \s+5\(*S\s0
+.if \n(.g .if !c\(*S .ds Su the summation operator
+\*(Su;
+.TP
+binary
+a binary operator such as +;
+.TP
+relation
+a relation such as =;
+.TP
+opening
+a opening bracket such as (;
+.TP
+closing
+a closing bracket such as );
+.TP
+punctuation
+a punctuation character such as ,;
+.TP
+inner
+a subformula contained within brackets;
+.TP
+suppress
+spacing that suppresses automatic spacing adjustment.
+.LP
+Components of an equation get a type in one of two ways.
+.TP
+.BI type\ t\ e
+This yields an equation component that contains
+.I e
+but that has type
+.IR t ,
+where
+.I t
+is one of the types mentioned above.
+For example,
+.B times
+is defined as
+.RS
+.IP
+.B
+type "binary" \e(mu
+.RE
+.IP
+The name of the type doesn't have to be quoted, but quoting protects
+from macro expansion.
+.TP
+.BI chartype\ t\ text
+Unquoted groups of characters are split up into individual characters,
+and the type of each character is looked up;
+this changes the type that is stored for each character;
+it says that the characters in
+.I text
+from now on have type
+.IR t .
+For example,
+.RS
+.IP
+.B
+chartype "punctuation" .,;:
+.RE
+.IP
+would make the characters
+.B .,;:
+have type punctuation
+whenever they subsequently appeared in an equation.
+The type
+.I t
+can also be
+.B letter
+or
+.BR digit ;
+in these cases
+.B chartype
+changes the font type of the characters.
+See the Fonts subsection.
+.SS New primitives
+.TP
+.IB e1\ smallover\ e2
+This is similar to
+.BR over ;
+.B smallover
+reduces the size of
+.I e1
+and
+.IR e2 ;
+it also puts less vertical space between
+.I e1
+or
+.I e2
+and the fraction bar.
+The
+.B over
+primitive corresponds to the \*(tx
+.B \eover
+primitive in display styles;
+.B smallover
+corresponds to
+.B \eover
+in non-display styles.
+.TP
+.BI vcenter\ e
+This vertically centers
+.I e
+about the math axis.
+The math axis is the vertical position about which characters
+such as + and - are centered; also it is the vertical position
+used for the bar of fractions.
+For example,
+.B sum
+is defined as
+.RS
+.IP
+.B
+{ type "operator" vcenter size +5 \e(*S }
+.RE
+.TP
+.IB e1\ accent\ e2
+This sets
+.I e2
+as an accent over
+.IR e1 .
+.I e2
+is assumed to be at the correct height for a lowercase letter;
+.I e2
+will be moved down according if
+.I e1
+is taller or shorter than a lowercase letter.
+For example,
+.B hat
+is defined as
+.RS
+.IP
+.B
+accent { "^" }
+.RE
+.IP
+.BR dotdot ,
+.BR dot ,
+.BR tilde ,
+.B vec
+and
+.B dyad
+are also defined using the
+.B accent
+primitive.
+.TP
+.IB e1\ uaccent\ e2
+This sets
+.I e2
+as an accent under
+.IR e1 .
+.I e2
+is assumed to be at the correct height for a character without a descender;
+.I e2
+will be moved down if
+.I e1
+has a descender.
+.B utilde
+is pre-defined using
+.B uaccent
+as a tilde accent below the baseline.
+.TP
+.BI split\ \(ts text \(ts
+This has the same effect as simply
+.RS
+.IP
+.I text
+.RE
+.IP
+but
+.I text
+is not subject to macro expansion because it is quoted;
+.I text
+will be split up and the spacing between individual characters
+will be adjusted.
+.TP
+.BI nosplit\ text
+This has the same effect as
+.RS
+.IP
+.BI \(ts text \(ts
+.RE
+.IP
+but because
+.I text
+is not quoted it will be subject to macro expansion;
+.I text
+will not be split up
+and the spacing between individual characters will not be adjusted.
+.TP
+.IB e\ opprime
+This is a variant of
+.B prime
+that acts as an operator on
+.IR e .
+It produces a different result from
+.B prime
+in a case such as
+.BR A\ opprime\ sub\ 1 :
+with
+.B opprime
+the
+.B 1
+will be tucked under the prime as a subscript to the
+.B A
+(as is conventional in mathematical typesetting),
+whereas with
+.B prime
+the
+.B 1
+will be a subscript to the prime character.
+The precedence of
+.B opprime
+is the same as that of
+.B bar
+and
+.BR under ,
+which is higher than that of everything except
+.B accent
+and
+.BR uaccent .
+In unquoted text a
+.B '
+that is not the first character will be treated like
+.BR opprime .
+.TP
+.BI special\ text\ e
+This constructs a new object from
+.I e
+using a
+.BR @g@troff (@MAN1EXT@)
+macro named
+.IR text .
+When the macro is called,
+the string
+.B 0s
+will contain the output for
+.IR e ,
+and the number registers
+.BR 0w ,
+.BR 0h ,
+.BR 0d ,
+.BR 0skern
+and
+.BR 0skew
+will contain the width, height, depth, subscript kern, and skew of
+.IR e .
+(The
+.I "subscript kern"
+of an object says how much a subscript on that object should be tucked in;
+the
+.I skew
+of an object says how far to the right of the center of the object an
+accent over the object should be placed.)
+The macro must modify
+.B 0s
+so that it will output the desired result with its origin at the current
+point, and increase the current horizontal position by the width
+of the object.
+The number registers must also be modified so that they correspond to the
+result.
+.RS
+.LP
+For example, suppose you wanted a construct that `cancels' an expression
+by drawing a diagonal line through it.
+.IP
+.nf
+.ft B
+.ne 6+\n(.Vu
+\&.EQ
+define cancel 'special Ca'
+\&.EN
+\&.de Ca
+\&.ds 0s \eZ'\e\e*(0s'\ev'\e\en(0du'\eD'l \e\en(0wu -\e\en(0hu-\e\en(0du'\ev'\e\en(0hu'
+\&..
+.ft
+.fi
+.LP
+Then you could cancel an expression
+.I e
+with
+.BI cancel\ {\ e\ }
+.LP
+Here's a more complicated construct that draws a box round an expression:
+.IP
+.nf
+.ft B
+.ne 11+\n(.Vu
+\&.EQ
+define box 'special Bx'
+\&.EN
+\&.de Bx
+\&.ds 0s \eZ'\eh'1n'\e\e*(0s'\e
+\eZ'\ev'\e\en(0du+1n'\eD'l \e\en(0wu+2n 0'\eD'l 0 -\e\en(0hu-\e\en(0du-2n'\e
+\eD'l -\e\en(0wu-2n 0'\eD'l 0 \e\en(0hu+\e\en(0du+2n''\eh'\e\en(0wu+2n'
+\&.nr 0w +2n
+\&.nr 0d +1n
+\&.nr 0h +1n
+\&..
+.ft
+.fi
+.RE
+.SS Customization
+The appearance of equations is controlled by
+a large number of parameters. These can be set using
+the
+.B set
+command.
+.TP
+.BI set\ p\ n
+This sets parameter
+.I p
+to value
+.I n ;
+.I n
+is an integer.
+For example,
+.RS
+.IP
+.B
+set x_height 45
+.RE
+.IP
+says that
+.B eqn
+should assume an x height of 0.45 ems.
+.RS
+.LP
+Possible parameters are as follows.
+Values are in units of hundredths of an em unless otherwise stated.
+These descriptions are intended to be expository rather than
+definitive.
+.TP \w'\fBdefault_rule_thickness'u+2n
+.B minimum_size
+.B eqn
+will not set anything at a smaller point-size than this.
+The value is in points.
+.TP
+.B fat_offset
+The
+.B fat
+primitive emboldens an equation
+by overprinting two copies of the equation
+horizontally offset by this amount.
+.TP
+.B over_hang
+A fraction bar will be longer by twice this amount than
+the maximum of the widths of the numerator and denominator;
+in other words, it will overhang the numerator and
+denominator by at least this amount.
+.TP
+.B accent_width
+When
+.B bar
+or
+.B under
+is applied to a single character,
+the line will be this long.
+Normally,
+.B bar
+or
+.B under
+produces a line whose length is the width of the object to which it applies;
+in the case of a single character,
+this tends to produce a line that looks too long.
+.TP
+.B delimiter_factor
+Extensible delimiters produced with the
+.B left
+and
+.B right
+primitives will have a combined height and depth of at least this many
+thousandths of twice the maximum amount by which the sub-equation that
+the delimiters enclose extends away from the axis.
+.TP
+.B delimiter_shortfall
+Extensible delimiters produced with the
+.B left
+and
+.B right
+primitives will have a combined height and depth
+not less than the difference of
+twice the maximum amount by which the sub-equation that
+the delimiters enclose extends away from the axis
+and this amount.
+.TP
+.B null_delimiter_space
+This much horizontal space is inserted
+on each side of a fraction.
+.TP
+.B script_space
+The width of subscripts and superscripts is increased by this amount.
+.TP
+.B thin_space
+This amount of space is automatically inserted after punctuation
+characters.
+.TP
+.B medium_space
+This amount of space is automatically inserted on either side
+of binary operators.
+.TP
+.B thick_space
+This amount of space is automatically inserted on either side of
+relations.
+.TP
+.B x_height
+The height of lowercase letters without ascenders such as x.
+.TP
+.B axis_height
+The height above the baseline of the center of characters
+such as \(pl and \(mi.
+It is important that this value is correct for the font
+you are using.
+.TP
+.B default_rule_thickness
+This should set to the thickness of the
+.B \e(ru
+character, or the thickness of horizontal lines produced with the
+.B \eD
+escape sequence.
+.TP
+.B num1
+The
+.B over
+command will shift up the numerator by at least this amount.
+.TP
+.B num2
+The
+.B smallover
+command will shift up the numerator by at least this amount.
+.TP
+.B denom1
+The
+.B over
+command will shift down the denominator by at least this amount.
+.TP
+.B denom2
+The
+.B smallover
+command will shift down the denominator by at least this amount.
+.TP
+.B sup1
+Normally superscripts will be shifted up by at least this amount.
+.TP
+.B sup2
+Superscripts within superscripts or upper limits
+or numerators of
+.B smallover
+fractions
+will be shifted up by at least this amount.
+This is usually less than sup1.
+.TP
+.B sup3
+Superscripts within denominators or square roots
+or subscripts or lower limits will be shifted up by at least
+this amount.
+This is usually less than sup2.
+.TP
+.B sub1
+Subscripts will normally be shifted down by at least this amount.
+.TP
+.B sub2
+When there is both a subscript and a superscript, the subscript
+will be shifted down by at least this amount.
+.TP
+.B sup_drop
+The baseline of a superscript will be no more
+than this much amount below the top of the object on
+which the superscript is set.
+.TP
+.B sub_drop
+The baseline of a subscript will be at least this much below
+the bottom of the object on which the subscript is set.
+.TP
+.B big_op_spacing1
+The baseline of an upper limit will be at least this
+much above the top of the object on which the limit is set.
+.TP
+.B big_op_spacing2
+The baseline of a lower limit will be at least this
+much below the bottom of the object on which the limit is set.
+.TP
+.B big_op_spacing3
+The bottom of an upper limit will be at least this much above the
+top of the object on which the limit is set.
+.TP
+.B big_op_spacing4
+The top of a lower limit will be at least this much below
+the bottom of the object on which the limit is set.
+.TP
+.B big_op_spacing5
+This much vertical space will be added above and below limits.
+.TP
+.B baseline_sep
+The baselines of the rows in a pile or matrix will normally be
+this far apart.
+In most cases this should be equal to the sum of
+.B num1
+and
+.BR denom1 .
+.TP
+.B shift_down
+The midpoint between the top baseline and the bottom baseline
+in a matrix or pile will be shifted down by this much from the axis.
+In most cases this should be equal to
+.BR axis_height .
+.TP
+.B column_sep
+This much space will be added between columns in a matrix.
+.TP
+.B matrix_side_sep
+This much space will be added at each side of a matrix.
+.TP
+.B draw_lines
+If this is non-zero, lines will be drawn using the
+.B \eD
+escape sequence, rather than with the
+.B \el
+escape sequence and the
+.B \e(ru
+character.
+.TP
+.B body_height
+The amount by which the height of the equation exceeds this
+will be added as extra space before the line containing the equation
+(using
+.BR \ex .)
+The default value is 85.
+.TP
+.B body_depth
+The amount by which the depth of the equation exceeds this
+will be added as extra space after the line containing the equation
+(using
+.BR \ex .)
+The default value is 35.
+.TP
+.B nroff
+If this is non-zero,
+then
+.B ndefine
+will behave like
+.B define
+and
+.B tdefine
+will be ignored,
+otherwise
+.B tdefine
+will behave like
+.B define
+and
+.B ndefine
+will be ignored.
+The default value is 0
+(This is typically changed to 1 by the
+.B eqnrc
+file for the
+.BR ascii ,
+.B latin1
+and
+.B utf8
+devices.)
+.LP
+A more precise description of the role of many of these
+parameters can be found in Appendix H of
+.IR The\ \*(txbook .
+.RE
+.SS Macros
+Macros can take arguments.
+In a macro body,
+.BI $ n
+where
+.I n
+is between 1 and 9,
+will be replaced by the
+.IR n-th
+argument if the macro is called with arguments;
+if there are fewer than
+.I n
+arguments, it will be replaced by nothing.
+A word containing a left parenthesis where the part of the word
+before the left parenthesis has been defined using the
+.B define
+command
+will be recognized as a macro call with arguments;
+characters following the left parenthesis
+up to a matching right parenthesis will be treated as comma-separated
+arguments;
+commas inside nested parentheses do not terminate an argument.
+.TP
+.BI sdefine\ name\ X\ anything\ X
+This is like the
+.B define
+command, but
+.I name
+will not be recognized if called with arguments.
+.TP
+.BI include\ \(ts file \(ts
+Include the contents of
+.IR file .
+Lines of
+.I file
+beginning with
+.B .EQ
+or
+.B .EN
+will be ignored.
+.TP
+.BI ifdef\ name\ X\ anything\ X
+If
+.I name
+has been defined by
+.B define
+(or has been automatically defined because
+.I name
+is the output device)
+process
+.IR anything ;
+otherwise ignore
+.IR anything .
+.I X
+can be any character not appearing in
+.IR anything .
+.SS Fonts
+.B eqn
+normally uses at least two fonts to set an equation:
+an italic font for letters,
+and a roman font for everything else.
+The existing
+.B gfont
+command
+changes the font that is used as the italic font.
+By default this is
+.BR I .
+The font that is used as the roman font can be changed
+using the new
+.B grfont
+command.
+.TP
+.BI grfont\ f
+Set the roman font to
+.IR f .
+.LP
+The
+.B italic
+primitive uses the current italic font set by
+.BR gfont ;
+the
+.B roman
+primitive uses the current roman font set by
+.BR grfont .
+There is also a new
+.B gbfont
+command, which changes the font used by the
+.B bold
+primitive.
+If you only use the
+.BR roman ,
+.B italic
+and
+.B bold
+primitives to changes fonts within an equation,
+you can change all the fonts used by your equations
+just by using
+.BR gfont ,
+.B grfont
+and
+.B gbfont
+commands.
+.LP
+You can control which characters are treated as letters
+(and therefore set in italics) by using the
+.B chartype
+command described above.
+A type of
+.B letter
+will cause a character to be set in italic type.
+A type of
+.B digit
+will cause a character to be set in roman type.
+.SH FILES
+.Tp \w'\fB@MACRODIR@/eqnrc'u+2n
+.B @MACRODIR@/eqnrc
+Initialization file.
+.SH BUGS
+Inline equations will be set at the point size that is current at the
+beginning of the input line.
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@),
+.BR groff_font (@MAN5EXT@),
+.I The\ \*(txbook
diff --git a/src/preproc/eqn/eqn.tab.h b/src/preproc/eqn/eqn.tab.h
new file mode 100755
index 00000000..9a8b3cb2
--- /dev/null
+++ b/src/preproc/eqn/eqn.tab.h
@@ -0,0 +1,67 @@
+#define OVER 257
+#define SMALLOVER 258
+#define SQRT 259
+#define SUB 260
+#define SUP 261
+#define LPILE 262
+#define RPILE 263
+#define CPILE 264
+#define PILE 265
+#define LEFT 266
+#define RIGHT 267
+#define TO 268
+#define FROM 269
+#define SIZE 270
+#define FONT 271
+#define ROMAN 272
+#define BOLD 273
+#define ITALIC 274
+#define FAT 275
+#define ACCENT 276
+#define BAR 277
+#define UNDER 278
+#define ABOVE 279
+#define TEXT 280
+#define QUOTED_TEXT 281
+#define FWD 282
+#define BACK 283
+#define DOWN 284
+#define UP 285
+#define MATRIX 286
+#define COL 287
+#define LCOL 288
+#define RCOL 289
+#define CCOL 290
+#define MARK 291
+#define LINEUP 292
+#define TYPE 293
+#define VCENTER 294
+#define PRIME 295
+#define SPLIT 296
+#define NOSPLIT 297
+#define UACCENT 298
+#define SPECIAL 299
+#define SPACE 300
+#define GFONT 301
+#define GSIZE 302
+#define DEFINE 303
+#define NDEFINE 304
+#define TDEFINE 305
+#define SDEFINE 306
+#define UNDEF 307
+#define IFDEF 308
+#define INCLUDE 309
+#define DELIM 310
+#define CHARTYPE 311
+#define SET 312
+#define GRFONT 313
+#define GBFONT 314
+typedef union {
+ char *str;
+ box *b;
+ pile_box *pb;
+ matrix_box *mb;
+ int n;
+ column *col;
+} YYSTYPE;
+extern YYSTYPE yylval;
diff --git a/src/preproc/eqn/eqn.y b/src/preproc/eqn/eqn.y
new file mode 100644
index 00000000..833a0f01
--- /dev/null
+++ b/src/preproc/eqn/eqn.y
@@ -0,0 +1,331 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+%{
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "lib.h"
+#include "box.h"
+extern int non_empty_flag;
+char *strsave(const char *);
+int yylex();
+void yyerror(const char *);
+%}
+
+%union {
+ char *str;
+ box *b;
+ pile_box *pb;
+ matrix_box *mb;
+ int n;
+ column *col;
+}
+
+%token OVER
+%token SMALLOVER
+%token SQRT
+%token SUB
+%token SUP
+%token LPILE
+%token RPILE
+%token CPILE
+%token PILE
+%token LEFT
+%token RIGHT
+%token TO
+%token FROM
+%token SIZE
+%token FONT
+%token ROMAN
+%token BOLD
+%token ITALIC
+%token FAT
+%token ACCENT
+%token BAR
+%token UNDER
+%token ABOVE
+%token <str> TEXT
+%token <str> QUOTED_TEXT
+%token FWD
+%token BACK
+%token DOWN
+%token UP
+%token MATRIX
+%token COL
+%token LCOL
+%token RCOL
+%token CCOL
+%token MARK
+%token LINEUP
+%token TYPE
+%token VCENTER
+%token PRIME
+%token SPLIT
+%token NOSPLIT
+%token UACCENT
+%token SPECIAL
+
+/* these are handled in the lexer */
+%token SPACE
+%token GFONT
+%token GSIZE
+%token DEFINE
+%token NDEFINE
+%token TDEFINE
+%token SDEFINE
+%token UNDEF
+%token IFDEF
+%token INCLUDE
+%token DELIM
+%token CHARTYPE
+%token SET
+%token GRFONT
+%token GBFONT
+
+/* The original eqn manual says that `left' is right associative. It's lying.
+Consider `left ( ~ left ( ~ right ) right )'. */
+
+%right LEFT
+%left RIGHT
+%right LPILE RPILE CPILE PILE TEXT QUOTED_TEXT MATRIX MARK LINEUP '^' '~' '\t' '{' SPLIT NOSPLIT
+%right FROM TO
+%left SQRT OVER SMALLOVER
+%right SUB SUP
+%right ROMAN BOLD ITALIC FAT FONT SIZE FWD BACK DOWN UP TYPE VCENTER SPECIAL
+%right BAR UNDER PRIME
+%left ACCENT UACCENT
+
+%type <b> mark from_to sqrt_over script simple equation nonsup
+%type <n> number
+%type <str> text delim
+%type <pb> pile_element_list pile_arg
+%type <mb> column_list
+%type <col> column column_arg column_element_list
+
+%%
+top:
+ /* empty */
+ | equation
+ { $1->top_level(); non_empty_flag = 1; }
+ ;
+
+equation:
+ mark
+ { $$ = $1; }
+ | equation mark
+ {
+ list_box *lb = $1->to_list_box();
+ if (!lb)
+ lb = new list_box($1);
+ lb->append($2);
+ $$ = lb;
+ }
+ ;
+
+mark:
+ from_to
+ { $$ = $1; }
+ | MARK mark
+ { $$ = make_mark_box($2); }
+ | LINEUP mark
+ { $$ = make_lineup_box($2); }
+ ;
+
+from_to:
+ sqrt_over %prec FROM
+ { $$ = $1; }
+ | sqrt_over TO from_to
+ { $$ = make_limit_box($1, 0, $3); }
+ | sqrt_over FROM sqrt_over
+ { $$ = make_limit_box($1, $3, 0); }
+ | sqrt_over FROM sqrt_over TO from_to
+ { $$ = make_limit_box($1, $3, $5); }
+ | sqrt_over FROM sqrt_over FROM from_to
+ { $$ = make_limit_box($1, make_limit_box($3, $5, 0), 0); }
+ ;
+
+sqrt_over:
+ script
+ { $$ = $1; }
+ | SQRT sqrt_over
+ { $$ = make_sqrt_box($2); }
+ | sqrt_over OVER sqrt_over
+ { $$ = make_over_box($1, $3); }
+ | sqrt_over SMALLOVER sqrt_over
+ { $$ = make_small_over_box($1, $3); }
+ ;
+
+script:
+ nonsup
+ { $$ = $1; }
+ | simple SUP script
+ { $$ = make_script_box($1, 0, $3); }
+ ;
+
+nonsup:
+ simple %prec SUP
+ { $$ = $1; }
+ | simple SUB nonsup
+ { $$ = make_script_box($1, $3, 0); }
+ | simple SUB simple SUP script
+ { $$ = make_script_box($1, $3, $5); }
+ ;
+
+simple:
+ TEXT
+ { $$ = split_text($1); }
+ | QUOTED_TEXT
+ { $$ = new quoted_text_box($1); }
+ | SPLIT QUOTED_TEXT
+ { $$ = split_text($2); }
+ | NOSPLIT TEXT
+ { $$ = new quoted_text_box($2); }
+ | '^'
+ { $$ = new half_space_box; }
+ | '~'
+ { $$ = new space_box; }
+ | '\t'
+ { $$ = new tab_box; }
+ | '{' equation '}'
+ { $$ = $2; }
+ | PILE pile_arg
+ { $2->set_alignment(CENTER_ALIGN); $$ = $2; }
+ | LPILE pile_arg
+ { $2->set_alignment(LEFT_ALIGN); $$ = $2; }
+ | RPILE pile_arg
+ { $2->set_alignment(RIGHT_ALIGN); $$ = $2; }
+ | CPILE pile_arg
+ { $2->set_alignment(CENTER_ALIGN); $$ = $2; }
+ | MATRIX '{' column_list '}'
+ { $$ = $3; }
+ | LEFT delim equation RIGHT delim
+ { $$ = make_delim_box($2, $3, $5); }
+ | LEFT delim equation
+ { $$ = make_delim_box($2, $3, 0); }
+ | simple BAR
+ { $$ = make_overline_box($1); }
+ | simple UNDER
+ { $$ = make_underline_box($1); }
+ | simple PRIME
+ { $$ = make_prime_box($1); }
+ | simple ACCENT simple
+ { $$ = make_accent_box($1, $3); }
+ | simple UACCENT simple
+ { $$ = make_uaccent_box($1, $3); }
+ | ROMAN simple
+ { $$ = new font_box(strsave(get_grfont()), $2); }
+ | BOLD simple
+ { $$ = new font_box(strsave(get_gbfont()), $2); }
+ | ITALIC simple
+ { $$ = new font_box(strsave(get_gfont()), $2); }
+ | FAT simple
+ { $$ = new fat_box($2); }
+ | FONT text simple
+ { $$ = new font_box($2, $3); }
+ | SIZE text simple
+ { $$ = new size_box($2, $3); }
+ | FWD number simple
+ { $$ = new hmotion_box($2, $3); }
+ | BACK number simple
+ { $$ = new hmotion_box(-$2, $3); }
+ | UP number simple
+ { $$ = new vmotion_box($2, $3); }
+ | DOWN number simple
+ { $$ = new vmotion_box(-$2, $3); }
+ | TYPE text simple
+ { $3->set_spacing_type($2); $$ = $3; }
+ | VCENTER simple
+ { $$ = new vcenter_box($2); }
+ | SPECIAL text simple
+ { $$ = make_special_box($2, $3); }
+ ;
+
+number:
+ text
+ {
+ int n;
+ if (sscanf($1, "%d", &n) == 1)
+ $$ = n;
+ a_delete $1;
+ }
+ ;
+
+pile_element_list:
+ equation
+ { $$ = new pile_box($1); }
+ | pile_element_list ABOVE equation
+ { $1->append($3); $$ = $1; }
+ ;
+
+pile_arg:
+ '{' pile_element_list '}'
+ { $$ = $2; }
+ | number '{' pile_element_list '}'
+ { $3->set_space($1); $$ = $3; }
+ ;
+
+column_list:
+ column
+ { $$ = new matrix_box($1); }
+ | column_list column
+ { $1->append($2); $$ = $1; }
+ ;
+
+column_element_list:
+ equation
+ { $$ = new column($1); }
+ | column_element_list ABOVE equation
+ { $1->append($3); $$ = $1; }
+ ;
+
+column_arg:
+ '{' column_element_list '}'
+ { $$ = $2; }
+ | number '{' column_element_list '}'
+ { $3->set_space($1); $$ = $3; }
+ ;
+
+column:
+ COL column_arg
+ { $2->set_alignment(CENTER_ALIGN); $$ = $2; }
+ | LCOL column_arg
+ { $2->set_alignment(LEFT_ALIGN); $$ = $2; }
+ | RCOL column_arg
+ { $2->set_alignment(RIGHT_ALIGN); $$ = $2; }
+ | CCOL column_arg
+ { $2->set_alignment(CENTER_ALIGN); $$ = $2; }
+ ;
+
+text: TEXT
+ { $$ = $1; }
+ | QUOTED_TEXT
+ { $$ = $1; }
+ ;
+
+delim:
+ text
+ { $$ = $1; }
+ | '{'
+ { $$ = strsave("{"); }
+ | '}'
+ { $$ = strsave("}"); }
+ ;
+
+%%
diff --git a/src/preproc/eqn/lex.cc b/src/preproc/eqn/lex.cc
new file mode 100644
index 00000000..a46d20cd
--- /dev/null
+++ b/src/preproc/eqn/lex.cc
@@ -0,0 +1,1165 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "eqn.h"
+#include "eqn.tab.h"
+#include "stringclass.h"
+#include "ptable.h"
+
+struct definition {
+ char is_macro;
+ char is_simple;
+ union {
+ int tok;
+ char *contents;
+ };
+ definition();
+ ~definition();
+};
+
+definition::definition() : is_macro(1), is_simple(0)
+{
+ contents = 0;
+}
+
+definition::~definition()
+{
+ if (is_macro)
+ a_delete contents;
+}
+
+declare_ptable(definition)
+implement_ptable(definition)
+
+PTABLE(definition) macro_table;
+
+static struct {
+ const char *name;
+ int token;
+} token_table[] = {
+ { "over", OVER },
+ { "smallover", SMALLOVER },
+ { "sqrt", SQRT },
+ { "sub", SUB },
+ { "sup", SUP },
+ { "lpile", LPILE },
+ { "rpile", RPILE },
+ { "cpile", CPILE },
+ { "pile", PILE },
+ { "left", LEFT },
+ { "right", RIGHT },
+ { "to", TO },
+ { "from", FROM },
+ { "size", SIZE },
+ { "font", FONT },
+ { "roman", ROMAN },
+ { "bold", BOLD },
+ { "italic", ITALIC },
+ { "fat", FAT },
+ { "bar", BAR },
+ { "under", UNDER },
+ { "accent", ACCENT },
+ { "uaccent", UACCENT },
+ { "above", ABOVE },
+ { "fwd", FWD },
+ { "back", BACK },
+ { "down", DOWN },
+ { "up", UP },
+ { "matrix", MATRIX },
+ { "col", COL },
+ { "lcol", LCOL },
+ { "rcol", RCOL },
+ { "ccol", CCOL },
+ { "mark", MARK },
+ { "lineup", LINEUP },
+ { "space", SPACE },
+ { "gfont", GFONT },
+ { "gsize", GSIZE },
+ { "define", DEFINE },
+ { "sdefine", SDEFINE },
+ { "ndefine", NDEFINE },
+ { "tdefine", TDEFINE },
+ { "undef", UNDEF },
+ { "ifdef", IFDEF },
+ { "include", INCLUDE },
+ { "copy", INCLUDE },
+ { "delim", DELIM },
+ { "chartype", CHARTYPE },
+ { "type", TYPE },
+ { "vcenter", VCENTER },
+ { "set", SET },
+ { "opprime", PRIME },
+ { "grfont", GRFONT },
+ { "gbfont", GBFONT },
+ { "split", SPLIT },
+ { "nosplit", NOSPLIT },
+ { "special", SPECIAL },
+};
+
+static struct {
+ const char *name;
+ const char *def;
+} def_table[] = {
+ { "ALPHA", "\\(*A" },
+ { "BETA", "\\(*B" },
+ { "CHI", "\\(*X" },
+ { "DELTA", "\\(*D" },
+ { "EPSILON", "\\(*E" },
+ { "ETA", "\\(*Y" },
+ { "GAMMA", "\\(*G" },
+ { "IOTA", "\\(*I" },
+ { "KAPPA", "\\(*K" },
+ { "LAMBDA", "\\(*L" },
+ { "MU", "\\(*M" },
+ { "NU", "\\(*N" },
+ { "OMEGA", "\\(*W" },
+ { "OMICRON", "\\(*O" },
+ { "PHI", "\\(*F" },
+ { "PI", "\\(*P" },
+ { "PSI", "\\(*Q" },
+ { "RHO", "\\(*R" },
+ { "SIGMA", "\\(*S" },
+ { "TAU", "\\(*T" },
+ { "THETA", "\\(*H" },
+ { "UPSILON", "\\(*U" },
+ { "XI", "\\(*C" },
+ { "ZETA", "\\(*Z" },
+ { "Alpha", "\\(*A" },
+ { "Beta", "\\(*B" },
+ { "Chi", "\\(*X" },
+ { "Delta", "\\(*D" },
+ { "Epsilon", "\\(*E" },
+ { "Eta", "\\(*Y" },
+ { "Gamma", "\\(*G" },
+ { "Iota", "\\(*I" },
+ { "Kappa", "\\(*K" },
+ { "Lambda", "\\(*L" },
+ { "Mu", "\\(*M" },
+ { "Nu", "\\(*N" },
+ { "Omega", "\\(*W" },
+ { "Omicron", "\\(*O" },
+ { "Phi", "\\(*F" },
+ { "Pi", "\\(*P" },
+ { "Psi", "\\(*Q" },
+ { "Rho", "\\(*R" },
+ { "Sigma", "\\(*S" },
+ { "Tau", "\\(*T" },
+ { "Theta", "\\(*H" },
+ { "Upsilon", "\\(*U" },
+ { "Xi", "\\(*C" },
+ { "Zeta", "\\(*Z" },
+ { "alpha", "\\(*a" },
+ { "beta", "\\(*b" },
+ { "chi", "\\(*x" },
+ { "delta", "\\(*d" },
+ { "epsilon", "\\(*e" },
+ { "eta", "\\(*y" },
+ { "gamma", "\\(*g" },
+ { "iota", "\\(*i" },
+ { "kappa", "\\(*k" },
+ { "lambda", "\\(*l" },
+ { "mu", "\\(*m" },
+ { "nu", "\\(*n" },
+ { "omega", "\\(*w" },
+ { "omicron", "\\(*o" },
+ { "phi", "\\(*f" },
+ { "pi", "\\(*p" },
+ { "psi", "\\(*q" },
+ { "rho", "\\(*r" },
+ { "sigma", "\\(*s" },
+ { "tau", "\\(*t" },
+ { "theta", "\\(*h" },
+ { "upsilon", "\\(*u" },
+ { "xi", "\\(*c" },
+ { "zeta", "\\(*z" },
+ { "max", "{type \"operator\" roman \"max\"}" },
+ { "min", "{type \"operator\" roman \"min\"}" },
+ { "lim", "{type \"operator\" roman \"lim\"}" },
+ { "sin", "{type \"operator\" roman \"sin\"}" },
+ { "cos", "{type \"operator\" roman \"cos\"}" },
+ { "tan", "{type \"operator\" roman \"tan\"}" },
+ { "sinh", "{type \"operator\" roman \"sinh\"}" },
+ { "cosh", "{type \"operator\" roman \"cosh\"}" },
+ { "tanh", "{type \"operator\" roman \"tanh\"}" },
+ { "arc", "{type \"operator\" roman \"arc\"}" },
+ { "log", "{type \"operator\" roman \"log\"}" },
+ { "ln", "{type \"operator\" roman \"ln\"}" },
+ { "exp", "{type \"operator\" roman \"exp\"}" },
+ { "Re", "{type \"operator\" roman \"Re\"}" },
+ { "Im", "{type \"operator\" roman \"Im\"}" },
+ { "det", "{type \"operator\" roman \"det\"}" },
+ { "and", "{roman \"and\"}" },
+ { "if", "{roman \"if\"}" },
+ { "for", "{roman \"for\"}" },
+ { "sum", "{type \"operator\" vcenter size +5 \\(*S}" },
+ { "prod", "{type \"operator\" vcenter size +5 \\(*P}" },
+ { "int", "{type \"operator\" vcenter size +8 \\(is}" },
+ { "union", "{type \"operator\" vcenter size +5 \\(cu}" },
+ { "inter", "{type \"operator\" vcenter size +5 \\(ca}" },
+ { "times", "type \"binary\" \\(mu" },
+ { "ldots", "type \"inner\" { . . . }" },
+ { "inf", "\\(if" },
+ { "partial", "\\(pd" },
+ { "nothing", "\"\"" },
+ { "half", "{1 smallover 2}" },
+ { "hat_def", "roman \"^\"" },
+ { "hat", "accent { hat_def }" },
+ { "dot_def", "back 15 \"\\v'-52M'.\\v'52M'\"" },
+ { "dot", "accent { dot_def }" },
+ { "dotdot_def", "back 25 \"\\v'-52M'..\\v'52M'\"" },
+ { "dotdot", "accent { dotdot_def }" },
+ { "tilde_def", "\"~\"" },
+ { "tilde", "accent { tilde_def }" },
+ { "utilde_def", "\"\\v'75M'~\\v'-75M'\"" },
+ { "utilde", "uaccent { utilde_def }" },
+ { "vec_def", "up 52 size -5 \\(->" },
+ { "vec", "accent { vec_def }" },
+ { "dyad_def", "up 52 size -5 {\\(<- back 60 \\(->}" },
+ { "dyad", "accent { dyad_def }" },
+ { "==", "type \"relation\" \\(==" },
+ { "!=", "type \"relation\" \\(!=" },
+ { "+-", "type \"binary\" \\(+-" },
+ { "->", "type \"relation\" \\(->" },
+ { "<-", "type \"relation\" \\(<-" },
+ { "<<", "{ < back 20 < }" },
+ { ">>", "{ > back 20 > }" },
+ { "...", "type \"inner\" vcenter { . . . }" },
+ { "prime", "'" },
+ { "approx", "type \"relation\" \"\\(~=\"" },
+ { "grad", "\\(gr" },
+ { "del", "\\(gr" },
+ { "cdot", "type \"binary\" vcenter ." },
+ { "dollar", "$" },
+};
+
+void init_table(const char *device)
+{
+ int i;
+ for (i = 0; i < sizeof(token_table)/sizeof(token_table[0]); i++) {
+ definition *def = new definition;
+ def->is_macro = 0;
+ def->tok = token_table[i].token;
+ macro_table.define(token_table[i].name, def);
+ }
+ for (i = 0; i < sizeof(def_table)/sizeof(def_table[0]); i++) {
+ definition *def = new definition;
+ def->is_macro = 1;
+ def->contents = strsave(def_table[i].def);
+ def->is_simple = 1;
+ macro_table.define(def_table[i].name, def);
+ }
+ definition *def = new definition;
+ def->is_macro = 1;
+ def->contents = strsave("1");
+ macro_table.define(device, def);
+}
+
+class input {
+ input *next;
+public:
+ input(input *p);
+ virtual ~input();
+ virtual int get() = 0;
+ virtual int peek() = 0;
+ virtual int get_location(char **, int *);
+
+ friend int get_char();
+ friend int peek_char();
+ friend int get_location(char **, int *);
+ friend void init_lex(const char *str, const char *filename, int lineno);
+};
+
+class file_input : public input {
+ FILE *fp;
+ char *filename;
+ int lineno;
+ string line;
+ const char *ptr;
+ int read_line();
+public:
+ file_input(FILE *, const char *, input *);
+ ~file_input();
+ int get();
+ int peek();
+ int get_location(char **, int *);
+};
+
+
+class macro_input : public input {
+ char *s;
+ char *p;
+public:
+ macro_input(const char *, input *);
+ ~macro_input();
+ int get();
+ int peek();
+};
+
+class top_input : public macro_input {
+ char *filename;
+ int lineno;
+ public:
+ top_input(const char *, const char *, int, input *);
+ ~top_input();
+ int get();
+ int get_location(char **, int *);
+};
+
+class argument_macro_input: public input {
+ char *s;
+ char *p;
+ char *ap;
+ int argc;
+ char *argv[9];
+public:
+ argument_macro_input(const char *, int, char **, input *);
+ ~argument_macro_input();
+ int get();
+ int peek();
+};
+
+input::input(input *x) : next(x)
+{
+}
+
+input::~input()
+{
+}
+
+int input::get_location(char **, int *)
+{
+ return 0;
+}
+
+file_input::file_input(FILE *f, const char *fn, input *p)
+: input(p), lineno(0), ptr("")
+{
+ fp = f;
+ filename = strsave(fn);
+}
+
+file_input::~file_input()
+{
+ a_delete filename;
+ fclose(fp);
+}
+
+int file_input::read_line()
+{
+ for (;;) {
+ line.clear();
+ lineno++;
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ else if (illegal_input_char(c))
+ lex_error("illegal input character code %1", c);
+ else {
+ line += char(c);
+ if (c == '\n')
+ break;
+ }
+ }
+ if (line.length() == 0)
+ return 0;
+ if (!(line.length() >= 3 && line[0] == '.' && line[1] == 'E'
+ && (line[2] == 'Q' || line[2] == 'N')
+ && (line.length() == 3 || line[3] == ' ' || line[3] == '\n'
+ || compatible_flag))) {
+ line += '\0';
+ ptr = line.contents();
+ return 1;
+ }
+ }
+}
+
+int file_input::get()
+{
+ if (*ptr != '\0' || read_line())
+ return *ptr++ & 0377;
+ else
+ return EOF;
+}
+
+int file_input::peek()
+{
+ if (*ptr != '\0' || read_line())
+ return *ptr;
+ else
+ return EOF;
+}
+
+int file_input::get_location(char **fnp, int *lnp)
+{
+ *fnp = filename;
+ *lnp = lineno;
+ return 1;
+}
+
+macro_input::macro_input(const char *str, input *x) : input(x)
+{
+ p = s = strsave(str);
+}
+
+macro_input::~macro_input()
+{
+ a_delete s;
+}
+
+int macro_input::get()
+{
+ if (p == 0 || *p == '\0')
+ return EOF;
+ else
+ return *p++ & 0377;
+}
+
+int macro_input::peek()
+{
+ if (p == 0 || *p == '\0')
+ return EOF;
+ else
+ return *p & 0377;
+}
+
+top_input::top_input(const char *str, const char *fn, int ln, input *x)
+: macro_input(str, x), lineno(ln)
+{
+ filename = strsave(fn);
+}
+
+top_input::~top_input()
+{
+ a_delete filename;
+}
+
+int top_input::get()
+{
+ int c = macro_input::get();
+ if (c == '\n')
+ lineno++;
+ return c;
+}
+
+int top_input::get_location(char **fnp, int *lnp)
+{
+ *fnp = filename;
+ *lnp = lineno;
+ return 1;
+}
+
+// Character representing $1. Must be illegal input character.
+#define ARG1 14
+
+argument_macro_input::argument_macro_input(const char *body, int ac,
+ char **av, input *x)
+: input(x), ap(0), argc(ac)
+{
+ int i;
+ for (i = 0; i < argc; i++)
+ argv[i] = av[i];
+ p = s = strsave(body);
+ int j = 0;
+ for (i = 0; s[i] != '\0'; i++)
+ if (s[i] == '$' && s[i+1] >= '0' && s[i+1] <= '9') {
+ if (s[i+1] != '0')
+ s[j++] = ARG1 + s[++i] - '1';
+ }
+ else
+ s[j++] = s[i];
+ s[j] = '\0';
+}
+
+
+argument_macro_input::~argument_macro_input()
+{
+ for (int i = 0; i < argc; i++)
+ a_delete argv[i];
+ a_delete s;
+}
+
+int argument_macro_input::get()
+{
+ if (ap) {
+ if (*ap != '\0')
+ return *ap++ & 0377;
+ ap = 0;
+ }
+ if (p == 0)
+ return EOF;
+ while (*p >= ARG1 && *p <= ARG1 + 8) {
+ int i = *p++ - ARG1;
+ if (i < argc && argv[i] != 0 && argv[i][0] != '\0') {
+ ap = argv[i];
+ return *ap++ & 0377;
+ }
+ }
+ if (*p == '\0')
+ return EOF;
+ return *p++ & 0377;
+}
+
+int argument_macro_input::peek()
+{
+ if (ap) {
+ if (*ap != '\0')
+ return *ap & 0377;
+ ap = 0;
+ }
+ if (p == 0)
+ return EOF;
+ while (*p >= ARG1 && *p <= ARG1 + 8) {
+ int i = *p++ - ARG1;
+ if (i < argc && argv[i] != 0 && argv[i][0] != '\0') {
+ ap = argv[i];
+ return *ap & 0377;
+ }
+ }
+ if (*p == '\0')
+ return EOF;
+ return *p & 0377;
+}
+
+static input *current_input = 0;
+
+/* we insert a newline between input from different levels */
+
+int get_char()
+{
+ if (current_input == 0)
+ return EOF;
+ else {
+ int c = current_input->get();
+ if (c != EOF)
+ return c;
+ else {
+ input *tem = current_input;
+ current_input = current_input->next;
+ delete tem;
+ return '\n';
+ }
+ }
+}
+
+int peek_char()
+{
+ if (current_input == 0)
+ return EOF;
+ else {
+ int c = current_input->peek();
+ if (c != EOF)
+ return c;
+ else
+ return '\n';
+ }
+}
+
+int get_location(char **fnp, int *lnp)
+{
+ for (input *p = current_input; p; p = p->next)
+ if (p->get_location(fnp, lnp))
+ return 1;
+ return 0;
+}
+
+string token_buffer;
+const int NCONTEXT = 4;
+string context_ring[NCONTEXT];
+int context_index = 0;
+
+void flush_context()
+{
+ for (int i = 0; i < NCONTEXT; i++)
+ context_ring[i] = "";
+ context_index = 0;
+}
+
+void show_context()
+{
+ int i = context_index;
+ fputs(" context is\n\t", stderr);
+ for (;;) {
+ int j = (i + 1) % NCONTEXT;
+ if (j == context_index) {
+ fputs(">>> ", stderr);
+ put_string(context_ring[i], stderr);
+ fputs(" <<<", stderr);
+ break;
+ }
+ else if (context_ring[i].length() > 0) {
+ put_string(context_ring[i], stderr);
+ putc(' ', stderr);
+ }
+ i = j;
+ }
+ putc('\n', stderr);
+}
+
+void add_context(const string &s)
+{
+ context_ring[context_index] = s;
+ context_index = (context_index + 1) % NCONTEXT;
+}
+
+void add_context(char c)
+{
+ context_ring[context_index] = c;
+ context_index = (context_index + 1) % NCONTEXT;
+}
+
+void add_quoted_context(const string &s)
+{
+ string &r = context_ring[context_index];
+ r = '"';
+ for (int i = 0; i < s.length(); i++)
+ if (s[i] == '"')
+ r += "\\\"";
+ else
+ r += s[i];
+ r += '"';
+ context_index = (context_index + 1) % NCONTEXT;
+}
+
+void init_lex(const char *str, const char *filename, int lineno)
+{
+ while (current_input != 0) {
+ input *tem = current_input;
+ current_input = current_input->next;
+ delete tem;
+ }
+ current_input = new top_input(str, filename, lineno, 0);
+ flush_context();
+}
+
+
+void get_delimited_text()
+{
+ char *filename;
+ int lineno;
+ int got_location = get_location(&filename, &lineno);
+ int start = get_char();
+ while (start == ' ' || start == '\t' || start == '\n')
+ start = get_char();
+ token_buffer.clear();
+ if (start == EOF) {
+ if (got_location)
+ error_with_file_and_line(filename, lineno,
+ "end of input while defining macro");
+ else
+ error("end of input while defining macro");
+ return;
+ }
+ for (;;) {
+ int c = get_char();
+ if (c == EOF) {
+ if (got_location)
+ error_with_file_and_line(filename, lineno,
+ "end of input while defining macro");
+ else
+ error("end of input while defining macro");
+ add_context(start + token_buffer);
+ return;
+ }
+ if (c == start)
+ break;
+ token_buffer += char(c);
+ }
+ add_context(start + token_buffer + start);
+}
+
+void interpolate_macro_with_args(const char *body)
+{
+ char *argv[9];
+ int argc = 0;
+ int i;
+ for (i = 0; i < 9; i++)
+ argv[i] = 0;
+ int level = 0;
+ int c;
+ do {
+ token_buffer.clear();
+ for (;;) {
+ c = get_char();
+ if (c == EOF) {
+ lex_error("end of input while scanning macro arguments");
+ break;
+ }
+ if (level == 0 && (c == ',' || c == ')')) {
+ if (token_buffer.length() > 0) {
+ token_buffer += '\0';
+ argv[argc] = strsave(token_buffer.contents());
+ }
+ // for `foo()', argc = 0
+ if (argc > 0 || c != ')' || i > 0)
+ argc++;
+ break;
+ }
+ token_buffer += char(c);
+ if (c == '(')
+ level++;
+ else if (c == ')')
+ level--;
+ }
+ } while (c != ')' && c != EOF);
+ current_input = new argument_macro_input(body, argc, argv, current_input);
+}
+
+/* If lookup flag is non-zero the token will be looked up to see
+if it is macro. If it's 1, it will looked up to see if it's a token.
+*/
+
+int get_token(int lookup_flag = 0)
+{
+ for (;;) {
+ int c = get_char();
+ while (c == ' ' || c == '\n')
+ c = get_char();
+ switch (c) {
+ case EOF:
+ {
+ add_context("end of input");
+ }
+ return 0;
+ case '"':
+ {
+ int quoted = 0;
+ token_buffer.clear();
+ for (;;) {
+ c = get_char();
+ if (c == EOF) {
+ lex_error("missing \"");
+ break;
+ }
+ else if (c == '\n') {
+ lex_error("newline before end of quoted text");
+ break;
+ }
+ else if (c == '"') {
+ if (!quoted)
+ break;
+ token_buffer[token_buffer.length() - 1] = '"';
+ quoted = 0;
+ }
+ else {
+ token_buffer += c;
+ quoted = quoted ? 0 : c == '\\';
+ }
+ }
+ }
+ add_quoted_context(token_buffer);
+ return QUOTED_TEXT;
+ case '{':
+ case '}':
+ case '^':
+ case '~':
+ case '\t':
+ add_context(c);
+ return c;
+ default:
+ {
+ int break_flag = 0;
+ int quoted = 0;
+ token_buffer.clear();
+ if (c == '\\')
+ quoted = 1;
+ else
+ token_buffer += c;
+ int done = 0;
+ while (!done) {
+ c = peek_char();
+ if (!quoted && lookup_flag != 0 && c == '(') {
+ token_buffer += '\0';
+ definition *def = macro_table.lookup(token_buffer.contents());
+ if (def && def->is_macro && !def->is_simple) {
+ (void)get_char(); // skip initial '('
+ interpolate_macro_with_args(def->contents);
+ break_flag = 1;
+ break;
+ }
+ token_buffer.set_length(token_buffer.length() - 1);
+ }
+ if (quoted) {
+ quoted = 0;
+ switch (c) {
+ case EOF:
+ lex_error("`\\' ignored at end of equation");
+ done = 1;
+ break;
+ case '\n':
+ lex_error("`\\' ignored because followed by newline");
+ done = 1;
+ break;
+ case '\t':
+ lex_error("`\\' ignored because followed by tab");
+ done = 1;
+ break;
+ case '"':
+ (void)get_char();
+ token_buffer += '"';
+ break;
+ default:
+ (void)get_char();
+ token_buffer += '\\';
+ token_buffer += c;
+ break;
+ }
+ }
+ else {
+ switch (c) {
+ case EOF:
+ case '{':
+ case '}':
+ case '^':
+ case '~':
+ case '"':
+ case ' ':
+ case '\t':
+ case '\n':
+ done = 1;
+ break;
+ case '\\':
+ (void)get_char();
+ quoted = 1;
+ break;
+ default:
+ (void)get_char();
+ token_buffer += char(c);
+ break;
+ }
+ }
+ }
+ if (break_flag || token_buffer.length() == 0)
+ break;
+ if (lookup_flag != 0) {
+ token_buffer += '\0';
+ definition *def = macro_table.lookup(token_buffer.contents());
+ token_buffer.set_length(token_buffer.length() - 1);
+ if (def) {
+ if (def->is_macro) {
+ current_input = new macro_input(def->contents, current_input);
+ break;
+ }
+ else if (lookup_flag == 1) {
+ add_context(token_buffer);
+ return def->tok;
+ }
+ }
+ }
+ add_context(token_buffer);
+ return TEXT;
+ }
+ }
+ }
+}
+
+void do_include()
+{
+ int t = get_token(2);
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad filename for include");
+ return;
+ }
+ token_buffer += '\0';
+ const char *filename = token_buffer.contents();
+ errno = 0;
+ FILE *fp = fopen(filename, "r");
+ if (fp == 0) {
+ lex_error("can't open included file `%1'", filename);
+ return;
+ }
+ current_input = new file_input(fp, filename, current_input);
+}
+
+void ignore_definition()
+{
+ int t = get_token();
+ if (t != TEXT) {
+ lex_error("bad definition");
+ return;
+ }
+ get_delimited_text();
+}
+
+void do_definition(int is_simple)
+{
+ int t = get_token();
+ if (t != TEXT) {
+ lex_error("bad definition");
+ return;
+ }
+ token_buffer += '\0';
+ const char *name = token_buffer.contents();
+ definition *def = macro_table.lookup(name);
+ if (def == 0) {
+ def = new definition;
+ macro_table.define(name, def);
+ }
+ else if (def->is_macro) {
+ a_delete def->contents;
+ }
+ get_delimited_text();
+ token_buffer += '\0';
+ def->is_macro = 1;
+ def->contents = strsave(token_buffer.contents());
+ def->is_simple = is_simple;
+}
+
+void do_undef()
+{
+ int t = get_token();
+ if (t != TEXT) {
+ lex_error("bad undef command");
+ return;
+ }
+ token_buffer += '\0';
+ macro_table.define(token_buffer.contents(), 0);
+}
+
+void do_gsize()
+{
+ int t = get_token(2);
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad argument to gsize command");
+ return;
+ }
+ token_buffer += '\0';
+ if (!set_gsize(token_buffer.contents()))
+ lex_error("invalid size `%1'", token_buffer.contents());
+}
+
+void do_gfont()
+{
+ int t = get_token(2);
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad argument to gfont command");
+ return;
+ }
+ token_buffer += '\0';
+ set_gfont(token_buffer.contents());
+}
+
+void do_grfont()
+{
+ int t = get_token(2);
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad argument to grfont command");
+ return;
+ }
+ token_buffer += '\0';
+ set_grfont(token_buffer.contents());
+}
+
+void do_gbfont()
+{
+ int t = get_token(2);
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad argument to gbfont command");
+ return;
+ }
+ token_buffer += '\0';
+ set_gbfont(token_buffer.contents());
+}
+
+void do_space()
+{
+ int t = get_token(2);
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad argument to space command");
+ return;
+ }
+ token_buffer += '\0';
+ char *ptr;
+ long n = strtol(token_buffer.contents(), &ptr, 10);
+ if (n == 0 && ptr == token_buffer.contents())
+ lex_error("bad argument `%1' to space command", token_buffer.contents());
+ else
+ set_space(int(n));
+}
+
+void do_ifdef()
+{
+ int t = get_token();
+ if (t != TEXT) {
+ lex_error("bad ifdef");
+ return;
+ }
+ token_buffer += '\0';
+ definition *def = macro_table.lookup(token_buffer.contents());
+ int result = def && def->is_macro && !def->is_simple;
+ get_delimited_text();
+ if (result) {
+ token_buffer += '\0';
+ current_input = new macro_input(token_buffer.contents(), current_input);
+ }
+}
+
+void do_delim()
+{
+ int c = get_char();
+ while (c == ' ' || c == '\n')
+ c = get_char();
+ int d;
+ if (c == EOF || (d = get_char()) == EOF)
+ lex_error("end of file while reading argument to `delim'");
+ else {
+ if (c == 'o' && d == 'f' && peek_char() == 'f') {
+ (void)get_char();
+ start_delim = end_delim = '\0';
+ }
+ else {
+ start_delim = c;
+ end_delim = d;
+ }
+ }
+}
+
+void do_chartype()
+{
+ int t = get_token(2);
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad chartype");
+ return;
+ }
+ token_buffer += '\0';
+ string type = token_buffer;
+ t = get_token();
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad chartype");
+ return;
+ }
+ token_buffer += '\0';
+ set_char_type(type.contents(), strsave(token_buffer.contents()));
+}
+
+void do_set()
+{
+ int t = get_token(2);
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad set");
+ return;
+ }
+ token_buffer += '\0';
+ string param = token_buffer;
+ t = get_token();
+ if (t != TEXT && t != QUOTED_TEXT) {
+ lex_error("bad set");
+ return;
+ }
+ token_buffer += '\0';
+ int n;
+ if (sscanf(&token_buffer[0], "%d", &n) != 1) {
+ lex_error("bad number `%1'", token_buffer.contents());
+ return;
+ }
+ set_param(param.contents(), n);
+}
+
+int yylex()
+{
+ for (;;) {
+ int tk = get_token(1);
+ switch(tk) {
+ case UNDEF:
+ do_undef();
+ break;
+ case SDEFINE:
+ do_definition(1);
+ break;
+ case DEFINE:
+ do_definition(0);
+ break;
+ case TDEFINE:
+ if (!nroff)
+ do_definition(0);
+ else
+ ignore_definition();
+ break;
+ case NDEFINE:
+ if (nroff)
+ do_definition(0);
+ else
+ ignore_definition();
+ break;
+ case GSIZE:
+ do_gsize();
+ break;
+ case GFONT:
+ do_gfont();
+ break;
+ case GRFONT:
+ do_grfont();
+ break;
+ case GBFONT:
+ do_gbfont();
+ break;
+ case SPACE:
+ do_space();
+ break;
+ case INCLUDE:
+ do_include();
+ break;
+ case IFDEF:
+ do_ifdef();
+ break;
+ case DELIM:
+ do_delim();
+ break;
+ case CHARTYPE:
+ do_chartype();
+ break;
+ case SET:
+ do_set();
+ break;
+ case QUOTED_TEXT:
+ case TEXT:
+ token_buffer += '\0';
+ yylval.str = strsave(token_buffer.contents());
+ // fall through
+ default:
+ return tk;
+ }
+ }
+}
+
+void lex_error(const char *message,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ char *filename;
+ int lineno;
+ if (!get_location(&filename, &lineno))
+ error(message, arg1, arg2, arg3);
+ else
+ error_with_file_and_line(filename, lineno, message, arg1, arg2, arg3);
+}
+
+void yyerror(const char *s)
+{
+ char *filename;
+ int lineno;
+ if (!get_location(&filename, &lineno))
+ error(s);
+ else
+ error_with_file_and_line(filename, lineno, s);
+ show_context();
+}
+
diff --git a/src/preproc/eqn/limit.cc b/src/preproc/eqn/limit.cc
new file mode 100644
index 00000000..046885d2
--- /dev/null
+++ b/src/preproc/eqn/limit.cc
@@ -0,0 +1,195 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+class limit_box : public box {
+private:
+ box *p;
+ box *from;
+ box *to;
+public:
+ limit_box(box *, box *, box *);
+ ~limit_box();
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+ void check_tabs(int);
+};
+
+box *make_limit_box(box *pp, box *qq, box *rr)
+{
+ return new limit_box(pp, qq, rr);
+}
+
+limit_box::limit_box(box *pp, box *qq, box *rr)
+: p(pp), from(qq), to(rr)
+{
+ spacing_type = p->spacing_type;
+}
+
+limit_box::~limit_box()
+{
+ delete p;
+ delete from;
+ delete to;
+}
+
+int limit_box::compute_metrics(int style)
+{
+ printf(".nr " SIZE_FORMAT " \\n[.s]\n", uid);
+ if (!(style <= SCRIPT_STYLE && one_size_reduction_flag))
+ set_script_size();
+ printf(".nr " SMALL_SIZE_FORMAT " \\n[.s]\n", uid);
+ int res = 0;
+ int mark_uid = -1;
+ if (from != 0) {
+ res = from->compute_metrics(cramped_style(script_style(style)));
+ if (res)
+ mark_uid = from->uid;
+ }
+ if (to != 0) {
+ int r = to->compute_metrics(script_style(style));
+ if (res && r)
+ error("multiple marks and lineups");
+ else {
+ mark_uid = to->uid;
+ res = r;
+ }
+ }
+ printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
+ int r = p->compute_metrics(style);
+ p->compute_subscript_kern();
+ if (res && r)
+ error("multiple marks and lineups");
+ else {
+ mark_uid = p->uid;
+ res = r;
+ }
+ printf(".nr " LEFT_WIDTH_FORMAT " "
+ "0\\n[" WIDTH_FORMAT "]",
+ uid, p->uid);
+ if (from != 0)
+ printf(">?(\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
+ p->uid, from->uid);
+ if (to != 0)
+ printf(">?(-\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
+ p->uid, to->uid);
+ printf("/2\n");
+ printf(".nr " WIDTH_FORMAT " "
+ "0\\n[" WIDTH_FORMAT "]",
+ uid, p->uid);
+ if (from != 0)
+ printf(">?(-\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
+ p->uid, from->uid);
+ if (to != 0)
+ printf(">?(\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
+ p->uid, to->uid);
+ printf("/2+\\n[" LEFT_WIDTH_FORMAT "]\n", uid);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid);
+ if (to != 0)
+ printf(">?\\n[" WIDTH_FORMAT "]", to->uid);
+ if (from != 0)
+ printf(">?\\n[" WIDTH_FORMAT "]", from->uid);
+ printf("\n");
+ if (res)
+ printf(".nr " MARK_REG " +(\\n[" LEFT_WIDTH_FORMAT "]"
+ "-(\\n[" WIDTH_FORMAT "]/2))\n",
+ uid, mark_uid);
+ if (to != 0) {
+ printf(".nr " SUP_RAISE_FORMAT " %dM+\\n[" DEPTH_FORMAT
+ "]>?%dM+\\n[" HEIGHT_FORMAT "]\n",
+ uid, big_op_spacing1, to->uid, big_op_spacing3, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
+ HEIGHT_FORMAT "]+%dM\n",
+ uid, uid, to->uid, big_op_spacing5);
+ }
+ else
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ if (from != 0) {
+ printf(".nr " SUB_LOWER_FORMAT " %dM+\\n[" HEIGHT_FORMAT
+ "]>?%dM+\\n[" DEPTH_FORMAT "]\n",
+ uid, big_op_spacing2, from->uid, big_op_spacing4, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n["
+ DEPTH_FORMAT "]+%dM\n",
+ uid, uid, from->uid, big_op_spacing5);
+ }
+ else
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ return res;
+}
+
+void limit_box::output()
+{
+ printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
+ if (to != 0) {
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
+ "+(-\\n[" WIDTH_FORMAT "]u+\\n[" SUB_KERN_FORMAT "]u/2u)'",
+ uid, to->uid, p->uid);
+ to->output();
+ printf(DELIMITER_CHAR);
+ }
+ if (from != 0) {
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
+ printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
+ "+(-\\n[" SUB_KERN_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
+ uid, p->uid, from->uid);
+ from->output();
+ printf(DELIMITER_CHAR);
+ }
+ printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
+ "-(\\n[" WIDTH_FORMAT "]u/2u)'",
+ uid, p->uid);
+ p->output();
+ printf(DELIMITER_CHAR);
+ printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
+}
+
+void limit_box::debug_print()
+{
+ fprintf(stderr, "{ ");
+ p->debug_print();
+ fprintf(stderr, " }");
+ if (from) {
+ fprintf(stderr, " from { ");
+ from->debug_print();
+ fprintf(stderr, " }");
+ }
+ if (to) {
+ fprintf(stderr, " to { ");
+ to->debug_print();
+ fprintf(stderr, " }");
+ }
+}
+
+void limit_box::check_tabs(int level)
+{
+ if (to)
+ to->check_tabs(level + 1);
+ if (from)
+ from->check_tabs(level + 1);
+ p->check_tabs(level + 1);
+}
diff --git a/src/preproc/eqn/list.cc b/src/preproc/eqn/list.cc
new file mode 100644
index 00000000..1118fa1b
--- /dev/null
+++ b/src/preproc/eqn/list.cc
@@ -0,0 +1,237 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+list_box *box::to_list_box()
+{
+ return 0;
+}
+
+list_box *list_box::to_list_box()
+{
+ return this;
+}
+
+void list_box::append(box *pp)
+{
+ list_box *q = pp->to_list_box();
+ if (q == 0)
+ list.append(pp);
+ else {
+ for (int i = 0; i < q->list.len; i++) {
+ list.append(q->list.p[i]);
+ q->list.p[i] = 0;
+ }
+ q->list.len = 0;
+ delete q;
+ }
+}
+
+list_box::list_box(box *pp) : list(pp), sty(-1)
+{
+ list_box *q = pp->to_list_box();
+ if (q != 0) {
+ // flatten it
+ list.p[0] = q->list.p[0];
+ for (int i = 1; i < q->list.len; i++) {
+ list.append(q->list.p[i]);
+ q->list.p[i] = 0;
+ }
+ q->list.len = 0;
+ delete q;
+ }
+}
+
+static int compute_spacing(int is_script, int left, int right)
+{
+ if (left == SUPPRESS_TYPE || right == SUPPRESS_TYPE)
+ return 0;
+ if (left == PUNCTUATION_TYPE)
+ return is_script ? 0 : thin_space;
+ if (left == OPENING_TYPE || right == CLOSING_TYPE)
+ return 0;
+ if (right == BINARY_TYPE || left == BINARY_TYPE)
+ return is_script ? 0 : medium_space;
+ if (right == RELATION_TYPE) {
+ if (left == RELATION_TYPE)
+ return 0;
+ else
+ return is_script ? 0 : thick_space;
+ }
+ if (left == RELATION_TYPE)
+ return is_script ? 0 : thick_space;
+ if (right == OPERATOR_TYPE)
+ return thin_space;
+ if (left == INNER_TYPE || right == INNER_TYPE)
+ return is_script ? 0 : thin_space;
+ if (left == OPERATOR_TYPE && right == ORDINARY_TYPE)
+ return thin_space;
+ return 0;
+}
+
+int list_box::compute_metrics(int style)
+{
+ sty = style;
+ int i;
+ for (i = 0; i < list.len; i++) {
+ int t = list.p[i]->spacing_type;
+ // 5
+ if (t == BINARY_TYPE) {
+ int prevt;
+ if (i == 0
+ || (prevt = list.p[i-1]->spacing_type) == BINARY_TYPE
+ || prevt == OPERATOR_TYPE
+ || prevt == RELATION_TYPE
+ || prevt == OPENING_TYPE
+ || prevt == PUNCTUATION_TYPE)
+ list.p[i]->spacing_type = ORDINARY_TYPE;
+ }
+ // 7
+ else if ((t == RELATION_TYPE || t == CLOSING_TYPE
+ || t == PUNCTUATION_TYPE)
+ && i > 0 && list.p[i-1]->spacing_type == BINARY_TYPE)
+ list.p[i-1]->spacing_type = ORDINARY_TYPE;
+ }
+ for (i = 0; i < list.len; i++) {
+ unsigned flags = 0;
+ if (i - 1 >= 0 && list.p[i - 1]->right_is_italic())
+ flags |= HINT_PREV_IS_ITALIC;
+ if (i + 1 < list.len && list.p[i + 1]->left_is_italic())
+ flags |= HINT_NEXT_IS_ITALIC;
+ if (flags)
+ list.p[i]->hint(flags);
+ }
+ is_script = (style <= SCRIPT_STYLE);
+ int total_spacing = 0;
+ for (i = 1; i < list.len; i++)
+ total_spacing += compute_spacing(is_script, list.p[i-1]->spacing_type,
+ list.p[i]->spacing_type);
+ int res = 0;
+ for (i = 0; i < list.len; i++)
+ if (!list.p[i]->is_simple()) {
+ int r = list.p[i]->compute_metrics(style);
+ if (r) {
+ if (res)
+ error("multiple marks and lineups");
+ else {
+ compute_sublist_width(i);
+ printf(".nr " MARK_REG " +\\n[" TEMP_REG"]\n");
+ res = r;
+ }
+ }
+ }
+ printf(".nr " WIDTH_FORMAT " %dM", uid, total_spacing);
+ for (i = 0; i < list.len; i++)
+ if (!list.p[i]->is_simple())
+ printf("+\\n[" WIDTH_FORMAT "]", list.p[i]->uid);
+ printf("\n");
+ printf(".nr " HEIGHT_FORMAT " 0", uid);
+ for (i = 0; i < list.len; i++)
+ if (!list.p[i]->is_simple())
+ printf(">?\\n[" HEIGHT_FORMAT "]", list.p[i]->uid);
+ printf("\n");
+ printf(".nr " DEPTH_FORMAT " 0", uid);
+ for (i = 0; i < list.len; i++)
+ if (!list.p[i]->is_simple())
+ printf(">?\\n[" DEPTH_FORMAT "]", list.p[i]->uid);
+ printf("\n");
+ int have_simple = 0;
+ for (i = 0; i < list.len && !have_simple; i++)
+ have_simple = list.p[i]->is_simple();
+ if (have_simple) {
+ printf(".nr " WIDTH_FORMAT " +\\w" DELIMITER_CHAR, uid);
+ for (i = 0; i < list.len; i++)
+ if (list.p[i]->is_simple())
+ list.p[i]->output();
+ printf(DELIMITER_CHAR "\n");
+ printf(".nr " HEIGHT_FORMAT " \\n[rst]>?\\n[" HEIGHT_FORMAT "]\n",
+ uid, uid);
+ printf(".nr " DEPTH_FORMAT " 0-\\n[rsb]>?\\n[" DEPTH_FORMAT "]\n",
+ uid, uid);
+ }
+ return res;
+}
+
+void list_box::compute_sublist_width(int n)
+{
+ int total_spacing = 0;
+ int i;
+ for (i = 1; i < n + 1 && i < list.len; i++)
+ total_spacing += compute_spacing(is_script, list.p[i-1]->spacing_type,
+ list.p[i]->spacing_type);
+ printf(".nr " TEMP_REG " %dM", total_spacing);
+ for (i = 0; i < n; i++)
+ if (!list.p[i]->is_simple())
+ printf("+\\n[" WIDTH_FORMAT "]", list.p[i]->uid);
+ int have_simple = 0;
+ for (i = 0; i < n && !have_simple; i++)
+ have_simple = list.p[i]->is_simple();
+ if (have_simple) {
+ printf("+\\w" DELIMITER_CHAR);
+ for (i = 0; i < n; i++)
+ if (list.p[i]->is_simple())
+ list.p[i]->output();
+ printf(DELIMITER_CHAR);
+ }
+ printf("\n");
+}
+
+void list_box::compute_subscript_kern()
+{
+ // We can only call compute_subscript_kern if we have called
+ // compute_metrics first.
+ if (list.p[list.len-1]->is_simple())
+ list.p[list.len-1]->compute_metrics(sty);
+ list.p[list.len-1]->compute_subscript_kern();
+ printf(".nr " SUB_KERN_FORMAT " \\n[" SUB_KERN_FORMAT "]\n",
+ uid, list.p[list.len-1]->uid);
+}
+
+void list_box::output()
+{
+ for (int i = 0; i < list.len; i++) {
+ if (i > 0) {
+ int n = compute_spacing(is_script,
+ list.p[i-1]->spacing_type,
+ list.p[i]->spacing_type);
+ if (n > 0)
+ printf("\\h'%dM'", n);
+ }
+ list.p[i]->output();
+ }
+}
+
+void list_box::handle_char_type(int st, int ft)
+{
+ for (int i = 0; i < list.len; i++)
+ list.p[i]->handle_char_type(st, ft);
+}
+
+void list_box::debug_print()
+{
+ list.list_debug_print(" ");
+}
+
+void list_box::check_tabs(int level)
+{
+ list.list_check_tabs(level);
+}
diff --git a/src/preproc/eqn/main.cc b/src/preproc/eqn/main.cc
new file mode 100644
index 00000000..6260daa8
--- /dev/null
+++ b/src/preproc/eqn/main.cc
@@ -0,0 +1,356 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "eqn.h"
+#include "stringclass.h"
+#include "device.h"
+#include "searchpath.h"
+#include "macropath.h"
+
+#define STARTUP_FILE "eqnrc"
+
+extern int yyparse();
+
+static char *delim_search(char *, int);
+static int inline_equation(FILE *, string &, string &);
+
+char start_delim = '\0';
+char end_delim = '\0';
+int non_empty_flag;
+int inline_flag;
+int draw_flag = 0;
+int one_size_reduction_flag = 0;
+int compatible_flag = 0;
+int no_newline_in_delim_flag = 0;
+
+int read_line(FILE *fp, string *p)
+{
+ p->clear();
+ int c = -1;
+ while ((c = getc(fp)) != EOF) {
+ if (!illegal_input_char(c))
+ *p += char(c);
+ else
+ error("illegal input character code `%1'", c);
+ if (c == '\n')
+ break;
+ }
+ current_lineno++;
+ return p->length() > 0;
+}
+
+void do_file(FILE *fp, const char *filename)
+{
+ string linebuf;
+ string str;
+ printf(".lf 1 %s\n", filename);
+ current_filename = filename;
+ current_lineno = 0;
+ while (read_line(fp, &linebuf)) {
+ if (linebuf.length() >= 4
+ && linebuf[0] == '.' && linebuf[1] == 'l' && linebuf[2] == 'f'
+ && (linebuf[3] == ' ' || linebuf[3] == '\n' || compatible_flag)) {
+ put_string(linebuf, stdout);
+ linebuf += '\0';
+ if (interpret_lf_args(linebuf.contents() + 3))
+ current_lineno--;
+ }
+ else if (linebuf.length() >= 4
+ && linebuf[0] == '.'
+ && linebuf[1] == 'E'
+ && linebuf[2] == 'Q'
+ && (linebuf[3] == ' ' || linebuf[3] == '\n' || compatible_flag)) {
+ put_string(linebuf, stdout);
+ put_string(".if '\\*(.T'html' \\X(graphic-start(\\c\n", stdout);
+ int start_lineno = current_lineno + 1;
+ str.clear();
+ for (;;) {
+ if (!read_line(fp, &linebuf))
+ fatal("end of file before .EN");
+ if (linebuf.length() >= 3 && linebuf[0] == '.' && linebuf[1] == 'E') {
+ if (linebuf[2] == 'N'
+ && (linebuf.length() == 3 || linebuf[3] == ' '
+ || linebuf[3] == '\n' || compatible_flag))
+ break;
+ else if (linebuf[2] == 'Q' && linebuf.length() > 3
+ && (linebuf[3] == ' ' || linebuf[3] == '\n'
+ || compatible_flag))
+ fatal("nested .EQ");
+ }
+ str += linebuf;
+ }
+ str += '\0';
+ start_string();
+ init_lex(str.contents(), current_filename, start_lineno);
+ non_empty_flag = 0;
+ inline_flag = 0;
+ yyparse();
+ if (non_empty_flag) {
+ printf(".lf %d\n", current_lineno - 1);
+ output_string();
+ }
+ restore_compatibility();
+ printf(".lf %d\n", current_lineno);
+ put_string(".if '\\*(.T'html' \\X(graphic-end(\\c\n", stdout);
+ put_string(linebuf, stdout);
+ }
+ else if (start_delim != '\0' && linebuf.search(start_delim) >= 0
+ && inline_equation(fp, linebuf, str))
+ ;
+ else
+ put_string(linebuf, stdout);
+ }
+ current_filename = 0;
+ current_lineno = 0;
+}
+
+/* Handle an inline equation. Return 1 if it was an inline equation,
+0 otherwise. */
+
+static int inline_equation(FILE *fp, string &linebuf, string &str)
+{
+ linebuf += '\0';
+ char *ptr = &linebuf[0];
+ char *start = delim_search(ptr, start_delim);
+ if (!start) {
+ // It wasn't a delimiter after all.
+ linebuf.set_length(linebuf.length() - 1); // strip the '\0'
+ return 0;
+ }
+ start_string();
+ inline_flag = 1;
+ for (;;) {
+ if (no_newline_in_delim_flag && strchr(start + 1, end_delim) == 0) {
+ error("missing `%1'", end_delim);
+ char *nl = strchr(start + 1, '\n');
+ if (nl != 0)
+ *nl = '\0';
+ do_text(ptr);
+ break;
+ }
+ int start_lineno = current_lineno;
+ *start = '\0';
+ do_text(ptr);
+ ptr = start + 1;
+ str.clear();
+ for (;;) {
+ char *end = strchr(ptr, end_delim);
+ if (end != 0) {
+ *end = '\0';
+ str += ptr;
+ ptr = end + 1;
+ break;
+ }
+ str += ptr;
+ if (!read_line(fp, &linebuf))
+ fatal("end of file before `%1'", end_delim);
+ linebuf += '\0';
+ ptr = &linebuf[0];
+ }
+ str += '\0';
+ put_string(".if '\\*(.T'html' \\X(graphic-start(\\c\n", stdout);
+ init_lex(str.contents(), current_filename, start_lineno);
+ yyparse();
+ start = delim_search(ptr, start_delim);
+ if (start == 0) {
+ char *nl = strchr(ptr, '\n');
+ if (nl != 0)
+ *nl = '\0';
+ do_text(ptr);
+ break;
+ }
+ }
+ printf(".lf %d\n", current_lineno);
+ output_string();
+ restore_compatibility();
+ put_string(".if '\\*(.T'html' \\X(graphic-end(\\c\n", stdout);
+ printf(".lf %d\n", current_lineno + 1);
+ return 1;
+}
+
+/* Search for delim. Skip over number register and string names etc. */
+
+static char *delim_search(char *ptr, int delim)
+{
+ while (*ptr) {
+ if (*ptr == delim)
+ return ptr;
+ if (*ptr++ == '\\') {
+ switch (*ptr) {
+ case 'n':
+ case '*':
+ case 'f':
+ case 'g':
+ case 'k':
+ switch (*++ptr) {
+ case '\0':
+ case '\\':
+ break;
+ case '(':
+ if (*++ptr != '\\' && *ptr != '\0' && *++ptr != '\\' && *ptr != '\0')
+ ptr++;
+ break;
+ case '[':
+ while (*++ptr != '\0')
+ if (*ptr == ']') {
+ ptr++;
+ break;
+ }
+ break;
+ default:
+ ptr++;
+ break;
+ }
+ break;
+ case '\\':
+ case '\0':
+ break;
+ default:
+ ptr++;
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+void usage()
+{
+ fprintf(stderr,
+ "usage: %s [ -rvDCNR ] -dxx -fn -sn -pn -mn -Mdir -Ts [ files ... ]\n",
+ program_name);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int opt;
+ int load_startup_file = 1;
+ while ((opt = getopt(argc, argv, "DCRvd:f:p:s:m:T:M:rN")) != EOF)
+ switch (opt) {
+ case 'C':
+ compatible_flag = 1;
+ break;
+ case 'R': // don't load eqnchar
+ load_startup_file = 0;
+ break;
+ case 'M':
+ macro_path.command_line_dir(optarg);
+ break;
+ case 'v':
+ {
+ extern const char *Version_string;
+ fprintf(stderr, "GNU eqn version %s\n", Version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'd':
+ if (optarg[0] == '\0' || optarg[1] == '\0')
+ error("-d requires two character argument");
+ else if (illegal_input_char(optarg[0]))
+ error("bad delimiter `%1'", optarg[0]);
+ else if (illegal_input_char(optarg[1]))
+ error("bad delimiter `%1'", optarg[1]);
+ else {
+ start_delim = optarg[0];
+ end_delim = optarg[1];
+ }
+ break;
+ case 'f':
+ set_gfont(optarg);
+ break;
+ case 'T':
+ device = optarg;
+ break;
+ case 's':
+ if (!set_gsize(optarg))
+ error("invalid size `%1'", optarg);
+ break;
+ case 'p':
+ {
+ int n;
+ if (sscanf(optarg, "%d", &n) == 1)
+ set_script_reduction(n);
+ else
+ error("bad size `%1'", optarg);
+ }
+ break;
+ case 'm':
+ {
+ int n;
+ if (sscanf(optarg, "%d", &n) == 1)
+ set_minimum_size(n);
+ else
+ error("bad size `%1'", optarg);
+ }
+ break;
+ case 'r':
+ one_size_reduction_flag = 1;
+ break;
+ case 'D':
+ warning("-D option is obsolete: use `set draw_lines 1' instead");
+ draw_flag = 1;
+ break;
+ case 'N':
+ no_newline_in_delim_flag = 1;
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ }
+ init_table(device);
+ init_char_table();
+ printf(".if !'\\*(.T'%s' "
+ ".tm warning: %s should have been given a `-T\\*(.T' option\n",
+ device, program_name);
+ if (load_startup_file) {
+ char *path;
+ FILE *fp = macro_path.open_file(STARTUP_FILE, &path);
+ if (fp) {
+ do_file(fp, path);
+ fclose(fp);
+ a_delete path;
+ }
+ }
+ if (optind >= argc)
+ do_file(stdin, "-");
+ else
+ for (int i = optind; i < argc; i++)
+ if (strcmp(argv[i], "-") == 0)
+ do_file(stdin, "-");
+ else {
+ errno = 0;
+ FILE *fp = fopen(argv[i], "r");
+ if (!fp)
+ fatal("can't open `%1': %2", argv[i], strerror(errno));
+ else {
+ do_file(fp, argv[i]);
+ fclose(fp);
+ }
+ }
+ if (ferror(stdout) || fflush(stdout) < 0)
+ fatal("output error");
+ return 0;
+}
diff --git a/src/preproc/eqn/mark.cc b/src/preproc/eqn/mark.cc
new file mode 100644
index 00000000..99d1b75f
--- /dev/null
+++ b/src/preproc/eqn/mark.cc
@@ -0,0 +1,121 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+class mark_box : public pointer_box {
+public:
+ mark_box(box *);
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+};
+
+// we push down marks so that they don't interfere with spacing
+
+box *make_mark_box(box *p)
+{
+ list_box *b = p->to_list_box();
+ if (b != 0) {
+ b->list.p[0] = make_mark_box(b->list.p[0]);
+ return b;
+ }
+ else
+ return new mark_box(p);
+}
+
+mark_box::mark_box(box *pp) : pointer_box(pp)
+{
+}
+
+void mark_box::output()
+{
+ p->output();
+}
+
+int mark_box::compute_metrics(int style)
+{
+ int res = p->compute_metrics(style);
+ if (res)
+ error("multiple marks and lineups");
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " MARK_REG " 0\n");
+ return FOUND_MARK;
+}
+
+void mark_box::debug_print()
+{
+ fprintf(stderr, "mark { ");
+ p->debug_print();
+ fprintf(stderr, " }");
+}
+
+
+class lineup_box : public pointer_box {
+public:
+ lineup_box(box *);
+ void output();
+ int compute_metrics(int style);
+ void debug_print();
+};
+
+// we push down lineups so that they don't interfere with spacing
+
+box *make_lineup_box(box *p)
+{
+ list_box *b = p->to_list_box();
+ if (b != 0) {
+ b->list.p[0] = make_lineup_box(b->list.p[0]);
+ return b;
+ }
+ else
+ return new lineup_box(p);
+}
+
+lineup_box::lineup_box(box *pp) : pointer_box(pp)
+{
+}
+
+void lineup_box::output()
+{
+ p->output();
+}
+
+int lineup_box::compute_metrics(int style)
+{
+ int res = p->compute_metrics(style);
+ if (res)
+ error("multiple marks and lineups");
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " MARK_REG " 0\n");
+ return FOUND_LINEUP;
+}
+
+void lineup_box::debug_print()
+{
+ fprintf(stderr, "lineup { ");
+ p->debug_print();
+ fprintf(stderr, " }");
+}
diff --git a/src/preproc/eqn/neqn.sh b/src/preproc/eqn/neqn.sh
new file mode 100644
index 00000000..a979ebcb
--- /dev/null
+++ b/src/preproc/eqn/neqn.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# Provision of this shell script should not be taken to imply that use of
+# GNU eqn with groff -Tascii|-Tlatin1|-Tutf8 is supported.
+
+exec @g@eqn -Tascii ${1+"$@"}
diff --git a/src/preproc/eqn/other.cc b/src/preproc/eqn/other.cc
new file mode 100644
index 00000000..eb9e50a2
--- /dev/null
+++ b/src/preproc/eqn/other.cc
@@ -0,0 +1,601 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+class accent_box : public pointer_box {
+private:
+ box *ab;
+public:
+ accent_box(box *, box *);
+ ~accent_box();
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+ void check_tabs(int);
+};
+
+box *make_accent_box(box *p, box *q)
+{
+ return new accent_box(p, q);
+}
+
+accent_box::accent_box(box *pp, box *qq) : pointer_box(pp), ab(qq)
+{
+}
+
+accent_box::~accent_box()
+{
+ delete ab;
+}
+
+#if 0
+int accent_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ p->compute_skew();
+ ab->compute_metrics(style);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
+ uid, p->uid, x_height);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n["
+ SUP_RAISE_FORMAT "]\n",
+ uid, ab->uid, uid);
+ return r;
+}
+
+void accent_box::output()
+{
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u+\\n["
+ SKEW_FORMAT "]u'",
+ p->uid, ab->uid, p->uid);
+ printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ ab->output();
+ printf("\\h'-\\n[" WIDTH_FORMAT "]u'", ab->uid);
+ printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u+\\n["
+ SKEW_FORMAT "]u)'",
+ p->uid, ab->uid, p->uid);
+ p->output();
+}
+#endif
+
+/* This version copes with the possibility of an accent's being wider
+than its accentee. LEFT_WIDTH_FORMAT gives the distance from the
+left edge of the resulting box to the middle of the accentee's box.*/
+
+int accent_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ p->compute_skew();
+ ab->compute_metrics(style);
+ printf(".nr " LEFT_WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
+ ">?(\\n[" WIDTH_FORMAT "]/2-\\n[" SKEW_FORMAT "])\n",
+ uid, p->uid, ab->uid, p->uid);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
+ ">?(\\n[" WIDTH_FORMAT "]/2+\\n[" SKEW_FORMAT "])"
+ "+\\n[" LEFT_WIDTH_FORMAT "]\n",
+ uid, p->uid, ab->uid, p->uid, uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
+ uid, p->uid, x_height);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n["
+ SUP_RAISE_FORMAT "]\n",
+ uid, ab->uid, uid);
+ if (r)
+ printf(".nr " MARK_REG " +\\n[" LEFT_WIDTH_FORMAT "]"
+ "-(\\n[" WIDTH_FORMAT "]/2)'\n",
+ uid, p->uid);
+ return r;
+}
+
+void accent_box::output()
+{
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u+\\n[" SKEW_FORMAT "]u"
+ "-(\\n[" WIDTH_FORMAT "]u/2u)'",
+ uid, p->uid, ab->uid);
+ printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ ab->output();
+ printf(DELIMITER_CHAR);
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'",
+ uid, p->uid);
+ p->output();
+ printf(DELIMITER_CHAR);
+ printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
+}
+
+void accent_box::check_tabs(int level)
+{
+ ab->check_tabs(level + 1);
+ p->check_tabs(level + 1);
+}
+
+void accent_box::debug_print()
+{
+ fprintf(stderr, "{ ");
+ p->debug_print();
+ fprintf(stderr, " } accent { ");
+ ab->debug_print();
+ fprintf(stderr, " }");
+}
+
+class overline_char_box : public simple_box {
+public:
+ overline_char_box();
+ void output();
+ void debug_print();
+};
+
+overline_char_box::overline_char_box()
+{
+}
+
+void overline_char_box::output()
+{
+ printf("\\v'-%dM/2u-%dM'", 7*default_rule_thickness, x_height);
+ printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"),
+ accent_width);
+ printf("\\v'%dM/2u+%dM'", 7*default_rule_thickness, x_height);
+}
+
+void overline_char_box::debug_print()
+{
+ fprintf(stderr, "<overline char>");
+}
+
+class overline_box : public pointer_box {
+public:
+ overline_box(box *);
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+};
+
+box *make_overline_box(box *p)
+{
+ if (p->is_char())
+ return new accent_box(p, new overline_char_box);
+ else
+ return new overline_box(p);
+}
+
+overline_box::overline_box(box *pp) : pointer_box(pp)
+{
+}
+
+int overline_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(cramped_style(style));
+ // 9
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+%dM\n",
+ uid, p->uid, default_rule_thickness*5);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ return r;
+}
+
+void overline_box::output()
+{
+ // 9
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\v'-\\n[" HEIGHT_FORMAT "]u-(%dM/2u)'",
+ p->uid, 7*default_rule_thickness);
+ if (draw_flag)
+ printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid);
+ else
+ printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid);
+ printf(DELIMITER_CHAR);
+ p->output();
+}
+
+void overline_box::debug_print()
+{
+ fprintf(stderr, "{ ");
+ p->debug_print();
+ fprintf(stderr, " } bar");
+}
+
+class uaccent_box : public pointer_box {
+ box *ab;
+public:
+ uaccent_box(box *, box *);
+ ~uaccent_box();
+ int compute_metrics(int);
+ void output();
+ void compute_subscript_kern();
+ void check_tabs(int);
+ void debug_print();
+};
+
+box *make_uaccent_box(box *p, box *q)
+{
+ return new uaccent_box(p, q);
+}
+
+uaccent_box::uaccent_box(box *pp, box *qq)
+: pointer_box(pp), ab(qq)
+{
+}
+
+uaccent_box::~uaccent_box()
+{
+ delete ab;
+}
+
+int uaccent_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ ab->compute_metrics(style);
+ printf(".nr " LEFT_WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
+ ">?(\\n[" WIDTH_FORMAT "]/2)\n",
+ uid, p->uid, ab->uid);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
+ ">?(\\n[" WIDTH_FORMAT "]/2)"
+ "+\\n[" LEFT_WIDTH_FORMAT "]\n",
+ uid, p->uid, ab->uid, uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
+ "+\\n[" DEPTH_FORMAT "]\n",
+ uid, p->uid, ab->uid);
+ if (r)
+ printf(".nr " MARK_REG " +\\n[" LEFT_WIDTH_FORMAT "]"
+ "-(\\n[" WIDTH_FORMAT "]/2)'\n",
+ uid, p->uid);
+ return r;
+}
+
+void uaccent_box::output()
+{
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'",
+ uid, ab->uid);
+ printf("\\v'\\n[" DEPTH_FORMAT "]u'", p->uid);
+ ab->output();
+ printf(DELIMITER_CHAR);
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'",
+ uid, p->uid);
+ p->output();
+ printf(DELIMITER_CHAR);
+ printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
+}
+
+void uaccent_box::check_tabs(int level)
+{
+ ab->check_tabs(level + 1);
+ p->check_tabs(level + 1);
+}
+
+void uaccent_box::compute_subscript_kern()
+{
+ box::compute_subscript_kern(); // want 0 subscript kern
+}
+
+void uaccent_box::debug_print()
+{
+ fprintf(stderr, "{ ");
+ p->debug_print();
+ fprintf(stderr, " } uaccent { ");
+ ab->debug_print();
+ fprintf(stderr, " }");
+}
+
+class underline_char_box : public simple_box {
+public:
+ underline_char_box();
+ void output();
+ void debug_print();
+};
+
+underline_char_box::underline_char_box()
+{
+}
+
+void underline_char_box::output()
+{
+ printf("\\v'%dM/2u'", 7*default_rule_thickness);
+ printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"),
+ accent_width);
+ printf("\\v'-%dM/2u'", 7*default_rule_thickness);
+}
+
+void underline_char_box::debug_print()
+{
+ fprintf(stderr, "<underline char>");
+}
+
+
+class underline_box : public pointer_box {
+public:
+ underline_box(box *);
+ int compute_metrics(int);
+ void output();
+ void compute_subscript_kern();
+ void debug_print();
+};
+
+box *make_underline_box(box *p)
+{
+ if (p->is_char())
+ return new uaccent_box(p, new underline_char_box);
+ else
+ return new underline_box(p);
+}
+
+underline_box::underline_box(box *pp) : pointer_box(pp)
+{
+}
+
+int underline_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ // 10
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n",
+ uid, p->uid, default_rule_thickness*5);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ return r;
+}
+
+void underline_box::output()
+{
+ // 10
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\v'\\n[" DEPTH_FORMAT "]u+(%dM/2u)'",
+ p->uid, 7*default_rule_thickness);
+ if (draw_flag)
+ printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid);
+ else
+ printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid);
+ printf(DELIMITER_CHAR);
+ p->output();
+}
+
+// we want an underline box to have 0 subscript kern
+
+void underline_box::compute_subscript_kern()
+{
+ box::compute_subscript_kern();
+}
+
+void underline_box::debug_print()
+{
+ fprintf(stderr, "{ ");
+ p->debug_print();
+ fprintf(stderr, " } under");
+}
+
+size_box::size_box(char *s, box *pp) : pointer_box(pp), size(s)
+{
+}
+
+int size_box::compute_metrics(int style)
+{
+ printf(".nr " SIZE_FORMAT " \\n[.s]\n", uid);
+ printf(".ps %s\n", size);
+ printf(".nr " SMALL_SIZE_FORMAT " \\n[.s]\n", uid);
+ int r = p->compute_metrics(style);
+ printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ return r;
+}
+
+void size_box::output()
+{
+ printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
+ p->output();
+ printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
+}
+
+size_box::~size_box()
+{
+ a_delete size;
+}
+
+void size_box::debug_print()
+{
+ fprintf(stderr, "size %s { ", size);
+ p->debug_print();
+ fprintf(stderr, " }");
+}
+
+
+font_box::font_box(char *s, box *pp) : pointer_box(pp), f(s)
+{
+}
+
+font_box::~font_box()
+{
+ a_delete f;
+}
+
+int font_box::compute_metrics(int style)
+{
+ const char *old_roman_font = current_roman_font;
+ current_roman_font = f;
+ printf(".nr " FONT_FORMAT " \\n[.f]\n", uid);
+ printf(".ft %s\n", f);
+ int r = p->compute_metrics(style);
+ current_roman_font = old_roman_font;
+ printf(".ft \\n[" FONT_FORMAT "]\n", uid);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ return r;
+}
+
+void font_box::output()
+{
+ printf("\\f[%s]", f);
+ const char *old_roman_font = current_roman_font;
+ current_roman_font = f;
+ p->output();
+ current_roman_font = old_roman_font;
+ printf("\\f[\\n[" FONT_FORMAT "]]", uid);
+}
+
+void font_box::debug_print()
+{
+ fprintf(stderr, "font %s { ", f);
+ p->debug_print();
+ fprintf(stderr, " }");
+}
+
+fat_box::fat_box(box *pp) : pointer_box(pp)
+{
+}
+
+int fat_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]+%dM\n",
+ uid, p->uid, fat_offset);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ return r;
+}
+
+void fat_box::output()
+{
+ p->output();
+ printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p->uid);
+ printf("\\h'%dM'", fat_offset);
+ p->output();
+}
+
+
+void fat_box::debug_print()
+{
+ fprintf(stderr, "fat { ");
+ p->debug_print();
+ fprintf(stderr, " }");
+}
+
+
+vmotion_box::vmotion_box(int i, box *pp) : pointer_box(pp), n(i)
+{
+}
+
+int vmotion_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ if (n > 0) {
+ printf(".nr " HEIGHT_FORMAT " %dM+\\n[" HEIGHT_FORMAT "]\n",
+ uid, n, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ }
+ else {
+ printf(".nr " DEPTH_FORMAT " %dM+\\n[" DEPTH_FORMAT "]>?0\n",
+ uid, -n, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n",
+ uid, p->uid);
+ }
+ return r;
+}
+
+void vmotion_box::output()
+{
+ printf("\\v'%dM'", -n);
+ p->output();
+ printf("\\v'%dM'", n);
+}
+
+void vmotion_box::debug_print()
+{
+ if (n >= 0)
+ fprintf(stderr, "up %d { ", n);
+ else
+ fprintf(stderr, "down %d { ", -n);
+ p->debug_print();
+ fprintf(stderr, " }");
+}
+
+hmotion_box::hmotion_box(int i, box *pp) : pointer_box(pp), n(i)
+{
+}
+
+int hmotion_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]+%dM\n",
+ uid, p->uid, n);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ if (r)
+ printf(".nr " MARK_REG " +%dM\n", n);
+ return r;
+}
+
+void hmotion_box::output()
+{
+ printf("\\h'%dM'", n);
+ p->output();
+}
+
+void hmotion_box::debug_print()
+{
+ if (n >= 0)
+ fprintf(stderr, "fwd %d { ", n);
+ else
+ fprintf(stderr, "back %d { ", -n);
+ p->debug_print();
+ fprintf(stderr, " }");
+}
+
+vcenter_box::vcenter_box(box *pp) : pointer_box(pp)
+{
+}
+
+int vcenter_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " SUP_RAISE_FORMAT " \\n[" DEPTH_FORMAT "]-\\n["
+ HEIGHT_FORMAT "]/2+%dM\n",
+ uid, p->uid, p->uid, axis_height);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n["
+ SUP_RAISE_FORMAT "]>?0\n", uid, p->uid, uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]-\\n["
+ SUP_RAISE_FORMAT "]>?0\n", uid, p->uid, uid);
+
+ return r;
+}
+
+void vcenter_box::output()
+{
+ printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ p->output();
+ printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
+}
+
+void vcenter_box::debug_print()
+{
+ fprintf(stderr, "vcenter { ");
+ p->debug_print();
+ fprintf(stderr, " }");
+}
+
diff --git a/src/preproc/eqn/over.cc b/src/preproc/eqn/over.cc
new file mode 100644
index 00000000..06b03212
--- /dev/null
+++ b/src/preproc/eqn/over.cc
@@ -0,0 +1,196 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+class over_box : public box {
+private:
+ int reduce_size;
+ box *num;
+ box *den;
+public:
+ over_box(int small, box *, box *);
+ ~over_box();
+ void debug_print();
+ int compute_metrics(int);
+ void output();
+ void check_tabs(int);
+};
+
+box *make_over_box(box *pp, box *qq)
+{
+ return new over_box(0, pp, qq);
+}
+
+box *make_small_over_box(box *pp, box *qq)
+{
+ return new over_box(1, pp, qq);
+}
+
+over_box::over_box(int is_small, box *pp, box *qq)
+: reduce_size(is_small), num(pp), den(qq)
+{
+ spacing_type = INNER_TYPE;
+}
+
+over_box::~over_box()
+{
+ delete num;
+ delete den;
+}
+
+int over_box::compute_metrics(int style)
+{
+ if (reduce_size) {
+ style = script_style(style);
+ printf(".nr " SIZE_FORMAT " \\n[.s]\n", uid);
+ set_script_size();
+ printf(".nr " SMALL_SIZE_FORMAT " \\n[.s]\n", uid);
+ }
+ int mark_uid;
+ int res = num->compute_metrics(style);
+ if (res)
+ mark_uid = num->uid;
+ int r = den->compute_metrics(cramped_style(style));
+ if (r && res)
+ error("multiple marks and lineups");
+ else {
+ mark_uid = den->uid;
+ res = r;
+ }
+ if (reduce_size)
+ printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
+ printf(".nr " WIDTH_FORMAT " (\\n[" WIDTH_FORMAT "]>?\\n[" WIDTH_FORMAT "]",
+ uid, num->uid, den->uid);
+ // allow for \(ru being wider than both the numerator and denominator
+ if (!draw_flag)
+ fputs(">?\\w" DELIMITER_CHAR "\\(ru" DELIMITER_CHAR, stdout);
+ printf(")+%dM\n", null_delimiter_space*2 + over_hang*2);
+ // 15b
+ printf(".nr " SUP_RAISE_FORMAT " %dM\n",
+ uid, (reduce_size ? num2 : num1));
+ printf(".nr " SUB_LOWER_FORMAT " %dM\n",
+ uid, (reduce_size ? denom2 : denom1));
+
+ // 15d
+ printf(".nr " SUP_RAISE_FORMAT " +(\\n[" DEPTH_FORMAT
+ "]-\\n[" SUP_RAISE_FORMAT "]+%dM+(%dM/2)+%dM)>?0\n",
+ uid, num->uid, uid, axis_height, default_rule_thickness,
+ default_rule_thickness*(reduce_size ? 1 : 3));
+ printf(".nr " SUB_LOWER_FORMAT " +(\\n[" HEIGHT_FORMAT
+ "]-\\n[" SUB_LOWER_FORMAT "]-%dM+(%dM/2)+%dM)>?0\n",
+ uid, den->uid, uid, axis_height, default_rule_thickness,
+ default_rule_thickness*(reduce_size ? 1 : 3));
+
+
+ printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
+ HEIGHT_FORMAT "]\n",
+ uid, uid, num->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n["
+ DEPTH_FORMAT "]\n",
+ uid, uid, den->uid);
+ if (res)
+ printf(".nr " MARK_REG " +(\\n[" WIDTH_FORMAT "]-\\n["
+ WIDTH_FORMAT "]/2)\n", uid, mark_uid);
+ return res;
+}
+
+#define USE_Z
+
+void over_box::output()
+{
+ if (reduce_size)
+ printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
+#ifdef USE_Z
+ printf("\\Z" DELIMITER_CHAR);
+#endif
+ // move up to the numerator baseline
+ printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ // move across so that it's centered
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
+ uid, num->uid);
+
+ // print the numerator
+ num->output();
+
+#ifdef USE_Z
+ printf(DELIMITER_CHAR);
+#else
+ // back again
+ printf("\\h'-\\n[" WIDTH_FORMAT "]u'", num->uid);
+ printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
+ uid, num->uid);
+ // down again
+ printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
+#endif
+#ifdef USE_Z
+ printf("\\Z" DELIMITER_CHAR);
+#endif
+ // move down to the denominator baseline
+ printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
+
+ // move across so that it's centered
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
+ uid, den->uid);
+
+ // print the the denominator
+ den->output();
+
+#ifdef USE_Z
+ printf(DELIMITER_CHAR);
+#else
+ // back again
+ printf("\\h'-\\n[" WIDTH_FORMAT "]u'", den->uid);
+ printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
+ uid, den->uid);
+ // up again
+ printf("\\v'-\\n[" SUB_LOWER_FORMAT "]u'", uid);
+#endif
+ if (reduce_size)
+ printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
+ // draw the line
+ printf("\\h'%dM'", null_delimiter_space);
+ printf("\\v'-%dM'", axis_height);
+ fputs(draw_flag ? "\\D'l" : "\\l'", stdout);
+ printf("\\n[" WIDTH_FORMAT "]u-%dM",
+ uid, 2*null_delimiter_space);
+ fputs(draw_flag ? " 0'" : "\\&\\(ru'", stdout);
+ printf("\\v'%dM'", axis_height);
+ printf("\\h'%dM'", null_delimiter_space);
+}
+
+void over_box::debug_print()
+{
+ fprintf(stderr, "{ ");
+ num->debug_print();
+ if (reduce_size)
+ fprintf(stderr, " } smallover { ");
+ else
+ fprintf(stderr, " } over { ");
+ den->debug_print();
+ fprintf(stderr, " }");
+}
+
+void over_box::check_tabs(int level)
+{
+ num->check_tabs(level + 1);
+ den->check_tabs(level + 1);
+}
diff --git a/src/preproc/eqn/pbox.h b/src/preproc/eqn/pbox.h
new file mode 100644
index 00000000..d1f16ac4
--- /dev/null
+++ b/src/preproc/eqn/pbox.h
@@ -0,0 +1,141 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+extern int fat_offset;
+
+extern int over_hang;
+extern int accent_width;
+
+extern int delimiter_factor;
+extern int delimiter_shortfall;
+
+extern int null_delimiter_space;
+extern int script_space;
+extern int thin_space;
+extern int medium_space;
+extern int thick_space;
+
+extern int num1;
+extern int num2;
+// we don't use num3, because we don't have \atop
+extern int denom1;
+extern int denom2;
+extern int axis_height;
+extern int sup1;
+extern int sup2;
+extern int sup3;
+extern int default_rule_thickness;
+extern int sub1;
+extern int sub2;
+extern int sup_drop;
+extern int sub_drop;
+extern int x_height;
+extern int big_op_spacing1;
+extern int big_op_spacing2;
+extern int big_op_spacing3;
+extern int big_op_spacing4;
+extern int big_op_spacing5;
+
+extern int baseline_sep;
+extern int shift_down;
+extern int column_sep;
+extern int matrix_side_sep;
+
+// ms.eqn relies on this!
+
+#define LINE_STRING "10"
+#define MARK_OR_LINEUP_FLAG_REG "MK"
+
+#define WIDTH_FORMAT PREFIX "w%d"
+#define HEIGHT_FORMAT PREFIX "h%d"
+#define DEPTH_FORMAT PREFIX "d%d"
+#define TOTAL_FORMAT PREFIX "t%d"
+#define SIZE_FORMAT PREFIX "z%d"
+#define SMALL_SIZE_FORMAT PREFIX "Z%d"
+#define SUP_RAISE_FORMAT PREFIX "p%d"
+#define SUB_LOWER_FORMAT PREFIX "b%d"
+#define SUB_KERN_FORMAT PREFIX "k%d"
+#define FONT_FORMAT PREFIX "f%d"
+#define SKEW_FORMAT PREFIX "s%d"
+#define LEFT_WIDTH_FORMAT PREFIX "lw%d"
+#define LEFT_DELIM_STRING_FORMAT PREFIX "l%d"
+#define RIGHT_DELIM_STRING_FORMAT PREFIX "r%d"
+#define SQRT_STRING_FORMAT PREFIX "sqr%d"
+#define SQRT_WIDTH_FORMAT PREFIX "sq%d"
+#define BASELINE_SEP_FORMAT PREFIX "bs%d"
+// this needs two parameters, the uid and the column index
+#define COLUMN_WIDTH_FORMAT PREFIX "cw%d,%d"
+
+#define BAR_STRING PREFIX "sqb"
+#define TEMP_REG PREFIX "temp"
+#define MARK_REG PREFIX "mark"
+#define MARK_WIDTH_REG PREFIX "mwidth"
+#define SAVED_MARK_REG PREFIX "smark"
+#define MAX_SIZE_REG PREFIX "mxsz"
+#define REPEAT_APPEND_STRING_MACRO PREFIX "ras"
+#define TOP_HEIGHT_REG PREFIX "th"
+#define TOP_DEPTH_REG PREFIX "td"
+#define MID_HEIGHT_REG PREFIX "mh"
+#define MID_DEPTH_REG PREFIX "md"
+#define BOT_HEIGHT_REG PREFIX "bh"
+#define BOT_DEPTH_REG PREFIX "bd"
+#define EXT_HEIGHT_REG PREFIX "eh"
+#define EXT_DEPTH_REG PREFIX "ed"
+#define TOTAL_HEIGHT_REG PREFIX "tot"
+#define DELTA_REG PREFIX "delta"
+#define DELIM_STRING PREFIX "delim"
+#define DELIM_WIDTH_REG PREFIX "dwidth"
+#define SAVED_FONT_REG PREFIX "sfont"
+#define SAVED_PREV_FONT_REG PREFIX "spfont"
+#define SAVED_INLINE_FONT_REG PREFIX "sifont"
+#define SAVED_INLINE_PREV_FONT_REG PREFIX "sipfont"
+#define SAVED_SIZE_REG PREFIX "ssize"
+#define SAVED_INLINE_SIZE_REG PREFIX "sisize"
+#define SAVED_INLINE_PREV_SIZE_REG PREFIX "sipsize"
+#define SAVE_FONT_STRING PREFIX "sfont"
+#define RESTORE_FONT_STRING PREFIX "rfont"
+#define INDEX_REG PREFIX "i"
+#define TEMP_MACRO PREFIX "tempmac"
+
+#define DELIMITER_CHAR "\\(EQ"
+
+const int CRAMPED_SCRIPT_STYLE = 0;
+const int SCRIPT_STYLE = 1;
+const int CRAMPED_DISPLAY_STYLE = 2;
+const int DISPLAY_STYLE = 3;
+
+extern int script_style(int);
+extern int cramped_style(int);
+
+const int ORDINARY_TYPE = 0;
+const int OPERATOR_TYPE = 1;
+const int BINARY_TYPE = 2;
+const int RELATION_TYPE = 3;
+const int OPENING_TYPE = 4;
+const int CLOSING_TYPE = 5;
+const int PUNCTUATION_TYPE = 6;
+const int INNER_TYPE = 7;
+const int SUPPRESS_TYPE = 8;
+
+void set_script_size();
+
+enum { HINT_PREV_IS_ITALIC = 01, HINT_NEXT_IS_ITALIC = 02 };
+
+extern const char *current_roman_font;
diff --git a/src/preproc/eqn/pile.cc b/src/preproc/eqn/pile.cc
new file mode 100644
index 00000000..0df5241f
--- /dev/null
+++ b/src/preproc/eqn/pile.cc
@@ -0,0 +1,293 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+// piles and matrices
+
+#include "eqn.h"
+#include "pbox.h"
+
+// SUP_RAISE_FORMAT gives the first baseline
+// BASELINE_SEP_FORMAT gives the separation between baselines
+
+int pile_box::compute_metrics(int style)
+{
+ int i;
+ for (i = 0; i < col.len; i++)
+ col.p[i]->compute_metrics(style);
+ printf(".nr " WIDTH_FORMAT " 0", uid);
+ for (i = 0; i < col.len; i++)
+ printf(">?\\n[" WIDTH_FORMAT "]", col.p[i]->uid);
+ printf("\n");
+ printf(".nr " BASELINE_SEP_FORMAT " %dM",
+ uid, baseline_sep+col.space);
+ for (i = 1; i < col.len; i++)
+ printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
+ col.p[i-1]->uid, col.p[i]->uid, default_rule_thickness*5);
+ // round it so that it's a multiple of the vertical resolution
+ printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n");
+
+ printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
+ "+%dM\n",
+ uid, uid, col.len-1, axis_height - shift_down);
+ printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
+ HEIGHT_FORMAT "]\n",
+ uid, uid, col.p[0]->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d+\\n["
+ DEPTH_FORMAT "]-\\n[" SUP_RAISE_FORMAT "]\n",
+ uid, uid, col.len-1, col.p[col.len-1]->uid, uid);
+ return FOUND_NOTHING;
+}
+
+void pile_box::output()
+{
+ int i;
+ printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ for (i = 0; i < col.len; i++) {
+ switch (col.align) {
+ case LEFT_ALIGN:
+ break;
+ case CENTER_ALIGN:
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
+ uid, col.p[i]->uid);
+ break;
+ case RIGHT_ALIGN:
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
+ uid, col.p[i]->uid);
+ break;
+ default:
+ assert(0);
+ }
+ col.p[i]->output();
+ printf("\\h'-\\n[" WIDTH_FORMAT "]u'", col.p[i]->uid);
+ switch (col.align) {
+ case LEFT_ALIGN:
+ break;
+ case CENTER_ALIGN:
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
+ col.p[i]->uid, uid);
+ break;
+ case RIGHT_ALIGN:
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
+ col.p[i]->uid, uid);
+ break;
+ default:
+ assert(0);
+ }
+ if (i != col.len - 1)
+ printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
+ }
+ printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", col.len - 1, uid);
+ printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
+}
+
+pile_box::pile_box(box *pp) : col(pp)
+{
+}
+
+void pile_box::check_tabs(int level)
+{
+ col.list_check_tabs(level);
+}
+
+void pile_box::debug_print()
+{
+ col.debug_print("pile");
+}
+
+int matrix_box::compute_metrics(int style)
+{
+ int i, j;
+ int maxlen = 0;
+ int space = 0;
+ for (i = 0; i < len; i++) {
+ for (j = 0; j < p[i]->len; j++)
+ p[i]->p[j]->compute_metrics(style);
+ if (p[i]->len > maxlen)
+ maxlen = p[i]->len;
+ if (p[i]->space > space)
+ space = p[i]->space;
+ }
+ for (i = 0; i < len; i++) {
+ printf(".nr " COLUMN_WIDTH_FORMAT " 0", uid, i);
+ for (j = 0; j < p[i]->len; j++)
+ printf(">?\\n[" WIDTH_FORMAT "]", p[i]->p[j]->uid);
+ printf("\n");
+ }
+ printf(".nr " WIDTH_FORMAT " %dM",
+ uid, column_sep*(len-1)+2*matrix_side_sep);
+ for (i = 0; i < len; i++)
+ printf("+\\n[" COLUMN_WIDTH_FORMAT "]", uid, i);
+ printf("\n");
+ printf(".nr " BASELINE_SEP_FORMAT " %dM",
+ uid, baseline_sep+space);
+ for (i = 0; i < len; i++)
+ for (j = 1; j < p[i]->len; j++)
+ printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
+ p[i]->p[j-1]->uid, p[i]->p[j]->uid, default_rule_thickness*5);
+ // round it so that it's a multiple of the vertical resolution
+ printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n");
+ printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
+ "+%dM\n",
+ uid, uid, maxlen-1, axis_height - shift_down);
+ printf(".nr " HEIGHT_FORMAT " 0\\n[" SUP_RAISE_FORMAT "]+(0",
+ uid, uid);
+ for (i = 0; i < len; i++)
+ printf(">?\\n[" HEIGHT_FORMAT "]", p[i]->p[0]->uid);
+ printf(")>?0\n");
+ printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d-\\n["
+ SUP_RAISE_FORMAT "]+(0",
+ uid, uid, maxlen-1, uid);
+ for (i = 0; i < len; i++)
+ if (p[i]->len == maxlen)
+ printf(">?\\n[" DEPTH_FORMAT "]", p[i]->p[maxlen-1]->uid);
+ printf(")>?0\n");
+ return FOUND_NOTHING;
+}
+
+void matrix_box::output()
+{
+ printf("\\h'%dM'", matrix_side_sep);
+ for (int i = 0; i < len; i++) {
+ int j;
+ printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ for (j = 0; j < p[i]->len; j++) {
+ switch (p[i]->align) {
+ case LEFT_ALIGN:
+ break;
+ case CENTER_ALIGN:
+ printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
+ uid, i, p[i]->p[j]->uid);
+ break;
+ case RIGHT_ALIGN:
+ printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
+ uid, i, p[i]->p[j]->uid);
+ break;
+ default:
+ assert(0);
+ }
+ p[i]->p[j]->output();
+ printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p[i]->p[j]->uid);
+ switch (p[i]->align) {
+ case LEFT_ALIGN:
+ break;
+ case CENTER_ALIGN:
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u/2u'",
+ p[i]->p[j]->uid, uid, i);
+ break;
+ case RIGHT_ALIGN:
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u'",
+ p[i]->p[j]->uid, uid, i);
+ break;
+ default:
+ assert(0);
+ }
+ if (j != p[i]->len - 1)
+ printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
+ }
+ printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", p[i]->len - 1, uid);
+ printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u'", uid, i);
+ if (i != len - 1)
+ printf("\\h'%dM'", column_sep);
+ }
+ printf("\\h'%dM'", matrix_side_sep);
+}
+
+matrix_box::matrix_box(column *pp)
+{
+ p = new column*[10];
+ for (int i = 0; i < 10; i++)
+ p[i] = 0;
+ maxlen = 10;
+ len = 1;
+ p[0] = pp;
+}
+
+matrix_box::~matrix_box()
+{
+ for (int i = 0; i < len; i++)
+ delete p[i];
+ a_delete p;
+}
+
+void matrix_box::append(column *pp)
+{
+ if (len + 1 > maxlen) {
+ column **oldp = p;
+ maxlen *= 2;
+ p = new column*[maxlen];
+ memcpy(p, oldp, sizeof(column*)*len);
+ a_delete oldp;
+ }
+ p[len++] = pp;
+}
+
+void matrix_box::check_tabs(int level)
+{
+ for (int i = 0; i < len; i++)
+ p[i]->list_check_tabs(level);
+}
+
+void matrix_box::debug_print()
+{
+ fprintf(stderr, "matrix { ");
+ p[0]->debug_print("col");
+ for (int i = 1; i < len; i++) {
+ fprintf(stderr, " ");
+ p[i]->debug_print("col");
+ }
+ fprintf(stderr, " }");
+}
+
+column::column(box *pp) : box_list(pp), align(CENTER_ALIGN), space(0)
+{
+}
+
+void column::set_alignment(alignment a)
+{
+ align = a;
+}
+
+void column::set_space(int n)
+{
+ space = n;
+}
+
+void column::debug_print(const char *s)
+{
+ char c = '\0'; // shut up -Wall
+ switch (align) {
+ case LEFT_ALIGN:
+ c = 'l';
+ break;
+ case RIGHT_ALIGN:
+ c = 'r';
+ break;
+ case CENTER_ALIGN:
+ c = 'c';
+ break;
+ default:
+ assert(0);
+ }
+ fprintf(stderr, "%c%s %d { ", c, s, space);
+ list_debug_print(" above ");
+ fprintf(stderr, " }");
+}
+
diff --git a/src/preproc/eqn/script.cc b/src/preproc/eqn/script.cc
new file mode 100644
index 00000000..7c2e6c25
--- /dev/null
+++ b/src/preproc/eqn/script.cc
@@ -0,0 +1,221 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+class script_box : public pointer_box {
+private:
+ box *sub;
+ box *sup;
+public:
+ script_box(box *, box *, box *);
+ ~script_box();
+ int compute_metrics(int);
+ void output();
+ void debug_print();
+ int left_is_italic();
+ void hint(unsigned);
+ void check_tabs(int);
+};
+
+/* The idea is that the script should attach to the rightmost box
+of a list. For example, given `2x sup 3', the superscript should
+attach to `x' rather than `2x'. */
+
+box *make_script_box(box *nuc, box *sub, box *sup)
+{
+ list_box *b = nuc->to_list_box();
+ if (b != 0) {
+ b->list.p[b->list.len-1] = make_script_box(b->list.p[b->list.len - 1],
+ sub,
+ sup);
+ return b;
+ }
+ else
+ return new script_box(nuc, sub, sup);
+}
+
+script_box::script_box(box *pp, box *qq, box *rr)
+: pointer_box(pp), sub(qq), sup(rr)
+{
+}
+
+script_box::~script_box()
+{
+ delete sub;
+ delete sup;
+}
+
+int script_box::left_is_italic()
+{
+ return p->left_is_italic();
+}
+
+int script_box::compute_metrics(int style)
+{
+ int res = p->compute_metrics(style);
+ p->compute_subscript_kern();
+ printf(".nr " SIZE_FORMAT " \\n[.s]\n", uid);
+ if (!(style <= SCRIPT_STYLE && one_size_reduction_flag))
+ set_script_size();
+ printf(".nr " SMALL_SIZE_FORMAT " \\n[.s]\n", uid);
+ if (sub != 0)
+ sub->compute_metrics(cramped_style(script_style(style)));
+ if (sup != 0)
+ sup->compute_metrics(script_style(style));
+ // 18a
+ if (p->is_char()) {
+ printf(".nr " SUP_RAISE_FORMAT " 0\n", uid);
+ printf(".nr " SUB_LOWER_FORMAT " 0\n", uid);
+ }
+ else {
+ printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
+ uid, p->uid, sup_drop);
+ printf(".nr " SUB_LOWER_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n",
+ uid, p->uid, sub_drop);
+ }
+ printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
+ if (sup == 0) {
+ assert(sub != 0);
+ // 18b
+ printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM>?(\\n["
+ HEIGHT_FORMAT "]-(%dM*4/5))\n",
+ uid, uid, sub1, sub->uid, x_height);
+ }
+ else {
+ // sup != 0
+ // 18c
+ int p;
+ if (style == DISPLAY_STYLE)
+ p = sup1;
+ else if (style & 1) // not cramped
+ p = sup2;
+ else
+ p = sup3;
+ printf(".nr " SUP_RAISE_FORMAT " \\n[" SUP_RAISE_FORMAT
+ "]>?%dM>?(\\n[" DEPTH_FORMAT "]+(%dM/4))\n",
+ uid, uid, p, sup->uid, x_height);
+ // 18d
+ if (sub != 0) {
+ printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM\n",
+ uid, uid, sub2);
+ // 18e
+ printf(".nr " TEMP_REG " \\n[" DEPTH_FORMAT "]-\\n["
+ SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "]-\\n["
+ SUB_LOWER_FORMAT "]+(4*%dM)\n",
+ sup->uid, uid, sub->uid, uid, default_rule_thickness);
+ printf(".if \\n[" TEMP_REG "] \\{");
+ printf(".nr " SUB_LOWER_FORMAT " +\\n[" TEMP_REG "]\n", uid);
+ printf(".nr " TEMP_REG " (%dM*4/5)-\\n[" SUP_RAISE_FORMAT
+ "]+\\n[" DEPTH_FORMAT "]>?0\n",
+ x_height, uid, sup->uid);
+ printf(".nr " SUP_RAISE_FORMAT " +\\n[" TEMP_REG "]\n", uid);
+ printf(".nr " SUB_LOWER_FORMAT " -\\n[" TEMP_REG "]\n", uid);
+ printf(".\\}\n");
+ }
+ }
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid);
+ if (sub != 0 && sup != 0)
+ printf("+((\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]>?\\n["
+ WIDTH_FORMAT "])+%dM)>?0\n",
+ sub->uid, p->uid, sup->uid, script_space);
+ else if (sub != 0)
+ printf("+(\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]+%dM)>?0\n",
+ sub->uid, p->uid, script_space);
+ else if (sup != 0)
+ printf("+(\\n[" WIDTH_FORMAT "]+%dM)>?0\n", sup->uid, script_space);
+ else
+ printf("\n");
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]",
+ uid, p->uid);
+ if (sup != 0)
+ printf(">?(\\n[" SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "])",
+ uid, sup->uid);
+ if (sub != 0)
+ printf(">?(-\\n[" SUB_LOWER_FORMAT "]+\\n[" HEIGHT_FORMAT "])",
+ uid, sub->uid);
+ printf("\n");
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]",
+ uid, p->uid);
+ if (sub != 0)
+ printf(">?(\\n[" SUB_LOWER_FORMAT "]+\\n[" DEPTH_FORMAT "])",
+ uid, sub->uid);
+ if (sup != 0)
+ printf(">?(-\\n[" SUP_RAISE_FORMAT "]+\\n[" DEPTH_FORMAT "])",
+ uid, sup->uid);
+ printf("\n");
+ return res;
+}
+
+void script_box::output()
+{
+ p->output();
+ if (sup != 0) {
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
+ sup->output();
+ printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
+ printf(DELIMITER_CHAR);
+ }
+ if (sub != 0) {
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
+ printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
+ printf("\\h'-\\n[" SUB_KERN_FORMAT "]u'", p->uid);
+ sub->output();
+ printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
+ printf(DELIMITER_CHAR);
+ }
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
+ uid, p->uid);
+}
+
+void script_box::hint(unsigned flags)
+{
+ p->hint(flags & ~HINT_NEXT_IS_ITALIC);
+}
+
+void script_box::debug_print()
+{
+ fprintf(stderr, "{ ");
+ p->debug_print();
+ fprintf(stderr, " }");
+ if (sub) {
+ fprintf(stderr, " sub { ");
+ sub->debug_print();
+ fprintf(stderr, " }");
+ }
+ if (sup) {
+ fprintf(stderr, " sup { ");
+ sup->debug_print();
+ fprintf(stderr, " }");
+ }
+}
+
+void script_box::check_tabs(int level)
+{
+ if (sup)
+ sup->check_tabs(level + 1);
+ if (sub)
+ sub->check_tabs(level + 1);
+ p->check_tabs(level);
+}
diff --git a/src/preproc/eqn/special.cc b/src/preproc/eqn/special.cc
new file mode 100644
index 00000000..310261ae
--- /dev/null
+++ b/src/preproc/eqn/special.cc
@@ -0,0 +1,115 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+#define STRING_FORMAT PREFIX "str%d"
+
+#define SPECIAL_STRING "0s"
+#define SPECIAL_WIDTH_REG "0w"
+#define SPECIAL_HEIGHT_REG "0h"
+#define SPECIAL_DEPTH_REG "0d"
+#define SPECIAL_SUB_KERN_REG "0skern"
+#define SPECIAL_SKEW_REG "0skew"
+
+/*
+For example:
+
+.de Cl
+.ds 0s \Z'\\*[0s]'\v'\\n(0du'\D'l \\n(0wu -\\n(0hu-\\n(0du'\v'\\n(0hu'
+..
+.EQ
+define cancel 'special Cl'
+.EN
+*/
+
+
+class special_box : public pointer_box {
+ char *macro_name;
+public:
+ special_box(char *, box *);
+ ~special_box();
+ int compute_metrics(int);
+ void compute_subscript_kern();
+ void compute_skew();
+ void output();
+ void debug_print();
+};
+
+box *make_special_box(char *s, box *p)
+{
+ return new special_box(s, p);
+}
+
+special_box::special_box(char *s, box *pp) : pointer_box(pp), macro_name(s)
+{
+}
+
+special_box::~special_box()
+{
+ a_delete macro_name;
+}
+
+int special_box::compute_metrics(int style)
+{
+ int r = p->compute_metrics(style);
+ p->compute_subscript_kern();
+ p->compute_skew();
+ printf(".ds " SPECIAL_STRING " \"");
+ p->output();
+ printf("\n");
+ printf(".nr " SPECIAL_WIDTH_REG " 0\\n[" WIDTH_FORMAT "]\n", p->uid);
+ printf(".nr " SPECIAL_HEIGHT_REG " \\n[" HEIGHT_FORMAT "]\n", p->uid);
+ printf(".nr " SPECIAL_DEPTH_REG " \\n[" DEPTH_FORMAT "]\n", p->uid);
+ printf(".nr " SPECIAL_SUB_KERN_REG " \\n[" SUB_KERN_FORMAT "]\n", p->uid);
+ printf(".nr " SPECIAL_SKEW_REG " 0\\n[" SKEW_FORMAT "]\n", p->uid);
+ printf(".%s\n", macro_name);
+ printf(".rn " SPECIAL_STRING " " STRING_FORMAT "\n", uid);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" SPECIAL_WIDTH_REG "]\n", uid);
+ printf(".nr " HEIGHT_FORMAT " 0>?\\n[" SPECIAL_HEIGHT_REG "]\n", uid);
+ printf(".nr " DEPTH_FORMAT " 0>?\\n[" SPECIAL_DEPTH_REG "]\n", uid);
+ printf(".nr " SUB_KERN_FORMAT " 0>?\\n[" SPECIAL_SUB_KERN_REG "]\n", uid);
+ printf(".nr " SKEW_FORMAT " 0\\n[" SPECIAL_SKEW_REG "]\n", uid);
+ // User will have to change MARK_REG if appropriate.
+ return r;
+}
+
+void special_box::compute_subscript_kern()
+{
+ // Already computed in compute_metrics(), so do nothing.
+}
+
+void special_box::compute_skew()
+{
+ // Already computed in compute_metrics(), so do nothing.
+}
+
+void special_box::output()
+{
+ printf("\\*[" STRING_FORMAT "]", uid);
+}
+
+void special_box::debug_print()
+{
+ fprintf(stderr, "special %s { ", macro_name);
+ p->debug_print();
+ fprintf(stderr, " }");
+}
diff --git a/src/preproc/eqn/sqrt.cc b/src/preproc/eqn/sqrt.cc
new file mode 100644
index 00000000..6109ffea
--- /dev/null
+++ b/src/preproc/eqn/sqrt.cc
@@ -0,0 +1,179 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+
+
+class sqrt_box : public pointer_box {
+public:
+ sqrt_box(box *);
+ int compute_metrics(int style);
+ void output();
+ void debug_print();
+ void check_tabs(int);
+};
+
+box *make_sqrt_box(box *pp)
+{
+ return new sqrt_box(pp);
+}
+
+sqrt_box::sqrt_box(box *pp) : pointer_box(pp)
+{
+}
+
+#define SQRT_CHAR "\\(sr"
+#define RADICAL_EXTENSION_CHAR "\\[radicalex]"
+
+#define SQRT_CHAIN "\\[sr\\\\n[" INDEX_REG "]]"
+#define BAR_CHAIN "\\[radicalex\\\\n[" INDEX_REG "]]"
+
+int sqrt_box::compute_metrics(int style)
+{
+ // 11
+ int r = p->compute_metrics(cramped_style(style));
+ printf(".nr " TEMP_REG " \\n[" HEIGHT_FORMAT "]+\\n[" DEPTH_FORMAT
+ "]+%dM+(%dM/4)\n",
+ p->uid, p->uid, default_rule_thickness,
+ (style > SCRIPT_STYLE ? x_height : default_rule_thickness));
+ printf(".nr " SIZE_FORMAT " \\n[.s]\n", uid);
+ printf(".ds " SQRT_STRING_FORMAT " " SQRT_CHAR "\n", uid);
+ printf(".ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n");
+ printf(".nr " SQRT_WIDTH_FORMAT
+ " 0\\w" DELIMITER_CHAR SQRT_CHAR DELIMITER_CHAR "\n",
+ uid);
+ printf(".if \\n[rst]-\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{",
+ default_rule_thickness);
+
+ printf(".nr " INDEX_REG " 0\n"
+ ".de " TEMP_MACRO "\n"
+ ".ie c" SQRT_CHAIN " \\{"
+ ".ds " SQRT_STRING_FORMAT " " SQRT_CHAIN "\n"
+ ".ie c" BAR_CHAIN " .ds " BAR_STRING " " BAR_CHAIN "\n"
+ ".el .ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n"
+ ".nr " SQRT_WIDTH_FORMAT
+ " 0\\w" DELIMITER_CHAR SQRT_CHAIN DELIMITER_CHAR "\n"
+ ".if \\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{"
+ ".nr " INDEX_REG " +1\n"
+ "." TEMP_MACRO "\n"
+ ".\\}\\}\n"
+ ".el .nr " INDEX_REG " 0-1\n"
+ "..\n"
+ "." TEMP_MACRO "\n",
+ uid, uid, default_rule_thickness);
+
+ printf(".if \\n[" INDEX_REG "]<0 \\{");
+
+ // Determine the maximum point size
+ printf(".ps 1000\n");
+ printf(".nr " MAX_SIZE_REG " \\n[.s]\n");
+ printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
+ // We define a macro that will increase the current point size
+ // until we get a radical sign that's tall enough or we reach
+ // the maximum point size.
+ printf(".de " TEMP_MACRO "\n"
+ ".nr " SQRT_WIDTH_FORMAT
+ " 0\\w" DELIMITER_CHAR "\\*[" SQRT_STRING_FORMAT "]" DELIMITER_CHAR "\n"
+ ".if \\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "]"
+ "&(\\\\n[.s]<\\n[" MAX_SIZE_REG "]) \\{"
+ ".ps +1\n"
+ "." TEMP_MACRO "\n"
+ ".\\}\n"
+ "..\n"
+ "." TEMP_MACRO "\n",
+ uid, uid, default_rule_thickness);
+
+ printf(".\\}\\}\n");
+
+ printf(".nr " SMALL_SIZE_FORMAT " \\n[.s]\n", uid);
+ // set TEMP_REG to the amount by which the radical sign is too big
+ printf(".nr " TEMP_REG " \\n[rst]-\\n[rsb]-%dM-\\n[" TEMP_REG "]\n",
+ default_rule_thickness);
+ // If TEMP_REG is negative, the bottom of the radical sign should
+ // be -TEMP_REG above the bottom of p. If it's positive, the bottom
+ // of the radical sign should be TEMP_REG/2 below the bottom of p.
+ // This calculates the amount by which the baseline of the radical
+ // should be raised.
+ printf(".nr " SUP_RAISE_FORMAT " (-\\n[" TEMP_REG "]>?(-\\n[" TEMP_REG "]/2))"
+ "-\\n[rsb]-\\n[" DEPTH_FORMAT "]\n", uid, p->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
+ ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
+ uid, p->uid, uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
+ ">?(-\\n[" SUP_RAISE_FORMAT "]-\\n[rsb])\n",
+ uid, p->uid, uid);
+ // Do this last, so we don't lose height and depth information on
+ // the radical sign.
+ // Remember that the width of the bar might be greater than the width of p.
+
+ printf(".nr " TEMP_REG " "
+ "\\n[" WIDTH_FORMAT "]"
+ ">?\\w" DELIMITER_CHAR "\\*[" BAR_STRING "]" DELIMITER_CHAR "\n",
+ p->uid);
+ printf(".as " SQRT_STRING_FORMAT " "
+ "\\l'\\n[" TEMP_REG "]u\\&\\*[" BAR_STRING "]'\n",
+ uid);
+ printf(".nr " WIDTH_FORMAT " \\n[" TEMP_REG "]"
+ "+\\n[" SQRT_WIDTH_FORMAT "]\n",
+ uid, uid);
+
+ if (r)
+ printf(".nr " MARK_REG " +\\n[" SQRT_WIDTH_FORMAT "]\n", uid);
+ // the top of the bar might be higher than the top of the radical sign
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
+ ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
+ uid, p->uid, uid);
+ // put a bit of extra space above the bar
+ printf(".nr " HEIGHT_FORMAT " +%dM\n", uid, default_rule_thickness);
+ printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
+ return r;
+}
+
+void sqrt_box::output()
+{
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
+ printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
+ printf("\\*[" SQRT_STRING_FORMAT "]", uid);
+ printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
+ printf(DELIMITER_CHAR);
+
+ printf("\\Z" DELIMITER_CHAR);
+ printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u"
+ "+\\n[" SQRT_WIDTH_FORMAT "]u/2u'",
+ uid, p->uid, uid);
+ p->output();
+ printf(DELIMITER_CHAR);
+
+ printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
+}
+
+void sqrt_box::debug_print()
+{
+ fprintf(stderr, "sqrt { ");
+ p->debug_print();
+ fprintf(stderr, " }");
+}
+
+void sqrt_box::check_tabs(int level)
+{
+ p->check_tabs(level + 1);
+}
diff --git a/src/preproc/eqn/text.cc b/src/preproc/eqn/text.cc
new file mode 100644
index 00000000..b0f1700c
--- /dev/null
+++ b/src/preproc/eqn/text.cc
@@ -0,0 +1,528 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "eqn.h"
+#include "pbox.h"
+#include "ptable.h"
+
+class char_box : public simple_box {
+ unsigned char c;
+ char next_is_italic;
+ char prev_is_italic;
+public:
+ char_box(unsigned char);
+ void debug_print();
+ void output();
+ int is_char();
+ int left_is_italic();
+ int right_is_italic();
+ void hint(unsigned);
+ void handle_char_type(int, int);
+};
+
+class special_char_box : public simple_box {
+ char *s;
+public:
+ special_char_box(const char *);
+ ~special_char_box();
+ void output();
+ void debug_print();
+ int is_char();
+ void handle_char_type(int, int);
+};
+
+const char *spacing_type_table[] = {
+ "ordinary",
+ "operator",
+ "binary",
+ "relation",
+ "opening",
+ "closing",
+ "punctuation",
+ "inner",
+ "suppress",
+ 0,
+};
+
+const int DIGIT_TYPE = 0;
+const int LETTER_TYPE = 1;
+
+const char *font_type_table[] = {
+ "digit",
+ "letter",
+ 0,
+};
+
+struct char_info {
+ int spacing_type;
+ int font_type;
+ char_info();
+};
+
+char_info::char_info()
+: spacing_type(ORDINARY_TYPE), font_type(DIGIT_TYPE)
+{
+}
+
+static char_info char_table[256];
+
+declare_ptable(char_info)
+implement_ptable(char_info)
+
+PTABLE(char_info) special_char_table;
+
+static int get_special_char_spacing_type(const char *ch)
+{
+ char_info *p = special_char_table.lookup(ch);
+ return p ? p->spacing_type : ORDINARY_TYPE;
+}
+
+static int get_special_char_font_type(const char *ch)
+{
+ char_info *p = special_char_table.lookup(ch);
+ return p ? p->font_type : DIGIT_TYPE;
+}
+
+static void set_special_char_type(const char *ch, int st, int ft)
+{
+ char_info *p = special_char_table.lookup(ch);
+ if (!p) {
+ p = new char_info;
+ special_char_table.define(ch, p);
+ }
+ if (st >= 0)
+ p->spacing_type = st;
+ if (ft >= 0)
+ p->font_type = ft;
+}
+
+void init_char_table()
+{
+ set_special_char_type("pl", 2, -1); // binary
+ set_special_char_type("mi", 2, -1);
+ set_special_char_type("eq", 3, -1); // relation
+ set_special_char_type("<=", 3, -1);
+ set_special_char_type(">=", 3, -1);
+ char_table['}'].spacing_type = 5; // closing
+ char_table[')'].spacing_type = 5;
+ char_table[']'].spacing_type = 5;
+ char_table['{'].spacing_type = 4; // opening
+ char_table['('].spacing_type = 4;
+ char_table['['].spacing_type = 4;
+ char_table[','].spacing_type = 6; // punctuation
+ char_table[';'].spacing_type = 6;
+ char_table[':'].spacing_type = 6;
+ char_table['.'].spacing_type = 6;
+ char_table['>'].spacing_type = 3;
+ char_table['<'].spacing_type = 3;
+ char_table['*'].spacing_type = 2; // binary
+ for (int i = 0; i < 256; i++)
+ if (csalpha(i))
+ char_table[i].font_type = LETTER_TYPE;
+}
+
+static int lookup_spacing_type(const char *type)
+{
+ for (int i = 0; spacing_type_table[i] != 0; i++)
+ if (strcmp(spacing_type_table[i], type) == 0)
+ return i;
+ return -1;
+}
+
+static int lookup_font_type(const char *type)
+{
+ for (int i = 0; font_type_table[i] != 0; i++)
+ if (strcmp(font_type_table[i], type) == 0)
+ return i;
+ return -1;
+}
+
+void box::set_spacing_type(char *type)
+{
+ int t = lookup_spacing_type(type);
+ if (t < 0)
+ error("unrecognised type `%1'", type);
+ else
+ spacing_type = t;
+ a_delete type;
+}
+
+char_box::char_box(unsigned char cc)
+: c(cc), next_is_italic(0), prev_is_italic(0)
+{
+ spacing_type = char_table[c].spacing_type;
+}
+
+void char_box::hint(unsigned flags)
+{
+ if (flags & HINT_PREV_IS_ITALIC)
+ prev_is_italic = 1;
+ if (flags & HINT_NEXT_IS_ITALIC)
+ next_is_italic = 1;
+}
+
+void char_box::output()
+{
+ int font_type = char_table[c].font_type;
+ if (font_type != LETTER_TYPE)
+ printf("\\f[%s]", current_roman_font);
+ if (!prev_is_italic)
+ fputs("\\,", stdout);
+ if (c == '\\')
+ fputs("\\e", stdout);
+ else
+ putchar(c);
+ if (!next_is_italic)
+ fputs("\\/", stdout);
+ else
+ fputs("\\&", stdout); // suppress ligaturing and kerning
+ if (font_type != LETTER_TYPE)
+ fputs("\\fP", stdout);
+}
+
+int char_box::left_is_italic()
+{
+ int font_type = char_table[c].font_type;
+ return font_type == LETTER_TYPE;
+}
+
+int char_box::right_is_italic()
+{
+ int font_type = char_table[c].font_type;
+ return font_type == LETTER_TYPE;
+}
+
+int char_box::is_char()
+{
+ return 1;
+}
+
+void char_box::debug_print()
+{
+ if (c == '\\') {
+ putc('\\', stderr);
+ putc('\\', stderr);
+ }
+ else
+ putc(c, stderr);
+}
+
+special_char_box::special_char_box(const char *t)
+{
+ s = strsave(t);
+ spacing_type = get_special_char_spacing_type(s);
+}
+
+special_char_box::~special_char_box()
+{
+ a_delete s;
+}
+
+void special_char_box::output()
+{
+ int font_type = get_special_char_font_type(s);
+ if (font_type != LETTER_TYPE)
+ printf("\\f[%s]", current_roman_font);
+ printf("\\,\\[%s]\\/", s);
+ if (font_type != LETTER_TYPE)
+ printf("\\fP");
+}
+
+int special_char_box::is_char()
+{
+ return 1;
+}
+
+void special_char_box::debug_print()
+{
+ fprintf(stderr, "\\[%s]", s);
+}
+
+
+void char_box::handle_char_type(int st, int ft)
+{
+ if (st >= 0)
+ char_table[c].spacing_type = st;
+ if (ft >= 0)
+ char_table[c].font_type = ft;
+}
+
+void special_char_box::handle_char_type(int st, int ft)
+{
+ set_special_char_type(s, st, ft);
+}
+
+void set_char_type(const char *type, char *ch)
+{
+ assert(ch != 0);
+ int st = lookup_spacing_type(type);
+ int ft = lookup_font_type(type);
+ if (st < 0 && ft < 0) {
+ error("bad character type `%1'", type);
+ a_delete ch;
+ return;
+ }
+ box *b = split_text(ch);
+ b->handle_char_type(st, ft);
+ delete b;
+}
+
+/* We give primes special treatment so that in ``x' sub 2'', the ``2''
+will be tucked under the prime */
+
+class prime_box : public pointer_box {
+ box *pb;
+public:
+ prime_box(box *);
+ ~prime_box();
+ int compute_metrics(int style);
+ void output();
+ void compute_subscript_kern();
+ void debug_print();
+ void handle_char_type(int, int);
+};
+
+box *make_prime_box(box *pp)
+{
+ return new prime_box(pp);
+}
+
+prime_box::prime_box(box *pp) : pointer_box(pp)
+{
+ pb = new special_char_box("fm");
+}
+
+prime_box::~prime_box()
+{
+ delete pb;
+}
+
+int prime_box::compute_metrics(int style)
+{
+ int res = p->compute_metrics(style);
+ pb->compute_metrics(style);
+ printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]"
+ "+\\n[" WIDTH_FORMAT "]\n",
+ uid, p->uid, pb->uid);
+ printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
+ ">?\\n[" HEIGHT_FORMAT "]\n",
+ uid, p->uid, pb->uid);
+ printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
+ ">?\\n[" DEPTH_FORMAT "]\n",
+ uid, p->uid, pb->uid);
+ return res;
+}
+
+void prime_box::compute_subscript_kern()
+{
+ p->compute_subscript_kern();
+ printf(".nr " SUB_KERN_FORMAT " 0\\n[" WIDTH_FORMAT "]"
+ "+\\n[" SUB_KERN_FORMAT "]>?0\n",
+ uid, pb->uid, p->uid);
+}
+
+void prime_box::output()
+{
+ p->output();
+ pb->output();
+}
+
+void prime_box::handle_char_type(int st, int ft)
+{
+ p->handle_char_type(st, ft);
+ pb->handle_char_type(st, ft);
+}
+
+void prime_box::debug_print()
+{
+ p->debug_print();
+ putc('\'', stderr);
+}
+
+box *split_text(char *text)
+{
+ list_box *lb = 0;
+ box *fb = 0;
+ char *s = text;
+ while (*s != '\0') {
+ char c = *s++;
+ box *b = 0;
+ switch (c) {
+ case '+':
+ b = new special_char_box("pl");
+ break;
+ case '-':
+ b = new special_char_box("mi");
+ break;
+ case '=':
+ b = new special_char_box("eq");
+ break;
+ case '\'':
+ b = new special_char_box("fm");
+ break;
+ case '<':
+ if (*s == '=') {
+ b = new special_char_box("<=");
+ s++;
+ break;
+ }
+ goto normal_char;
+ case '>':
+ if (*s == '=') {
+ b = new special_char_box(">=");
+ s++;
+ break;
+ }
+ goto normal_char;
+ case '\\':
+ if (*s == '\0') {
+ lex_error("bad escape");
+ break;
+ }
+ c = *s++;
+ switch (c) {
+ case '(':
+ {
+ char buf[3];
+ if (*s != '\0') {
+ buf[0] = *s++;
+ if (*s != '\0') {
+ buf[1] = *s++;
+ buf[2] = '\0';
+ b = new special_char_box(buf);
+ }
+ else {
+ lex_error("bad escape");
+ }
+ }
+ else {
+ lex_error("bad escape");
+ }
+ }
+ break;
+ case '[':
+ {
+ char *ch = s;
+ while (*s != ']' && *s != '\0')
+ s++;
+ if (*s == '\0')
+ lex_error("bad escape");
+ else {
+ *s++ = '\0';
+ b = new special_char_box(ch);
+ }
+ }
+ break;
+ case 'f':
+ case 'g':
+ case 'k':
+ case 'n':
+ case '*':
+ {
+ char *escape_start = s - 2;
+ switch (*s) {
+ case '(':
+ if (*++s != '\0')
+ ++s;
+ break;
+ case '[':
+ for (++s; *s != '\0' && *s != ']'; s++)
+ ;
+ break;
+ }
+ if (*s == '\0')
+ lex_error("bad escape");
+ else {
+ ++s;
+ char *buf = new char[s - escape_start + 1];
+ memcpy(buf, escape_start, s - escape_start);
+ buf[s - escape_start] = '\0';
+ b = new quoted_text_box(buf);
+ }
+ }
+ break;
+ case '-':
+ case '_':
+ {
+ char buf[2];
+ buf[0] = c;
+ buf[1] = '\0';
+ b = new special_char_box(buf);
+ }
+ break;
+ case '`':
+ b = new special_char_box("ga");
+ break;
+ case '\'':
+ b = new special_char_box("aa");
+ break;
+ case 'e':
+ case '\\':
+ b = new char_box('\\');
+ break;
+ case '^':
+ case '|':
+ case '0':
+ {
+ char buf[3];
+ buf[0] = '\\';
+ buf[1] = c;
+ buf[2] = '\0';
+ b = new quoted_text_box(strsave(buf));
+ break;
+ }
+ default:
+ lex_error("unquoted escape");
+ b = new quoted_text_box(strsave(s - 2));
+ s = strchr(s, '\0');
+ break;
+ }
+ break;
+ default:
+ normal_char:
+ b = new char_box(c);
+ break;
+ }
+ while (*s == '\'') {
+ if (b == 0)
+ b = new quoted_text_box(0);
+ b = new prime_box(b);
+ s++;
+ }
+ if (b != 0) {
+ if (lb != 0)
+ lb->append(b);
+ else if (fb != 0) {
+ lb = new list_box(fb);
+ lb->append(b);
+ }
+ else
+ fb = b;
+ }
+ }
+ delete text;
+ if (lb != 0)
+ return lb;
+ else if (fb != 0)
+ return fb;
+ else
+ return new quoted_text_box(0);
+}
+
diff --git a/src/preproc/pic/Makefile.sub b/src/preproc/pic/Makefile.sub
new file mode 100644
index 00000000..a15c030e
--- /dev/null
+++ b/src/preproc/pic/Makefile.sub
@@ -0,0 +1,31 @@
+PROG=pic
+MAN1=pic.n
+XLIBS=$(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=\
+ pic.o \
+ lex.o \
+ main.o \
+ object.o \
+ common.o \
+ troff.o \
+ tex.o
+ # fig.o
+CCSRCS=\
+ $(srcdir)/lex.cc \
+ $(srcdir)/main.cc \
+ $(srcdir)/object.cc \
+ $(srcdir)/common.cc \
+ $(srcdir)/troff.cc \
+ $(srcdir)/tex.cc
+HDRS=\
+ $(srcdir)/common.h \
+ $(srcdir)/object.h \
+ $(srcdir)/output.h \
+ $(srcdir)/pic.h \
+ $(srcdir)/position.h \
+ $(srcdir)/text.h
+GRAM=$(srcdir)/pic.y
+YTABC=$(srcdir)/pic.cc
+YTABH=$(srcdir)/pic.tab.h
+NAMEPREFIX=$(g)
diff --git a/src/preproc/pic/TODO b/src/preproc/pic/TODO
new file mode 100644
index 00000000..2346b575
--- /dev/null
+++ b/src/preproc/pic/TODO
@@ -0,0 +1,37 @@
+Dotted and dashed ellipses.
+
+In troff mode, dotted and dashed splines.
+
+Make DELIMITED have type lstr; this would allow us to give better
+error messages for problems within the body of for and if constructs.
+
+In troff mode without -x, fake \D't' with .ps commands.
+
+Perhaps an option to set command char.
+
+Add an output class for dumb line printers. It wouldn't be pretty but
+it would be better than nothing. Integrate it with texinfo. Useful
+for groff -Tascii as well.
+
+Option to allow better positioning of arrowheads on arcs.
+
+Perhaps add PostScript output mode.
+
+Change the interface to the output class so that output devices have
+the opportunity to handle arrowheads themselves.
+
+Consider whether the line thickness should scale.
+
+Consider whether the test in a for loop should be fuzzy (as it
+apparently is in grap).
+
+Possibly change fillval so that zero is black.
+
+Provide a way of getting text blocks (positioned with `.in' rather
+than \h), into pic. Should be possible to use block of diverted text
+in pic. Possibly something similar to T{ and T} in tbl.
+
+Option to provide macro backtraces.
+
+Have a path that is searched by `copy' statement. Set by environment
+variable or command line option.
diff --git a/src/preproc/pic/common.cc b/src/preproc/pic/common.cc
new file mode 100644
index 00000000..e83ef312
--- /dev/null
+++ b/src/preproc/pic/common.cc
@@ -0,0 +1,497 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "pic.h"
+#include "common.h"
+
+// output a dashed circle as a series of arcs
+
+void common_output::dashed_circle(const position &cent, double rad,
+ const line_type &lt)
+{
+ assert(lt.type == line_type::dashed);
+ line_type slt = lt;
+ slt.type = line_type::solid;
+ double dash_angle = lt.dash_width/rad;
+ int ndashes;
+ double gap_angle;
+ if (dash_angle >= M_PI/4.0) {
+ if (dash_angle < M_PI/2.0) {
+ gap_angle = M_PI/2.0 - dash_angle;
+ ndashes = 4;
+ }
+ else if (dash_angle < M_PI) {
+ gap_angle = M_PI - dash_angle;
+ ndashes = 2;
+ }
+ else {
+ circle(cent, rad, slt, -1.0);
+ return;
+ }
+ }
+ else {
+ ndashes = 4*int(ceil(M_PI/(4.0*dash_angle)));
+ gap_angle = (M_PI*2.0)/ndashes - dash_angle;
+ }
+ for (int i = 0; i < ndashes; i++) {
+ double start_angle = i*(dash_angle+gap_angle) - dash_angle/2.0;
+ solid_arc(cent, rad, start_angle, start_angle + dash_angle, lt);
+ }
+}
+
+// output a dotted circle as a series of dots
+
+void common_output::dotted_circle(const position &cent, double rad,
+ const line_type &lt)
+{
+ assert(lt.type == line_type::dotted);
+ double gap_angle = lt.dash_width/rad;
+ int ndots;
+ if (gap_angle >= M_PI/2.0) {
+ // always have at least 2 dots
+ gap_angle = M_PI;
+ ndots = 2;
+ }
+ else {
+ ndots = 4*int(M_PI/(2.0*gap_angle));
+ gap_angle = (M_PI*2.0)/ndots;
+ }
+ double ang = 0.0;
+ for (int i = 0; i < ndots; i++, ang += gap_angle)
+ dot(cent + position(cos(ang), sin(ang))*rad, lt);
+}
+
+// return non-zero iff we can compute a center
+
+int compute_arc_center(const position &start, const position &cent,
+ const position &end, position *result)
+{
+ // This finds the point along the vector from start to cent that
+ // is equidistant between start and end.
+ distance c = cent - start;
+ distance e = end - start;
+ double n = c*e;
+ if (n == 0.0)
+ return 0;
+ *result = start + c*((e*e)/(2.0*n));
+ return 1;
+}
+
+// output a dashed arc as a series of arcs
+
+void common_output::dashed_arc(const position &start, const position &cent,
+ const position &end, const line_type &lt)
+{
+ assert(lt.type == line_type::dashed);
+ position c;
+ if (!compute_arc_center(start, cent, end, &c)) {
+ line(start, &end, 1, lt);
+ return;
+ }
+ distance start_offset = start - c;
+ distance end_offset = end - c;
+ double start_angle = atan2(start_offset.y, start_offset.x);
+ double end_angle = atan2(end_offset.y, end_offset.x);
+ double rad = hypot(c - start);
+ double dash_angle = lt.dash_width/rad;
+ double total_angle = end_angle - start_angle;
+ while (total_angle < 0)
+ total_angle += M_PI + M_PI;
+ if (total_angle <= dash_angle*2.0) {
+ solid_arc(cent, rad, start_angle, end_angle, lt);
+ return;
+ }
+ int ndashes = int((total_angle - dash_angle)/(dash_angle*2.0) + .5);
+ double dash_and_gap_angle = (total_angle - dash_angle)/ndashes;
+ for (int i = 0; i <= ndashes; i++)
+ solid_arc(cent, rad, start_angle + i*dash_and_gap_angle,
+ start_angle + i*dash_and_gap_angle + dash_angle, lt);
+}
+
+// output a dotted arc as a series of dots
+
+void common_output::dotted_arc(const position &start, const position &cent,
+ const position &end, const line_type &lt)
+{
+ assert(lt.type == line_type::dotted);
+ position c;
+ if (!compute_arc_center(start, cent, end, &c)) {
+ line(start, &end, 1, lt);
+ return;
+ }
+ distance start_offset = start - c;
+ distance end_offset = end - c;
+ double start_angle = atan2(start_offset.y, start_offset.x);
+ double total_angle = atan2(end_offset.y, end_offset.x) - start_angle;
+ while (total_angle < 0)
+ total_angle += M_PI + M_PI;
+ double rad = hypot(c - start);
+ int ndots = int(total_angle/(lt.dash_width/rad) + .5);
+ if (ndots == 0)
+ dot(start, lt);
+ else {
+ for (int i = 0; i <= ndots; i++) {
+ double a = start_angle + (total_angle*i)/ndots;
+ dot(cent + position(cos(a), sin(a))*rad, lt);
+ }
+ }
+}
+
+void common_output::solid_arc(const position &cent, double rad,
+ double start_angle, double end_angle,
+ const line_type &lt)
+{
+ line_type slt = lt;
+ slt.type = line_type::solid;
+ arc(cent + position(cos(start_angle), sin(start_angle))*rad,
+ cent,
+ cent + position(cos(end_angle), sin(end_angle))*rad,
+ slt);
+}
+
+
+void common_output::rounded_box(const position &cent, const distance &dim,
+ double rad, const line_type &lt, double fill)
+{
+ if (fill >= 0.0)
+ filled_rounded_box(cent, dim, rad, fill);
+ switch (lt.type) {
+ case line_type::invisible:
+ break;
+ case line_type::dashed:
+ dashed_rounded_box(cent, dim, rad, lt);
+ break;
+ case line_type::dotted:
+ dotted_rounded_box(cent, dim, rad, lt);
+ break;
+ case line_type::solid:
+ solid_rounded_box(cent, dim, rad, lt);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+void common_output::dashed_rounded_box(const position &cent,
+ const distance &dim, double rad,
+ const line_type &lt)
+{
+ line_type slt = lt;
+ slt.type = line_type::solid;
+
+ double hor_length = dim.x + (M_PI/2.0 - 2.0)*rad;
+ int n_hor_dashes = int(hor_length/(lt.dash_width*2.0) + .5);
+ double hor_gap_width = (n_hor_dashes != 0
+ ? hor_length/n_hor_dashes - lt.dash_width
+ : 0.0);
+
+ double vert_length = dim.y + (M_PI/2.0 - 2.0)*rad;
+ int n_vert_dashes = int(vert_length/(lt.dash_width*2.0) + .5);
+ double vert_gap_width = (n_vert_dashes != 0
+ ? vert_length/n_vert_dashes - lt.dash_width
+ : 0.0);
+ // Note that each corner arc has to be split into two for dashing,
+ // because one part is dashed using vert_gap_width, and the other
+ // using hor_gap_width.
+ double offset = lt.dash_width/2.0;
+ dash_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
+ -M_PI/4.0, 0, slt, lt.dash_width, vert_gap_width, &offset);
+ dash_line(cent + position(dim.x/2.0, -dim.y/2.0 + rad),
+ cent + position(dim.x/2.0, dim.y/2.0 - rad),
+ slt, lt.dash_width, vert_gap_width, &offset);
+ dash_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
+ 0, M_PI/4.0, slt, lt.dash_width, vert_gap_width, &offset);
+
+ offset = lt.dash_width/2.0;
+ dash_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
+ M_PI/4.0, M_PI/2, slt, lt.dash_width, hor_gap_width, &offset);
+ dash_line(cent + position(dim.x/2.0 - rad, dim.y/2.0),
+ cent + position(-dim.x/2.0 + rad, dim.y/2.0),
+ slt, lt.dash_width, hor_gap_width, &offset);
+ dash_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
+ M_PI/2, 3*M_PI/4.0, slt, lt.dash_width, hor_gap_width, &offset);
+
+ offset = lt.dash_width/2.0;
+ dash_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
+ 3.0*M_PI/4.0, M_PI, slt, lt.dash_width, vert_gap_width, &offset);
+ dash_line(cent + position(-dim.x/2.0, dim.y/2.0 - rad),
+ cent + position(-dim.x/2.0, -dim.y/2.0 + rad),
+ slt, lt.dash_width, vert_gap_width, &offset);
+ dash_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
+ M_PI, 5.0*M_PI/4.0, slt, lt.dash_width, vert_gap_width, &offset);
+
+ offset = lt.dash_width/2.0;
+ dash_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
+ 5*M_PI/4.0, 3*M_PI/2.0, slt, lt.dash_width, hor_gap_width, &offset);
+ dash_line(cent + position(-dim.x/2.0 + rad, -dim.y/2.0),
+ cent + position(dim.x/2.0 - rad, -dim.y/2.0),
+ slt, lt.dash_width, hor_gap_width, &offset);
+ dash_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
+ 3*M_PI/2, 7*M_PI/4, slt, lt.dash_width, hor_gap_width, &offset);
+}
+
+// Used by dashed_rounded_box.
+
+void common_output::dash_arc(const position &cent, double rad,
+ double start_angle, double end_angle,
+ const line_type &lt,
+ double dash_width, double gap_width,
+ double *offsetp)
+{
+ double length = (end_angle - start_angle)*rad;
+ double pos = 0.0;
+ for (;;) {
+ if (*offsetp >= dash_width) {
+ double rem = dash_width + gap_width - *offsetp;
+ if (pos + rem > length) {
+ *offsetp += length - pos;
+ break;
+ }
+ else {
+ pos += rem;
+ *offsetp = 0.0;
+ }
+ }
+ else {
+ double rem = dash_width - *offsetp;
+ if (pos + rem > length) {
+ solid_arc(cent, rad, start_angle + pos/rad, end_angle, lt);
+ *offsetp += length - pos;
+ break;
+ }
+ else {
+ solid_arc(cent, rad, start_angle + pos/rad,
+ start_angle + (pos + rem)/rad, lt);
+ pos += rem;
+ *offsetp = dash_width;
+ }
+ }
+ }
+}
+
+// Used by dashed_rounded_box.
+
+void common_output::dash_line(const position &start, const position &end,
+ const line_type &lt,
+ double dash_width, double gap_width,
+ double *offsetp)
+{
+ distance dist = end - start;
+ double length = hypot(dist);
+ if (length == 0.0)
+ return;
+ double pos = 0.0;
+ for (;;) {
+ if (*offsetp >= dash_width) {
+ double rem = dash_width + gap_width - *offsetp;
+ if (pos + rem > length) {
+ *offsetp += length - pos;
+ break;
+ }
+ else {
+ pos += rem;
+ *offsetp = 0.0;
+ }
+ }
+ else {
+ double rem = dash_width - *offsetp;
+ if (pos + rem > length) {
+ line(start + dist*(pos/length), &end, 1, lt);
+ *offsetp += length - pos;
+ break;
+ }
+ else {
+ position p(start + dist*((pos + rem)/length));
+ line(start + dist*(pos/length), &p, 1, lt);
+ pos += rem;
+ *offsetp = dash_width;
+ }
+ }
+ }
+}
+
+void common_output::dotted_rounded_box(const position &cent,
+ const distance &dim, double rad,
+ const line_type &lt)
+{
+ line_type slt = lt;
+ slt.type = line_type::solid;
+
+ double hor_length = dim.x + (M_PI/2.0 - 2.0)*rad;
+ int n_hor_dots = int(hor_length/lt.dash_width + .5);
+ double hor_gap_width = (n_hor_dots != 0
+ ? hor_length/n_hor_dots
+ : lt.dash_width);
+
+ double vert_length = dim.y + (M_PI/2.0 - 2.0)*rad;
+ int n_vert_dots = int(vert_length/lt.dash_width + .5);
+ double vert_gap_width = (n_vert_dots != 0
+ ? vert_length/n_vert_dots
+ : lt.dash_width);
+ double epsilon = lt.dash_width/(rad*100.0);
+
+ double offset = 0.0;
+ dot_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
+ -M_PI/4.0, 0, slt, vert_gap_width, &offset);
+ dot_line(cent + position(dim.x/2.0, -dim.y/2.0 + rad),
+ cent + position(dim.x/2.0, dim.y/2.0 - rad),
+ slt, vert_gap_width, &offset);
+ dot_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
+ 0, M_PI/4.0 - epsilon, slt, vert_gap_width, &offset);
+
+ offset = 0.0;
+ dot_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
+ M_PI/4.0, M_PI/2, slt, hor_gap_width, &offset);
+ dot_line(cent + position(dim.x/2.0 - rad, dim.y/2.0),
+ cent + position(-dim.x/2.0 + rad, dim.y/2.0),
+ slt, hor_gap_width, &offset);
+ dot_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
+ M_PI/2, 3*M_PI/4.0 - epsilon, slt, hor_gap_width, &offset);
+
+ offset = 0.0;
+ dot_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
+ 3.0*M_PI/4.0, M_PI, slt, vert_gap_width, &offset);
+ dot_line(cent + position(-dim.x/2.0, dim.y/2.0 - rad),
+ cent + position(-dim.x/2.0, -dim.y/2.0 + rad),
+ slt, vert_gap_width, &offset);
+ dot_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
+ M_PI, 5.0*M_PI/4.0 - epsilon, slt, vert_gap_width, &offset);
+
+ offset = 0.0;
+ dot_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
+ 5*M_PI/4.0, 3*M_PI/2.0, slt, hor_gap_width, &offset);
+ dot_line(cent + position(-dim.x/2.0 + rad, -dim.y/2.0),
+ cent + position(dim.x/2.0 - rad, -dim.y/2.0),
+ slt, hor_gap_width, &offset);
+ dot_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
+ 3*M_PI/2, 7*M_PI/4 - epsilon, slt, hor_gap_width, &offset);
+}
+
+// Used by dotted_rounded_box.
+
+void common_output::dot_arc(const position &cent, double rad,
+ double start_angle, double end_angle,
+ const line_type &lt, double gap_width,
+ double *offsetp)
+{
+ double length = (end_angle - start_angle)*rad;
+ double pos = 0.0;
+ for (;;) {
+ if (*offsetp == 0.0) {
+ double ang = start_angle + pos/rad;
+ dot(cent + position(cos(ang), sin(ang))*rad, lt);
+ }
+ double rem = gap_width - *offsetp;
+ if (pos + rem > length) {
+ *offsetp += length - pos;
+ break;
+ }
+ else {
+ pos += rem;
+ *offsetp = 0.0;
+ }
+ }
+}
+
+// Used by dotted_rounded_box.
+
+void common_output::dot_line(const position &start, const position &end,
+ const line_type &lt, double gap_width,
+ double *offsetp)
+{
+ distance dist = end - start;
+ double length = hypot(dist);
+ if (length == 0.0)
+ return;
+ double pos = 0.0;
+ for (;;) {
+ if (*offsetp == 0.0)
+ dot(start + dist*(pos/length), lt);
+ double rem = gap_width - *offsetp;
+ if (pos + rem > length) {
+ *offsetp += length - pos;
+ break;
+ }
+ else {
+ pos += rem;
+ *offsetp = 0.0;
+ }
+ }
+}
+
+
+void common_output::solid_rounded_box(const position &cent,
+ const distance &dim, double rad,
+ const line_type &lt)
+{
+ position tem = cent - dim/2.0;
+ arc(tem + position(0.0, rad),
+ tem + position(rad, rad),
+ tem + position(rad, 0.0),
+ lt);
+ tem = cent + position(-dim.x/2.0, dim.y/2.0);
+ arc(tem + position(rad, 0.0),
+ tem + position(rad, -rad),
+ tem + position(0.0, -rad),
+ lt);
+ tem = cent + dim/2.0;
+ arc(tem + position(0.0, -rad),
+ tem + position(-rad, -rad),
+ tem + position(-rad, 0.0),
+ lt);
+ tem = cent + position(dim.x/2.0, -dim.y/2.0);
+ arc(tem + position(-rad, 0.0),
+ tem + position(-rad, rad),
+ tem + position(0.0, rad),
+ lt);
+ position end;
+ end = cent + position(-dim.x/2.0, dim.y/2.0 - rad);
+ line(cent - dim/2.0 + position(0.0, rad), &end, 1, lt);
+ end = cent + position(dim.x/2.0 - rad, dim.y/2.0);
+ line(cent + position(-dim.x/2.0 + rad, dim.y/2.0), &end, 1, lt);
+ end = cent + position(dim.x/2.0, -dim.y/2.0 + rad);
+ line(cent + position(dim.x/2.0, dim.y/2.0 - rad), &end, 1, lt);
+ end = cent + position(-dim.x/2.0 + rad, -dim.y/2.0);
+ line(cent + position(dim.x/2.0 - rad, -dim.y/2.0), &end, 1, lt);
+}
+
+void common_output::filled_rounded_box(const position &cent,
+ const distance &dim, double rad,
+ double fill)
+{
+ line_type ilt;
+ ilt.type = line_type::invisible;
+ circle(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad, ilt, fill);
+ circle(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad, ilt, fill);
+ circle(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad, ilt, fill);
+ circle(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad, ilt, fill);
+ position vec[4];
+ vec[0] = cent + position(dim.x/2.0, dim.y/2.0 - rad);
+ vec[1] = cent + position(-dim.x/2.0, dim.y/2.0 - rad);
+ vec[2] = cent + position(-dim.x/2.0, -dim.y/2.0 + rad);
+ vec[3] = cent + position(dim.x/2.0, -dim.y/2.0 + rad);
+ polygon(vec, 4, ilt, fill);
+ vec[0] = cent + position(dim.x/2.0 - rad, dim.y/2.0);
+ vec[1] = cent + position(-dim.x/2.0 + rad, dim.y/2.0);
+ vec[2] = cent + position(-dim.x/2.0 + rad, -dim.y/2.0);
+ vec[3] = cent + position(dim.x/2.0 - rad, -dim.y/2.0);
+ polygon(vec, 4, ilt, fill);
+}
diff --git a/src/preproc/pic/common.h b/src/preproc/pic/common.h
new file mode 100644
index 00000000..25a6e10c
--- /dev/null
+++ b/src/preproc/pic/common.h
@@ -0,0 +1,70 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+class common_output : public output {
+private:
+ void dash_line(const position &start, const position &end,
+ const line_type &lt, double dash_width, double gap_width,
+ double *offsetp);
+ void dash_arc(const position &cent, double rad,
+ double start_angle, double end_angle, const line_type &lt,
+ double dash_width, double gap_width, double *offsetp);
+ void dot_line(const position &start, const position &end,
+ const line_type &lt, double gap_width, double *offsetp);
+ void dot_arc(const position &cent, double rad,
+ double start_angle, double end_angle, const line_type &lt,
+ double gap_width, double *offsetp);
+protected:
+ virtual void dot(const position &, const line_type &) = 0;
+ void dashed_circle(const position &, double rad, const line_type &);
+ void dotted_circle(const position &, double rad, const line_type &);
+ void dashed_arc(const position &, const position &, const position &,
+ const line_type &);
+ void dotted_arc(const position &, const position &, const position &,
+ const line_type &);
+ virtual void solid_arc(const position &cent, double rad, double start_angle,
+ double end_angle, const line_type &lt);
+ void dashed_rounded_box(const position &, const distance &, double,
+ const line_type &);
+ void dotted_rounded_box(const position &, const distance &, double,
+ const line_type &);
+ void solid_rounded_box(const position &, const distance &, double,
+ const line_type &);
+ void filled_rounded_box(const position &, const distance &, double, double);
+public:
+ void start_picture(double sc, const position &ll, const position &ur) = 0;
+ void finish_picture() = 0;
+ void circle(const position &, double rad, const line_type &, double) = 0;
+ void text(const position &, text_piece *, int, double) = 0;
+ void line(const position &, const position *, int n, const line_type &) = 0;
+ void polygon(const position *, int n, const line_type &, double) = 0;
+ void spline(const position &, const position *, int n,
+ const line_type &) = 0;
+ void arc(const position &, const position &, const position &,
+ const line_type &) = 0;
+ void ellipse(const position &, const distance &,
+ const line_type &, double) = 0;
+ void rounded_box(const position &, const distance &, double,
+ const line_type &, double);
+};
+
+int compute_arc_center(const position &start, const position &cent,
+ const position &end, position *result);
+
diff --git a/src/preproc/pic/depend b/src/preproc/pic/depend
new file mode 100755
index 00000000..73ac3ab9
--- /dev/null
+++ b/src/preproc/pic/depend
@@ -0,0 +1,21 @@
+pic.tab.o : pic.tab.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \
+ ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \
+ output.h ../lib/ptable.h object.h
+lex.o : lex.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \
+ ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \
+ output.h ../lib/ptable.h object.h pic.tab.h
+main.o : main.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \
+ ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \
+ output.h
+object.o : object.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \
+ ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \
+ output.h ../lib/ptable.h object.h
+common.o : common.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \
+ ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \
+ output.h common.h
+troff.o : troff.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \
+ ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \
+ output.h common.h
+tex.o : tex.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \
+ ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \
+ output.h common.h
diff --git a/src/preproc/pic/lex.cc b/src/preproc/pic/lex.cc
new file mode 100644
index 00000000..238a62f4
--- /dev/null
+++ b/src/preproc/pic/lex.cc
@@ -0,0 +1,1939 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "pic.h"
+#include "ptable.h"
+#include "object.h"
+#include "pic.tab.h"
+
+declare_ptable(char)
+implement_ptable(char)
+
+PTABLE(char) macro_table;
+
+class macro_input : public input {
+ char *s;
+ char *p;
+public:
+ macro_input(const char *);
+ ~macro_input();
+ int get();
+ int peek();
+};
+
+class argument_macro_input : public input {
+ char *s;
+ char *p;
+ char *ap;
+ int argc;
+ char *argv[9];
+public:
+ argument_macro_input(const char *, int, char **);
+ ~argument_macro_input();
+ int get();
+ int peek();
+};
+
+input::input() : next(0)
+{
+}
+
+input::~input()
+{
+}
+
+int input::get_location(const char **, int *)
+{
+ return 0;
+}
+
+file_input::file_input(FILE *f, const char *fn)
+: fp(f), filename(fn), lineno(0), ptr("")
+{
+}
+
+file_input::~file_input()
+{
+ fclose(fp);
+}
+
+int file_input::read_line()
+{
+ for (;;) {
+ line.clear();
+ lineno++;
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ else if (illegal_input_char(c))
+ lex_error("illegal input character code %1", c);
+ else {
+ line += char(c);
+ if (c == '\n')
+ break;
+ }
+ }
+ if (line.length() == 0)
+ return 0;
+ if (!(line.length() >= 3 && line[0] == '.' && line[1] == 'P'
+ && (line[2] == 'S' || line[2] == 'E' || line[2] == 'F')
+ && (line.length() == 3 || line[3] == ' ' || line[3] == '\n'
+ || compatible_flag))) {
+ line += '\0';
+ ptr = line.contents();
+ return 1;
+ }
+ }
+}
+
+int file_input::get()
+{
+ if (*ptr != '\0' || read_line())
+ return (unsigned char)*ptr++;
+ else
+ return EOF;
+}
+
+int file_input::peek()
+{
+ if (*ptr != '\0' || read_line())
+ return (unsigned char)*ptr;
+ else
+ return EOF;
+}
+
+int file_input::get_location(const char **fnp, int *lnp)
+{
+ *fnp = filename;
+ *lnp = lineno;
+ return 1;
+}
+
+macro_input::macro_input(const char *str)
+{
+ p = s = strsave(str);
+}
+
+macro_input::~macro_input()
+{
+ a_delete s;
+}
+
+int macro_input::get()
+{
+ if (p == 0 || *p == '\0')
+ return EOF;
+ else
+ return (unsigned char)*p++;
+}
+
+int macro_input::peek()
+{
+ if (p == 0 || *p == '\0')
+ return EOF;
+ else
+ return (unsigned char)*p;
+}
+
+// Character representing $1. Must be illegal input character.
+#define ARG1 14
+
+char *process_body(const char *body)
+{
+ char *s = strsave(body);
+ int j = 0;
+ for (int i = 0; s[i] != '\0'; i++)
+ if (s[i] == '$' && s[i+1] >= '0' && s[i+1] <= '9') {
+ if (s[i+1] != '0')
+ s[j++] = ARG1 + s[++i] - '1';
+ }
+ else
+ s[j++] = s[i];
+ s[j] = '\0';
+ return s;
+}
+
+
+argument_macro_input::argument_macro_input(const char *body, int ac, char **av)
+: ap(0), argc(ac)
+{
+ for (int i = 0; i < argc; i++)
+ argv[i] = av[i];
+ p = s = process_body(body);
+}
+
+
+argument_macro_input::~argument_macro_input()
+{
+ for (int i = 0; i < argc; i++)
+ a_delete argv[i];
+ a_delete s;
+}
+
+int argument_macro_input::get()
+{
+ if (ap) {
+ if (*ap != '\0')
+ return (unsigned char)*ap++;
+ ap = 0;
+ }
+ if (p == 0)
+ return EOF;
+ while (*p >= ARG1 && *p <= ARG1 + 8) {
+ int i = *p++ - ARG1;
+ if (i < argc && argv[i] != 0 && argv[i][0] != '\0') {
+ ap = argv[i];
+ return (unsigned char)*ap++;
+ }
+ }
+ if (*p == '\0')
+ return EOF;
+ return (unsigned char)*p++;
+}
+
+int argument_macro_input::peek()
+{
+ if (ap) {
+ if (*ap != '\0')
+ return (unsigned char)*ap;
+ ap = 0;
+ }
+ if (p == 0)
+ return EOF;
+ while (*p >= ARG1 && *p <= ARG1 + 8) {
+ int i = *p++ - ARG1;
+ if (i < argc && argv[i] != 0 && argv[i][0] != '\0') {
+ ap = argv[i];
+ return (unsigned char)*ap;
+ }
+ }
+ if (*p == '\0')
+ return EOF;
+ return (unsigned char)*p;
+}
+
+class input_stack {
+ static input *current_input;
+ static int bol_flag;
+public:
+ static void push(input *);
+ static void clear();
+ static int get_char();
+ static int peek_char();
+ static int get_location(const char **fnp, int *lnp);
+ static void push_back(unsigned char c, int was_bol = 0);
+ static int bol();
+};
+
+input *input_stack::current_input = 0;
+int input_stack::bol_flag = 0;
+
+inline int input_stack::bol()
+{
+ return bol_flag;
+}
+
+void input_stack::clear()
+{
+ while (current_input != 0) {
+ input *tem = current_input;
+ current_input = current_input->next;
+ delete tem;
+ }
+ bol_flag = 1;
+}
+
+void input_stack::push(input *in)
+{
+ in->next = current_input;
+ current_input = in;
+}
+
+void lex_init(input *top)
+{
+ input_stack::clear();
+ input_stack::push(top);
+}
+
+void lex_cleanup()
+{
+ while (input_stack::get_char() != EOF)
+ ;
+}
+
+int input_stack::get_char()
+{
+ while (current_input != 0) {
+ int c = current_input->get();
+ if (c != EOF) {
+ bol_flag = c == '\n';
+ return c;
+ }
+ // don't pop the top-level input off the stack
+ if (current_input->next == 0)
+ return EOF;
+ input *tem = current_input;
+ current_input = current_input->next;
+ delete tem;
+ }
+ return EOF;
+}
+
+int input_stack::peek_char()
+{
+ while (current_input != 0) {
+ int c = current_input->peek();
+ if (c != EOF)
+ return c;
+ if (current_input->next == 0)
+ return EOF;
+ input *tem = current_input;
+ current_input = current_input->next;
+ delete tem;
+ }
+ return EOF;
+}
+
+class char_input : public input {
+ int c;
+public:
+ char_input(int);
+ int get();
+ int peek();
+};
+
+char_input::char_input(int n) : c((unsigned char)n)
+{
+}
+
+int char_input::get()
+{
+ int n = c;
+ c = EOF;
+ return n;
+}
+
+int char_input::peek()
+{
+ return c;
+}
+
+void input_stack::push_back(unsigned char c, int was_bol)
+{
+ push(new char_input(c));
+ bol_flag = was_bol;
+}
+
+int input_stack::get_location(const char **fnp, int *lnp)
+{
+ for (input *p = current_input; p; p = p->next)
+ if (p->get_location(fnp, lnp))
+ return 1;
+ return 0;
+}
+
+string context_buffer;
+
+string token_buffer;
+double token_double;
+int token_int;
+
+void interpolate_macro_with_args(const char *body)
+{
+ char *argv[9];
+ int argc = 0;
+ int i;
+ for (i = 0; i < 9; i++)
+ argv[i] = 0;
+ int level = 0;
+ int c;
+ enum { NORMAL, IN_STRING, IN_STRING_QUOTED } state = NORMAL;
+ do {
+ token_buffer.clear();
+ for (;;) {
+ c = input_stack::get_char();
+ if (c == EOF) {
+ lex_error("end of input while scanning macro arguments");
+ break;
+ }
+ if (state == NORMAL && level == 0 && (c == ',' || c == ')')) {
+ if (token_buffer.length() > 0) {
+ token_buffer += '\0';
+ argv[argc] = strsave(token_buffer.contents());
+ }
+ // for `foo()', argc = 0
+ if (argc > 0 || c != ')' || i > 0)
+ argc++;
+ break;
+ }
+ token_buffer += char(c);
+ switch (state) {
+ case NORMAL:
+ if (c == '"')
+ state = IN_STRING;
+ else if (c == '(')
+ level++;
+ else if (c == ')')
+ level--;
+ break;
+ case IN_STRING:
+ if (c == '"')
+ state = NORMAL;
+ else if (c == '\\')
+ state = IN_STRING_QUOTED;
+ break;
+ case IN_STRING_QUOTED:
+ state = IN_STRING;
+ break;
+ }
+ }
+ } while (c != ')' && c != EOF);
+ input_stack::push(new argument_macro_input(body, argc, argv));
+}
+
+static int docmp(const char *s1, int n1, const char *s2, int n2)
+{
+ if (n1 < n2) {
+ int r = memcmp(s1, s2, n1);
+ return r ? r : -1;
+ }
+ else if (n1 > n2) {
+ int r = memcmp(s1, s2, n2);
+ return r ? r : 1;
+ }
+ else
+ return memcmp(s1, s2, n1);
+}
+
+int lookup_keyword(const char *str, int len)
+{
+ static struct keyword {
+ const char *name;
+ int token;
+ } table[] = {
+ { "Here", HERE },
+ { "above", ABOVE },
+ { "aligned", ALIGNED },
+ { "and", AND },
+ { "arc", ARC },
+ { "arrow", ARROW },
+ { "at", AT },
+ { "atan2", ATAN2 },
+ { "below", BELOW },
+ { "between", BETWEEN },
+ { "bottom", BOTTOM },
+ { "box", BOX },
+ { "by", BY },
+ { "ccw", CCW },
+ { "center", CENTER },
+ { "chop", CHOP },
+ { "circle", CIRCLE },
+ { "command", COMMAND },
+ { "copy", COPY },
+ { "cos", COS },
+ { "cw", CW },
+ { "dashed", DASHED },
+ { "define", DEFINE },
+ { "diam", DIAMETER },
+ { "diameter", DIAMETER },
+ { "do", DO },
+ { "dotted", DOTTED },
+ { "down", DOWN },
+ { "ellipse", ELLIPSE },
+ { "else", ELSE },
+ { "end", END },
+ { "exp", EXP },
+ { "fill", FILL },
+ { "filled", FILL },
+ { "for", FOR },
+ { "from", FROM },
+ { "height", HEIGHT },
+ { "ht", HEIGHT },
+ { "if", IF },
+ { "int", INT },
+ { "invis", INVISIBLE },
+ { "invisible", INVISIBLE },
+ { "last", LAST },
+ { "left", LEFT },
+ { "line", LINE },
+ { "ljust", LJUST },
+ { "log", LOG },
+ { "lower", LOWER },
+ { "max", K_MAX },
+ { "min", K_MIN },
+ { "move", MOVE },
+ { "of", OF },
+ { "plot", PLOT },
+ { "print", PRINT },
+ { "rad", RADIUS },
+ { "radius", RADIUS },
+ { "rand", RAND },
+ { "reset", RESET },
+ { "right", RIGHT },
+ { "rjust", RJUST },
+ { "same", SAME },
+ { "sh", SH },
+ { "sin", SIN },
+ { "spline", SPLINE },
+ { "sprintf", SPRINTF },
+ { "sqrt", SQRT },
+ { "srand", SRAND },
+ { "start", START },
+ { "the", THE },
+ { "then", THEN },
+ { "thick", THICKNESS },
+ { "thickness", THICKNESS },
+ { "thru", THRU },
+ { "to", TO },
+ { "top", TOP },
+ { "undef", UNDEF },
+ { "until", UNTIL },
+ { "up", UP },
+ { "upper", UPPER },
+ { "way", WAY },
+ { "wid", WIDTH },
+ { "width", WIDTH },
+ { "with", WITH },
+ };
+
+ const keyword *start = table;
+ const keyword *end = table + sizeof(table)/sizeof(table[0]);
+ while (start < end) {
+ // start <= target < end
+ const keyword *mid = start + (end - start)/2;
+
+ int cmp = docmp(str, len, mid->name, strlen(mid->name));
+ if (cmp == 0)
+ return mid->token;
+ if (cmp < 0)
+ end = mid;
+ else
+ start = mid + 1;
+ }
+ return 0;
+}
+
+int get_token_after_dot(int c)
+{
+ // get_token deals with the case where c is a digit
+ switch (c) {
+ case 'h':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ context_buffer = ".ht";
+ return DOT_HT;
+ }
+ else if (c == 'e') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'i') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'g') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'h') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ context_buffer = ".height";
+ return DOT_HT;
+ }
+ input_stack::push_back('h');
+ }
+ input_stack::push_back('g');
+ }
+ input_stack::push_back('i');
+ }
+ input_stack::push_back('e');
+ }
+ input_stack::push_back('h');
+ return '.';
+ case 'x':
+ input_stack::get_char();
+ context_buffer = ".x";
+ return DOT_X;
+ case 'y':
+ input_stack::get_char();
+ context_buffer = ".y";
+ return DOT_Y;
+ case 'c':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'e') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'n') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'e') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'r') {
+ input_stack::get_char();
+ context_buffer = ".center";
+ return DOT_C;
+ }
+ input_stack::push_back('e');
+ }
+ input_stack::push_back('t');
+ }
+ input_stack::push_back('n');
+ }
+ input_stack::push_back('e');
+ }
+ context_buffer = ".c";
+ return DOT_C;
+ case 'n':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'e') {
+ input_stack::get_char();
+ context_buffer = ".ne";
+ return DOT_NE;
+ }
+ else if (c == 'w') {
+ input_stack::get_char();
+ context_buffer = ".nw";
+ return DOT_NW;
+ }
+ else {
+ context_buffer = ".n";
+ return DOT_N;
+ }
+ break;
+ case 'e':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'n') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'd') {
+ input_stack::get_char();
+ context_buffer = ".end";
+ return DOT_END;
+ }
+ input_stack::push_back('n');
+ context_buffer = ".e";
+ return DOT_E;
+ }
+ context_buffer = ".e";
+ return DOT_E;
+ case 'w':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'i') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'd') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'h') {
+ input_stack::get_char();
+ context_buffer = ".width";
+ return DOT_WID;
+ }
+ input_stack::push_back('t');
+ }
+ context_buffer = ".wid";
+ return DOT_WID;
+ }
+ input_stack::push_back('i');
+ }
+ context_buffer = ".w";
+ return DOT_W;
+ case 's':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'e') {
+ input_stack::get_char();
+ context_buffer = ".se";
+ return DOT_SE;
+ }
+ else if (c == 'w') {
+ input_stack::get_char();
+ context_buffer = ".sw";
+ return DOT_SW;
+ }
+ else {
+ if (c == 't') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'a') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'r') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ context_buffer = ".start";
+ return DOT_START;
+ }
+ input_stack::push_back('r');
+ }
+ input_stack::push_back('a');
+ }
+ input_stack::push_back('t');
+ }
+ context_buffer = ".s";
+ return DOT_S;
+ }
+ break;
+ case 't':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'o') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'p') {
+ input_stack::get_char();
+ context_buffer = ".top";
+ return DOT_N;
+ }
+ input_stack::push_back('o');
+ }
+ context_buffer = ".t";
+ return DOT_N;
+ case 'l':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'e') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'f') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ context_buffer = ".left";
+ return DOT_W;
+ }
+ input_stack::push_back('f');
+ }
+ input_stack::push_back('e');
+ }
+ context_buffer = ".l";
+ return DOT_W;
+ case 'r':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'a') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'd') {
+ input_stack::get_char();
+ context_buffer = ".rad";
+ return DOT_RAD;
+ }
+ input_stack::push_back('a');
+ }
+ else if (c == 'i') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'g') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'h') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ context_buffer = ".right";
+ return DOT_E;
+ }
+ input_stack::push_back('h');
+ }
+ input_stack::push_back('g');
+ }
+ input_stack::push_back('i');
+ }
+ context_buffer = ".r";
+ return DOT_E;
+ case 'b':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'o') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'o') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'm') {
+ input_stack::get_char();
+ context_buffer = ".bottom";
+ return DOT_S;
+ }
+ input_stack::push_back('o');
+ }
+ input_stack::push_back('t');
+ }
+ context_buffer = ".bot";
+ return DOT_S;
+ }
+ input_stack::push_back('o');
+ }
+ context_buffer = ".b";
+ return DOT_S;
+ default:
+ context_buffer = '.';
+ return '.';
+ }
+}
+
+int get_token(int lookup_flag)
+{
+ context_buffer.clear();
+ for (;;) {
+ int n = 0;
+ int bol = input_stack::bol();
+ int c = input_stack::get_char();
+ if (bol && c == command_char) {
+ token_buffer.clear();
+ token_buffer += c;
+ // the newline is not part of the token
+ for (;;) {
+ c = input_stack::peek_char();
+ if (c == EOF || c == '\n')
+ break;
+ input_stack::get_char();
+ token_buffer += char(c);
+ }
+ context_buffer = token_buffer;
+ return COMMAND_LINE;
+ }
+ switch (c) {
+ case EOF:
+ return EOF;
+ case ' ':
+ case '\t':
+ break;
+ case '\\':
+ {
+ int d = input_stack::peek_char();
+ if (d != '\n') {
+ context_buffer = '\\';
+ return '\\';
+ }
+ input_stack::get_char();
+ break;
+ }
+ case '#':
+ do {
+ c = input_stack::get_char();
+ } while (c != '\n' && c != EOF);
+ if (c == '\n')
+ context_buffer = '\n';
+ return c;
+ case '"':
+ context_buffer = '"';
+ token_buffer.clear();
+ for (;;) {
+ c = input_stack::get_char();
+ if (c == '\\') {
+ context_buffer += '\\';
+ c = input_stack::peek_char();
+ if (c == '"') {
+ input_stack::get_char();
+ token_buffer += '"';
+ context_buffer += '"';
+ }
+ else
+ token_buffer += '\\';
+ }
+ else if (c == '\n') {
+ error("newline in string");
+ break;
+ }
+ else if (c == EOF) {
+ error("missing `\"'");
+ break;
+ }
+ else if (c == '"') {
+ context_buffer += '"';
+ break;
+ }
+ else {
+ context_buffer += char(c);
+ token_buffer += char(c);
+ }
+ }
+ return TEXT;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ int overflow = 0;
+ n = 0;
+ for (;;) {
+ if (n > (INT_MAX - 9)/10) {
+ overflow = 1;
+ break;
+ }
+ n *= 10;
+ n += c - '0';
+ context_buffer += char(c);
+ c = input_stack::peek_char();
+ if (c == EOF || !csdigit(c))
+ break;
+ c = input_stack::get_char();
+ }
+ token_double = n;
+ if (overflow) {
+ for (;;) {
+ token_double *= 10.0;
+ token_double += c - '0';
+ context_buffer += char(c);
+ c = input_stack::peek_char();
+ if (c == EOF || !csdigit(c))
+ break;
+ c = input_stack::get_char();
+ }
+ // if somebody asks for 1000000000000th, we will silently
+ // give them INT_MAXth
+ double temp = token_double; // work around gas 1.34/sparc bug
+ if (token_double > INT_MAX)
+ n = INT_MAX;
+ else
+ n = int(temp);
+ }
+ }
+ switch (c) {
+ case 'i':
+ case 'I':
+ context_buffer += char(c);
+ input_stack::get_char();
+ return NUMBER;
+ case '.':
+ {
+ context_buffer += '.';
+ input_stack::get_char();
+ got_dot:
+ double factor = 1.0;
+ for (;;) {
+ c = input_stack::peek_char();
+ if (!c == EOF || !csdigit(c))
+ break;
+ input_stack::get_char();
+ context_buffer += char(c);
+ factor /= 10.0;
+ if (c != '0')
+ token_double += factor*(c - '0');
+ }
+ if (c != 'e' && c != 'E') {
+ if (c == 'i' || c == 'I') {
+ context_buffer += char(c);
+ input_stack::get_char();
+ }
+ return NUMBER;
+ }
+ }
+ // fall through
+ case 'e':
+ case 'E':
+ {
+ int echar = c;
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ int sign = '+';
+ if (c == '+' || c == '-') {
+ sign = c;
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == EOF || !csdigit(c)) {
+ input_stack::push_back(sign);
+ input_stack::push_back(echar);
+ return NUMBER;
+ }
+ context_buffer += char(echar);
+ context_buffer += char(sign);
+ }
+ else {
+ if (c == EOF || !csdigit(c)) {
+ input_stack::push_back(echar);
+ return NUMBER;
+ }
+ context_buffer += char(echar);
+ }
+ input_stack::get_char();
+ context_buffer += char(c);
+ n = c - '0';
+ for (;;) {
+ c = input_stack::peek_char();
+ if (c == EOF || !csdigit(c))
+ break;
+ input_stack::get_char();
+ context_buffer += char(c);
+ n = n*10 + (c - '0');
+ }
+ if (sign == '-')
+ n = -n;
+ if (c == 'i' || c == 'I') {
+ context_buffer += char(c);
+ input_stack::get_char();
+ }
+ token_double *= pow(10.0, n);
+ return NUMBER;
+ }
+ case 'n':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'd') {
+ input_stack::get_char();
+ token_int = n;
+ context_buffer += "nd";
+ return ORDINAL;
+ }
+ input_stack::push_back('n');
+ return NUMBER;
+ case 'r':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'd') {
+ input_stack::get_char();
+ token_int = n;
+ context_buffer += "rd";
+ return ORDINAL;
+ }
+ input_stack::push_back('r');
+ return NUMBER;
+ case 't':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'h') {
+ input_stack::get_char();
+ token_int = n;
+ context_buffer += "th";
+ return ORDINAL;
+ }
+ input_stack::push_back('t');
+ return NUMBER;
+ case 's':
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ token_int = n;
+ context_buffer += "st";
+ return ORDINAL;
+ }
+ input_stack::push_back('s');
+ return NUMBER;
+ default:
+ return NUMBER;
+ }
+ break;
+ case '\'':
+ {
+ c = input_stack::peek_char();
+ if (c == 't') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == 'h') {
+ input_stack::get_char();
+ context_buffer = "'th";
+ return TH;
+ }
+ else
+ input_stack::push_back('t');
+ }
+ context_buffer = "'";
+ return '\'';
+ }
+ case '.':
+ {
+ c = input_stack::peek_char();
+ if (c != EOF && csdigit(c)) {
+ n = 0;
+ token_double = 0.0;
+ context_buffer = '.';
+ goto got_dot;
+ }
+ return get_token_after_dot(c);
+ }
+ case '<':
+ c = input_stack::peek_char();
+ if (c == '-') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ if (c == '>') {
+ input_stack::get_char();
+ context_buffer = "<->";
+ return DOUBLE_ARROW_HEAD;
+ }
+ context_buffer = "<-";
+ return LEFT_ARROW_HEAD;
+ }
+ else if (c == '=') {
+ input_stack::get_char();
+ context_buffer = "<=";
+ return LESSEQUAL;
+ }
+ context_buffer = "<";
+ return '<';
+ case '-':
+ c = input_stack::peek_char();
+ if (c == '>') {
+ input_stack::get_char();
+ context_buffer = "->";
+ return RIGHT_ARROW_HEAD;
+ }
+ context_buffer = "-";
+ return '-';
+ case '!':
+ c = input_stack::peek_char();
+ if (c == '=') {
+ input_stack::get_char();
+ context_buffer = "!=";
+ return NOTEQUAL;
+ }
+ context_buffer = "!";
+ return '!';
+ case '>':
+ c = input_stack::peek_char();
+ if (c == '=') {
+ input_stack::get_char();
+ context_buffer = ">=";
+ return GREATEREQUAL;
+ }
+ context_buffer = ">";
+ return '>';
+ case '=':
+ c = input_stack::peek_char();
+ if (c == '=') {
+ input_stack::get_char();
+ context_buffer = "==";
+ return EQUALEQUAL;
+ }
+ context_buffer = "=";
+ return '=';
+ case '&':
+ c = input_stack::peek_char();
+ if (c == '&') {
+ input_stack::get_char();
+ context_buffer = "&&";
+ return ANDAND;
+ }
+ context_buffer = "&";
+ return '&';
+ case '|':
+ c = input_stack::peek_char();
+ if (c == '|') {
+ input_stack::get_char();
+ context_buffer = "||";
+ return OROR;
+ }
+ context_buffer = "|";
+ return '|';
+ default:
+ if (c != EOF && csalpha(c)) {
+ token_buffer.clear();
+ token_buffer = c;
+ for (;;) {
+ c = input_stack::peek_char();
+ if (c == EOF || (!csalnum(c) && c != '_'))
+ break;
+ input_stack::get_char();
+ token_buffer += char(c);
+ }
+ int tok = lookup_keyword(token_buffer.contents(),
+ token_buffer.length());
+ if (tok != 0) {
+ context_buffer = token_buffer;
+ return tok;
+ }
+ char *def = 0;
+ if (lookup_flag) {
+ token_buffer += '\0';
+ def = macro_table.lookup(token_buffer.contents());
+ token_buffer.set_length(token_buffer.length() - 1);
+ if (def) {
+ if (c == '(') {
+ input_stack::get_char();
+ interpolate_macro_with_args(def);
+ }
+ else
+ input_stack::push(new macro_input(def));
+ }
+ }
+ if (!def) {
+ context_buffer = token_buffer;
+ if (csupper(token_buffer[0]))
+ return LABEL;
+ else
+ return VARIABLE;
+ }
+ }
+ else {
+ context_buffer = char(c);
+ return (unsigned char)c;
+ }
+ break;
+ }
+ }
+}
+
+int get_delimited()
+{
+ token_buffer.clear();
+ int c = input_stack::get_char();
+ while (c == ' ' || c == '\t' || c == '\n')
+ c = input_stack::get_char();
+ if (c == EOF) {
+ lex_error("missing delimiter");
+ return 0;
+ }
+ context_buffer = char(c);
+ int had_newline = 0;
+ int start = c;
+ int level = 0;
+ enum { NORMAL, IN_STRING, IN_STRING_QUOTED, DELIM_END } state = NORMAL;
+ for (;;) {
+ c = input_stack::get_char();
+ if (c == EOF) {
+ lex_error("missing closing delimiter");
+ return 0;
+ }
+ if (c == '\n')
+ had_newline = 1;
+ else if (!had_newline)
+ context_buffer += char(c);
+ switch (state) {
+ case NORMAL:
+ if (start == '{') {
+ if (c == '{') {
+ level++;
+ break;
+ }
+ if (c == '}') {
+ if (--level < 0)
+ state = DELIM_END;
+ break;
+ }
+ }
+ else {
+ if (c == start) {
+ state = DELIM_END;
+ break;
+ }
+ }
+ if (c == '"')
+ state = IN_STRING;
+ break;
+ case IN_STRING_QUOTED:
+ if (c == '\n')
+ state = NORMAL;
+ else
+ state = IN_STRING;
+ break;
+ case IN_STRING:
+ if (c == '"' || c == '\n')
+ state = NORMAL;
+ else if (c == '\\')
+ state = IN_STRING_QUOTED;
+ break;
+ case DELIM_END:
+ // This case it just to shut cfront 2.0 up.
+ default:
+ assert(0);
+ }
+ if (state == DELIM_END)
+ break;
+ token_buffer += c;
+ }
+ return 1;
+}
+
+void do_define()
+{
+ int t = get_token(0); // do not expand what we are defining
+ if (t != VARIABLE && t != LABEL) {
+ lex_error("can only define variable or placename");
+ return;
+ }
+ token_buffer += '\0';
+ string nm = token_buffer;
+ const char *name = nm.contents();
+ if (!get_delimited())
+ return;
+ token_buffer += '\0';
+ macro_table.define(name, strsave(token_buffer.contents()));
+}
+
+void do_undef()
+{
+ int t = get_token(0); // do not expand what we are undefining
+ if (t != VARIABLE && t != LABEL) {
+ lex_error("can only define variable or placename");
+ return;
+ }
+ token_buffer += '\0';
+ macro_table.define(token_buffer.contents(), 0);
+}
+
+
+class for_input : public input {
+ char *var;
+ char *body;
+ double to;
+ int by_is_multiplicative;
+ double by;
+ const char *p;
+ int done_newline;
+public:
+ for_input(char *, double, int, double, char *);
+ ~for_input();
+ int get();
+ int peek();
+};
+
+for_input::for_input(char *vr, double t, int bim, double b, char *bd)
+: var(vr), body(bd), to(t), by_is_multiplicative(bim), by(b), p(body),
+ done_newline(0)
+{
+}
+
+for_input::~for_input()
+{
+ a_delete var;
+ a_delete body;
+}
+
+int for_input::get()
+{
+ if (p == 0)
+ return EOF;
+ for (;;) {
+ if (*p != '\0')
+ return (unsigned char)*p++;
+ if (!done_newline) {
+ done_newline = 1;
+ return '\n';
+ }
+ double val;
+ if (!lookup_variable(var, &val)) {
+ lex_error("body of `for' terminated enclosing block");
+ return EOF;
+ }
+ if (by_is_multiplicative)
+ val *= by;
+ else
+ val += by;
+ define_variable(var, val);
+ if (val > to) {
+ p = 0;
+ return EOF;
+ }
+ p = body;
+ done_newline = 0;
+ }
+}
+
+int for_input::peek()
+{
+ if (p == 0)
+ return EOF;
+ if (*p != '\0')
+ return (unsigned char)*p;
+ if (!done_newline)
+ return '\n';
+ double val;
+ if (!lookup_variable(var, &val))
+ return EOF;
+ if (by_is_multiplicative) {
+ if (val * by > to)
+ return EOF;
+ }
+ else {
+ if (val + by > to)
+ return EOF;
+ }
+ if (*body == '\0')
+ return EOF;
+ return (unsigned char)*body;
+}
+
+void do_for(char *var, double from, double to, int by_is_multiplicative,
+ double by, char *body)
+{
+ define_variable(var, from);
+ if (from <= to)
+ input_stack::push(new for_input(var, to, by_is_multiplicative, by, body));
+}
+
+
+void do_copy(const char *filename)
+{
+ errno = 0;
+ FILE *fp = fopen(filename, "r");
+ if (fp == 0) {
+ lex_error("can't open `%1': %2", filename, strerror(errno));
+ return;
+ }
+ input_stack::push(new file_input(fp, filename));
+}
+
+class copy_thru_input : public input {
+ int done;
+ char *body;
+ char *until;
+ const char *p;
+ const char *ap;
+ int argv[9];
+ int argc;
+ string line;
+ int get_line();
+ virtual int inget() = 0;
+public:
+ copy_thru_input(const char *b, const char *u);
+ ~copy_thru_input();
+ int get();
+ int peek();
+};
+
+class copy_file_thru_input : public copy_thru_input {
+ input *in;
+public:
+ copy_file_thru_input(input *, const char *b, const char *u);
+ ~copy_file_thru_input();
+ int inget();
+};
+
+copy_file_thru_input::copy_file_thru_input(input *i, const char *b,
+ const char *u)
+: copy_thru_input(b, u), in(i)
+{
+}
+
+copy_file_thru_input::~copy_file_thru_input()
+{
+ delete in;
+}
+
+int copy_file_thru_input::inget()
+{
+ if (!in)
+ return EOF;
+ else
+ return in->get();
+}
+
+class copy_rest_thru_input : public copy_thru_input {
+public:
+ copy_rest_thru_input(const char *, const char *u);
+ int inget();
+};
+
+copy_rest_thru_input::copy_rest_thru_input(const char *b, const char *u)
+: copy_thru_input(b, u)
+{
+}
+
+int copy_rest_thru_input::inget()
+{
+ while (next != 0) {
+ int c = next->get();
+ if (c != EOF)
+ return c;
+ if (next->next == 0)
+ return EOF;
+ input *tem = next;
+ next = next->next;
+ delete tem;
+ }
+ return EOF;
+
+}
+
+copy_thru_input::copy_thru_input(const char *b, const char *u)
+: done(0)
+{
+ ap = 0;
+ body = process_body(b);
+ p = 0;
+ until = strsave(u);
+}
+
+
+copy_thru_input::~copy_thru_input()
+{
+ a_delete body;
+ a_delete until;
+}
+
+int copy_thru_input::get()
+{
+ if (ap) {
+ if (*ap != '\0')
+ return (unsigned char)*ap++;
+ ap = 0;
+ }
+ for (;;) {
+ if (p == 0) {
+ if (!get_line())
+ break;
+ p = body;
+ }
+ if (*p == '\0') {
+ p = 0;
+ return '\n';
+ }
+ while (*p >= ARG1 && *p <= ARG1 + 8) {
+ int i = *p++ - ARG1;
+ if (i < argc && line[argv[i]] != '\0') {
+ ap = line.contents() + argv[i];
+ return (unsigned char)*ap++;
+ }
+ }
+ if (*p != '\0')
+ return (unsigned char)*p++;
+ }
+ return EOF;
+}
+
+int copy_thru_input::peek()
+{
+ if (ap) {
+ if (*ap != '\0')
+ return (unsigned char)*ap;
+ ap = 0;
+ }
+ for (;;) {
+ if (p == 0) {
+ if (!get_line())
+ break;
+ p = body;
+ }
+ if (*p == '\0')
+ return '\n';
+ while (*p >= ARG1 && *p <= ARG1 + 8) {
+ int i = *p++ - ARG1;
+ if (i < argc && line[argv[i]] != '\0') {
+ ap = line.contents() + argv[i];
+ return (unsigned char)*ap;
+ }
+ }
+ if (*p != '\0')
+ return (unsigned char)*p;
+ }
+ return EOF;
+}
+
+int copy_thru_input::get_line()
+{
+ if (done)
+ return 0;
+ line.clear();
+ argc = 0;
+ int c = inget();
+ for (;;) {
+ while (c == ' ')
+ c = inget();
+ if (c == EOF || c == '\n')
+ break;
+ if (argc == 9) {
+ do {
+ c = inget();
+ } while (c != '\n' && c != EOF);
+ break;
+ }
+ argv[argc++] = line.length();
+ do {
+ line += char(c);
+ c = inget();
+ } while (c != ' ' && c != '\n');
+ line += '\0';
+ }
+ if (until != 0 && argc > 0 && strcmp(&line[argv[0]], until) == 0) {
+ done = 1;
+ return 0;
+ }
+ return argc > 0 || c == '\n';
+}
+
+class simple_file_input : public input {
+ const char *filename;
+ int lineno;
+ FILE *fp;
+public:
+ simple_file_input(FILE *, const char *);
+ ~simple_file_input();
+ int get();
+ int peek();
+ int get_location(const char **, int *);
+};
+
+simple_file_input::simple_file_input(FILE *p, const char *s)
+: filename(s), lineno(1), fp(p)
+{
+}
+
+simple_file_input::~simple_file_input()
+{
+ // don't delete the filename
+ fclose(fp);
+}
+
+int simple_file_input::get()
+{
+ int c = getc(fp);
+ while (illegal_input_char(c)) {
+ error("illegal input character code %1", c);
+ c = getc(fp);
+ }
+ if (c == '\n')
+ lineno++;
+ return c;
+}
+
+int simple_file_input::peek()
+{
+ int c = getc(fp);
+ while (illegal_input_char(c)) {
+ error("illegal input character code %1", c);
+ c = getc(fp);
+ }
+ if (c != EOF)
+ ungetc(c, fp);
+ return c;
+}
+
+int simple_file_input::get_location(const char **fnp, int *lnp)
+{
+ *fnp = filename;
+ *lnp = lineno;
+ return 1;
+}
+
+
+void copy_file_thru(const char *filename, const char *body, const char *until)
+{
+ errno = 0;
+ FILE *fp = fopen(filename, "r");
+ if (fp == 0) {
+ lex_error("can't open `%1': %2", filename, strerror(errno));
+ return;
+ }
+ input *in = new copy_file_thru_input(new simple_file_input(fp, filename),
+ body, until);
+ input_stack::push(in);
+}
+
+void copy_rest_thru(const char *body, const char *until)
+{
+ input_stack::push(new copy_rest_thru_input(body, until));
+}
+
+void push_body(const char *s)
+{
+ input_stack::push(new char_input('\n'));
+ input_stack::push(new macro_input(s));
+}
+
+int delim_flag = 0;
+
+char *get_thru_arg()
+{
+ int c = input_stack::peek_char();
+ while (c == ' ') {
+ input_stack::get_char();
+ c = input_stack::peek_char();
+ }
+ if (c != EOF && csalpha(c)) {
+ // looks like a macro
+ input_stack::get_char();
+ token_buffer = c;
+ for (;;) {
+ c = input_stack::peek_char();
+ if (c == EOF || (!csalnum(c) && c != '_'))
+ break;
+ input_stack::get_char();
+ token_buffer += char(c);
+ }
+ context_buffer = token_buffer;
+ token_buffer += '\0';
+ char *def = macro_table.lookup(token_buffer.contents());
+ if (def)
+ return strsave(def);
+ // I guess it wasn't a macro after all; so push the macro name back.
+ // -2 because we added a '\0'
+ for (int i = token_buffer.length() - 2; i >= 0; i--)
+ input_stack::push_back(token_buffer[i]);
+ }
+ if (get_delimited()) {
+ token_buffer += '\0';
+ return strsave(token_buffer.contents());
+ }
+ else
+ return 0;
+}
+
+int lookahead_token = -1;
+string old_context_buffer;
+
+void do_lookahead()
+{
+ if (lookahead_token == -1) {
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ }
+}
+
+int yylex()
+{
+ if (delim_flag) {
+ assert(lookahead_token == -1);
+ if (delim_flag == 2) {
+ if ((yylval.str = get_thru_arg()) != 0)
+ return DELIMITED;
+ else
+ return 0;
+ }
+ else {
+ if (get_delimited()) {
+ token_buffer += '\0';
+ yylval.str = strsave(token_buffer.contents());
+ return DELIMITED;
+ }
+ else
+ return 0;
+ }
+ }
+ for (;;) {
+ int t;
+ if (lookahead_token >= 0) {
+ t = lookahead_token;
+ lookahead_token = -1;
+ }
+ else
+ t = get_token(1);
+ switch (t) {
+ case '\n':
+ return ';';
+ case EOF:
+ return 0;
+ case DEFINE:
+ do_define();
+ break;
+ case UNDEF:
+ do_undef();
+ break;
+ case ORDINAL:
+ yylval.n = token_int;
+ return t;
+ case NUMBER:
+ yylval.x = token_double;
+ return t;
+ case COMMAND_LINE:
+ case TEXT:
+ token_buffer += '\0';
+ if (!input_stack::get_location(&yylval.lstr.filename,
+ &yylval.lstr.lineno)) {
+ yylval.lstr.filename = 0;
+ yylval.lstr.lineno = -1;
+ }
+ yylval.lstr.str = strsave(token_buffer.contents());
+ return t;
+ case LABEL:
+ case VARIABLE:
+ token_buffer += '\0';
+ yylval.str = strsave(token_buffer.contents());
+ return t;
+ case LEFT:
+ // change LEFT to LEFT_CORNER when followed by OF
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token == OF)
+ return LEFT_CORNER;
+ else
+ return t;
+ case RIGHT:
+ // change RIGHT to RIGHT_CORNER when followed by OF
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token == OF)
+ return RIGHT_CORNER;
+ else
+ return t;
+ case UPPER:
+ // recognise UPPER only before LEFT or RIGHT
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token != LEFT && lookahead_token != RIGHT) {
+ yylval.str = strsave("upper");
+ return VARIABLE;
+ }
+ else
+ return t;
+ case LOWER:
+ // recognise LOWER only before LEFT or RIGHT
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token != LEFT && lookahead_token != RIGHT) {
+ yylval.str = strsave("lower");
+ return VARIABLE;
+ }
+ else
+ return t;
+ case TOP:
+ // recognise TOP only before OF
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token != OF) {
+ yylval.str = strsave("top");
+ return VARIABLE;
+ }
+ else
+ return t;
+ case BOTTOM:
+ // recognise BOTTOM only before OF
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token != OF) {
+ yylval.str = strsave("bottom");
+ return VARIABLE;
+ }
+ else
+ return t;
+ case CENTER:
+ // recognise CENTER only before OF
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token != OF) {
+ yylval.str = strsave("center");
+ return VARIABLE;
+ }
+ else
+ return t;
+ case START:
+ // recognise START only before OF
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token != OF) {
+ yylval.str = strsave("start");
+ return VARIABLE;
+ }
+ else
+ return t;
+ case END:
+ // recognise END only before OF
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token != OF) {
+ yylval.str = strsave("end");
+ return VARIABLE;
+ }
+ else
+ return t;
+ default:
+ return t;
+ }
+ }
+}
+
+void lex_error(const char *message,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ const char *filename;
+ int lineno;
+ if (!input_stack::get_location(&filename, &lineno))
+ error(message, arg1, arg2, arg3);
+ else
+ error_with_file_and_line(filename, lineno, message, arg1, arg2, arg3);
+}
+
+void lex_warning(const char *message,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ const char *filename;
+ int lineno;
+ if (!input_stack::get_location(&filename, &lineno))
+ warning(message, arg1, arg2, arg3);
+ else
+ warning_with_file_and_line(filename, lineno, message, arg1, arg2, arg3);
+}
+
+void yyerror(const char *s)
+{
+ const char *filename;
+ int lineno;
+ const char *context = 0;
+ if (lookahead_token == -1) {
+ if (context_buffer.length() > 0) {
+ context_buffer += '\0';
+ context = context_buffer.contents();
+ }
+ }
+ else {
+ if (old_context_buffer.length() > 0) {
+ old_context_buffer += '\0';
+ context = old_context_buffer.contents();
+ }
+ }
+ if (!input_stack::get_location(&filename, &lineno)) {
+ if (context) {
+ if (context[0] == '\n' && context[1] == '\0')
+ error("%1 before newline", s);
+ else
+ error("%1 before `%2'", s, context);
+ }
+ else
+ error("%1 at end of picture", s);
+ }
+ else {
+ if (context) {
+ if (context[0] == '\n' && context[1] == '\0')
+ error_with_file_and_line(filename, lineno, "%1 before newline", s);
+ else
+ error_with_file_and_line(filename, lineno, "%1 before `%2'",
+ s, context);
+ }
+ else
+ error_with_file_and_line(filename, lineno, "%1 at end of picture", s);
+ }
+}
+
diff --git a/src/preproc/pic/main.cc b/src/preproc/pic/main.cc
new file mode 100644
index 00000000..1536513a
--- /dev/null
+++ b/src/preproc/pic/main.cc
@@ -0,0 +1,624 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "pic.h"
+
+extern int yyparse();
+
+output *out;
+
+int flyback_flag;
+int zero_length_line_flag = 0;
+// Non-zero means we're using a groff driver.
+int driver_extension_flag = 1;
+int compatible_flag = 0;
+int safer_flag = 1;
+int command_char = '.'; // the character that introduces lines
+ // that should be passed through tranparently
+static int lf_flag = 1; // non-zero if we should attempt to understand
+ // lines beginning with `.lf'
+
+// Non-zero means a parse error was encountered.
+static int had_parse_error = 0;
+
+void do_file(const char *filename);
+
+class top_input : public input {
+ FILE *fp;
+ int bol;
+ int eof;
+ int push_back[3];
+ int start_lineno;
+public:
+ top_input(FILE *);
+ int get();
+ int peek();
+ int get_location(const char **, int *);
+};
+
+top_input::top_input(FILE *p) : fp(p), bol(1), eof(0)
+{
+ push_back[0] = push_back[1] = push_back[2] = EOF;
+ start_lineno = current_lineno;
+}
+
+int top_input::get()
+{
+ if (eof)
+ return EOF;
+ if (push_back[2] != EOF) {
+ int c = push_back[2];
+ push_back[2] = EOF;
+ return c;
+ }
+ else if (push_back[1] != EOF) {
+ int c = push_back[1];
+ push_back[1] = EOF;
+ return c;
+ }
+ else if (push_back[0] != EOF) {
+ int c = push_back[0];
+ push_back[0] = EOF;
+ return c;
+ }
+ int c = getc(fp);
+ while (illegal_input_char(c)) {
+ error("illegal input character code %1", int(c));
+ c = getc(fp);
+ bol = 0;
+ }
+ if (bol && c == '.') {
+ c = getc(fp);
+ if (c == 'P') {
+ c = getc(fp);
+ if (c == 'F' || c == 'E') {
+ int d = getc(fp);
+ if (d != EOF)
+ ungetc(d, fp);
+ if (d == EOF || d == ' ' || d == '\n' || compatible_flag) {
+ eof = 1;
+ flyback_flag = c == 'F';
+ return EOF;
+ }
+ push_back[0] = c;
+ push_back[1] = 'P';
+ return '.';
+ }
+ if (c == 'S') {
+ c = getc(fp);
+ if (c != EOF)
+ ungetc(c, fp);
+ if (c == EOF || c == ' ' || c == '\n' || compatible_flag) {
+ error("nested .PS");
+ eof = 1;
+ return EOF;
+ }
+ push_back[0] = 'S';
+ push_back[1] = 'P';
+ return '.';
+ }
+ if (c != EOF)
+ ungetc(c, fp);
+ push_back[0] = 'P';
+ return '.';
+ }
+ else {
+ if (c != EOF)
+ ungetc(c, fp);
+ return '.';
+ }
+ }
+ if (c == '\n') {
+ bol = 1;
+ current_lineno++;
+ return '\n';
+ }
+ bol = 0;
+ if (c == EOF) {
+ eof = 1;
+ error("end of file before .PE or .PF");
+ error_with_file_and_line(current_filename, start_lineno - 1,
+ ".PS was here");
+ }
+ return c;
+}
+
+int top_input::peek()
+{
+ if (eof)
+ return EOF;
+ if (push_back[2] != EOF)
+ return push_back[2];
+ if (push_back[1] != EOF)
+ return push_back[1];
+ if (push_back[0] != EOF)
+ return push_back[0];
+ int c = getc(fp);
+ while (illegal_input_char(c)) {
+ error("illegal input character code %1", int(c));
+ c = getc(fp);
+ bol = 0;
+ }
+ if (bol && c == '.') {
+ c = getc(fp);
+ if (c == 'P') {
+ c = getc(fp);
+ if (c == 'F' || c == 'E') {
+ int d = getc(fp);
+ if (d != EOF)
+ ungetc(d, fp);
+ if (d == EOF || d == ' ' || d == '\n' || compatible_flag) {
+ eof = 1;
+ flyback_flag = c == 'F';
+ return EOF;
+ }
+ push_back[0] = c;
+ push_back[1] = 'P';
+ push_back[2] = '.';
+ return '.';
+ }
+ if (c == 'S') {
+ c = getc(fp);
+ if (c != EOF)
+ ungetc(c, fp);
+ if (c == EOF || c == ' ' || c == '\n' || compatible_flag) {
+ error("nested .PS");
+ eof = 1;
+ return EOF;
+ }
+ push_back[0] = 'S';
+ push_back[1] = 'P';
+ push_back[2] = '.';
+ return '.';
+ }
+ if (c != EOF)
+ ungetc(c, fp);
+ push_back[0] = 'P';
+ push_back[1] = '.';
+ return '.';
+ }
+ else {
+ if (c != EOF)
+ ungetc(c, fp);
+ push_back[0] = '.';
+ return '.';
+ }
+ }
+ if (c != EOF)
+ ungetc(c, fp);
+ if (c == '\n')
+ return '\n';
+ return c;
+}
+
+int top_input::get_location(const char **filenamep, int *linenop)
+{
+ *filenamep = current_filename;
+ *linenop = current_lineno;
+ return 1;
+}
+
+void do_picture(FILE *fp)
+{
+ flyback_flag = 0;
+ int c;
+ while ((c = getc(fp)) == ' ')
+ ;
+ if (c == '<') {
+ string filename;
+ while ((c = getc(fp)) == ' ')
+ ;
+ while (c != EOF && c != ' ' && c != '\n') {
+ filename += char(c);
+ c = getc(fp);
+ }
+ if (c == ' ') {
+ do {
+ c = getc(fp);
+ } while (c != EOF && c != '\n');
+ }
+ if (c == '\n')
+ current_lineno++;
+ if (filename.length() == 0)
+ error("missing filename after `<'");
+ else {
+ filename += '\0';
+ const char *old_filename = current_filename;
+ int old_lineno = current_lineno;
+ // filenames must be permanent
+ do_file(strsave(filename.contents()));
+ current_filename = old_filename;
+ current_lineno = old_lineno;
+ }
+ out->set_location(current_filename, current_lineno);
+ }
+ else {
+ out->set_location(current_filename, current_lineno);
+ string start_line;
+ while (c != EOF) {
+ if (c == '\n') {
+ current_lineno++;
+ break;
+ }
+ start_line += c;
+ c = getc(fp);
+ }
+ if (c == EOF)
+ return;
+ start_line += '\0';
+ double wid, ht;
+ switch (sscanf(&start_line[0], "%lf %lf", &wid, &ht)) {
+ case 1:
+ ht = 0.0;
+ break;
+ case 2:
+ break;
+ default:
+ ht = wid = 0.0;
+ break;
+ }
+ out->set_desired_width_height(wid, ht);
+ out->set_args(start_line.contents());
+ lex_init(new top_input(fp));
+ if (yyparse()) {
+ had_parse_error = 1;
+ lex_error("giving up on this picture");
+ }
+ parse_cleanup();
+ lex_cleanup();
+
+ // skip the rest of the .PF/.PE line
+ while ((c = getc(fp)) != EOF && c != '\n')
+ ;
+ if (c == '\n')
+ current_lineno++;
+ out->set_location(current_filename, current_lineno);
+ }
+}
+
+void do_file(const char *filename)
+{
+ FILE *fp;
+ if (strcmp(filename, "-") == 0)
+ fp = stdin;
+ else {
+ errno = 0;
+ fp = fopen(filename, "r");
+ if (fp == 0)
+ fatal("can't open `%1': %2", filename, strerror(errno));
+ }
+ out->set_location(filename, 1);
+ current_filename = filename;
+ current_lineno = 1;
+ enum { START, MIDDLE, HAD_DOT, HAD_P, HAD_PS, HAD_l, HAD_lf } state = START;
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ switch (state) {
+ case START:
+ if (c == '.')
+ state = HAD_DOT;
+ else {
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case MIDDLE:
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ break;
+ case HAD_DOT:
+ if (c == 'P')
+ state = HAD_P;
+ else if (lf_flag && c == 'l')
+ state = HAD_l;
+ else {
+ putchar('.');
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case HAD_P:
+ if (c == 'S')
+ state = HAD_PS;
+ else {
+ putchar('.');
+ putchar('P');
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case HAD_PS:
+ if (c == ' ' || c == '\n' || compatible_flag) {
+ ungetc(c, fp);
+ do_picture(fp);
+ state = START;
+ }
+ else {
+ fputs(".PS", stdout);
+ putchar(c);
+ state = MIDDLE;
+ }
+ break;
+ case HAD_l:
+ if (c == 'f')
+ state = HAD_lf;
+ else {
+ putchar('.');
+ putchar('l');
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case HAD_lf:
+ if (c == ' ' || c == '\n' || compatible_flag) {
+ string line;
+ while (c != EOF) {
+ line += c;
+ if (c == '\n') {
+ current_lineno++;
+ break;
+ }
+ c = getc(fp);
+ }
+ line += '\0';
+ interpret_lf_args(line.contents());
+ printf(".lf%s", line.contents());
+ state = START;
+ }
+ else {
+ fputs(".lf", stdout);
+ putchar(c);
+ state = MIDDLE;
+ }
+ break;
+ default:
+ assert(0);
+ }
+ }
+ switch (state) {
+ case START:
+ break;
+ case MIDDLE:
+ putchar('\n');
+ break;
+ case HAD_DOT:
+ fputs(".\n", stdout);
+ break;
+ case HAD_P:
+ fputs(".P\n", stdout);
+ break;
+ case HAD_PS:
+ fputs(".PS\n", stdout);
+ break;
+ case HAD_l:
+ fputs(".l\n", stdout);
+ break;
+ case HAD_lf:
+ fputs(".lf\n", stdout);
+ break;
+ }
+ if (fp != stdin)
+ fclose(fp);
+}
+
+#ifdef FIG_SUPPORT
+void do_whole_file(const char *filename)
+{
+ // Do not set current_filename.
+ FILE *fp;
+ if (strcmp(filename, "-") == 0)
+ fp = stdin;
+ else {
+ errno = 0;
+ fp = fopen(filename, "r");
+ if (fp == 0)
+ fatal("can't open `%1': %2", filename, strerror(errno));
+ }
+ lex_init(new file_input(fp, filename));
+ if (yyparse())
+ had_parse_error = 1;
+ parse_cleanup();
+ lex_cleanup();
+}
+#endif
+
+void usage()
+{
+ fprintf(stderr, "usage: %s [ -nvC ] [ filename ... ]\n", program_name);
+#ifdef TEX_SUPPORT
+ fprintf(stderr, " %s -t [ -cvzC ] [ filename ... ]\n", program_name);
+#endif
+#ifdef FIG_SUPPORT
+ fprintf(stderr, " %s -f [ -v ] [ filename ]\n", program_name);
+#endif
+ exit(1);
+}
+
+#ifdef __MSDOS__
+static char *fix_program_name(char *arg, char *dflt)
+{
+ if (!arg)
+ return dflt;
+ char *prog = strchr(arg, '\0');
+ for (;;) {
+ if (prog == arg)
+ break;
+ --prog;
+ if (strchr("\\/:", *prog)) {
+ prog++;
+ break;
+ }
+ }
+ char *ext = strchr(prog, '.');
+ if (ext)
+ *ext = '\0';
+ for (char *p = prog; *p; p++)
+ if ('A' <= *p && *p <= 'Z')
+ *p = 'a' + (*p - 'A');
+ return prog;
+}
+#endif /* __MSDOS__ */
+
+int main(int argc, char **argv)
+{
+#ifdef __MSDOS__
+ argv[0] = fix_program_name(argv[0], "pic");
+#endif /* __MSDOS__ */
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int opt;
+#ifdef TEX_SUPPORT
+ int tex_flag = 0;
+ int tpic_flag = 0;
+#endif
+#ifdef FIG_SUPPORT
+ int whole_file_flag = 0;
+ int fig_flag = 0;
+#endif
+ while ((opt = getopt(argc, argv, "T:CDSUtcvnxzpf")) != EOF)
+ switch (opt) {
+ case 'C':
+ compatible_flag = 1;
+ break;
+ case 'D':
+ case 'T':
+ break;
+ case 'S':
+ safer_flag = 1;
+ break;
+ case 'U':
+ safer_flag = 0;
+ break;
+ case 'f':
+#ifdef FIG_SUPPORT
+ whole_file_flag++;
+ fig_flag++;
+#else
+ fatal("fig support not included");
+#endif
+ break;
+ case 'n':
+ driver_extension_flag = 0;
+ break;
+ case 'p':
+ case 'x':
+ warning("-%1 option is obsolete", char(opt));
+ break;
+ case 't':
+#ifdef TEX_SUPPORT
+ tex_flag++;
+#else
+ fatal("TeX support not included");
+#endif
+ break;
+ case 'c':
+#ifdef TEX_SUPPORT
+ tpic_flag++;
+#else
+ fatal("TeX support not included");
+#endif
+ break;
+ case 'v':
+ {
+ extern const char *Version_string;
+ fprintf(stderr, "GNU pic version %s\n", Version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'z':
+ // zero length lines will be printed as dots
+ zero_length_line_flag++;
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ }
+ parse_init();
+#ifdef TEX_SUPPORT
+ if (tpic_flag) {
+ out = make_tpic_output();
+ lf_flag = 0;
+ }
+ else if (tex_flag) {
+ out = make_tex_output();
+ command_char = '\\';
+ lf_flag = 0;
+ }
+ else
+#endif
+#ifdef FIG_SUPPORT
+ if (fig_flag)
+ out = make_fig_output();
+ else
+#endif
+ out = make_troff_output();
+#ifdef FIG_SUPPORT
+ if (whole_file_flag) {
+ if (optind >= argc)
+ do_whole_file("-");
+ else if (argc - optind > 1)
+ usage();
+ else
+ do_whole_file(argv[optind]);
+ }
+ else {
+#endif
+ if (optind >= argc)
+ do_file("-");
+ else
+ for (int i = optind; i < argc; i++)
+ do_file(argv[i]);
+#ifdef FIG_SUPPORT
+ }
+#endif
+ delete out;
+ if (ferror(stdout) || fflush(stdout) < 0)
+ fatal("output error");
+ return had_parse_error;
+}
+
diff --git a/src/preproc/pic/object.cc b/src/preproc/pic/object.cc
new file mode 100644
index 00000000..6b346330
--- /dev/null
+++ b/src/preproc/pic/object.cc
@@ -0,0 +1,1833 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "pic.h"
+#include "ptable.h"
+#include "object.h"
+
+void print_object_list(object *);
+
+line_type::line_type()
+: type(solid), thickness(1.0)
+{
+}
+
+output::output() : args(0), desired_height(0.0), desired_width(0.0)
+{
+}
+
+output::~output()
+{
+ a_delete args;
+}
+
+void output::set_desired_width_height(double wid, double ht)
+{
+ desired_width = wid;
+ desired_height = ht;
+}
+
+void output::set_args(const char *s)
+{
+ a_delete args;
+ if (s == 0 || *s == '\0')
+ args = 0;
+ else
+ args = strsave(s);
+}
+
+void output::command(const char *, const char *, int)
+{
+}
+
+void output::set_location(const char *, int)
+{
+}
+
+int output::supports_filled_polygons()
+{
+ return 0;
+}
+
+void output::begin_block(const position &, const position &)
+{
+}
+
+void output::end_block()
+{
+}
+
+double output::compute_scale(double sc, const position &ll, const position &ur)
+{
+ distance dim = ur - ll;
+ if (desired_width != 0.0 || desired_height != 0.0) {
+ sc = 0.0;
+ if (desired_width != 0.0) {
+ if (dim.x == 0.0)
+ error("width specified for picture with zero width");
+ else
+ sc = dim.x/desired_width;
+ }
+ if (desired_height != 0.0) {
+ if (dim.y == 0.0)
+ error("height specified for picture with zero height");
+ else {
+ double tem = dim.y/desired_height;
+ if (tem > sc)
+ sc = tem;
+ }
+ }
+ return sc == 0.0 ? 1.0 : sc;
+ }
+ else {
+ if (sc <= 0.0)
+ sc = 1.0;
+ distance sdim = dim/sc;
+ double max_width = 0.0;
+ lookup_variable("maxpswid", &max_width);
+ double max_height = 0.0;
+ lookup_variable("maxpsht", &max_height);
+ if ((max_width > 0.0 && sdim.x > max_width)
+ || (max_height > 0.0 && sdim.y > max_height)) {
+ double xscale = dim.x/max_width;
+ double yscale = dim.y/max_height;
+ return xscale > yscale ? xscale : yscale;
+ }
+ else
+ return sc;
+ }
+}
+
+position::position(const place &pl)
+{
+ if (pl.obj != 0) {
+ // Use two statements to work around bug in SGI C++.
+ object *tem = pl.obj;
+ *this = tem->origin();
+ }
+ else {
+ x = pl.x;
+ y = pl.y;
+ }
+}
+
+position::position() : x(0.0), y(0.0)
+{
+}
+
+position::position(double a, double b) : x(a), y(b)
+{
+}
+
+
+int operator==(const position &a, const position &b)
+{
+ return a.x == b.x && a.y == b.y;
+}
+
+int operator!=(const position &a, const position &b)
+{
+ return a.x != b.x || a.y != b.y;
+}
+
+position &position::operator+=(const position &a)
+{
+ x += a.x;
+ y += a.y;
+ return *this;
+}
+
+position &position::operator-=(const position &a)
+{
+ x -= a.x;
+ y -= a.y;
+ return *this;
+}
+
+position &position::operator*=(double a)
+{
+ x *= a;
+ y *= a;
+ return *this;
+}
+
+position &position::operator/=(double a)
+{
+ x /= a;
+ y /= a;
+ return *this;
+}
+
+position operator-(const position &a)
+{
+ return position(-a.x, -a.y);
+}
+
+position operator+(const position &a, const position &b)
+{
+ return position(a.x + b.x, a.y + b.y);
+}
+
+position operator-(const position &a, const position &b)
+{
+ return position(a.x - b.x, a.y - b.y);
+}
+
+position operator/(const position &a, double n)
+{
+ return position(a.x/n, a.y/n);
+}
+
+position operator*(const position &a, double n)
+{
+ return position(a.x*n, a.y*n);
+}
+
+// dot product
+
+double operator*(const position &a, const position &b)
+{
+ return a.x*b.x + a.y*b.y;
+}
+
+double hypot(const position &a)
+{
+ return hypot(a.x, a.y);
+}
+
+struct arrow_head_type {
+ double height;
+ double width;
+ int solid;
+};
+
+void draw_arrow(const position &pos, const distance &dir,
+ const arrow_head_type &aht, const line_type &lt)
+{
+ double hyp = hypot(dir);
+ if (hyp == 0.0) {
+ error("cannot draw arrow on object with zero length");
+ return;
+ }
+ position base = -dir;
+ base *= aht.height/hyp;
+ position n(dir.y, -dir.x);
+ n *= aht.width/(hyp*2.0);
+ line_type slt = lt;
+ slt.type = line_type::solid;
+ if (aht.solid && out->supports_filled_polygons()) {
+ position v[3];
+ v[0] = pos;
+ v[1] = pos + base + n;
+ v[2] = pos + base - n;
+ // A value > 1 means fill with the current color.
+ out->polygon(v, 3, slt, 2.0);
+ }
+ else {
+ position v[2];
+ v[0] = pos;
+ v[1] = pos + base + n;
+ out->line(pos + base - n, v, 2, slt);
+ }
+}
+
+object::object() : prev(0), next(0)
+{
+}
+
+object::~object()
+{
+}
+
+void object::move_by(const position &)
+{
+}
+
+void object::print()
+{
+}
+
+void object::print_text()
+{
+}
+
+int object::blank()
+{
+ return 0;
+}
+
+struct bounding_box {
+ int blank;
+ position ll;
+ position ur;
+
+ bounding_box();
+ void encompass(const position &);
+};
+
+bounding_box::bounding_box()
+: blank(1)
+{
+}
+
+void bounding_box::encompass(const position &pos)
+{
+ if (blank) {
+ ll = pos;
+ ur = pos;
+ blank = 0;
+ }
+ else {
+ if (pos.x < ll.x)
+ ll.x = pos.x;
+ if (pos.y < ll.y)
+ ll.y = pos.y;
+ if (pos.x > ur.x)
+ ur.x = pos.x;
+ if (pos.y > ur.y)
+ ur.y = pos.y;
+ }
+}
+
+void object::update_bounding_box(bounding_box *)
+{
+}
+
+position object::origin()
+{
+ return position(0.0,0.0);
+}
+
+position object::north()
+{
+ return origin();
+}
+
+position object::south()
+{
+ return origin();
+}
+
+position object::east()
+{
+ return origin();
+}
+
+position object::west()
+{
+ return origin();
+}
+
+position object::north_east()
+{
+ return origin();
+}
+
+position object::north_west()
+{
+ return origin();
+}
+
+position object::south_east()
+{
+ return origin();
+}
+
+position object::south_west()
+{
+ return origin();
+}
+
+position object::start()
+{
+ return origin();
+}
+
+position object::end()
+{
+ return origin();
+}
+
+position object::center()
+{
+ return origin();
+}
+
+double object::width()
+{
+ return 0.0;
+}
+
+double object::radius()
+{
+ return 0.0;
+}
+
+double object::height()
+{
+ return 0.0;
+}
+
+place *object::find_label(const char *)
+{
+ return 0;
+}
+
+segment::segment(const position &a, int n, segment *p)
+: is_absolute(n), pos(a), next(p)
+{
+}
+
+text_item::text_item(char *t, const char *fn, int ln)
+: next(0), text(t), filename(fn), lineno(ln)
+{
+ adj.h = CENTER_ADJUST;
+ adj.v = NONE_ADJUST;
+}
+
+text_item::~text_item()
+{
+ a_delete text;
+}
+
+object_spec::object_spec(object_type t) : type(t)
+{
+ flags = 0;
+ tbl = 0;
+ segment_list = 0;
+ segment_width = segment_height = 0.0;
+ segment_is_absolute = 0;
+ text = 0;
+ with = 0;
+ dir = RIGHT_DIRECTION;
+}
+
+object_spec::~object_spec()
+{
+ delete tbl;
+ while (segment_list != 0) {
+ segment *tem = segment_list;
+ segment_list = segment_list->next;
+ delete tem;
+ }
+ object *p = oblist.head;
+ while (p != 0) {
+ object *tem = p;
+ p = p->next;
+ delete tem;
+ }
+ while (text != 0) {
+ text_item *tem = text;
+ text = text->next;
+ delete tem;
+ }
+ delete with;
+}
+
+class command_object : public object {
+ char *s;
+ const char *filename;
+ int lineno;
+public:
+ command_object(char *, const char *, int);
+ ~command_object();
+ object_type type() { return OTHER_OBJECT; }
+ void print();
+};
+
+command_object::command_object(char *p, const char *fn, int ln)
+: s(p), filename(fn), lineno(ln)
+{
+}
+
+command_object::~command_object()
+{
+ a_delete s;
+}
+
+void command_object::print()
+{
+ out->command(s, filename, lineno);
+}
+
+object *make_command_object(char *s, const char *fn, int ln)
+{
+ return new command_object(s, fn, ln);
+}
+
+class mark_object : public object {
+public:
+ mark_object();
+ object_type type();
+};
+
+object *make_mark_object()
+{
+ return new mark_object();
+}
+
+mark_object::mark_object()
+{
+}
+
+object_type mark_object::type()
+{
+ return MARK_OBJECT;
+}
+
+object_list::object_list() : head(0), tail(0)
+{
+}
+
+void object_list::append(object *obj)
+{
+ if (tail == 0) {
+ obj->next = obj->prev = 0;
+ head = tail = obj;
+ }
+ else {
+ obj->prev = tail;
+ obj->next = 0;
+ tail->next = obj;
+ tail = obj;
+ }
+}
+
+void object_list::wrap_up_block(object_list *ol)
+{
+ object *p;
+ for (p = tail; p && p->type() != MARK_OBJECT; p = p->prev)
+ ;
+ assert(p != 0);
+ ol->head = p->next;
+ if (ol->head) {
+ ol->tail = tail;
+ ol->head->prev = 0;
+ }
+ else
+ ol->tail = 0;
+ tail = p->prev;
+ if (tail)
+ tail->next = 0;
+ else
+ head = 0;
+ delete p;
+}
+
+text_piece::text_piece()
+: text(0), filename(0), lineno(-1)
+{
+ adj.h = CENTER_ADJUST;
+ adj.v = NONE_ADJUST;
+}
+
+text_piece::~text_piece()
+{
+ a_delete text;
+}
+
+class graphic_object : public object {
+ int ntext;
+ text_piece *text;
+ int aligned;
+protected:
+ line_type lt;
+public:
+ graphic_object();
+ ~graphic_object();
+ object_type type() = 0;
+ void print_text();
+ void add_text(text_item *, int);
+ void set_dotted(double);
+ void set_dashed(double);
+ void set_thickness(double);
+ void set_invisible();
+ virtual void set_fill(double);
+};
+
+graphic_object::graphic_object() : ntext(0), text(0), aligned(0)
+{
+}
+
+void graphic_object::set_dotted(double wid)
+{
+ lt.type = line_type::dotted;
+ lt.dash_width = wid;
+}
+
+void graphic_object::set_dashed(double wid)
+{
+ lt.type = line_type::dashed;
+ lt.dash_width = wid;
+}
+
+void graphic_object::set_thickness(double th)
+{
+ lt.thickness = th;
+}
+
+void graphic_object::set_fill(double)
+{
+}
+
+void graphic_object::set_invisible()
+{
+ lt.type = line_type::invisible;
+}
+
+void graphic_object::add_text(text_item *t, int a)
+{
+ aligned = a;
+ int len = 0;
+ text_item *p;
+ for (p = t; p; p = p->next)
+ len++;
+ if (len == 0)
+ text = 0;
+ else {
+ text = new text_piece[len];
+ for (p = t, len = 0; p; p = p->next, len++) {
+ text[len].text = p->text;
+ p->text = 0;
+ text[len].adj = p->adj;
+ text[len].filename = p->filename;
+ text[len].lineno = p->lineno;
+ }
+ }
+ ntext = len;
+}
+
+void graphic_object::print_text()
+{
+ double angle = 0.0;
+ if (aligned) {
+ position d(end() - start());
+ if (d.x != 0.0 || d.y != 0.0)
+ angle = atan2(d.y, d.x);
+ }
+ if (text != 0)
+ out->text(center(), text, ntext, angle);
+}
+
+graphic_object::~graphic_object()
+{
+ if (text)
+ ad_delete(ntext) text;
+}
+
+class rectangle_object : public graphic_object {
+protected:
+ position cent;
+ position dim;
+public:
+ rectangle_object(const position &);
+ double width() { return dim.x; }
+ double height() { return dim.y; }
+ position origin() { return cent; }
+ position center() { return cent; }
+ position north() { return position(cent.x, cent.y + dim.y/2.0); }
+ position south() { return position(cent.x, cent.y - dim.y/2.0); }
+ position east() { return position(cent.x + dim.x/2.0, cent.y); }
+ position west() { return position(cent.x - dim.x/2.0, cent.y); }
+ position north_east() { return position(cent.x + dim.x/2.0, cent.y + dim.y/2.0); }
+ position north_west() { return position(cent.x - dim.x/2.0, cent.y + dim.y/2.0); }
+ position south_east() { return position(cent.x + dim.x/2.0, cent.y - dim.y/2.0); }
+ position south_west() { return position(cent.x - dim.x/2.0, cent.y - dim.y/2.0); }
+ object_type type() = 0;
+ void update_bounding_box(bounding_box *);
+ void move_by(const position &);
+};
+
+rectangle_object::rectangle_object(const position &d)
+: dim(d)
+{
+}
+
+void rectangle_object::update_bounding_box(bounding_box *p)
+{
+ p->encompass(cent - dim/2.0);
+ p->encompass(cent + dim/2.0);
+}
+
+void rectangle_object::move_by(const position &a)
+{
+ cent += a;
+}
+
+class closed_object : public rectangle_object {
+public:
+ closed_object(const position &);
+ object_type type() = 0;
+ void set_fill(double);
+protected:
+ double fill; // < 0 if not filled
+};
+
+closed_object::closed_object(const position &pos)
+: rectangle_object(pos), fill(-1.0)
+{
+}
+
+void closed_object::set_fill(double f)
+{
+ assert(f >= 0.0);
+ fill = f;
+}
+
+
+class box_object : public closed_object {
+ double xrad;
+ double yrad;
+public:
+ box_object(const position &, double);
+ object_type type() { return BOX_OBJECT; }
+ void print();
+ position north_east();
+ position north_west();
+ position south_east();
+ position south_west();
+};
+
+box_object::box_object(const position &pos, double r)
+: closed_object(pos), xrad(dim.x > 0 ? r : -r), yrad(dim.y > 0 ? r : -r)
+{
+}
+
+const double CHOP_FACTOR = 1.0 - 1.0/M_SQRT2;
+
+position box_object::north_east()
+{
+ return position(cent.x + dim.x/2.0 - CHOP_FACTOR*xrad,
+ cent.y + dim.y/2.0 - CHOP_FACTOR*yrad);
+}
+
+position box_object::north_west()
+{
+ return position(cent.x - dim.x/2.0 + CHOP_FACTOR*xrad,
+ cent.y + dim.y/2.0 - CHOP_FACTOR*yrad);
+}
+
+position box_object::south_east()
+{
+ return position(cent.x + dim.x/2.0 - CHOP_FACTOR*xrad,
+ cent.y - dim.y/2.0 + CHOP_FACTOR*yrad);
+}
+
+position box_object::south_west()
+{
+ return position(cent.x - dim.x/2.0 + CHOP_FACTOR*xrad,
+ cent.y - dim.y/2.0 + CHOP_FACTOR*yrad);
+}
+
+void box_object::print()
+{
+ if (lt.type == line_type::invisible && fill < 0.0)
+ return;
+ if (xrad == 0.0) {
+ distance dim2 = dim/2.0;
+ position vec[4];
+ vec[0] = cent + position(dim2.x, -dim2.y);
+ vec[1] = cent + position(dim2.x, dim2.y);
+ vec[2] = cent + position(-dim2.x, dim2.y);
+ vec[3] = cent + position(-dim2.x, -dim2.y);
+ out->polygon(vec, 4, lt, fill);
+ }
+ else {
+ distance abs_dim(fabs(dim.x), fabs(dim.y));
+ out->rounded_box(cent, abs_dim, fabs(xrad), lt, fill);
+ }
+}
+
+graphic_object *object_spec::make_box(position *curpos, direction *dirp)
+{
+ static double last_box_height;
+ static double last_box_width;
+ static double last_box_radius;
+ static int have_last_box = 0;
+ if (!(flags & HAS_HEIGHT)) {
+ if ((flags & IS_SAME) && have_last_box)
+ height = last_box_height;
+ else
+ lookup_variable("boxht", &height);
+ }
+ if (!(flags & HAS_WIDTH)) {
+ if ((flags & IS_SAME) && have_last_box)
+ width = last_box_width;
+ else
+ lookup_variable("boxwid", &width);
+ }
+ if (!(flags & HAS_RADIUS)) {
+ if ((flags & IS_SAME) && have_last_box)
+ radius = last_box_radius;
+ else
+ lookup_variable("boxrad", &radius);
+ }
+ last_box_width = width;
+ last_box_height = height;
+ last_box_radius = radius;
+ have_last_box = 1;
+ radius = fabs(radius);
+ if (radius*2.0 > fabs(width))
+ radius = fabs(width/2.0);
+ if (radius*2.0 > fabs(height))
+ radius = fabs(height/2.0);
+ box_object *p = new box_object(position(width, height), radius);
+ if (!position_rectangle(p, curpos, dirp)) {
+ delete p;
+ p = 0;
+ }
+ return p;
+}
+
+// return non-zero for success
+
+int object_spec::position_rectangle(rectangle_object *p,
+ position *curpos, direction *dirp)
+{
+ position pos;
+ dir = *dirp; // ignore any direction in attribute list
+ position motion;
+ switch (dir) {
+ case UP_DIRECTION:
+ motion.y = p->height()/2.0;
+ break;
+ case DOWN_DIRECTION:
+ motion.y = -p->height()/2.0;
+ break;
+ case LEFT_DIRECTION:
+ motion.x = -p->width()/2.0;
+ break;
+ case RIGHT_DIRECTION:
+ motion.x = p->width()/2.0;
+ break;
+ default:
+ assert(0);
+ }
+ if (flags & HAS_AT) {
+ pos = at;
+ if (flags & HAS_WITH) {
+ place offset;
+ place here;
+ here.obj = p;
+ if (!with->follow(here, &offset))
+ return 0;
+ pos -= offset;
+ }
+ }
+ else {
+ pos = *curpos;
+ pos += motion;
+ }
+ p->move_by(pos);
+ pos += motion;
+ *curpos = pos;
+ return 1;
+}
+
+class block_object : public rectangle_object {
+ object_list oblist;
+ PTABLE(place) *tbl;
+public:
+ block_object(const position &, const object_list &ol, PTABLE(place) *t);
+ ~block_object();
+ place *find_label(const char *);
+ object_type type();
+ void move_by(const position &);
+ void print();
+};
+
+block_object::block_object(const position &d, const object_list &ol,
+ PTABLE(place) *t)
+: rectangle_object(d), oblist(ol), tbl(t)
+{
+}
+
+block_object::~block_object()
+{
+ delete tbl;
+ object *p = oblist.head;
+ while (p != 0) {
+ object *tem = p;
+ p = p->next;
+ delete tem;
+ }
+}
+
+void block_object::print()
+{
+ out->begin_block(south_west(), north_east());
+ print_object_list(oblist.head);
+ out->end_block();
+}
+
+static void adjust_objectless_places(PTABLE(place) *tbl, const position &a)
+{
+ // Adjust all the labels that aren't attached to objects.
+ PTABLE_ITERATOR(place) iter(tbl);
+ const char *key;
+ place *pl;
+ while (iter.next(&key, &pl))
+ if (key && csupper(key[0]) && pl->obj == 0) {
+ pl->x += a.x;
+ pl->y += a.y;
+ }
+}
+
+void block_object::move_by(const position &a)
+{
+ cent += a;
+ for (object *p = oblist.head; p; p = p->next)
+ p->move_by(a);
+ adjust_objectless_places(tbl, a);
+}
+
+
+place *block_object::find_label(const char *name)
+{
+ return tbl->lookup(name);
+}
+
+object_type block_object::type()
+{
+ return BLOCK_OBJECT;
+}
+
+graphic_object *object_spec::make_block(position *curpos, direction *dirp)
+{
+ bounding_box bb;
+ for (object *p = oblist.head; p; p = p->next)
+ p->update_bounding_box(&bb);
+ position dim;
+ if (!bb.blank) {
+ position m = -(bb.ll + bb.ur)/2.0;
+ for (object *p = oblist.head; p; p = p->next)
+ p->move_by(m);
+ adjust_objectless_places(tbl, m);
+ dim = bb.ur - bb.ll;
+ }
+ if (flags & HAS_WIDTH)
+ dim.x = width;
+ if (flags & HAS_HEIGHT)
+ dim.y = height;
+ block_object *block = new block_object(dim, oblist, tbl);
+ if (!position_rectangle(block, curpos, dirp)) {
+ delete block;
+ block = 0;
+ }
+ tbl = 0;
+ oblist.head = oblist.tail = 0;
+ return block;
+}
+
+class text_object : public rectangle_object {
+public:
+ text_object(const position &);
+ object_type type() { return TEXT_OBJECT; }
+};
+
+text_object::text_object(const position &d)
+: rectangle_object(d)
+{
+}
+
+graphic_object *object_spec::make_text(position *curpos, direction *dirp)
+{
+ if (!(flags & HAS_HEIGHT)) {
+ lookup_variable("textht", &height);
+ int nitems = 0;
+ for (text_item *t = text; t; t = t->next)
+ nitems++;
+ height *= nitems;
+ }
+ if (!(flags & HAS_WIDTH))
+ lookup_variable("textwid", &width);
+ text_object *p = new text_object(position(width, height));
+ if (!position_rectangle(p, curpos, dirp)) {
+ delete p;
+ p = 0;
+ }
+ return p;
+}
+
+
+class ellipse_object : public closed_object {
+public:
+ ellipse_object(const position &);
+ position north_east() { return position(cent.x + dim.x/(M_SQRT2*2.0),
+ cent.y + dim.y/(M_SQRT2*2.0)); }
+ position north_west() { return position(cent.x - dim.x/(M_SQRT2*2.0),
+ cent.y + dim.y/(M_SQRT2*2.0)); }
+ position south_east() { return position(cent.x + dim.x/(M_SQRT2*2.0),
+ cent.y - dim.y/(M_SQRT2*2.0)); }
+ position south_west() { return position(cent.x - dim.x/(M_SQRT2*2.0),
+ cent.y - dim.y/(M_SQRT2*2.0)); }
+ double radius() { return dim.x/2.0; }
+ object_type type() { return ELLIPSE_OBJECT; }
+ void print();
+};
+
+ellipse_object::ellipse_object(const position &d)
+: closed_object(d)
+{
+}
+
+void ellipse_object::print()
+{
+ if (lt.type == line_type::invisible && fill < 0.0)
+ return;
+ out->ellipse(cent, dim, lt, fill);
+}
+
+graphic_object *object_spec::make_ellipse(position *curpos, direction *dirp)
+{
+ static double last_ellipse_height;
+ static double last_ellipse_width;
+ static int have_last_ellipse = 0;
+ if (!(flags & HAS_HEIGHT)) {
+ if ((flags & IS_SAME) && have_last_ellipse)
+ height = last_ellipse_height;
+ else
+ lookup_variable("ellipseht", &height);
+ }
+ if (!(flags & HAS_WIDTH)) {
+ if ((flags & IS_SAME) && have_last_ellipse)
+ width = last_ellipse_width;
+ else
+ lookup_variable("ellipsewid", &width);
+ }
+ last_ellipse_width = width;
+ last_ellipse_height = height;
+ have_last_ellipse = 1;
+ ellipse_object *p = new ellipse_object(position(width, height));
+ if (!position_rectangle(p, curpos, dirp)) {
+ delete p;
+ return 0;
+ }
+ return p;
+}
+
+class circle_object : public ellipse_object {
+public:
+ circle_object(double);
+ object_type type() { return CIRCLE_OBJECT; }
+ void print();
+};
+
+circle_object::circle_object(double diam)
+: ellipse_object(position(diam, diam))
+{
+}
+
+void circle_object::print()
+{
+ if (lt.type == line_type::invisible && fill < 0.0)
+ return;
+ out->circle(cent, dim.x/2.0, lt, fill);
+}
+
+graphic_object *object_spec::make_circle(position *curpos, direction *dirp)
+{
+ static double last_circle_radius;
+ static int have_last_circle = 0;
+ if (!(flags & HAS_RADIUS)) {
+ if ((flags & IS_SAME) && have_last_circle)
+ radius = last_circle_radius;
+ else
+ lookup_variable("circlerad", &radius);
+ }
+ last_circle_radius = radius;
+ have_last_circle = 1;
+ circle_object *p = new circle_object(radius*2.0);
+ if (!position_rectangle(p, curpos, dirp)) {
+ delete p;
+ return 0;
+ }
+ return p;
+}
+
+class move_object : public graphic_object {
+ position strt;
+ position en;
+public:
+ move_object(const position &s, const position &e);
+ position origin() { return en; }
+ object_type type() { return MOVE_OBJECT; }
+ void update_bounding_box(bounding_box *);
+ void move_by(const position &);
+};
+
+move_object::move_object(const position &s, const position &e)
+: strt(s), en(e)
+{
+}
+
+void move_object::update_bounding_box(bounding_box *p)
+{
+ p->encompass(strt);
+ p->encompass(en);
+}
+
+void move_object::move_by(const position &a)
+{
+ strt += a;
+ en += a;
+}
+
+graphic_object *object_spec::make_move(position *curpos, direction *dirp)
+{
+ static position last_move;
+ static int have_last_move = 0;
+ *dirp = dir;
+ // No need to look at at since `at' attribute sets `from' attribute.
+ position startpos = (flags & HAS_FROM) ? from : *curpos;
+ if (!(flags & HAS_SEGMENT)) {
+ if ((flags && IS_SAME) && have_last_move)
+ segment_pos = last_move;
+ else {
+ switch (dir) {
+ case UP_DIRECTION:
+ segment_pos.y = segment_height;
+ break;
+ case DOWN_DIRECTION:
+ segment_pos.y = -segment_height;
+ break;
+ case LEFT_DIRECTION:
+ segment_pos.x = -segment_width;
+ break;
+ case RIGHT_DIRECTION:
+ segment_pos.x = segment_width;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ }
+ segment_list = new segment(segment_pos, segment_is_absolute, segment_list);
+ // Reverse the segment_list so that it's in forward order.
+ segment *old = segment_list;
+ segment_list = 0;
+ while (old != 0) {
+ segment *tem = old->next;
+ old->next = segment_list;
+ segment_list = old;
+ old = tem;
+ }
+ // Compute the end position.
+ position endpos = startpos;
+ for (segment *s = segment_list; s; s = s->next)
+ if (s->is_absolute)
+ endpos = s->pos;
+ else
+ endpos += s->pos;
+ have_last_move = 1;
+ last_move = endpos - startpos;
+ move_object *p = new move_object(startpos, endpos);
+ *curpos = endpos;
+ return p;
+}
+
+class linear_object : public graphic_object {
+protected:
+ char arrow_at_start;
+ char arrow_at_end;
+ arrow_head_type aht;
+ position strt;
+ position en;
+public:
+ linear_object(const position &s, const position &e);
+ position start() { return strt; }
+ position end() { return en; }
+ void move_by(const position &);
+ void update_bounding_box(bounding_box *) = 0;
+ object_type type() = 0;
+ void add_arrows(int at_start, int at_end, const arrow_head_type &);
+};
+
+class line_object : public linear_object {
+protected:
+ position *v;
+ int n;
+public:
+ line_object(const position &s, const position &e, position *, int);
+ ~line_object();
+ position origin() { return strt; }
+ position center() { return (strt + en)/2.0; }
+ position north() { return (en.y - strt.y) > 0 ? en : strt; }
+ position south() { return (en.y - strt.y) < 0 ? en : strt; }
+ position east() { return (en.x - strt.x) > 0 ? en : strt; }
+ position west() { return (en.x - strt.x) < 0 ? en : strt; }
+ object_type type() { return LINE_OBJECT; }
+ void update_bounding_box(bounding_box *);
+ void print();
+ void move_by(const position &);
+};
+
+class arrow_object : public line_object {
+public:
+ arrow_object(const position &, const position &, position *, int);
+ object_type type() { return ARROW_OBJECT; }
+};
+
+class spline_object : public line_object {
+public:
+ spline_object(const position &, const position &, position *, int);
+ object_type type() { return SPLINE_OBJECT; }
+ void print();
+ void update_bounding_box(bounding_box *);
+};
+
+linear_object::linear_object(const position &s, const position &e)
+: arrow_at_start(0), arrow_at_end(0), strt(s), en(e)
+{
+}
+
+void linear_object::move_by(const position &a)
+{
+ strt += a;
+ en += a;
+}
+
+void linear_object::add_arrows(int at_start, int at_end,
+ const arrow_head_type &a)
+{
+ arrow_at_start = at_start;
+ arrow_at_end = at_end;
+ aht = a;
+}
+
+line_object::line_object(const position &s, const position &e,
+ position *p, int i)
+: linear_object(s, e), v(p), n(i)
+{
+}
+
+void line_object::print()
+{
+ if (lt.type == line_type::invisible)
+ return;
+ out->line(strt, v, n, lt);
+ if (arrow_at_start)
+ draw_arrow(strt, strt-v[0], aht, lt);
+ if (arrow_at_end)
+ draw_arrow(en, v[n-1] - (n > 1 ? v[n - 2] : strt), aht, lt);
+}
+
+void line_object::update_bounding_box(bounding_box *p)
+{
+ p->encompass(strt);
+ for (int i = 0; i < n; i++)
+ p->encompass(v[i]);
+}
+
+void line_object::move_by(const position &pos)
+{
+ linear_object::move_by(pos);
+ for (int i = 0; i < n; i++)
+ v[i] += pos;
+}
+
+void spline_object::update_bounding_box(bounding_box *p)
+{
+ p->encompass(strt);
+ p->encompass(en);
+ /*
+
+ If
+
+ p1 = q1/2 + q2/2
+ p2 = q1/6 + q2*5/6
+ p3 = q2*5/6 + q3/6
+ p4 = q2/2 + q3/2
+ [ the points for the Bezier cubic ]
+
+ and
+
+ t = .5
+
+ then
+
+ (1-t)^3*p1 + 3*t*(t - 1)^2*p2 + 3*t^2*(1-t)*p3 + t^3*p4
+ [ the equation for the Bezier cubic ]
+
+ = .125*q1 + .75*q2 + .125*q3
+
+ */
+ for (int i = 1; i < n; i++)
+ p->encompass((i == 1 ? strt : v[i-2])*.125 + v[i-1]*.75 + v[i]*.125);
+}
+
+arrow_object::arrow_object(const position &s, const position &e,
+ position *p, int i)
+: line_object(s, e, p, i)
+{
+}
+
+spline_object::spline_object(const position &s, const position &e,
+ position *p, int i)
+: line_object(s, e, p, i)
+{
+}
+
+void spline_object::print()
+{
+ if (lt.type == line_type::invisible)
+ return;
+ out->spline(strt, v, n, lt);
+ if (arrow_at_start)
+ draw_arrow(strt, strt-v[0], aht, lt);
+ if (arrow_at_end)
+ draw_arrow(en, v[n-1] - (n > 1 ? v[n - 2] : strt), aht, lt);
+}
+
+line_object::~line_object()
+{
+ a_delete v;
+}
+
+linear_object *object_spec::make_line(position *curpos, direction *dirp)
+{
+ static position last_line;
+ static int have_last_line = 0;
+ *dirp = dir;
+ // No need to look at at since `at' attribute sets `from' attribute.
+ position startpos = (flags & HAS_FROM) ? from : *curpos;
+ if (!(flags & HAS_SEGMENT)) {
+ if ((flags & IS_SAME) && (type == LINE_OBJECT || type == ARROW_OBJECT)
+ && have_last_line)
+ segment_pos = last_line;
+ else
+ switch (dir) {
+ case UP_DIRECTION:
+ segment_pos.y = segment_height;
+ break;
+ case DOWN_DIRECTION:
+ segment_pos.y = -segment_height;
+ break;
+ case LEFT_DIRECTION:
+ segment_pos.x = -segment_width;
+ break;
+ case RIGHT_DIRECTION:
+ segment_pos.x = segment_width;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ segment_list = new segment(segment_pos, segment_is_absolute, segment_list);
+ // reverse the segment_list so that it's in forward order
+ segment *old = segment_list;
+ segment_list = 0;
+ while (old != 0) {
+ segment *tem = old->next;
+ old->next = segment_list;
+ segment_list = old;
+ old = tem;
+ }
+ // Absolutise all movements
+ position endpos = startpos;
+ int nsegments = 0;
+ segment *s;
+ for (s = segment_list; s; s = s->next, nsegments++)
+ if (s->is_absolute)
+ endpos = s->pos;
+ else {
+ endpos += s->pos;
+ s->pos = endpos;
+ s->is_absolute = 1; // to avoid confusion
+ }
+ // handle chop
+ line_object *p = 0;
+ position *v = new position[nsegments];
+ int i = 0;
+ for (s = segment_list; s; s = s->next, i++)
+ v[i] = s->pos;
+ if (flags & IS_DEFAULT_CHOPPED) {
+ lookup_variable("circlerad", &start_chop);
+ end_chop = start_chop;
+ flags |= IS_CHOPPED;
+ }
+ if (flags & IS_CHOPPED) {
+ position start_chop_vec, end_chop_vec;
+ if (start_chop != 0.0) {
+ start_chop_vec = v[0] - startpos;
+ start_chop_vec *= start_chop / hypot(start_chop_vec);
+ }
+ if (end_chop != 0.0) {
+ end_chop_vec = (v[nsegments - 1]
+ - (nsegments > 1 ? v[nsegments - 2] : startpos));
+ end_chop_vec *= end_chop / hypot(end_chop_vec);
+ }
+ startpos += start_chop_vec;
+ v[nsegments - 1] -= end_chop_vec;
+ endpos -= end_chop_vec;
+ }
+ switch (type) {
+ case SPLINE_OBJECT:
+ p = new spline_object(startpos, endpos, v, nsegments);
+ break;
+ case ARROW_OBJECT:
+ p = new arrow_object(startpos, endpos, v, nsegments);
+ break;
+ case LINE_OBJECT:
+ p = new line_object(startpos, endpos, v, nsegments);
+ break;
+ default:
+ assert(0);
+ }
+ have_last_line = 1;
+ last_line = endpos - startpos;
+ *curpos = endpos;
+ return p;
+}
+
+class arc_object : public linear_object {
+ int clockwise;
+ position cent;
+ double rad;
+public:
+ arc_object(int, const position &, const position &, const position &);
+ position origin() { return cent; }
+ position center() { return cent; }
+ double radius() { return rad; }
+ position north();
+ position south();
+ position east();
+ position west();
+ position north_east();
+ position north_west();
+ position south_east();
+ position south_west();
+ void update_bounding_box(bounding_box *);
+ object_type type() { return ARC_OBJECT; }
+ void print();
+ void move_by(const position &pos);
+};
+
+arc_object::arc_object(int cw, const position &s, const position &e,
+ const position &c)
+: linear_object(s, e), clockwise(cw), cent(c)
+{
+ rad = hypot(c - s);
+}
+
+void arc_object::move_by(const position &pos)
+{
+ linear_object::move_by(pos);
+ cent += pos;
+}
+
+// we get arc corners from the corresponding circle
+
+position arc_object::north()
+{
+ position result(cent);
+ result.y += rad;
+ return result;
+}
+
+position arc_object::south()
+{
+ position result(cent);
+ result.y -= rad;
+ return result;
+}
+
+position arc_object::east()
+{
+ position result(cent);
+ result.x += rad;
+ return result;
+}
+
+position arc_object::west()
+{
+ position result(cent);
+ result.x -= rad;
+ return result;
+}
+
+position arc_object::north_east()
+{
+ position result(cent);
+ result.x += rad/M_SQRT2;
+ result.y += rad/M_SQRT2;
+ return result;
+}
+
+position arc_object::north_west()
+{
+ position result(cent);
+ result.x -= rad/M_SQRT2;
+ result.y += rad/M_SQRT2;
+ return result;
+}
+
+position arc_object::south_east()
+{
+ position result(cent);
+ result.x += rad/M_SQRT2;
+ result.y -= rad/M_SQRT2;
+ return result;
+}
+
+position arc_object::south_west()
+{
+ position result(cent);
+ result.x -= rad/M_SQRT2;
+ result.y -= rad/M_SQRT2;
+ return result;
+}
+
+
+void arc_object::print()
+{
+ if (lt.type == line_type::invisible)
+ return;
+ if (clockwise)
+ out->arc(en, cent, strt, lt);
+ else
+ out->arc(strt, cent, en, lt);
+ if (arrow_at_start) {
+ position c = cent - strt;
+ draw_arrow(strt,
+ (clockwise ? position(c.y, -c.x) : position(-c.y, c.x)),
+ aht, lt);
+ }
+ if (arrow_at_end) {
+ position e = en - cent;
+ draw_arrow(en,
+ (clockwise ? position(e.y, -e.x) : position(-e.y, e.x)),
+ aht, lt);
+ }
+}
+
+inline double max(double a, double b)
+{
+ return a > b ? a : b;
+}
+
+void arc_object::update_bounding_box(bounding_box *p)
+{
+ p->encompass(strt);
+ p->encompass(en);
+ position start_offset = strt - cent;
+ if (start_offset.x == 0.0 && start_offset.y == 0.0)
+ return;
+ position end_offset = en - cent;
+ if (end_offset.x == 0.0 && end_offset.y == 0.0)
+ return;
+ double start_quad = atan2(start_offset.y, start_offset.x)/(M_PI/2.0);
+ double end_quad = atan2(end_offset.y, end_offset.x)/(M_PI/2.0);
+ if (clockwise) {
+ double temp = start_quad;
+ start_quad = end_quad;
+ end_quad = temp;
+ }
+ if (start_quad < 0.0)
+ start_quad += 4.0;
+ while (end_quad <= start_quad)
+ end_quad += 4.0;
+ double radius = max(hypot(start_offset), hypot(end_offset));
+ for (int q = int(start_quad) + 1; q < end_quad; q++) {
+ position offset;
+ switch (q % 4) {
+ case 0:
+ offset.x = radius;
+ break;
+ case 1:
+ offset.y = radius;
+ break;
+ case 2:
+ offset.x = -radius;
+ break;
+ case 3:
+ offset.y = -radius;
+ break;
+ }
+ p->encompass(cent + offset);
+ }
+}
+
+// We ignore the with attribute. The at attribute always refers to the center.
+
+linear_object *object_spec::make_arc(position *curpos, direction *dirp)
+{
+ *dirp = dir;
+ int cw = (flags & IS_CLOCKWISE) != 0;
+ // compute the start
+ position startpos;
+ if (flags & HAS_FROM)
+ startpos = from;
+ else
+ startpos = *curpos;
+ if (!(flags & HAS_RADIUS))
+ lookup_variable("arcrad", &radius);
+ // compute the end
+ position endpos;
+ if (flags & HAS_TO)
+ endpos = to;
+ else {
+ position m(radius, radius);
+ // Adjust the signs.
+ if (cw) {
+ if (dir == DOWN_DIRECTION || dir == LEFT_DIRECTION)
+ m.x = -m.x;
+ if (dir == DOWN_DIRECTION || dir == RIGHT_DIRECTION)
+ m.y = -m.y;
+ *dirp = direction((dir + 3) % 4);
+ }
+ else {
+ if (dir == UP_DIRECTION || dir == LEFT_DIRECTION)
+ m.x = -m.x;
+ if (dir == DOWN_DIRECTION || dir == LEFT_DIRECTION)
+ m.y = -m.y;
+ *dirp = direction((dir + 1) % 4);
+ }
+ endpos = startpos + m;
+ }
+ // compute the center
+ position centerpos;
+ if (flags & HAS_AT)
+ centerpos = at;
+ else if (startpos == endpos)
+ centerpos = startpos;
+ else {
+ position h = (endpos - startpos)/2.0;
+ double d = hypot(h);
+ if (radius <= 0)
+ radius = .25;
+ // make the radius big enough
+ while (radius < d)
+ radius *= 2.0;
+ double alpha = acos(d/radius);
+ double theta = atan2(h.y, h.x);
+ if (cw)
+ theta -= alpha;
+ else
+ theta += alpha;
+ centerpos = position(cos(theta), sin(theta))*radius + startpos;
+ }
+ arc_object *p = new arc_object(cw, startpos, endpos, centerpos);
+ *curpos = endpos;
+ return p;
+}
+
+graphic_object *object_spec::make_linear(position *curpos, direction *dirp)
+{
+ linear_object *obj;
+ if (type == ARC_OBJECT)
+ obj = make_arc(curpos, dirp);
+ else
+ obj = make_line(curpos, dirp);
+ if (type == ARROW_OBJECT
+ && (flags & (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD)) == 0)
+ flags |= HAS_RIGHT_ARROW_HEAD;
+ if (obj && (flags & (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD))) {
+ arrow_head_type a;
+ int at_start = (flags & HAS_LEFT_ARROW_HEAD) != 0;
+ int at_end = (flags & HAS_RIGHT_ARROW_HEAD) != 0;
+ if (flags & HAS_HEIGHT)
+ a.height = height;
+ else
+ lookup_variable("arrowht", &a.height);
+ if (flags & HAS_WIDTH)
+ a.width = width;
+ else
+ lookup_variable("arrowwid", &a.width);
+ double solid;
+ lookup_variable("arrowhead", &solid);
+ a.solid = solid != 0.0;
+ obj->add_arrows(at_start, at_end, a);
+ }
+ return obj;
+}
+
+object *object_spec::make_object(position *curpos, direction *dirp)
+{
+ graphic_object *obj = 0;
+ switch (type) {
+ case BLOCK_OBJECT:
+ obj = make_block(curpos, dirp);
+ break;
+ case BOX_OBJECT:
+ obj = make_box(curpos, dirp);
+ break;
+ case TEXT_OBJECT:
+ obj = make_text(curpos, dirp);
+ break;
+ case ELLIPSE_OBJECT:
+ obj = make_ellipse(curpos, dirp);
+ break;
+ case CIRCLE_OBJECT:
+ obj = make_circle(curpos, dirp);
+ break;
+ case MOVE_OBJECT:
+ obj = make_move(curpos, dirp);
+ break;
+ case ARC_OBJECT:
+ case LINE_OBJECT:
+ case SPLINE_OBJECT:
+ case ARROW_OBJECT:
+ obj = make_linear(curpos, dirp);
+ break;
+ case MARK_OBJECT:
+ case OTHER_OBJECT:
+ default:
+ assert(0);
+ break;
+ }
+ if (obj) {
+ if (flags & IS_INVISIBLE)
+ obj->set_invisible();
+ if (text != 0)
+ obj->add_text(text, (flags & IS_ALIGNED) != 0);
+ if (flags & IS_DOTTED)
+ obj->set_dotted(dash_width);
+ else if (flags & IS_DASHED)
+ obj->set_dashed(dash_width);
+ double th;
+ if (flags & HAS_THICKNESS)
+ th = thickness;
+ else
+ lookup_variable("linethick", &th);
+ obj->set_thickness(th);
+ if (flags & (IS_DEFAULT_FILLED|IS_FILLED)) {
+ if (flags & IS_DEFAULT_FILLED)
+ lookup_variable("fillval", &fill);
+ if (fill < 0.0)
+ error("bad fill value %1", fill);
+ else
+ obj->set_fill(fill);
+ }
+ }
+ return obj;
+}
+
+struct string_list {
+ string_list *next;
+ char *str;
+ string_list(char *);
+ ~string_list();
+};
+
+string_list::string_list(char *s)
+: next(0), str(s)
+{
+}
+
+string_list::~string_list()
+{
+ a_delete str;
+}
+
+/* A path is used to hold the argument to the with attribute. For example,
+`.nw' or `.A.s' or `.A'. The major operation on a path is to take a
+place and follow the path through the place to place within the place.
+Note that `.A.B.C.sw' will work. */
+
+path::path(corner c)
+: crn(c), label_list(0), ypath(0)
+{
+}
+
+path::path(char *l, corner c)
+: crn(c), ypath(0)
+{
+ label_list = new string_list(l);
+}
+
+path::~path()
+{
+ while (label_list) {
+ string_list *tem = label_list;
+ label_list = label_list->next;
+ delete tem;
+ }
+ delete ypath;
+}
+
+void path::append(corner c)
+{
+ assert(crn == 0);
+ crn = c;
+}
+
+void path::append(char *s)
+{
+ string_list **p;
+ for (p = &label_list; *p; p = &(*p)->next)
+ ;
+ *p = new string_list(s);
+}
+
+void path::set_ypath(path *p)
+{
+ ypath = p;
+}
+
+// return non-zero for success
+
+int path::follow(const place &pl, place *result) const
+{
+ const place *p = &pl;
+ for (string_list *lb = label_list; lb; lb = lb->next)
+ if (p->obj == 0 || (p = p->obj->find_label(lb->str)) == 0) {
+ lex_error("object does not contain a place `%1'", lb->str);
+ return 0;
+ }
+ if (crn == 0 || p->obj == 0)
+ *result = *p;
+ else {
+ position pos = ((p->obj)->*(crn))();
+ result->x = pos.x;
+ result->y = pos.y;
+ result->obj = 0;
+ }
+ if (ypath) {
+ place tem;
+ if (!ypath->follow(pl, &tem))
+ return 0;
+ result->y = tem.y;
+ if (result->obj != tem.obj)
+ result->obj = 0;
+ }
+ return 1;
+}
+
+void print_object_list(object *p)
+{
+ for (; p; p = p->next) {
+ p->print();
+ p->print_text();
+ }
+}
+
+void print_picture(object *obj)
+{
+ bounding_box bb;
+ for (object *p = obj; p; p = p->next)
+ p->update_bounding_box(&bb);
+ double scale;
+ lookup_variable("scale", &scale);
+ out->start_picture(scale, bb.ll, bb.ur);
+ print_object_list(obj);
+ out->finish_picture();
+}
+
diff --git a/src/preproc/pic/object.h b/src/preproc/pic/object.h
new file mode 100644
index 00000000..2748e81e
--- /dev/null
+++ b/src/preproc/pic/object.h
@@ -0,0 +1,217 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+struct place;
+
+enum object_type {
+ OTHER_OBJECT,
+ BOX_OBJECT,
+ CIRCLE_OBJECT,
+ ELLIPSE_OBJECT,
+ ARC_OBJECT,
+ SPLINE_OBJECT,
+ LINE_OBJECT,
+ ARROW_OBJECT,
+ MOVE_OBJECT,
+ TEXT_OBJECT,
+ BLOCK_OBJECT,
+ MARK_OBJECT
+ };
+
+struct bounding_box;
+
+struct object {
+ object *prev;
+ object *next;
+ object();
+ virtual ~object();
+ virtual position origin();
+ virtual double width();
+ virtual double radius();
+ virtual double height();
+ virtual position north();
+ virtual position south();
+ virtual position east();
+ virtual position west();
+ virtual position north_east();
+ virtual position north_west();
+ virtual position south_east();
+ virtual position south_west();
+ virtual position start();
+ virtual position end();
+ virtual position center();
+ virtual place *find_label(const char *);
+ virtual void move_by(const position &);
+ virtual int blank();
+ virtual void update_bounding_box(bounding_box *);
+ virtual object_type type() = 0;
+ virtual void print();
+ virtual void print_text();
+};
+
+typedef position (object::*corner)();
+
+struct place {
+ object *obj;
+ double x, y;
+};
+
+struct string_list;
+
+class path {
+ corner crn;
+ string_list *label_list;
+ path *ypath;
+public:
+ path(corner = 0);
+ path(char *, corner = 0);
+ ~path();
+ void append(corner);
+ void append(char *);
+ void set_ypath(path *);
+ int follow(const place &, place *) const;
+};
+
+struct object_list {
+ object *head;
+ object *tail;
+ object_list();
+ void append(object *);
+ void wrap_up_block(object_list *);
+};
+
+declare_ptable(place)
+
+// these go counterclockwise
+enum direction {
+ RIGHT_DIRECTION,
+ UP_DIRECTION,
+ LEFT_DIRECTION,
+ DOWN_DIRECTION
+ };
+
+struct graphics_state {
+ double x, y;
+ direction dir;
+};
+
+struct saved_state : public graphics_state {
+ saved_state *prev;
+ PTABLE(place) *tbl;
+};
+
+
+struct text_item {
+ text_item *next;
+ char *text;
+ adjustment adj;
+ const char *filename;
+ int lineno;
+
+ text_item(char *, const char *, int);
+ ~text_item();
+};
+
+const unsigned long IS_DOTTED = 01;
+const unsigned long IS_DASHED = 02;
+const unsigned long IS_CLOCKWISE = 04;
+const unsigned long IS_INVISIBLE = 020;
+const unsigned long HAS_LEFT_ARROW_HEAD = 040;
+const unsigned long HAS_RIGHT_ARROW_HEAD = 0100;
+const unsigned long HAS_SEGMENT = 0200;
+const unsigned long IS_SAME = 0400;
+const unsigned long HAS_FROM = 01000;
+const unsigned long HAS_AT = 02000;
+const unsigned long HAS_WITH = 04000;
+const unsigned long HAS_HEIGHT = 010000;
+const unsigned long HAS_WIDTH = 020000;
+const unsigned long HAS_RADIUS = 040000;
+const unsigned long HAS_TO = 0100000;
+const unsigned long IS_CHOPPED = 0200000;
+const unsigned long IS_DEFAULT_CHOPPED = 0400000;
+const unsigned long HAS_THICKNESS = 01000000;
+const unsigned long IS_FILLED = 02000000;
+const unsigned long IS_DEFAULT_FILLED = 04000000;
+const unsigned long IS_ALIGNED = 010000000;
+
+struct segment {
+ int is_absolute;
+ position pos;
+ segment *next;
+ segment(const position &, int, segment *);
+};
+
+struct rectangle_object;
+struct graphic_object;
+struct linear_object;
+
+struct object_spec {
+ unsigned long flags;
+ object_type type;
+ object_list oblist;
+ PTABLE(place) *tbl;
+ double dash_width;
+ position from;
+ position to;
+ position at;
+ position by;
+ path *with;
+ text_item *text;
+ double height;
+ double radius;
+ double width;
+ double segment_width;
+ double segment_height;
+ double start_chop;
+ double end_chop;
+ double thickness;
+ double fill;
+ direction dir;
+ segment *segment_list;
+ position segment_pos;
+ int segment_is_absolute;
+
+ object_spec(object_type);
+ ~object_spec();
+ object *make_object(position *, direction *);
+ graphic_object *make_box(position *, direction *);
+ graphic_object *make_block(position *, direction *);
+ graphic_object *make_text(position *, direction *);
+ graphic_object *make_ellipse(position *, direction *);
+ graphic_object *make_circle(position *, direction *);
+ linear_object *make_line(position *, direction *);
+ linear_object *make_arc(position *, direction *);
+ graphic_object *make_linear(position *, direction *);
+ graphic_object *make_move(position *, direction *);
+ int position_rectangle(rectangle_object *p, position *curpos,
+ direction *dirp);
+};
+
+
+object *make_object(object_spec *, position *, direction *);
+
+object *make_mark_object();
+object *make_command_object(char *, const char *, int);
+
+int lookup_variable(const char *name, double *val);
+void define_variable(const char *name, double val);
+
+void print_picture(object *);
+
diff --git a/src/preproc/pic/output.h b/src/preproc/pic/output.h
new file mode 100644
index 00000000..ac490db4
--- /dev/null
+++ b/src/preproc/pic/output.h
@@ -0,0 +1,79 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+struct line_type {
+ enum { invisible, solid, dotted, dashed } type;
+ double dash_width;
+ double thickness; // the thickness is in points
+
+ line_type();
+};
+
+
+class output {
+protected:
+ char *args;
+ double desired_height; // zero if no height specified
+ double desired_width; // zero if no depth specified
+ double compute_scale(double, const position &, const position &);
+public:
+ output();
+ virtual ~output();
+ void set_desired_width_height(double wid, double ht);
+ void set_args(const char *);
+ virtual void start_picture(double sc, const position &ll, const position &ur) = 0;
+ virtual void finish_picture() = 0;
+ virtual void circle(const position &, double rad,
+ const line_type &, double) = 0;
+ virtual void text(const position &, text_piece *, int, double) = 0;
+ virtual void line(const position &, const position *, int n,
+ const line_type &) = 0;
+ virtual void polygon(const position *, int n,
+ const line_type &, double) = 0;
+ virtual void spline(const position &, const position *, int n,
+ const line_type &) = 0;
+ virtual void arc(const position &, const position &, const position &,
+ const line_type &) = 0;
+ virtual void ellipse(const position &, const distance &,
+ const line_type &, double) = 0;
+ virtual void rounded_box(const position &, const distance &, double,
+ const line_type &, double) = 0;
+ virtual void command(const char *, const char *, int);
+ virtual void set_location(const char *, int);
+ virtual int supports_filled_polygons();
+ virtual void begin_block(const position &ll, const position &ur);
+ virtual void end_block();
+};
+
+extern output *out;
+
+/* #define FIG_SUPPORT 1 */
+#define TEX_SUPPORT 1
+
+output *make_troff_output();
+
+#ifdef TEX_SUPPORT
+output *make_tex_output();
+output *make_tpic_output();
+#endif /* TEX_SUPPORT */
+
+#ifdef FIG_SUPPORT
+output *make_fig_output();
+#endif /* FIG_SUPPORT */
diff --git a/src/preproc/pic/pic.cc b/src/preproc/pic/pic.cc
new file mode 100755
index 00000000..045d5d24
--- /dev/null
+++ b/src/preproc/pic/pic.cc
@@ -0,0 +1,5220 @@
+#ifndef lint
+/*static char yysccsid[] = "from: @(#)yaccpar 1.9 (Berkeley) 02/21/93";*/
+static char yyrcsid[] = "$Id: pic.cc,v 1.1 2000/02/06 09:38:22 wlemb Exp $";
+#endif
+#define YYBYACC 1
+#define YYMAJOR 1
+#define YYMINOR 9
+#define yyclearin (yychar=(-1))
+#define yyerrok (yyerrflag=0)
+#define YYRECOVERING (yyerrflag!=0)
+#define YYPREFIX "yy"
+#line 20 "/home/cjk/groff/pic/pic.y"
+#include "pic.h"
+#include "ptable.h"
+#include "object.h"
+
+extern int delim_flag;
+extern void do_copy(const char *);
+extern void copy_rest_thru(const char *, const char *);
+extern void copy_file_thru(const char *, const char *, const char *);
+extern void push_body(const char *);
+extern void do_for(char *var, double from, double to,
+ int by_is_multiplicative, double by, char *body);
+extern void do_lookahead();
+
+#ifndef HAVE_FMOD
+extern "C" {
+ double fmod(double, double);
+}
+#endif
+
+#undef rand
+#undef srand
+extern "C" {
+ int rand();
+ void srand(unsigned int);
+}
+
+/* Maximum number of characters produced by printf("%g") */
+#define GDIGITS 14
+
+int yylex();
+void yyerror(const char *);
+
+void reset(const char *nm);
+void reset_all();
+
+place *lookup_label(const char *);
+void define_label(const char *label, const place *pl);
+
+direction current_direction;
+position current_position;
+
+implement_ptable(place)
+
+PTABLE(place) top_table;
+
+PTABLE(place) *current_table = &top_table;
+saved_state *current_saved_state = 0;
+
+object_list olist;
+
+const char *ordinal_postfix(int n);
+const char *object_type_name(object_type type);
+char *format_number(const char *form, double n);
+char *do_sprintf(const char *form, const double *v, int nv);
+
+#line 78 "/home/cjk/groff/pic/pic.y"
+typedef union {
+ char *str;
+ int n;
+ double x;
+ struct { double x, y; } pair;
+ struct { double x; char *body; } if_data;
+ struct { char *str; const char *filename; int lineno; } lstr;
+ struct { double *v; int nv; int maxv; } dv;
+ struct { double val; int is_multiplicative; } by;
+ place pl;
+ object *obj;
+ corner crn;
+ path *pth;
+ object_spec *spec;
+ saved_state *pstate;
+ graphics_state state;
+ object_type obtype;
+} YYSTYPE;
+#line 88 "y.tab.c"
+#define LABEL 257
+#define VARIABLE 258
+#define NUMBER 259
+#define TEXT 260
+#define COMMAND_LINE 261
+#define DELIMITED 262
+#define ORDINAL 263
+#define TH 264
+#define LEFT_ARROW_HEAD 265
+#define RIGHT_ARROW_HEAD 266
+#define DOUBLE_ARROW_HEAD 267
+#define LAST 268
+#define UP 269
+#define DOWN 270
+#define LEFT 271
+#define RIGHT 272
+#define BOX 273
+#define CIRCLE 274
+#define ELLIPSE 275
+#define ARC 276
+#define LINE 277
+#define ARROW 278
+#define MOVE 279
+#define SPLINE 280
+#define HEIGHT 281
+#define RADIUS 282
+#define WIDTH 283
+#define DIAMETER 284
+#define FROM 285
+#define TO 286
+#define AT 287
+#define WITH 288
+#define BY 289
+#define THEN 290
+#define DOTTED 291
+#define DASHED 292
+#define CHOP 293
+#define SAME 294
+#define INVISIBLE 295
+#define LJUST 296
+#define RJUST 297
+#define ABOVE 298
+#define BELOW 299
+#define OF 300
+#define THE 301
+#define WAY 302
+#define BETWEEN 303
+#define AND 304
+#define HERE 305
+#define DOT_N 306
+#define DOT_E 307
+#define DOT_W 308
+#define DOT_S 309
+#define DOT_NE 310
+#define DOT_SE 311
+#define DOT_NW 312
+#define DOT_SW 313
+#define DOT_C 314
+#define DOT_START 315
+#define DOT_END 316
+#define DOT_X 317
+#define DOT_Y 318
+#define DOT_HT 319
+#define DOT_WID 320
+#define DOT_RAD 321
+#define SIN 322
+#define COS 323
+#define ATAN2 324
+#define LOG 325
+#define EXP 326
+#define SQRT 327
+#define K_MAX 328
+#define K_MIN 329
+#define INT 330
+#define RAND 331
+#define SRAND 332
+#define COPY 333
+#define THRU 334
+#define TOP 335
+#define BOTTOM 336
+#define UPPER 337
+#define LOWER 338
+#define SH 339
+#define PRINT 340
+#define CW 341
+#define CCW 342
+#define FOR 343
+#define DO 344
+#define IF 345
+#define ELSE 346
+#define ANDAND 347
+#define OROR 348
+#define NOTEQUAL 349
+#define EQUALEQUAL 350
+#define LESSEQUAL 351
+#define GREATEREQUAL 352
+#define LEFT_CORNER 353
+#define RIGHT_CORNER 354
+#define CENTER 355
+#define END 356
+#define START 357
+#define RESET 358
+#define UNTIL 359
+#define PLOT 360
+#define THICKNESS 361
+#define FILL 362
+#define ALIGNED 363
+#define SPRINTF 364
+#define COMMAND 365
+#define DEFINE 366
+#define UNDEF 367
+#define YYERRCODE 256
+short yylhs[] = { -1,
+ 0, 0, 16, 17, 17, 28, 28, 29, 29, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30, 31, 30,
+ 30, 32, 33, 30, 34, 35, 30, 36, 30, 30,
+ 37, 30, 30, 30, 38, 38, 38, 26, 26, 27,
+ 27, 27, 39, 7, 23, 23, 2, 2, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 4, 4, 4,
+ 15, 15, 15, 15, 40, 42, 15, 15, 41, 41,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 43, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 25, 25, 24, 24, 19, 19,
+ 6, 6, 6, 6, 6, 6, 44, 44, 5, 5,
+ 13, 13, 13, 13, 13, 14, 14, 14, 22, 22,
+ 21, 21, 8, 8, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 11, 11, 12, 12, 12, 10, 10,
+ 10, 10, 10, 10, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 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, 1, 1, 1, 1,
+};
+short yylen[] = { 2,
+ 1, 1, 3, 1, 3, 0, 1, 1, 2, 3,
+ 4, 1, 1, 1, 1, 1, 2, 2, 0, 3,
+ 2, 0, 0, 7, 0, 0, 6, 0, 10, 1,
+ 0, 4, 1, 1, 2, 2, 3, 1, 2, 1,
+ 1, 1, 0, 5, 0, 2, 1, 1, 3, 3,
+ 3, 3, 3, 3, 3, 3, 2, 0, 2, 3,
+ 1, 4, 4, 4, 0, 0, 6, 1, 0, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+ 3, 0, 4, 3, 3, 3, 3, 2, 2, 3,
+ 2, 3, 2, 3, 2, 3, 3, 3, 3, 3,
+ 3, 2, 2, 3, 2, 3, 2, 3, 2, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 3, 2, 1, 5, 0, 3, 1, 1,
+ 1, 3, 3, 5, 5, 6, 1, 4, 3, 3,
+ 1, 2, 2, 3, 1, 1, 1, 3, 1, 3,
+ 1, 2, 2, 2, 1, 1, 1, 1, 1, 1,
+ 1, 2, 1, 2, 3, 1, 1, 2, 1, 5,
+ 4, 3, 3, 2, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 1, 1, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 2, 2, 2, 2, 2, 3,
+ 3, 3, 3, 3, 3, 2, 3, 4, 4, 6,
+ 4, 4, 4, 6, 6, 4, 4, 3, 4, 3,
+ 3, 3, 3, 3, 3, 3, 3, 2,
+};
+short yydefred[] = { 0,
+ 8, 0, 2, 0, 0, 0, 0, 125, 16, 12,
+ 13, 14, 15, 71, 72, 73, 74, 75, 76, 77,
+ 78, 0, 19, 0, 0, 0, 0, 0, 0, 0,
+ 65, 82, 0, 4, 0, 0, 79, 68, 0, 9,
+ 0, 0, 0, 0, 25, 0, 146, 203, 204, 149,
+ 151, 188, 189, 145, 175, 176, 177, 178, 179, 180,
+ 181, 182, 183, 184, 185, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 186, 187, 0, 0,
+ 194, 195, 200, 202, 201, 0, 0, 0, 0, 0,
+ 131, 129, 147, 0, 0, 0, 0, 0, 0, 41,
+ 0, 38, 0, 0, 0, 0, 0, 0, 0, 0,
+ 35, 0, 0, 0, 0, 0, 31, 3, 0, 113,
+ 114, 115, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 102, 0, 0, 0, 111,
+ 112, 119, 120, 121, 122, 116, 117, 0, 0, 124,
+ 0, 118, 36, 0, 0, 10, 0, 22, 0, 20,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 190, 192, 196, 198, 191, 193, 197, 199, 0,
+ 0, 0, 0, 0, 0, 0, 0, 137, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 205, 206, 207, 208,
+ 209, 0, 142, 0, 0, 163, 155, 156, 157, 158,
+ 159, 160, 161, 0, 154, 152, 153, 39, 0, 0,
+ 57, 0, 0, 0, 43, 0, 0, 0, 0, 81,
+ 127, 0, 0, 0, 0, 5, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 166, 100, 0, 169, 0, 0, 101,
+ 0, 0, 0, 0, 0, 37, 0, 0, 0, 0,
+ 0, 0, 62, 0, 11, 0, 26, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 228, 0, 0, 217,
+ 140, 0, 150, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 148, 132, 133, 162, 0, 0, 53, 0,
+ 0, 0, 0, 0, 51, 0, 0, 50, 49, 0,
+ 66, 83, 32, 174, 0, 0, 0, 0, 164, 0,
+ 168, 0, 0, 23, 0, 218, 219, 0, 221, 222,
+ 223, 0, 0, 226, 227, 229, 0, 0, 0, 0,
+ 0, 44, 0, 126, 0, 0, 173, 172, 0, 165,
+ 0, 0, 27, 0, 0, 0, 134, 138, 0, 0,
+ 0, 0, 70, 67, 171, 0, 24, 46, 220, 224,
+ 225, 136, 0, 0, 170, 0, 0, 28, 0, 0,
+ 29,
+};
+short yydgoto[] = { 2,
+ 106, 181, 108, 404, 91, 92, 33, 93, 94, 265,
+ 266, 267, 109, 96, 34, 3, 35, 36, 97, 225,
+ 98, 99, 383, 340, 110, 101, 102, 243, 5, 38,
+ 46, 286, 381, 159, 355, 410, 245, 39, 333, 115,
+ 394, 375, 116, 204,
+};
+short yysindex[] = { -44,
+ 0, 0, 0,11792, -40, -37, -14, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, -246, 0,10742, -229,10874, -218,11317, 6,10742,
+ 0, 0, -296, 0, -44,10435, 0, 0, -39, 0,
+ -44,10874, 13, -280, 0, -195, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 45, 47, 54, 76, 87,
+ 92, 109, 120, 142, 146, 158, 0, 0, -262, -219,
+ 0, 0, 0, 0, 0,10985,10874,11317,11317, 350,
+ 0, 0, 0, -76, -162, 1981, 18, -35, 734, 0,
+10742, 0, 139,10874,10874, 1064, -153, -269, -162, -156,
+ 0, 623, -59,10742, -44, -44, 0, 0,11764, 0,
+ 0, 0,11649,11649,11649,11649,11317,11317,11317,11317,
+11428,11428,11428, 1994,11538, 0,11649,11649,11649, 0,
+ 0, 0, 0, 0, 0, 0, 0,11317,11649, 0,
+ 1477, 0, 0, -55,10076, 0,10874, 0, -48, 0,
+10874,10874,10874,10874,10874,10874,10874,10874,10874,10574,
+10874, 0, 0, 0, 0, 0, 0, 0, 0, 1517,
+ 166, 174, 97, -46, 127, 127, -79, 0,11317,11317,
+11317,11317,11317,11317,11317,11428,11317,11317,11317,11317,
+11317,11317,11317,11428, -7, 180, 0, 0, 0, 0,
+ 0, -29, 0,11538,11538, 0, 0, 0, 0, 0,
+ 0, 0, 0, 136, 0, 0, 0, 0,11317, 127,
+ 0,10874,10874,11317, 0,10874,10874, -252, -252, 0,
+ 0, 106,11792, 141, -26, 0, 1477, 1477, 1477, 1477,
+ 1477, 1477, 1477, 1477, 350, 18, 18, 18, 1649, 1192,
+ -35, 1649, -8, 0, 0, 1661, 0,11095, 266, 0,
+ 1477, 1477, 1477, 1477, 1477, 0, -37, -14, 0, 0,
+ 0, -162, 0, 18, 0, -16, 0, 210, 212, 211,
+ 216, 218, 228, 232, 233, 231, 0, 238, 239, 0,
+ 0,11428, 0, -15, 1414, 1484, 595, 595, 507, 507,
+ 1477, 190, 251, 507, -19, -19, 127, 127, 127, 127,
+ -42, 180, 0, 0, 0, 0, -11, 1414, 0, 1505,
+ -57, 507, 30, 1414, 0, 1505, -57, 0, 0, 28,
+ 0, 0, 0, 0, -35, 1649, 1649, 254, 0, 43,
+ 0, 634, 174, 0, -52, 0, 0,10874, 0, 0,
+ 0,10874,10874, 0, 0, 0, 14, -1,11428,11428,
+11317, 0,11317, 0,11792, 1649, 0, 0, 1649, 0,
+ -52, 52, 0, 273, 274, 280, 0, 0, -21, 18,
+ 1075, 1477, 0, 0, 0, 281, 0, 0, 0, 0,
+ 0, 0,11207, -20, 0,11317, 1477, 0, 1477, 71,
+ 0,
+};
+short yyrindex[] = { 202,
+ 0, 0, 0, 332, 93, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 25, 0, 0, 0,
+ 0, 0, 58, 0, 161, 60, 0, 0, 70, 0,
+10326, 0, 0, 204, 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, 8870,
+ 0, 0, 0, 0, 4424, 8570, 8999, 0, 0, 0,
+ 376, 0, 0, 0, 0, 1390, 0, 2313, 0, 0,
+ 0, 9969, 0, 465,11903,11903, 0, 0, 206, 0,
+ 0, 0, 9151, 9360, 9110, 9239, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 9460, 9545, 9669, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 9786, 0,
+ 4973, 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, 293,
+ 0, 261, 0, 0, 455, 563, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3101, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 223,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 5273, 5381, 5681, 5789,
+ 6089, 6197, 6497, 6605, 0, 6905, 7013, 7313, 0, 0,
+ 0, 0, 0, 0, 0, 8656, 0, 0, 0, 0,
+ 7421, 7721, 7829, 8129, 8237, 0, 9547, 2399, 2602, 3043,
+ 37, 411, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3983, 4091, 3209, 3542, 2219, 2327,
+ 4865, 8699, 0, 2660, 1778, 1886, 896, 1004, 1337, 1445,
+ 0, 3650, 0, 0, 0, 0, 0, 27, 0, 230,
+ 466, 2768, 0, 95, 0, 908, 1015, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 293, 0, 0, 468, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 484, 0, 0, 0, 0, 0,
+ 468, 0, 0, 0, 0, 0, 0, 0, 0, 4532,
+ -9, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 33, 0, 34, 0,
+ 0,
+};
+short yygindex[] = { 0,
+ -24, 919, -89, 0, -69, 188, 0, 0, 768, 0,
+ 0, 327, 187, -83, -117, -18, 0, 0, 2276, -64,
+ 0, 0, -23, 0, 9, 314, -71, 7, 322, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+};
+#define YYTABLESIZE 12268
+short yytable[] = { 90,
+ 214, 246, 215, 112, 154, 90, 4, 8, 172, 173,
+ 206, 151, 37, 44, 1, 231, 182, 202, 40, 87,
+ 41, 214, 200, 215, 34, 202, 236, 201, 103, 228,
+ 200, 198, 100, 199, 227, 201, 63, 283, 100, 111,
+ 402, 118, 228, 43, 152, 113, 42, 155, 234, 117,
+ 197, 176, 177, 158, 387, 224, 214, 30, 215, 61,
+ 214, 180, 215, 185, 186, 270, 160, 236, 374, 33,
+ 236, 373, 128, 157, 203, 128, 90, 236, 237, 129,
+ 230, 129, 203, 34, 161, 236, 162, 45, 87, 90,
+ 174, 175, 7, 163, 52, 63, 242, 244, 247, 248,
+ 249, 250, 251, 252, 253, 254, 255, 255, 255, 100,
+ 269, 29, 271, 272, 273, 164, 30, 34, 61, 236,
+ 240, 322, 100, 274, 275, 7, 165, 37, 33, 63,
+ 255, 166, 7, 178, 179, 52, 235, 7, 52, 214,
+ 302, 215, 329, 331, 324, 325, 335, 337, 167, 34,
+ 30, 236, 61, 52, 207, 208, 209, 210, 211, 168,
+ 6, 63, 33, 37, 305, 306, 307, 308, 309, 310,
+ 311, 312, 314, 315, 316, 317, 318, 319, 320, 255,
+ 47, 169, 30, 7, 61, 170, 50, 52, 7, 269,
+ 269, 51, 238, 239, 33, 346, 347, 171, 353, 229,
+ 241, 6, 276, 21, 327, 7, 300, 328, 330, 332,
+ 95, 334, 336, 287, 301, 7, 95, 303, 153, 52,
+ 203, 304, 238, 205, 216, 212, 202, 323, 326, 237,
+ 341, 200, 198, 342, 199, 343, 201, 217, 218, 219,
+ 220, 221, 222, 352, 223, 354, 338, 339, 349, 47,
+ 356, 37, 357, 6, 358, 50, 359, 393, 360, 238,
+ 51, 370, 21, 238, 238, 238, 238, 238, 361, 238,
+ 237, 364, 95, 237, 371, 362, 363, 255, 365, 366,
+ 376, 238, 238, 203, 238, 6, 368, 95, 237, 236,
+ 236, 372, 6, 214, 369, 215, 21, 379, 7, 380,
+ 95, 388, 202, 131, 131, 131, 382, 200, 198, 195,
+ 199, 398, 201, 399, 400, 238, 236, 95, 95, 95,
+ 401, 405, 237, 408, 6, 234, 236, 197, 21, 236,
+ 7, 1, 411, 47, 58, 189, 190, 191, 192, 193,
+ 194, 282, 281, 114, 255, 255, 391, 238, 392, 7,
+ 7, 7, 7, 7, 237, 7, 119, 397, 52, 203,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 236, 236, 18, 59, 60, 407, 0,
+ 0, 409, 95, 37, 52, 0, 202, 0, 0, 0,
+ 95, 200, 198, 195, 199, 0, 201, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 196,
+ 64, 197, 0, 0, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 0, 7, 7, 7,
+ 7, 7, 7, 0, 18, 7, 0, 7, 0, 0,
+ 0, 52, 52, 203, 0, 7, 7, 7, 7, 7,
+ 7, 0, 7, 130, 216, 130, 7, 7, 6, 6,
+ 0, 6, 6, 0, 17, 56, 0, 45, 18, 64,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 0, 69, 0, 0, 238, 216, 95, 187,
+ 0, 216, 188, 237, 216, 216, 216, 216, 216, 216,
+ 18, 216, 0, 64, 0, 0, 56, 0, 0, 56,
+ 0, 0, 238, 216, 216, 0, 216, 0, 0, 237,
+ 0, 0, 238, 17, 56, 238, 45, 0, 0, 237,
+ 0, 0, 237, 0, 6, 64, 0, 0, 0, 0,
+ 6, 6, 69, 202, 6, 0, 6, 216, 200, 198,
+ 216, 199, 0, 201, 0, 95, 95, 17, 56, 6,
+ 45, 6, 238, 0, 0, 6, 6, 0, 0, 238,
+ 238, 238, 238, 238, 238, 0, 69, 237, 0, 216,
+ 0, 0, 0, 0, 0, 344, 0, 0, 348, 17,
+ 56, 0, 45, 0, 0, 238, 0, 0, 0, 238,
+ 203, 0, 238, 238, 238, 238, 238, 238, 69, 238,
+ 0, 0, 189, 190, 191, 192, 193, 194, 0, 0,
+ 0, 238, 238, 0, 238, 0, 0, 0, 0, 0,
+ 0, 202, 0, 0, 0, 0, 200, 198, 0, 199,
+ 0, 201, 0, 0, 0, 0, 0, 0, 0, 187,
+ 0, 0, 188, 0, 234, 238, 197, 0, 238, 202,
+ 0, 0, 0, 0, 200, 198, 0, 199, 0, 201,
+ 202, 0, 377, 378, 0, 200, 198, 195, 199, 0,
+ 201, 0, 234, 0, 197, 0, 0, 238, 203, 0,
+ 0, 0, 0, 234, 0, 197, 189, 190, 191, 192,
+ 193, 194, 395, 0, 0, 396, 0, 0, 0, 0,
+ 0, 216, 216, 216, 216, 0, 203, 216, 216, 216,
+ 216, 216, 216, 216, 216, 216, 216, 203, 0, 56,
+ 0, 0, 0, 0, 0, 216, 216, 216, 216, 216,
+ 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
+ 216, 216, 216, 216, 216, 56, 0, 216, 216, 216,
+ 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
+ 216, 0, 0, 0, 0, 0, 216, 216, 216, 216,
+ 216, 216, 216, 216, 216, 216, 216, 0, 0, 216,
+ 216, 216, 216, 0, 0, 216, 216, 0, 216, 0,
+ 0, 216, 216, 216, 216, 216, 216, 216, 216, 216,
+ 216, 216, 0, 56, 0, 216, 216, 216, 216, 238,
+ 238, 238, 238, 0, 224, 238, 238, 238, 238, 238,
+ 238, 238, 238, 238, 238, 0, 0, 0, 0, 0,
+ 0, 0, 0, 238, 238, 238, 238, 238, 238, 238,
+ 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
+ 238, 238, 238, 213, 0, 238, 238, 238, 238, 238,
+ 238, 238, 238, 238, 238, 238, 238, 238, 238, 0,
+ 0, 0, 8, 0, 238, 238, 238, 238, 238, 238,
+ 238, 238, 238, 238, 238, 212, 0, 238, 238, 238,
+ 238, 264, 0, 238, 238, 0, 238, 55, 0, 238,
+ 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
+ 0, 0, 0, 238, 238, 238, 238, 0, 212, 0,
+ 0, 0, 212, 0, 0, 212, 212, 212, 212, 212,
+ 212, 0, 212, 0, 107, 193, 194, 0, 55, 0,
+ 0, 55, 0, 0, 212, 212, 0, 212, 0, 0,
+ 156, 0, 0, 0, 0, 0, 55, 0, 0, 189,
+ 190, 191, 192, 193, 194, 0, 0, 0, 0, 0,
+ 232, 233, 191, 192, 193, 194, 29, 0, 212, 0,
+ 0, 212, 0, 216, 0, 0, 0, 0, 0, 0,
+ 55, 226, 0, 213, 0, 184, 217, 218, 219, 220,
+ 221, 222, 0, 223, 54, 0, 0, 0, 0, 0,
+ 212, 0, 0, 0, 0, 0, 264, 0, 0, 264,
+ 0, 0, 55, 351, 0, 0, 213, 0, 0, 0,
+ 213, 0, 0, 213, 213, 213, 213, 213, 213, 0,
+ 213, 0, 0, 0, 0, 54, 0, 0, 54, 0,
+ 0, 0, 213, 213, 0, 213, 0, 0, 0, 0,
+ 0, 0, 0, 54, 0, 285, 0, 0, 0, 288,
+ 289, 290, 291, 292, 293, 294, 295, 296, 298, 299,
+ 0, 0, 0, 0, 0, 0, 213, 0, 0, 213,
+ 202, 0, 0, 0, 0, 200, 198, 54, 199, 0,
+ 201, 202, 0, 264, 264, 0, 200, 198, 0, 199,
+ 0, 201, 0, 234, 0, 197, 0, 0, 213, 0,
+ 0, 0, 0, 0, 234, 0, 197, 0, 0, 54,
+ 0, 0, 0, 264, 0, 0, 264, 0, 0, 0,
+ 0, 0, 212, 212, 212, 212, 0, 203, 212, 212,
+ 212, 212, 212, 212, 212, 212, 212, 212, 203, 0,
+ 0, 55, 0, 0, 0, 0, 212, 212, 212, 212,
+ 212, 212, 212, 212, 212, 212, 212, 212, 212, 212,
+ 212, 212, 212, 212, 212, 212, 0, 55, 212, 212,
+ 212, 212, 212, 212, 212, 212, 212, 212, 212, 212,
+ 212, 212, 0, 0, 0, 0, 0, 212, 212, 212,
+ 212, 212, 212, 212, 212, 212, 212, 212, 0, 0,
+ 212, 212, 212, 212, 0, 0, 212, 212, 0, 212,
+ 0, 0, 212, 212, 212, 212, 212, 212, 212, 212,
+ 212, 212, 212, 0, 0, 55, 212, 212, 212, 212,
+ 213, 213, 213, 213, 0, 0, 213, 213, 213, 213,
+ 213, 213, 213, 213, 213, 213, 384, 0, 54, 0,
+ 385, 386, 224, 0, 213, 213, 213, 213, 213, 213,
+ 213, 213, 213, 213, 213, 213, 213, 213, 213, 213,
+ 213, 213, 213, 213, 54, 0, 213, 213, 213, 213,
+ 213, 213, 213, 213, 213, 213, 213, 213, 213, 213,
+ 0, 0, 0, 0, 0, 213, 213, 213, 213, 213,
+ 213, 213, 213, 213, 213, 213, 214, 0, 213, 213,
+ 213, 213, 0, 0, 213, 213, 0, 213, 0, 0,
+ 213, 213, 213, 213, 213, 213, 213, 213, 213, 213,
+ 213, 0, 54, 403, 213, 213, 213, 213, 0, 214,
+ 0, 0, 0, 214, 0, 0, 214, 214, 214, 214,
+ 214, 214, 0, 214, 0, 0, 0, 0, 0, 47,
+ 0, 0, 0, 0, 0, 214, 214, 0, 214, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 232, 233, 191, 192, 193, 194, 0, 0, 0, 0,
+ 0, 189, 190, 191, 192, 193, 194, 0, 0, 214,
+ 47, 0, 214, 47, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 215, 0, 0, 0, 47, 0,
+ 202, 216, 0, 0, 0, 200, 198, 0, 199, 345,
+ 201, 214, 0, 0, 217, 218, 219, 220, 221, 222,
+ 0, 223, 0, 234, 0, 197, 0, 215, 0, 0,
+ 0, 215, 47, 0, 215, 215, 215, 215, 215, 215,
+ 0, 215, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 215, 215, 0, 215, 203, 0, 0,
+ 0, 0, 0, 202, 47, 0, 0, 0, 200, 198,
+ 202, 199, 0, 201, 0, 200, 198, 0, 199, 0,
+ 201, 0, 0, 0, 0, 0, 234, 215, 197, 0,
+ 215, 202, 0, 234, 0, 197, 200, 198, 0, 199,
+ 0, 201, 0, 202, 0, 0, 0, 0, 200, 198,
+ 195, 199, 0, 201, 234, 0, 197, 0, 0, 215,
+ 203, 0, 0, 0, 0, 0, 196, 203, 197, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 214, 214, 214, 214, 0, 203, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 0,
+ 203, 0, 0, 0, 0, 0, 0, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 0, 0, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 47, 0, 0, 0, 0, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 0,
+ 0, 214, 214, 214, 214, 0, 0, 214, 214, 47,
+ 214, 0, 0, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 263, 0, 0, 214, 214, 214,
+ 214, 215, 215, 215, 215, 0, 350, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 0, 0, 0,
+ 0, 0, 0, 0, 0, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 0, 0, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 0, 191, 192, 193, 194, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 210, 0, 215,
+ 215, 215, 215, 0, 0, 215, 215, 0, 215, 0,
+ 0, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 215, 0, 0, 0, 215, 215, 215, 215, 0,
+ 210, 0, 0, 0, 0, 0, 187, 210, 210, 188,
+ 210, 210, 210, 189, 190, 191, 192, 193, 194, 0,
+ 189, 0, 191, 192, 193, 194, 210, 210, 0, 210,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 232, 0, 191, 192, 193, 194, 0, 0, 0,
+ 0, 0, 0, 232, 233, 191, 192, 193, 194, 0,
+ 210, 0, 0, 210, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 211, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 210, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 211, 52,
+ 53, 0, 0, 0, 0, 211, 211, 0, 211, 211,
+ 211, 52, 53, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 211, 211, 0, 211, 0, 0,
+ 0, 0, 0, 0, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 0, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63, 64, 65, 0, 211, 0,
+ 0, 211, 0, 77, 78, 79, 80, 0, 0, 0,
+ 0, 0, 0, 0, 0, 77, 78, 79, 80, 0,
+ 0, 81, 82, 83, 84, 85, 0, 0, 0, 0,
+ 211, 0, 0, 81, 82, 83, 84, 85, 0, 0,
+ 0, 0, 0, 0, 0, 0, 212, 0, 0, 0,
+ 0, 0, 0, 262, 210, 210, 210, 210, 0, 263,
+ 210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
+ 0, 0, 0, 0, 0, 0, 0, 0, 210, 210,
+ 210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
+ 210, 210, 210, 210, 210, 210, 210, 210, 0, 0,
+ 210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
+ 210, 210, 210, 210, 0, 0, 0, 0, 0, 210,
+ 210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
+ 0, 0, 210, 210, 210, 210, 0, 0, 210, 210,
+ 0, 210, 0, 0, 210, 210, 210, 210, 210, 210,
+ 210, 210, 210, 210, 210, 0, 0, 0, 210, 210,
+ 210, 210, 211, 211, 211, 211, 0, 0, 211, 211,
+ 211, 211, 211, 211, 211, 211, 211, 211, 0, 0,
+ 0, 0, 0, 0, 0, 0, 211, 211, 211, 211,
+ 211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
+ 211, 211, 211, 211, 211, 211, 0, 0, 211, 211,
+ 211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
+ 211, 211, 0, 0, 0, 0, 0, 211, 211, 211,
+ 211, 211, 211, 211, 211, 211, 211, 211, 231, 0,
+ 211, 211, 211, 211, 0, 0, 211, 211, 0, 211,
+ 0, 0, 211, 211, 211, 211, 211, 211, 211, 211,
+ 211, 211, 211, 0, 0, 0, 211, 211, 211, 211,
+ 259, 231, 0, 0, 0, 0, 260, 0, 231, 231,
+ 0, 261, 231, 0, 52, 53, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 231, 231, 0,
+ 231, 0, 0, 0, 0, 0, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63, 64, 65, 0, 0, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 0, 231, 48, 0, 231, 77, 78, 79, 80, 0,
+ 0, 0, 0, 0, 0, 0, 233, 0, 77, 78,
+ 79, 80, 0, 81, 82, 83, 84, 85, 0, 0,
+ 0, 0, 0, 231, 0, 0, 81, 82, 83, 84,
+ 85, 0, 0, 48, 0, 0, 48, 0, 0, 233,
+ 0, 183, 0, 0, 0, 0, 233, 233, 0, 0,
+ 233, 48, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 233, 233, 0, 233, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 48, 256, 257, 258, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 233,
+ 0, 0, 233, 0, 0, 0, 0, 0, 0, 0,
+ 284, 0, 0, 0, 0, 203, 0, 48, 0, 0,
+ 203, 203, 203, 203, 0, 203, 0, 0, 0, 0,
+ 0, 233, 0, 0, 0, 0, 0, 0, 203, 0,
+ 203, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 313, 0, 0, 0, 231, 231, 231, 231, 321,
+ 0, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 0, 203, 0, 0, 0, 0, 0, 0, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 0,
+ 0, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 0, 0, 0, 0, 0,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 0, 0, 231, 231, 231, 231, 0, 0, 231,
+ 231, 0, 231, 0, 0, 231, 231, 231, 231, 231,
+ 231, 231, 231, 231, 231, 231, 48, 367, 0, 231,
+ 231, 231, 231, 233, 233, 233, 233, 0, 0, 233,
+ 233, 233, 233, 233, 233, 233, 233, 233, 233, 0,
+ 0, 14, 48, 0, 0, 0, 0, 233, 233, 233,
+ 233, 233, 233, 233, 233, 233, 233, 233, 233, 233,
+ 233, 233, 233, 233, 233, 233, 233, 0, 0, 233,
+ 233, 233, 233, 233, 233, 233, 233, 233, 233, 233,
+ 233, 233, 233, 0, 389, 390, 0, 0, 233, 233,
+ 233, 233, 233, 233, 233, 233, 233, 233, 233, 232,
+ 14, 233, 233, 233, 233, 0, 0, 233, 233, 0,
+ 233, 0, 0, 233, 233, 233, 233, 233, 233, 233,
+ 233, 233, 233, 233, 0, 0, 0, 233, 233, 233,
+ 233, 0, 232, 0, 14, 0, 0, 188, 203, 232,
+ 232, 203, 0, 232, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 232, 232,
+ 0, 232, 0, 0, 0, 0, 14, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 203, 203, 203, 203, 203,
+ 203, 0, 232, 0, 0, 232, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 230, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 232, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 230, 0, 0, 0, 0, 0, 0, 230, 230, 0,
+ 0, 230, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 230, 230, 0, 230,
+ 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, 188, 0,
+ 230, 0, 0, 230, 188, 0, 0, 0, 0, 188,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 230, 0, 0, 0, 0, 0, 0, 0,
+ 0, 188, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 232, 232, 232, 232,
+ 0, 0, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 0, 0, 0, 0, 0, 0, 0, 0,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 0, 0, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 0, 0, 0, 0,
+ 0, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 0, 0, 232, 232, 232, 232, 0, 0,
+ 232, 232, 0, 232, 0, 0, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 0, 0, 0,
+ 232, 232, 232, 232, 230, 230, 230, 230, 0, 0,
+ 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
+ 0, 0, 15, 0, 0, 0, 0, 0, 230, 230,
+ 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
+ 230, 230, 230, 230, 230, 230, 230, 230, 0, 0,
+ 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
+ 230, 230, 230, 230, 0, 0, 0, 0, 0, 230,
+ 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
+ 143, 15, 230, 230, 230, 230, 0, 0, 230, 230,
+ 0, 230, 0, 0, 230, 230, 230, 230, 230, 230,
+ 230, 230, 230, 230, 230, 0, 0, 0, 230, 230,
+ 230, 230, 0, 143, 0, 15, 0, 0, 189, 0,
+ 143, 143, 0, 143, 143, 143, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 143,
+ 0, 0, 143, 0, 0, 0, 0, 15, 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, 143, 0, 0, 143, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 235, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 143, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 235, 0, 0, 0, 0, 0, 0, 235, 235,
+ 0, 0, 235, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 235, 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, 189,
+ 0, 235, 0, 0, 235, 189, 0, 0, 0, 0,
+ 189, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 235, 0, 0, 0, 0, 0, 0,
+ 0, 0, 189, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 143, 143, 143,
+ 143, 0, 0, 143, 0, 143, 143, 143, 143, 143,
+ 143, 143, 143, 0, 0, 0, 0, 0, 0, 0,
+ 0, 143, 143, 143, 143, 143, 143, 143, 143, 143,
+ 143, 143, 143, 143, 143, 143, 143, 143, 143, 143,
+ 0, 0, 0, 0, 143, 143, 143, 143, 143, 143,
+ 143, 143, 143, 143, 143, 143, 143, 143, 143, 143,
+ 143, 143, 143, 143, 143, 143, 143, 143, 143, 143,
+ 143, 143, 143, 0, 0, 143, 143, 143, 143, 0,
+ 0, 143, 143, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 143, 143, 143, 143, 143, 0, 0,
+ 0, 143, 143, 143, 143, 235, 235, 235, 235, 0,
+ 0, 235, 235, 235, 235, 235, 235, 235, 235, 235,
+ 235, 0, 0, 0, 0, 0, 0, 0, 0, 235,
+ 235, 235, 235, 235, 235, 235, 235, 235, 235, 235,
+ 235, 235, 235, 235, 235, 235, 235, 235, 235, 0,
+ 0, 235, 235, 235, 235, 235, 235, 235, 235, 235,
+ 235, 235, 235, 235, 235, 0, 0, 0, 0, 0,
+ 235, 235, 235, 235, 235, 235, 235, 235, 235, 235,
+ 235, 234, 0, 235, 235, 235, 235, 0, 0, 235,
+ 235, 0, 235, 0, 0, 235, 235, 235, 235, 0,
+ 0, 235, 235, 235, 235, 235, 0, 0, 0, 235,
+ 235, 235, 235, 0, 234, 0, 0, 0, 0, 0,
+ 0, 234, 234, 0, 0, 234, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 234, 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, 234, 0, 0, 234, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 234, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 144, 0, 0, 0, 0, 0, 0, 144,
+ 144, 0, 144, 144, 144, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 144, 0,
+ 0, 144, 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, 144, 0, 0, 144, 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, 144, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 234, 234,
+ 234, 234, 0, 0, 234, 234, 234, 234, 234, 234,
+ 234, 234, 234, 234, 0, 0, 0, 0, 0, 0,
+ 0, 0, 234, 234, 234, 234, 234, 234, 234, 234,
+ 234, 234, 234, 234, 234, 234, 234, 234, 234, 234,
+ 234, 234, 0, 0, 234, 234, 234, 234, 234, 234,
+ 234, 234, 234, 234, 234, 234, 234, 234, 0, 0,
+ 0, 0, 0, 234, 234, 234, 234, 234, 234, 234,
+ 234, 234, 234, 234, 0, 0, 234, 234, 234, 234,
+ 0, 0, 234, 234, 0, 234, 0, 0, 234, 234,
+ 234, 234, 0, 0, 234, 234, 234, 234, 234, 0,
+ 0, 0, 234, 234, 234, 234, 144, 144, 144, 144,
+ 0, 0, 144, 0, 144, 144, 144, 144, 144, 144,
+ 144, 144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
+ 144, 144, 144, 144, 144, 144, 144, 144, 144, 0,
+ 0, 0, 0, 144, 144, 144, 144, 144, 144, 144,
+ 144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
+ 144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
+ 144, 144, 236, 0, 144, 144, 144, 144, 0, 0,
+ 144, 144, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 144, 144, 144, 144, 144, 0, 0, 0,
+ 144, 144, 144, 144, 0, 236, 0, 0, 0, 0,
+ 0, 0, 236, 236, 0, 0, 236, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 236, 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, 236, 0, 0, 236, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 237, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 236, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 237, 0, 0, 0, 0, 0, 0,
+ 237, 237, 0, 0, 237, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 237,
+ 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, 237, 0, 0, 237, 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, 237, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 236,
+ 236, 236, 236, 0, 0, 236, 236, 236, 236, 236,
+ 236, 236, 236, 236, 236, 0, 0, 0, 0, 0,
+ 0, 0, 0, 236, 236, 236, 236, 236, 236, 236,
+ 236, 236, 236, 236, 236, 236, 236, 236, 236, 236,
+ 236, 236, 236, 0, 0, 236, 236, 236, 236, 236,
+ 236, 236, 236, 236, 236, 236, 236, 236, 236, 0,
+ 0, 0, 0, 0, 236, 236, 236, 236, 236, 236,
+ 236, 236, 236, 236, 236, 0, 0, 236, 236, 236,
+ 236, 0, 0, 236, 236, 0, 236, 0, 0, 236,
+ 236, 0, 0, 0, 0, 236, 236, 236, 236, 236,
+ 0, 0, 0, 236, 236, 236, 236, 237, 237, 237,
+ 237, 0, 0, 237, 237, 237, 237, 237, 237, 237,
+ 237, 237, 237, 0, 0, 0, 0, 0, 0, 0,
+ 0, 237, 237, 237, 237, 237, 237, 237, 237, 237,
+ 237, 237, 237, 237, 237, 237, 237, 237, 237, 237,
+ 237, 0, 0, 237, 237, 237, 237, 237, 237, 237,
+ 237, 237, 237, 237, 237, 237, 237, 0, 0, 0,
+ 0, 0, 237, 237, 237, 237, 237, 237, 237, 237,
+ 237, 237, 237, 130, 0, 237, 237, 237, 237, 0,
+ 0, 237, 237, 0, 237, 0, 0, 0, 237, 0,
+ 0, 0, 0, 237, 237, 237, 237, 237, 0, 0,
+ 0, 237, 237, 237, 237, 0, 130, 0, 0, 0,
+ 0, 0, 0, 130, 130, 0, 130, 130, 130, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 130, 0, 0, 130, 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, 130, 0, 0, 130,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 135, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 130, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 135, 0, 0, 0, 0, 0,
+ 0, 135, 135, 0, 0, 135, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 135, 0, 0, 135, 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, 135, 0, 0, 135, 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, 135, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 130, 130, 130, 130, 0, 0, 130, 0, 130, 130,
+ 130, 130, 130, 130, 130, 130, 0, 0, 0, 0,
+ 0, 0, 0, 0, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 130, 130, 130, 0, 0, 0, 0, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
+ 0, 0, 0, 0, 0, 130, 130, 130, 130, 130,
+ 130, 130, 130, 130, 130, 130, 0, 0, 130, 130,
+ 130, 130, 0, 0, 130, 130, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 130, 130, 130, 130,
+ 130, 0, 0, 0, 130, 130, 130, 130, 135, 135,
+ 135, 135, 0, 0, 135, 0, 135, 135, 135, 135,
+ 135, 135, 135, 135, 0, 0, 0, 0, 0, 0,
+ 0, 0, 135, 135, 135, 135, 135, 135, 135, 135,
+ 135, 135, 135, 135, 135, 135, 135, 135, 135, 135,
+ 135, 0, 0, 0, 0, 135, 135, 135, 135, 135,
+ 135, 135, 135, 135, 135, 135, 135, 135, 0, 0,
+ 0, 0, 0, 135, 135, 135, 135, 135, 135, 135,
+ 135, 135, 135, 135, 139, 0, 135, 135, 135, 135,
+ 0, 0, 135, 135, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 135, 135, 135, 135, 135, 0,
+ 0, 0, 135, 135, 135, 135, 0, 139, 0, 0,
+ 0, 0, 0, 0, 139, 139, 0, 0, 139, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 139, 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, 139, 0, 0,
+ 139, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 88, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 139,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 88, 0, 0, 0, 0,
+ 0, 0, 88, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 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, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 88, 0, 0, 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, 0, 0, 0, 0, 88, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 139, 139, 139, 139, 0, 0, 139, 0, 139,
+ 139, 139, 139, 139, 139, 139, 139, 0, 0, 0,
+ 0, 0, 0, 0, 0, 139, 139, 139, 139, 139,
+ 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
+ 139, 139, 139, 139, 0, 0, 0, 0, 139, 139,
+ 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
+ 139, 0, 0, 0, 0, 0, 139, 139, 139, 139,
+ 139, 139, 139, 139, 139, 139, 139, 0, 0, 139,
+ 139, 139, 139, 0, 0, 139, 139, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 139, 139, 139,
+ 139, 139, 0, 0, 0, 139, 139, 139, 139, 88,
+ 88, 88, 88, 0, 0, 88, 0, 88, 88, 88,
+ 88, 88, 88, 88, 88, 0, 0, 0, 0, 0,
+ 0, 0, 0, 88, 88, 88, 88, 88, 88, 88,
+ 88, 88, 88, 88, 88, 88, 88, 88, 88, 88,
+ 88, 88, 90, 0, 0, 0, 0, 88, 88, 88,
+ 88, 88, 88, 88, 88, 88, 88, 88, 88, 0,
+ 0, 0, 0, 0, 88, 88, 88, 88, 88, 88,
+ 88, 88, 88, 88, 88, 90, 0, 88, 88, 88,
+ 88, 0, 90, 88, 88, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 88, 88, 88, 88, 88,
+ 0, 90, 0, 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, 0, 0, 0, 0, 90, 0, 0, 90, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 92, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 90, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0,
+ 92, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 92,
+ 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, 92, 0, 0, 92, 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, 92, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 90,
+ 90, 90, 90, 0, 0, 90, 0, 90, 90, 90,
+ 90, 90, 90, 90, 90, 0, 0, 0, 0, 0,
+ 0, 0, 0, 90, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
+ 90, 90, 0, 0, 0, 0, 0, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90, 90, 0,
+ 0, 0, 0, 0, 90, 90, 90, 90, 90, 90,
+ 90, 90, 90, 90, 90, 0, 0, 90, 90, 90,
+ 90, 0, 0, 90, 90, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 90, 90, 90, 90, 90,
+ 0, 0, 0, 90, 90, 90, 90, 92, 92, 92,
+ 92, 0, 0, 92, 0, 92, 92, 92, 92, 92,
+ 92, 92, 92, 0, 0, 0, 0, 0, 0, 0,
+ 0, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 96, 0, 0, 0, 0, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 0, 0, 0,
+ 0, 0, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 96, 0, 92, 92, 92, 92, 0,
+ 96, 92, 92, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 92, 92, 92, 92, 92, 0, 96,
+ 0, 92, 92, 92, 92, 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, 96, 0, 0, 96, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 94, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 96, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 94, 0, 0, 0, 0, 0, 0, 94, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 94, 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, 94, 0, 0, 94, 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, 94, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 96, 96, 96,
+ 96, 0, 0, 96, 0, 96, 96, 96, 96, 96,
+ 96, 96, 96, 0, 0, 0, 0, 0, 0, 0,
+ 0, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 0, 0, 0, 0, 0, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 0, 0, 0,
+ 0, 0, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 0, 0, 96, 96, 96, 96, 0,
+ 0, 96, 96, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 96, 96, 96, 96, 96, 0, 0,
+ 0, 96, 96, 96, 96, 94, 94, 94, 94, 0,
+ 0, 94, 0, 94, 94, 94, 94, 94, 94, 94,
+ 94, 0, 0, 0, 0, 0, 0, 0, 0, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 84, 0,
+ 0, 0, 0, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 0, 0, 0, 0, 0,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 84, 0, 94, 94, 94, 94, 0, 84, 94,
+ 94, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 94, 94, 94, 94, 94, 0, 84, 0, 94,
+ 94, 94, 94, 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, 84, 0, 0, 84, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 85, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 84, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 85,
+ 0, 0, 0, 0, 0, 0, 85, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 85,
+ 0, 0, 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, 85, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 84, 84, 84, 84, 0,
+ 0, 84, 0, 84, 84, 84, 84, 84, 84, 84,
+ 84, 0, 0, 0, 0, 0, 0, 0, 0, 84,
+ 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+ 84, 84, 84, 84, 84, 84, 84, 84, 0, 0,
+ 0, 0, 0, 84, 84, 84, 84, 84, 84, 84,
+ 84, 84, 84, 84, 84, 0, 0, 0, 0, 0,
+ 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+ 84, 0, 0, 84, 84, 84, 84, 0, 0, 84,
+ 84, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 84, 84, 84, 84, 84, 0, 0, 0, 84,
+ 84, 84, 84, 85, 85, 85, 85, 0, 0, 85,
+ 0, 85, 85, 85, 85, 85, 85, 85, 85, 0,
+ 0, 0, 0, 0, 0, 0, 0, 85, 85, 85,
+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85, 85, 85, 86, 0, 0, 0,
+ 0, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 0, 0, 0, 0, 0, 85, 85,
+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 86,
+ 0, 85, 85, 85, 85, 0, 86, 85, 85, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 85,
+ 85, 85, 85, 85, 0, 86, 0, 85, 85, 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, 86,
+ 0, 0, 86, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 87, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 86, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 87, 0, 0,
+ 0, 0, 0, 0, 87, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 87, 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, 87, 0, 0,
+ 87, 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, 87,
+ 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, 0, 0, 86,
+ 0, 86, 86, 86, 86, 86, 86, 86, 86, 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, 0, 0, 0, 0,
+ 0, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 0, 0, 0, 0, 0, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 0,
+ 0, 86, 86, 86, 86, 0, 0, 86, 86, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 86,
+ 86, 86, 86, 86, 0, 0, 0, 86, 86, 86,
+ 86, 87, 87, 87, 87, 0, 0, 87, 0, 87,
+ 87, 87, 87, 87, 87, 87, 87, 0, 0, 0,
+ 0, 0, 0, 0, 0, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 87, 87, 87, 97, 0, 0, 0, 0, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
+ 87, 0, 0, 0, 0, 0, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 97, 0, 87,
+ 87, 87, 87, 0, 97, 87, 87, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 87, 87, 87,
+ 87, 87, 0, 97, 0, 87, 87, 87, 87, 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, 97, 0, 0,
+ 97, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 97,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 98, 0, 0, 0, 0,
+ 0, 0, 98, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 98, 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, 98, 0, 0, 98, 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, 98, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 97, 97, 97, 97, 0, 0, 97, 0, 97,
+ 97, 97, 97, 97, 97, 97, 97, 0, 0, 0,
+ 0, 0, 0, 0, 0, 97, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
+ 97, 97, 97, 97, 0, 0, 0, 0, 0, 97,
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
+ 97, 0, 0, 0, 0, 0, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 97, 97, 0, 0, 97,
+ 97, 97, 97, 0, 0, 97, 97, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 97, 97, 97,
+ 97, 97, 0, 0, 0, 97, 97, 97, 97, 98,
+ 98, 98, 98, 0, 0, 98, 0, 98, 98, 98,
+ 98, 98, 98, 98, 98, 0, 0, 0, 0, 0,
+ 0, 0, 0, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 99, 0, 0, 0, 0, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 0,
+ 0, 0, 0, 0, 98, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 99, 0, 98, 98, 98,
+ 98, 0, 99, 98, 98, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 98, 98, 98, 98, 98,
+ 0, 99, 0, 98, 98, 98, 98, 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, 99, 0, 0, 99, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 104, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 99, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 104, 0, 0, 0, 0, 0, 0,
+ 104, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 104,
+ 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, 104, 0, 0, 104, 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, 104, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 99,
+ 99, 99, 99, 0, 0, 99, 0, 99, 99, 99,
+ 99, 99, 99, 99, 99, 0, 0, 0, 0, 0,
+ 0, 0, 0, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 0, 0, 0, 0, 0, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99, 99, 0,
+ 0, 0, 0, 0, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 0, 0, 99, 99, 99,
+ 99, 0, 0, 99, 99, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 99, 99, 99, 99, 99,
+ 0, 0, 0, 99, 99, 99, 99, 104, 104, 104,
+ 104, 0, 0, 104, 0, 104, 104, 104, 104, 104,
+ 104, 104, 104, 0, 0, 0, 0, 0, 0, 0,
+ 0, 104, 104, 104, 104, 104, 104, 104, 104, 104,
+ 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
+ 106, 0, 0, 0, 0, 104, 104, 104, 104, 104,
+ 104, 104, 104, 104, 104, 104, 104, 0, 0, 0,
+ 0, 0, 104, 104, 104, 104, 104, 104, 104, 104,
+ 104, 104, 104, 106, 0, 104, 104, 104, 104, 0,
+ 106, 104, 104, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 104, 104, 104, 104, 104, 0, 106,
+ 0, 104, 104, 104, 104, 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, 106, 0, 0, 106, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 110, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 106, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 110, 0, 0, 0, 0, 0, 0, 110, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 110, 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, 110, 0, 0, 110, 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, 110, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 106, 106, 106,
+ 106, 0, 0, 106, 0, 106, 106, 106, 106, 106,
+ 106, 106, 106, 0, 0, 0, 0, 0, 0, 0,
+ 0, 106, 106, 106, 106, 106, 106, 106, 106, 106,
+ 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
+ 0, 0, 0, 0, 0, 106, 106, 106, 106, 106,
+ 106, 106, 106, 106, 106, 106, 106, 0, 0, 0,
+ 0, 0, 106, 106, 106, 106, 106, 106, 106, 106,
+ 106, 106, 106, 0, 0, 106, 106, 106, 106, 0,
+ 0, 106, 106, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 106, 106, 106, 106, 106, 0, 0,
+ 0, 106, 106, 106, 106, 110, 110, 110, 110, 0,
+ 0, 110, 0, 110, 110, 110, 110, 110, 110, 110,
+ 110, 0, 0, 0, 0, 0, 0, 0, 0, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 123, 0,
+ 0, 0, 0, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 0, 0, 0, 0, 0,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 123, 0, 110, 110, 110, 110, 0, 123, 110,
+ 110, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 110, 110, 110, 110, 110, 0, 123, 0, 110,
+ 110, 110, 110, 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, 123, 0, 0, 123, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 108, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 123, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 108,
+ 0, 0, 0, 0, 0, 0, 108, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 108, 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, 108,
+ 0, 0, 108, 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, 108, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 123, 123, 123, 123, 0,
+ 0, 123, 0, 123, 123, 123, 123, 123, 123, 123,
+ 123, 0, 0, 0, 0, 0, 0, 0, 0, 123,
+ 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
+ 123, 123, 123, 123, 123, 123, 123, 123, 0, 0,
+ 0, 0, 0, 123, 123, 123, 123, 123, 123, 123,
+ 123, 123, 123, 123, 123, 0, 0, 0, 0, 0,
+ 123, 123, 123, 123, 123, 123, 123, 123, 123, 123,
+ 123, 0, 0, 123, 123, 123, 123, 0, 0, 123,
+ 123, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 123, 123, 123, 123, 123, 0, 0, 0, 123,
+ 123, 123, 123, 108, 108, 108, 108, 0, 0, 108,
+ 0, 108, 108, 108, 108, 108, 108, 108, 108, 0,
+ 0, 0, 0, 0, 0, 0, 0, 108, 108, 108,
+ 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
+ 108, 108, 108, 108, 108, 108, 0, 0, 0, 0,
+ 0, 108, 108, 108, 108, 108, 108, 108, 108, 108,
+ 108, 108, 108, 0, 0, 0, 0, 0, 108, 108,
+ 108, 108, 108, 108, 108, 108, 108, 108, 108, 141,
+ 0, 108, 108, 108, 108, 0, 0, 108, 108, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 108,
+ 108, 108, 108, 108, 0, 0, 0, 108, 108, 108,
+ 108, 0, 141, 0, 0, 0, 0, 0, 0, 141,
+ 141, 0, 141, 141, 141, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 141, 0,
+ 0, 141, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 167, 0, 0, 0, 0,
+ 0, 0, 141, 0, 0, 141, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 167, 0,
+ 0, 0, 0, 0, 141, 167, 167, 0, 230, 167,
+ 167, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 167, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 230, 0, 0, 0, 0, 0, 0, 230, 230,
+ 0, 0, 230, 0, 0, 0, 0, 0, 167, 0,
+ 0, 167, 0, 0, 0, 0, 0, 230, 230, 0,
+ 230, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 167, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 230, 0, 0, 230, 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, 230, 0, 0, 141, 141, 141, 141,
+ 0, 0, 141, 0, 141, 141, 141, 141, 141, 141,
+ 141, 141, 0, 0, 0, 0, 0, 0, 0, 0,
+ 141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
+ 141, 141, 141, 141, 141, 141, 141, 141, 141, 40,
+ 0, 0, 0, 141, 141, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 141, 141, 141, 141,
+ 141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
+ 141, 141, 40, 0, 0, 0, 0, 0, 0, 40,
+ 141, 141, 167, 167, 167, 167, 0, 0, 167, 0,
+ 167, 167, 167, 167, 167, 167, 0, 0, 40, 0,
+ 141, 141, 141, 141, 0, 0, 167, 167, 167, 167,
+ 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
+ 167, 167, 167, 167, 167, 230, 230, 230, 230, 0,
+ 167, 230, 40, 0, 0, 40, 230, 0, 0, 230,
+ 230, 0, 0, 0, 0, 0, 0, 167, 167, 167,
+ 167, 167, 167, 167, 167, 167, 167, 167, 0, 0,
+ 0, 0, 0, 0, 40, 0, 167, 167, 42, 0,
+ 0, 0, 0, 230, 230, 230, 230, 230, 230, 230,
+ 230, 230, 230, 230, 230, 0, 167, 167, 167, 167,
+ 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
+ 230, 42, 0, 230, 230, 230, 230, 0, 42, 0,
+ 0, 0, 0, 0, 0, 230, 230, 230, 230, 230,
+ 230, 230, 230, 230, 230, 230, 0, 42, 0, 0,
+ 0, 0, 230, 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, 0, 0, 42, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 95,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 42, 0, 0, 40, 40, 40, 40,
+ 0, 0, 40, 0, 0, 0, 0, 40, 0, 0,
+ 40, 40, 0, 0, 0, 0, 0, 0, 0, 0,
+ 89, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 95, 0,
+ 0, 0, 0, 0, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 0, 0, 0, 0,
+ 0, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 95, 0, 40, 40, 40, 40, 0, 89,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 40, 40, 40, 40, 40, 0, 0, 0,
+ 0, 0, 0, 40, 95, 0, 0, 0, 93, 0,
+ 0, 0, 0, 89, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 42, 42, 42, 42, 0,
+ 0, 42, 0, 0, 0, 0, 42, 0, 0, 42,
+ 42, 0, 0, 0, 0, 89, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 93, 0, 0,
+ 0, 0, 0, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 0, 0, 0, 0, 0,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 93, 0, 42, 42, 42, 42, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 42, 42, 42, 42, 42, 0, 0, 0, 91,
+ 0, 0, 42, 93, 0, 0, 0, 0, 0, 95,
+ 0, 0, 0, 0, 95, 95, 95, 0, 95, 95,
+ 95, 95, 0, 0, 0, 0, 0, 0, 0, 0,
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 188,
+ 89, 0, 0, 0, 0, 89, 89, 89, 91, 89,
+ 89, 89, 89, 0, 0, 0, 0, 0, 0, 0,
+ 0, 89, 89, 89, 89, 89, 89, 89, 89, 89,
+ 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
+ 95, 95, 91, 0, 0, 0, 0, 0, 0, 103,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 95, 95, 95, 95, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 91, 0, 0, 0, 0, 0,
+ 0, 89, 89, 0, 0, 0, 0, 0, 93, 0,
+ 0, 0, 0, 93, 93, 93, 0, 93, 93, 93,
+ 93, 89, 89, 89, 89, 0, 0, 0, 103, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 189, 0,
+ 0, 0, 0, 0, 105, 0, 146, 0, 0, 0,
+ 0, 0, 103, 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, 93,
+ 93, 0, 0, 0, 103, 0, 0, 0, 0, 146,
+ 0, 146, 146, 0, 0, 0, 0, 0, 0, 93,
+ 93, 93, 93, 105, 0, 146, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 91,
+ 0, 0, 0, 0, 91, 91, 91, 0, 91, 91,
+ 91, 91, 0, 0, 0, 0, 0, 105, 0, 146,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 109, 105,
+ 0, 146, 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,
+ 91, 91, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 103,
+ 91, 91, 91, 91, 103, 103, 103, 109, 103, 103,
+ 103, 103, 0, 0, 0, 0, 0, 0, 0, 0,
+ 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
+ 103, 103, 103, 103, 103, 103, 103, 103, 103, 0,
+ 0, 109, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 107, 0, 0, 0, 0,
+ 0, 0, 0, 109, 0, 0, 0, 0, 0, 0,
+ 103, 103, 0, 0, 105, 0, 0, 0, 0, 105,
+ 105, 105, 0, 105, 105, 105, 105, 146, 146, 0,
+ 103, 103, 103, 103, 0, 105, 105, 105, 105, 105,
+ 105, 105, 105, 105, 105, 105, 105, 105, 105, 105,
+ 105, 105, 105, 105, 107, 0, 0, 0, 0, 0,
+ 0, 0, 146, 146, 146, 146, 146, 146, 146, 146,
+ 146, 146, 146, 146, 146, 146, 146, 146, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 107, 0,
+ 0, 146, 146, 146, 146, 105, 105, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 146,
+ 146, 146, 146, 146, 0, 105, 105, 105, 105, 0,
+ 107, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 109, 0,
+ 0, 0, 0, 109, 109, 109, 0, 109, 109, 109,
+ 109, 0, 0, 0, 0, 0, 0, 0, 0, 109,
+ 109, 109, 109, 109, 109, 109, 109, 109, 109, 109,
+ 109, 109, 109, 109, 109, 109, 109, 109, 80, 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, 80, 0, 0, 0, 0, 0, 0, 80, 109,
+ 109, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 80, 0, 109,
+ 109, 109, 109, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 107, 0, 0, 0, 0,
+ 107, 107, 107, 0, 107, 107, 107, 107, 0, 0,
+ 0, 80, 0, 0, 80, 0, 107, 107, 107, 107,
+ 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
+ 107, 107, 107, 107, 107, 0, 0, 0, 0, 0,
+ 0, 0, 0, 80, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 89, 0,
+ 0, 0, 0, 0, 0, 86, 0, 0, 0, 0,
+ 88, 0, 0, 0, 0, 0, 107, 107, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 107, 107, 107, 107,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 32, 0, 0, 0,
+ 0, 87, 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, 31, 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, 80, 80, 80, 0, 0,
+ 0, 80, 0, 80, 80, 80, 80, 80, 80, 80,
+ 80, 0, 0, 0, 0, 0, 0, 0, 0, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 0, 0,
+ 0, 0, 0, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 0, 0, 0, 0, 0,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 0, 0, 80, 80, 80, 80, 0, 0, 80,
+ 80, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 80, 80, 80, 80, 80, 0, 0, 0, 80,
+ 80, 80, 277, 278, 49, 8, 9, 0, 50, 0,
+ 0, 0, 0, 51, 10, 11, 279, 280, 14, 15,
+ 16, 17, 18, 19, 20, 21, 0, 0, 6, 0,
+ 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
+ 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 0, 0, 0, 0, 0, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, 75, 76, 22, 0,
+ 77, 78, 79, 80, 23, 24, 6, 0, 25, 0,
+ 26, 6, 0, 0, 0, 0, 0, 0, 81, 82,
+ 83, 84, 85, 27, 0, 28, 0, 0, 0, 29,
+ 30, 0, 0, 0, 0, 0, 0, 0, 6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 89, 0, 0,
+ 0, 0, 0, 0, 104, 0, 0, 0, 0, 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, 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,
+ 87, 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, 6, 6, 6, 6, 6, 0, 6, 0,
+ 0, 0, 0, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 105, 0, 0, 0,
+ 0, 0, 0, 104, 297, 0, 0, 0, 88, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 0, 0, 0, 0, 0, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 0,
+ 6, 6, 6, 6, 6, 6, 0, 0, 6, 87,
+ 6, 0, 0, 0, 0, 0, 0, 0, 6, 6,
+ 6, 6, 6, 6, 0, 6, 0, 0, 0, 6,
+ 6, 47, 48, 49, 8, 0, 0, 50, 0, 120,
+ 121, 122, 51, 123, 124, 125, 126, 0, 0, 0,
+ 0, 0, 0, 0, 0, 127, 128, 129, 130, 131,
+ 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+ 142, 143, 144, 145, 0, 0, 0, 0, 0, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 0, 0, 0, 0, 0, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 0, 0, 77,
+ 78, 79, 80, 0, 89, 146, 147, 0, 0, 0,
+ 0, 86, 0, 0, 0, 0, 88, 81, 82, 83,
+ 84, 85, 0, 0, 0, 148, 149, 150, 29, 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,
+ 47, 48, 49, 8, 0, 0, 50, 87, 0, 0,
+ 0, 51, 0, 0, 52, 53, 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, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 0, 0, 0, 0, 0, 66, 67, 68, 69, 70,
+ 71, 72, 73, 74, 75, 76, 105, 0, 77, 78,
+ 79, 80, 0, 104, 0, 0, 0, 0, 88, 0,
+ 0, 0, 0, 0, 0, 0, 81, 82, 83, 84,
+ 85, 0, 0, 0, 0, 0, 0, 29, 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, 87,
+ 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, 47, 48,
+ 49, 8, 0, 0, 50, 0, 0, 0, 0, 51,
+ 0, 0, 52, 53, 0, 0, 0, 105, 0, 0,
+ 0, 0, 0, 0, 86, 0, 0, 0, 0, 88,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 0, 0,
+ 0, 0, 0, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 0, 0, 77, 78, 79, 80,
+ 87, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 81, 82, 83, 84, 85, 0,
+ 0, 0, 0, 0, 0, 29, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 105, 0, 0,
+ 47, 48, 49, 8, 268, 0, 50, 0, 0, 88,
+ 0, 51, 0, 0, 52, 53, 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, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 87, 0, 0, 0, 0, 66, 67, 68, 69, 70,
+ 71, 72, 73, 74, 75, 76, 0, 0, 77, 78,
+ 79, 80, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 81, 82, 83, 84,
+ 85, 0, 0, 0, 0, 0, 0, 29, 0, 89,
+ 0, 47, 48, 49, 8, 0, 104, 50, 406, 0,
+ 0, 88, 51, 0, 0, 52, 53, 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, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 0, 87, 0, 0, 0, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 0, 0, 77,
+ 78, 79, 80, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 81, 82, 83,
+ 84, 85, 0, 0, 0, 0, 0, 0, 29, 89,
+ 0, 47, 48, 49, 8, 0, 104, 50, 0, 0,
+ 0, 88, 51, 0, 0, 52, 53, 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, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 0, 87, 0, 0, 0, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 0, 0, 77,
+ 78, 79, 80, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 81, 82, 83,
+ 84, 85, 0, 0, 0, 0, 0, 0, 29, 0,
+ 89, 0, 0, 47, 48, 49, 0, 86, 0, 50,
+ 0, 0, 88, 0, 51, 0, 0, 52, 53, 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, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 87, 0, 0, 0, 0, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 0,
+ 0, 77, 78, 79, 80, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 81,
+ 82, 83, 84, 85, 0, 0, 0, 0, 0, 0,
+ 89, 0, 0, 47, 48, 49, 0, 268, 0, 50,
+ 0, 0, 88, 0, 51, 0, 0, 52, 53, 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, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 87, 0, 0, 0, 0, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 0,
+ 0, 77, 78, 79, 80, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 81,
+ 82, 83, 84, 85, 0, 0, 0, 0, 0, 0,
+ 0, 89, 0, 0, 47, 48, 49, 0, 104, 0,
+ 50, 0, 0, 88, 0, 51, 0, 0, 52, 53,
+ 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, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 87, 0, 0, 0, 0, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 0, 0, 77, 78, 79, 80, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 81, 82, 83, 84, 85, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 47, 48, 49, 0, 0, 0,
+ 50, 0, 0, 0, 0, 51, 0, 0, 52, 53,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 40, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 32, 0, 0, 0, 0, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 0, 0, 77, 78, 79, 80, 0, 0, 0, 0,
+ 0, 0, 32, 0, 0, 0, 31, 0, 0, 0,
+ 81, 82, 83, 84, 85, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 47, 48, 49, 0, 0,
+ 0, 50, 0, 0, 31, 0, 51, 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, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 0, 0, 0, 0, 0,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 0, 0, 77, 78, 79, 80, 0, 0, 0,
+ 0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
+ 0, 81, 82, 83, 84, 85, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 7, 0, 8, 9, 6, 0, 0, 0, 0,
+ 0, 0, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 0, 0, 0, 0, 6, 7,
+ 0, 8, 9, 0, 0, 0, 0, 0, 0, 0,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 22, 0, 0, 0,
+ 0, 0, 23, 24, 0, 0, 25, 0, 26, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 27, 0, 28, 22, 0, 0, 29, 30, 0,
+ 23, 24, 0, 0, 25, 0, 26, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 27,
+ 0, 28, 0, 0, 0, 29, 30, 0, 0, 6,
+ 6, 0, 6, 6, 0, 0, 0, 0, 0, 0,
+ 0, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 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, 6, 0, 0, 0, 0,
+ 0, 6, 6, 0, 0, 6, 0, 6, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 6, 0, 0, 0, 6, 6,
+};
+short yycheck[] = { 24,
+ 43, 119, 45, 28, 44, 30, 0, 260, 271, 272,
+ 94, 36, 4, 260, 59, 105, 86, 37, 59, 96,
+ 58, 43, 42, 45, 0, 37, 0, 47, 258, 101,
+ 42, 43, 24, 45, 99, 47, 0, 155, 30, 258,
+ 62, 35, 114, 58, 36, 40, 61, 41, 60, 346,
+ 62, 271, 272, 334, 41, 91, 43, 0, 45, 0,
+ 43, 86, 45, 88, 89, 135, 262, 41, 41, 0,
+ 44, 44, 41, 61, 94, 44, 101, 347, 348, 43,
+ 105, 45, 94, 59, 40, 59, 40, 334, 96, 114,
+ 353, 354, 0, 40, 0, 59, 115, 116, 123, 124,
+ 125, 126, 127, 128, 129, 130, 131, 132, 133, 101,
+ 135, 364, 137, 138, 139, 40, 59, 93, 59, 93,
+ 112, 205, 114, 148, 149, 33, 40, 119, 59, 93,
+ 155, 40, 40, 353, 354, 41, 290, 45, 44, 43,
+ 44, 45, 232, 233, 214, 215, 236, 237, 40, 125,
+ 93, 125, 93, 59, 317, 318, 319, 320, 321, 40,
+ 0, 125, 93, 155, 189, 190, 191, 192, 193, 194,
+ 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
+ 257, 40, 125, 91, 125, 40, 263, 93, 96, 214,
+ 215, 268, 349, 350, 125, 260, 261, 40, 268, 61,
+ 260, 0, 258, 0, 229, 0, 41, 232, 233, 234,
+ 24, 236, 237, 262, 41, 123, 30, 264, 258, 125,
+ 94, 301, 0, 300, 260, 46, 37, 257, 93, 0,
+ 125, 42, 43, 93, 45, 262, 47, 273, 274, 275,
+ 276, 277, 278, 268, 280, 262, 238, 239, 257, 257,
+ 41, 243, 41, 93, 44, 263, 41, 375, 41, 37,
+ 268, 304, 59, 41, 42, 43, 44, 45, 41, 47,
+ 41, 41, 86, 44, 286, 44, 44, 302, 41, 41,
+ 345, 59, 60, 94, 62, 125, 302, 101, 59, 347,
+ 264, 262, 91, 43, 44, 45, 93, 44, 93, 257,
+ 114, 303, 37, 43, 44, 45, 359, 42, 43, 44,
+ 45, 260, 47, 41, 41, 93, 290, 131, 132, 133,
+ 41, 41, 93, 344, 123, 60, 300, 62, 125, 303,
+ 125, 0, 262, 41, 344, 347, 348, 349, 350, 351,
+ 352, 155, 155, 30, 369, 370, 371, 125, 373, 257,
+ 258, 259, 260, 261, 125, 263, 35, 381, 264, 94,
+ 268, 269, 270, 271, 272, 273, 274, 275, 276, 277,
+ 278, 279, 280, 347, 348, 0, 344, 344, 403, -1,
+ -1, 406, 196, 375, 290, -1, 37, -1, -1, -1,
+ 204, 42, 43, 44, 45, -1, 47, 305, 306, 307,
+ 308, 309, 310, 311, 312, 313, 314, 315, 316, 60,
+ 0, 62, -1, -1, 322, 323, 324, 325, 326, 327,
+ 328, 329, 330, 331, 332, 333, -1, 335, 336, 337,
+ 338, 339, 340, -1, 59, 343, -1, 345, -1, -1,
+ -1, 347, 348, 94, -1, 353, 354, 355, 356, 357,
+ 358, -1, 360, 43, 0, 45, 364, 365, 257, 258,
+ -1, 260, 261, -1, 0, 0, -1, 0, 93, 59,
+ 269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
+ 279, 280, -1, 0, -1, -1, 264, 33, 302, 300,
+ -1, 37, 303, 264, 40, 41, 42, 43, 44, 45,
+ 125, 47, -1, 93, -1, -1, 41, -1, -1, 44,
+ -1, -1, 290, 59, 60, -1, 62, -1, -1, 290,
+ -1, -1, 300, 59, 59, 303, 59, -1, -1, 300,
+ -1, -1, 303, -1, 333, 125, -1, -1, -1, -1,
+ 339, 340, 59, 37, 343, -1, 345, 93, 42, 43,
+ 96, 45, -1, 47, -1, 369, 370, 93, 93, 358,
+ 93, 360, 0, -1, -1, 364, 365, -1, -1, 347,
+ 348, 349, 350, 351, 352, -1, 93, 348, -1, 125,
+ -1, -1, -1, -1, -1, 259, -1, -1, 262, 125,
+ 125, -1, 125, -1, -1, 33, -1, -1, -1, 37,
+ 94, -1, 40, 41, 42, 43, 44, 45, 125, 47,
+ -1, -1, 347, 348, 349, 350, 351, 352, -1, -1,
+ -1, 59, 60, -1, 62, -1, -1, -1, -1, -1,
+ -1, 37, -1, -1, -1, -1, 42, 43, -1, 45,
+ -1, 47, -1, -1, -1, -1, -1, -1, -1, 300,
+ -1, -1, 303, -1, 60, 93, 62, -1, 96, 37,
+ -1, -1, -1, -1, 42, 43, -1, 45, -1, 47,
+ 37, -1, 346, 347, -1, 42, 43, 44, 45, -1,
+ 47, -1, 60, -1, 62, -1, -1, 125, 94, -1,
+ -1, -1, -1, 60, -1, 62, 347, 348, 349, 350,
+ 351, 352, 376, -1, -1, 379, -1, -1, -1, -1,
+ -1, 257, 258, 259, 260, -1, 94, 263, 264, 265,
+ 266, 267, 268, 269, 270, 271, 272, 94, -1, 264,
+ -1, -1, -1, -1, -1, 281, 282, 283, 284, 285,
+ 286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
+ 296, 297, 298, 299, 300, 290, -1, 303, 304, 305,
+ 306, 307, 308, 309, 310, 311, 312, 313, 314, 315,
+ 316, -1, -1, -1, -1, -1, 322, 323, 324, 325,
+ 326, 327, 328, 329, 330, 331, 332, -1, -1, 335,
+ 336, 337, 338, -1, -1, 341, 342, -1, 344, -1,
+ -1, 347, 348, 349, 350, 351, 352, 353, 354, 355,
+ 356, 357, -1, 348, -1, 361, 362, 363, 364, 257,
+ 258, 259, 260, -1, 91, 263, 264, 265, 266, 267,
+ 268, 269, 270, 271, 272, -1, -1, -1, -1, -1,
+ -1, -1, -1, 281, 282, 283, 284, 285, 286, 287,
+ 288, 289, 290, 291, 292, 293, 294, 295, 296, 297,
+ 298, 299, 300, 96, -1, 303, 304, 305, 306, 307,
+ 308, 309, 310, 311, 312, 313, 314, 315, 316, -1,
+ -1, -1, 260, -1, 322, 323, 324, 325, 326, 327,
+ 328, 329, 330, 331, 332, 0, -1, 335, 336, 337,
+ 338, 134, -1, 341, 342, -1, 344, 0, -1, 347,
+ 348, 349, 350, 351, 352, 353, 354, 355, 356, 357,
+ -1, -1, -1, 361, 362, 363, 364, -1, 33, -1,
+ -1, -1, 37, -1, -1, 40, 41, 42, 43, 44,
+ 45, -1, 47, -1, 26, 351, 352, -1, 41, -1,
+ -1, 44, -1, -1, 59, 60, -1, 62, -1, -1,
+ 42, -1, -1, -1, -1, -1, 59, -1, -1, 347,
+ 348, 349, 350, 351, 352, -1, -1, -1, -1, -1,
+ 347, 348, 349, 350, 351, 352, 364, -1, 93, -1,
+ -1, 96, -1, 260, -1, -1, -1, -1, -1, -1,
+ 93, 268, -1, 0, -1, 87, 273, 274, 275, 276,
+ 277, 278, -1, 280, 0, -1, -1, -1, -1, -1,
+ 125, -1, -1, -1, -1, -1, 259, -1, -1, 262,
+ -1, -1, 125, 266, -1, -1, 33, -1, -1, -1,
+ 37, -1, -1, 40, 41, 42, 43, 44, 45, -1,
+ 47, -1, -1, -1, -1, 41, -1, -1, 44, -1,
+ -1, -1, 59, 60, -1, 62, -1, -1, -1, -1,
+ -1, -1, -1, 59, -1, 157, -1, -1, -1, 161,
+ 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+ -1, -1, -1, -1, -1, -1, 93, -1, -1, 96,
+ 37, -1, -1, -1, -1, 42, 43, 93, 45, -1,
+ 47, 37, -1, 346, 347, -1, 42, 43, -1, 45,
+ -1, 47, -1, 60, -1, 62, -1, -1, 125, -1,
+ -1, -1, -1, -1, 60, -1, 62, -1, -1, 125,
+ -1, -1, -1, 376, -1, -1, 379, -1, -1, -1,
+ -1, -1, 257, 258, 259, 260, -1, 94, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 94, -1,
+ -1, 264, -1, -1, -1, -1, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, -1, 290, 303, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, -1, -1, -1, -1, -1, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, -1, -1,
+ 335, 336, 337, 338, -1, -1, 341, 342, -1, 344,
+ -1, -1, 347, 348, 349, 350, 351, 352, 353, 354,
+ 355, 356, 357, -1, -1, 348, 361, 362, 363, 364,
+ 257, 258, 259, 260, -1, -1, 263, 264, 265, 266,
+ 267, 268, 269, 270, 271, 272, 358, -1, 264, -1,
+ 362, 363, 91, -1, 281, 282, 283, 284, 285, 286,
+ 287, 288, 289, 290, 291, 292, 293, 294, 295, 296,
+ 297, 298, 299, 300, 290, -1, 303, 304, 305, 306,
+ 307, 308, 309, 310, 311, 312, 313, 314, 315, 316,
+ -1, -1, -1, -1, -1, 322, 323, 324, 325, 326,
+ 327, 328, 329, 330, 331, 332, 0, -1, 335, 336,
+ 337, 338, -1, -1, 341, 342, -1, 344, -1, -1,
+ 347, 348, 349, 350, 351, 352, 353, 354, 355, 356,
+ 357, -1, 348, 289, 361, 362, 363, 364, -1, 33,
+ -1, -1, -1, 37, -1, -1, 40, 41, 42, 43,
+ 44, 45, -1, 47, -1, -1, -1, -1, -1, 0,
+ -1, -1, -1, -1, -1, 59, 60, -1, 62, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 347, 348, 349, 350, 351, 352, -1, -1, -1, -1,
+ -1, 347, 348, 349, 350, 351, 352, -1, -1, 93,
+ 41, -1, 96, 44, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 0, -1, -1, -1, 59, -1,
+ 37, 260, -1, -1, -1, 42, 43, -1, 45, 268,
+ 47, 125, -1, -1, 273, 274, 275, 276, 277, 278,
+ -1, 280, -1, 60, -1, 62, -1, 33, -1, -1,
+ -1, 37, 93, -1, 40, 41, 42, 43, 44, 45,
+ -1, 47, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 59, 60, -1, 62, 94, -1, -1,
+ -1, -1, -1, 37, 125, -1, -1, -1, 42, 43,
+ 37, 45, -1, 47, -1, 42, 43, -1, 45, -1,
+ 47, -1, -1, -1, -1, -1, 60, 93, 62, -1,
+ 96, 37, -1, 60, -1, 62, 42, 43, -1, 45,
+ -1, 47, -1, 37, -1, -1, -1, -1, 42, 43,
+ 44, 45, -1, 47, 60, -1, 62, -1, -1, 125,
+ 94, -1, -1, -1, -1, -1, 60, 94, 62, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 257, 258, 259, 260, -1, 94, 263,
+ 264, 265, 266, 267, 268, 269, 270, 271, 272, -1,
+ 94, -1, -1, -1, -1, -1, -1, 281, 282, 283,
+ 284, 285, 286, 287, 288, 289, 290, 291, 292, 293,
+ 294, 295, 296, 297, 298, 299, 300, -1, -1, 303,
+ 304, 305, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, 264, -1, -1, -1, -1, 322, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, -1,
+ -1, 335, 336, 337, 338, -1, -1, 341, 342, 290,
+ 344, -1, -1, 347, 348, 349, 350, 351, 352, 353,
+ 354, 355, 356, 357, 46, -1, -1, 361, 362, 363,
+ 364, 257, 258, 259, 260, -1, 46, 263, 264, 265,
+ 266, 267, 268, 269, 270, 271, 272, -1, -1, -1,
+ -1, -1, -1, -1, -1, 281, 282, 283, 284, 285,
+ 286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
+ 296, 297, 298, 299, 300, -1, -1, 303, 304, 305,
+ 306, 307, 308, 309, 310, 311, 312, 313, 314, 315,
+ 316, -1, 349, 350, 351, 352, 322, 323, 324, 325,
+ 326, 327, 328, 329, 330, 331, 332, 0, -1, 335,
+ 336, 337, 338, -1, -1, 341, 342, -1, 344, -1,
+ -1, 347, 348, 349, 350, 351, 352, 353, 354, 355,
+ 356, 357, -1, -1, -1, 361, 362, 363, 364, -1,
+ 33, -1, -1, -1, -1, -1, 300, 40, 41, 303,
+ 43, 44, 45, 347, 348, 349, 350, 351, 352, -1,
+ 347, -1, 349, 350, 351, 352, 59, 60, -1, 62,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 347, -1, 349, 350, 351, 352, -1, -1, -1,
+ -1, -1, -1, 347, 348, 349, 350, 351, 352, -1,
+ 93, -1, -1, 96, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 0, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 125, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 33, 271,
+ 272, -1, -1, -1, -1, 40, 41, -1, 43, 44,
+ 45, 271, 272, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 59, 60, -1, 62, -1, -1,
+ -1, -1, -1, -1, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, -1, 306, 307, 308, 309,
+ 310, 311, 312, 313, 314, 315, 316, -1, 93, -1,
+ -1, 96, -1, 335, 336, 337, 338, -1, -1, -1,
+ -1, -1, -1, -1, -1, 335, 336, 337, 338, -1,
+ -1, 353, 354, 355, 356, 357, -1, -1, -1, -1,
+ 125, -1, -1, 353, 354, 355, 356, 357, -1, -1,
+ -1, -1, -1, -1, -1, -1, 46, -1, -1, -1,
+ -1, -1, -1, 40, 257, 258, 259, 260, -1, 46,
+ 263, 264, 265, 266, 267, 268, 269, 270, 271, 272,
+ -1, -1, -1, -1, -1, -1, -1, -1, 281, 282,
+ 283, 284, 285, 286, 287, 288, 289, 290, 291, 292,
+ 293, 294, 295, 296, 297, 298, 299, 300, -1, -1,
+ 303, 304, 305, 306, 307, 308, 309, 310, 311, 312,
+ 313, 314, 315, 316, -1, -1, -1, -1, -1, 322,
+ 323, 324, 325, 326, 327, 328, 329, 330, 331, 332,
+ -1, -1, 335, 336, 337, 338, -1, -1, 341, 342,
+ -1, 344, -1, -1, 347, 348, 349, 350, 351, 352,
+ 353, 354, 355, 356, 357, -1, -1, -1, 361, 362,
+ 363, 364, 257, 258, 259, 260, -1, -1, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, -1, -1,
+ -1, -1, -1, -1, -1, -1, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, -1, -1, 303, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, -1, -1, -1, -1, -1, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 0, -1,
+ 335, 336, 337, 338, -1, -1, 341, 342, -1, 344,
+ -1, -1, 347, 348, 349, 350, 351, 352, 353, 354,
+ 355, 356, 357, -1, -1, -1, 361, 362, 363, 364,
+ 257, 33, -1, -1, -1, -1, 263, -1, 40, 41,
+ -1, 268, 44, -1, 271, 272, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 59, 60, -1,
+ 62, -1, -1, -1, -1, -1, 306, 307, 308, 309,
+ 310, 311, 312, 313, 314, 315, 316, -1, -1, 306,
+ 307, 308, 309, 310, 311, 312, 313, 314, 315, 316,
+ -1, 93, 0, -1, 96, 335, 336, 337, 338, -1,
+ -1, -1, -1, -1, -1, -1, 0, -1, 335, 336,
+ 337, 338, -1, 353, 354, 355, 356, 357, -1, -1,
+ -1, -1, -1, 125, -1, -1, 353, 354, 355, 356,
+ 357, -1, -1, 41, -1, -1, 44, -1, -1, 33,
+ -1, 86, -1, -1, -1, -1, 40, 41, -1, -1,
+ 44, 59, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 59, 60, -1, 62, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 93, 131, 132, 133, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 93,
+ -1, -1, 96, -1, -1, -1, -1, -1, -1, -1,
+ 155, -1, -1, -1, -1, 37, -1, 125, -1, -1,
+ 42, 43, 44, 45, -1, 47, -1, -1, -1, -1,
+ -1, 125, -1, -1, -1, -1, -1, -1, 60, -1,
+ 62, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 196, -1, -1, -1, 257, 258, 259, 260, 204,
+ -1, 263, 264, 265, 266, 267, 268, 269, 270, 271,
+ 272, -1, 94, -1, -1, -1, -1, -1, -1, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
+ 292, 293, 294, 295, 296, 297, 298, 299, 300, -1,
+ -1, 303, 304, 305, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, -1, -1, -1, -1, -1,
+ 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, -1, -1, 335, 336, 337, 338, -1, -1, 341,
+ 342, -1, 344, -1, -1, 347, 348, 349, 350, 351,
+ 352, 353, 354, 355, 356, 357, 264, 302, -1, 361,
+ 362, 363, 364, 257, 258, 259, 260, -1, -1, 263,
+ 264, 265, 266, 267, 268, 269, 270, 271, 272, -1,
+ -1, 0, 290, -1, -1, -1, -1, 281, 282, 283,
+ 284, 285, 286, 287, 288, 289, 290, 291, 292, 293,
+ 294, 295, 296, 297, 298, 299, 300, -1, -1, 303,
+ 304, 305, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, -1, 369, 370, -1, -1, 322, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, 0,
+ 59, 335, 336, 337, 338, -1, -1, 341, 342, -1,
+ 344, -1, -1, 347, 348, 349, 350, 351, 352, 353,
+ 354, 355, 356, 357, -1, -1, -1, 361, 362, 363,
+ 364, -1, 33, -1, 93, -1, -1, 96, 300, 40,
+ 41, 303, -1, 44, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 59, 60,
+ -1, 62, -1, -1, -1, -1, 125, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 347, 348, 349, 350, 351,
+ 352, -1, 93, -1, -1, 96, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 0, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 125, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 33, -1, -1, -1, -1, -1, -1, 40, 41, -1,
+ -1, 44, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 59, 60, -1, 62,
+ -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, 257, -1,
+ 93, -1, -1, 96, 263, -1, -1, -1, -1, 268,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 125, -1, -1, -1, -1, -1, -1, -1,
+ -1, 300, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 257, 258, 259, 260,
+ -1, -1, 263, 264, 265, 266, 267, 268, 269, 270,
+ 271, 272, -1, -1, -1, -1, -1, -1, -1, -1,
+ 281, 282, 283, 284, 285, 286, 287, 288, 289, 290,
+ 291, 292, 293, 294, 295, 296, 297, 298, 299, 300,
+ -1, -1, 303, 304, 305, 306, 307, 308, 309, 310,
+ 311, 312, 313, 314, 315, 316, -1, -1, -1, -1,
+ -1, 322, 323, 324, 325, 326, 327, 328, 329, 330,
+ 331, 332, -1, -1, 335, 336, 337, 338, -1, -1,
+ 341, 342, -1, 344, -1, -1, 347, 348, 349, 350,
+ 351, 352, 353, 354, 355, 356, 357, -1, -1, -1,
+ 361, 362, 363, 364, 257, 258, 259, 260, -1, -1,
+ 263, 264, 265, 266, 267, 268, 269, 270, 271, 272,
+ -1, -1, 0, -1, -1, -1, -1, -1, 281, 282,
+ 283, 284, 285, 286, 287, 288, 289, 290, 291, 292,
+ 293, 294, 295, 296, 297, 298, 299, 300, -1, -1,
+ 303, 304, 305, 306, 307, 308, 309, 310, 311, 312,
+ 313, 314, 315, 316, -1, -1, -1, -1, -1, 322,
+ 323, 324, 325, 326, 327, 328, 329, 330, 331, 332,
+ 0, 59, 335, 336, 337, 338, -1, -1, 341, 342,
+ -1, 344, -1, -1, 347, 348, 349, 350, 351, 352,
+ 353, 354, 355, 356, 357, -1, -1, -1, 361, 362,
+ 363, 364, -1, 33, -1, 93, -1, -1, 96, -1,
+ 40, 41, -1, 43, 44, 45, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 59,
+ -1, -1, 62, -1, -1, -1, -1, 125, -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, 93, -1, -1, 96, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 0, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 125, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 33, -1, -1, -1, -1, -1, -1, 40, 41,
+ -1, -1, 44, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 59, -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, 257,
+ -1, 93, -1, -1, 96, 263, -1, -1, -1, -1,
+ 268, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 125, -1, -1, -1, -1, -1, -1,
+ -1, -1, 300, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 257, 258, 259,
+ 260, -1, -1, 263, -1, 265, 266, 267, 268, 269,
+ 270, 271, 272, -1, -1, -1, -1, -1, -1, -1,
+ -1, 281, 282, 283, 284, 285, 286, 287, 288, 289,
+ 290, 291, 292, 293, 294, 295, 296, 297, 298, 299,
+ -1, -1, -1, -1, 304, 305, 306, 307, 308, 309,
+ 310, 311, 312, 313, 314, 315, 316, 317, 318, 319,
+ 320, 321, 322, 323, 324, 325, 326, 327, 328, 329,
+ 330, 331, 332, -1, -1, 335, 336, 337, 338, -1,
+ -1, 341, 342, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 353, 354, 355, 356, 357, -1, -1,
+ -1, 361, 362, 363, 364, 257, 258, 259, 260, -1,
+ -1, 263, 264, 265, 266, 267, 268, 269, 270, 271,
+ 272, -1, -1, -1, -1, -1, -1, -1, -1, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
+ 292, 293, 294, 295, 296, 297, 298, 299, 300, -1,
+ -1, 303, 304, 305, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, -1, -1, -1, -1, -1,
+ 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, 0, -1, 335, 336, 337, 338, -1, -1, 341,
+ 342, -1, 344, -1, -1, 347, 348, 349, 350, -1,
+ -1, 353, 354, 355, 356, 357, -1, -1, -1, 361,
+ 362, 363, 364, -1, 33, -1, -1, -1, -1, -1,
+ -1, 40, 41, -1, -1, 44, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 59, -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, -1, 93, -1, -1, 96, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 125, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 33, -1, -1, -1, -1, -1, -1, 40,
+ 41, -1, 43, 44, 45, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 59, -1,
+ -1, 62, -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, 93, -1, -1, 96, -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, 125, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 257, 258,
+ 259, 260, -1, -1, 263, 264, 265, 266, 267, 268,
+ 269, 270, 271, 272, -1, -1, -1, -1, -1, -1,
+ -1, -1, 281, 282, 283, 284, 285, 286, 287, 288,
+ 289, 290, 291, 292, 293, 294, 295, 296, 297, 298,
+ 299, 300, -1, -1, 303, 304, 305, 306, 307, 308,
+ 309, 310, 311, 312, 313, 314, 315, 316, -1, -1,
+ -1, -1, -1, 322, 323, 324, 325, 326, 327, 328,
+ 329, 330, 331, 332, -1, -1, 335, 336, 337, 338,
+ -1, -1, 341, 342, -1, 344, -1, -1, 347, 348,
+ 349, 350, -1, -1, 353, 354, 355, 356, 357, -1,
+ -1, -1, 361, 362, 363, 364, 257, 258, 259, 260,
+ -1, -1, 263, -1, 265, 266, 267, 268, 269, 270,
+ 271, 272, -1, -1, -1, -1, -1, -1, -1, -1,
+ 281, 282, 283, 284, 285, 286, 287, 288, 289, 290,
+ 291, 292, 293, 294, 295, 296, 297, 298, 299, -1,
+ -1, -1, -1, 304, 305, 306, 307, 308, 309, 310,
+ 311, 312, 313, 314, 315, 316, 317, 318, 319, 320,
+ 321, 322, 323, 324, 325, 326, 327, 328, 329, 330,
+ 331, 332, 0, -1, 335, 336, 337, 338, -1, -1,
+ 341, 342, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 353, 354, 355, 356, 357, -1, -1, -1,
+ 361, 362, 363, 364, -1, 33, -1, -1, -1, -1,
+ -1, -1, 40, 41, -1, -1, 44, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 59, -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, -1, 93, -1, -1, 96, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 125, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 33, -1, -1, -1, -1, -1, -1,
+ 40, 41, -1, -1, 44, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 59,
+ -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, -1, 93, -1, -1, 96, -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, 125, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 257,
+ 258, 259, 260, -1, -1, 263, 264, 265, 266, 267,
+ 268, 269, 270, 271, 272, -1, -1, -1, -1, -1,
+ -1, -1, -1, 281, 282, 283, 284, 285, 286, 287,
+ 288, 289, 290, 291, 292, 293, 294, 295, 296, 297,
+ 298, 299, 300, -1, -1, 303, 304, 305, 306, 307,
+ 308, 309, 310, 311, 312, 313, 314, 315, 316, -1,
+ -1, -1, -1, -1, 322, 323, 324, 325, 326, 327,
+ 328, 329, 330, 331, 332, -1, -1, 335, 336, 337,
+ 338, -1, -1, 341, 342, -1, 344, -1, -1, 347,
+ 348, -1, -1, -1, -1, 353, 354, 355, 356, 357,
+ -1, -1, -1, 361, 362, 363, 364, 257, 258, 259,
+ 260, -1, -1, 263, 264, 265, 266, 267, 268, 269,
+ 270, 271, 272, -1, -1, -1, -1, -1, -1, -1,
+ -1, 281, 282, 283, 284, 285, 286, 287, 288, 289,
+ 290, 291, 292, 293, 294, 295, 296, 297, 298, 299,
+ 300, -1, -1, 303, 304, 305, 306, 307, 308, 309,
+ 310, 311, 312, 313, 314, 315, 316, -1, -1, -1,
+ -1, -1, 322, 323, 324, 325, 326, 327, 328, 329,
+ 330, 331, 332, 0, -1, 335, 336, 337, 338, -1,
+ -1, 341, 342, -1, 344, -1, -1, -1, 348, -1,
+ -1, -1, -1, 353, 354, 355, 356, 357, -1, -1,
+ -1, 361, 362, 363, 364, -1, 33, -1, -1, -1,
+ -1, -1, -1, 40, 41, -1, 43, 44, 45, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 59, -1, -1, 62, -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, 93, -1, -1, 96,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 0, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 125, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 33, -1, -1, -1, -1, -1,
+ -1, 40, 41, -1, -1, 44, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 59, -1, -1, 62, -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, 93, -1, -1, 96, -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, 125, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 257, 258, 259, 260, -1, -1, 263, -1, 265, 266,
+ 267, 268, 269, 270, 271, 272, -1, -1, -1, -1,
+ -1, -1, -1, -1, 281, 282, 283, 284, 285, 286,
+ 287, 288, 289, 290, 291, 292, 293, 294, 295, 296,
+ 297, 298, 299, -1, -1, -1, -1, 304, 305, 306,
+ 307, 308, 309, 310, 311, 312, 313, 314, 315, 316,
+ -1, -1, -1, -1, -1, 322, 323, 324, 325, 326,
+ 327, 328, 329, 330, 331, 332, -1, -1, 335, 336,
+ 337, 338, -1, -1, 341, 342, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 353, 354, 355, 356,
+ 357, -1, -1, -1, 361, 362, 363, 364, 257, 258,
+ 259, 260, -1, -1, 263, -1, 265, 266, 267, 268,
+ 269, 270, 271, 272, -1, -1, -1, -1, -1, -1,
+ -1, -1, 281, 282, 283, 284, 285, 286, 287, 288,
+ 289, 290, 291, 292, 293, 294, 295, 296, 297, 298,
+ 299, -1, -1, -1, -1, 304, 305, 306, 307, 308,
+ 309, 310, 311, 312, 313, 314, 315, 316, -1, -1,
+ -1, -1, -1, 322, 323, 324, 325, 326, 327, 328,
+ 329, 330, 331, 332, 0, -1, 335, 336, 337, 338,
+ -1, -1, 341, 342, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 353, 354, 355, 356, 357, -1,
+ -1, -1, 361, 362, 363, 364, -1, 33, -1, -1,
+ -1, -1, -1, -1, 40, 41, -1, -1, 44, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 59, -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, -1, 93, -1, -1,
+ 96, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 0, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 125,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 33, -1, -1, -1, -1,
+ -1, -1, 40, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 59, -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, -1, 93, -1, -1, 96, -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, 125, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 257, 258, 259, 260, -1, -1, 263, -1, 265,
+ 266, 267, 268, 269, 270, 271, 272, -1, -1, -1,
+ -1, -1, -1, -1, -1, 281, 282, 283, 284, 285,
+ 286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
+ 296, 297, 298, 299, -1, -1, -1, -1, 304, 305,
+ 306, 307, 308, 309, 310, 311, 312, 313, 314, 315,
+ 316, -1, -1, -1, -1, -1, 322, 323, 324, 325,
+ 326, 327, 328, 329, 330, 331, 332, -1, -1, 335,
+ 336, 337, 338, -1, -1, 341, 342, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 353, 354, 355,
+ 356, 357, -1, -1, -1, 361, 362, 363, 364, 257,
+ 258, 259, 260, -1, -1, 263, -1, 265, 266, 267,
+ 268, 269, 270, 271, 272, -1, -1, -1, -1, -1,
+ -1, -1, -1, 281, 282, 283, 284, 285, 286, 287,
+ 288, 289, 290, 291, 292, 293, 294, 295, 296, 297,
+ 298, 299, 0, -1, -1, -1, -1, 305, 306, 307,
+ 308, 309, 310, 311, 312, 313, 314, 315, 316, -1,
+ -1, -1, -1, -1, 322, 323, 324, 325, 326, 327,
+ 328, 329, 330, 331, 332, 33, -1, 335, 336, 337,
+ 338, -1, 40, 341, 342, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 353, 354, 355, 356, 357,
+ -1, 59, -1, 361, 362, 363, 364, -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, 93, -1, -1, 96, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 125, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 33, -1, -1, -1, -1, -1, -1,
+ 40, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 59,
+ -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, -1, 93, -1, -1, 96, -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, 125, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 257,
+ 258, 259, 260, -1, -1, 263, -1, 265, 266, 267,
+ 268, 269, 270, 271, 272, -1, -1, -1, -1, -1,
+ -1, -1, -1, 281, 282, 283, 284, 285, 286, 287,
+ 288, 289, 290, 291, 292, 293, 294, 295, 296, 297,
+ 298, 299, -1, -1, -1, -1, -1, 305, 306, 307,
+ 308, 309, 310, 311, 312, 313, 314, 315, 316, -1,
+ -1, -1, -1, -1, 322, 323, 324, 325, 326, 327,
+ 328, 329, 330, 331, 332, -1, -1, 335, 336, 337,
+ 338, -1, -1, 341, 342, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 353, 354, 355, 356, 357,
+ -1, -1, -1, 361, 362, 363, 364, 257, 258, 259,
+ 260, -1, -1, 263, -1, 265, 266, 267, 268, 269,
+ 270, 271, 272, -1, -1, -1, -1, -1, -1, -1,
+ -1, 281, 282, 283, 284, 285, 286, 287, 288, 289,
+ 290, 291, 292, 293, 294, 295, 296, 297, 298, 299,
+ 0, -1, -1, -1, -1, 305, 306, 307, 308, 309,
+ 310, 311, 312, 313, 314, 315, 316, -1, -1, -1,
+ -1, -1, 322, 323, 324, 325, 326, 327, 328, 329,
+ 330, 331, 332, 33, -1, 335, 336, 337, 338, -1,
+ 40, 341, 342, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 353, 354, 355, 356, 357, -1, 59,
+ -1, 361, 362, 363, 364, -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, 93, -1, -1, 96, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 0, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 125, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 33, -1, -1, -1, -1, -1, -1, 40, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 59, -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,
+ -1, 93, -1, -1, 96, -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, 125, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 257, 258, 259,
+ 260, -1, -1, 263, -1, 265, 266, 267, 268, 269,
+ 270, 271, 272, -1, -1, -1, -1, -1, -1, -1,
+ -1, 281, 282, 283, 284, 285, 286, 287, 288, 289,
+ 290, 291, 292, 293, 294, 295, 296, 297, 298, 299,
+ -1, -1, -1, -1, -1, 305, 306, 307, 308, 309,
+ 310, 311, 312, 313, 314, 315, 316, -1, -1, -1,
+ -1, -1, 322, 323, 324, 325, 326, 327, 328, 329,
+ 330, 331, 332, -1, -1, 335, 336, 337, 338, -1,
+ -1, 341, 342, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 353, 354, 355, 356, 357, -1, -1,
+ -1, 361, 362, 363, 364, 257, 258, 259, 260, -1,
+ -1, 263, -1, 265, 266, 267, 268, 269, 270, 271,
+ 272, -1, -1, -1, -1, -1, -1, -1, -1, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
+ 292, 293, 294, 295, 296, 297, 298, 299, 0, -1,
+ -1, -1, -1, 305, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, -1, -1, -1, -1, -1,
+ 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, 33, -1, 335, 336, 337, 338, -1, 40, 341,
+ 342, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 353, 354, 355, 356, 357, -1, 59, -1, 361,
+ 362, 363, 364, -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, 93, -1, -1, 96, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 0, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 125, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 33,
+ -1, -1, -1, -1, -1, -1, 40, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 59, -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, -1, 93,
+ -1, -1, 96, -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, 125, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 257, 258, 259, 260, -1,
+ -1, 263, -1, 265, 266, 267, 268, 269, 270, 271,
+ 272, -1, -1, -1, -1, -1, -1, -1, -1, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
+ 292, 293, 294, 295, 296, 297, 298, 299, -1, -1,
+ -1, -1, -1, 305, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, -1, -1, -1, -1, -1,
+ 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, -1, -1, 335, 336, 337, 338, -1, -1, 341,
+ 342, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 353, 354, 355, 356, 357, -1, -1, -1, 361,
+ 362, 363, 364, 257, 258, 259, 260, -1, -1, 263,
+ -1, 265, 266, 267, 268, 269, 270, 271, 272, -1,
+ -1, -1, -1, -1, -1, -1, -1, 281, 282, 283,
+ 284, 285, 286, 287, 288, 289, 290, 291, 292, 293,
+ 294, 295, 296, 297, 298, 299, 0, -1, -1, -1,
+ -1, 305, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, -1, -1, -1, -1, -1, 322, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, 33,
+ -1, 335, 336, 337, 338, -1, 40, 341, 342, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 353,
+ 354, 355, 356, 357, -1, 59, -1, 361, 362, 363,
+ 364, -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, 93,
+ -1, -1, 96, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 0, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 125, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 33, -1, -1,
+ -1, -1, -1, -1, 40, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 59, -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, -1, 93, -1, -1,
+ 96, -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, 125,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 257, 258, 259, 260, -1, -1, 263,
+ -1, 265, 266, 267, 268, 269, 270, 271, 272, -1,
+ -1, -1, -1, -1, -1, -1, -1, 281, 282, 283,
+ 284, 285, 286, 287, 288, 289, 290, 291, 292, 293,
+ 294, 295, 296, 297, 298, 299, -1, -1, -1, -1,
+ -1, 305, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, -1, -1, -1, -1, -1, 322, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, -1,
+ -1, 335, 336, 337, 338, -1, -1, 341, 342, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 353,
+ 354, 355, 356, 357, -1, -1, -1, 361, 362, 363,
+ 364, 257, 258, 259, 260, -1, -1, 263, -1, 265,
+ 266, 267, 268, 269, 270, 271, 272, -1, -1, -1,
+ -1, -1, -1, -1, -1, 281, 282, 283, 284, 285,
+ 286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
+ 296, 297, 298, 299, 0, -1, -1, -1, -1, 305,
+ 306, 307, 308, 309, 310, 311, 312, 313, 314, 315,
+ 316, -1, -1, -1, -1, -1, 322, 323, 324, 325,
+ 326, 327, 328, 329, 330, 331, 332, 33, -1, 335,
+ 336, 337, 338, -1, 40, 341, 342, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 353, 354, 355,
+ 356, 357, -1, 59, -1, 361, 362, 363, 364, -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, 93, -1, -1,
+ 96, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 0, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 125,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 33, -1, -1, -1, -1,
+ -1, -1, 40, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 59, -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, -1, 93, -1, -1, 96, -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, 125, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 257, 258, 259, 260, -1, -1, 263, -1, 265,
+ 266, 267, 268, 269, 270, 271, 272, -1, -1, -1,
+ -1, -1, -1, -1, -1, 281, 282, 283, 284, 285,
+ 286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
+ 296, 297, 298, 299, -1, -1, -1, -1, -1, 305,
+ 306, 307, 308, 309, 310, 311, 312, 313, 314, 315,
+ 316, -1, -1, -1, -1, -1, 322, 323, 324, 325,
+ 326, 327, 328, 329, 330, 331, 332, -1, -1, 335,
+ 336, 337, 338, -1, -1, 341, 342, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 353, 354, 355,
+ 356, 357, -1, -1, -1, 361, 362, 363, 364, 257,
+ 258, 259, 260, -1, -1, 263, -1, 265, 266, 267,
+ 268, 269, 270, 271, 272, -1, -1, -1, -1, -1,
+ -1, -1, -1, 281, 282, 283, 284, 285, 286, 287,
+ 288, 289, 290, 291, 292, 293, 294, 295, 296, 297,
+ 298, 299, 0, -1, -1, -1, -1, 305, 306, 307,
+ 308, 309, 310, 311, 312, 313, 314, 315, 316, -1,
+ -1, -1, -1, -1, 322, 323, 324, 325, 326, 327,
+ 328, 329, 330, 331, 332, 33, -1, 335, 336, 337,
+ 338, -1, 40, 341, 342, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 353, 354, 355, 356, 357,
+ -1, 59, -1, 361, 362, 363, 364, -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, 93, -1, -1, 96, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 125, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 33, -1, -1, -1, -1, -1, -1,
+ 40, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 59,
+ -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, -1, 93, -1, -1, 96, -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, 125, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 257,
+ 258, 259, 260, -1, -1, 263, -1, 265, 266, 267,
+ 268, 269, 270, 271, 272, -1, -1, -1, -1, -1,
+ -1, -1, -1, 281, 282, 283, 284, 285, 286, 287,
+ 288, 289, 290, 291, 292, 293, 294, 295, 296, 297,
+ 298, 299, -1, -1, -1, -1, -1, 305, 306, 307,
+ 308, 309, 310, 311, 312, 313, 314, 315, 316, -1,
+ -1, -1, -1, -1, 322, 323, 324, 325, 326, 327,
+ 328, 329, 330, 331, 332, -1, -1, 335, 336, 337,
+ 338, -1, -1, 341, 342, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 353, 354, 355, 356, 357,
+ -1, -1, -1, 361, 362, 363, 364, 257, 258, 259,
+ 260, -1, -1, 263, -1, 265, 266, 267, 268, 269,
+ 270, 271, 272, -1, -1, -1, -1, -1, -1, -1,
+ -1, 281, 282, 283, 284, 285, 286, 287, 288, 289,
+ 290, 291, 292, 293, 294, 295, 296, 297, 298, 299,
+ 0, -1, -1, -1, -1, 305, 306, 307, 308, 309,
+ 310, 311, 312, 313, 314, 315, 316, -1, -1, -1,
+ -1, -1, 322, 323, 324, 325, 326, 327, 328, 329,
+ 330, 331, 332, 33, -1, 335, 336, 337, 338, -1,
+ 40, 341, 342, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 353, 354, 355, 356, 357, -1, 59,
+ -1, 361, 362, 363, 364, -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, 93, -1, -1, 96, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 0, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 125, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 33, -1, -1, -1, -1, -1, -1, 40, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 59, -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,
+ -1, 93, -1, -1, 96, -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, 125, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 257, 258, 259,
+ 260, -1, -1, 263, -1, 265, 266, 267, 268, 269,
+ 270, 271, 272, -1, -1, -1, -1, -1, -1, -1,
+ -1, 281, 282, 283, 284, 285, 286, 287, 288, 289,
+ 290, 291, 292, 293, 294, 295, 296, 297, 298, 299,
+ -1, -1, -1, -1, -1, 305, 306, 307, 308, 309,
+ 310, 311, 312, 313, 314, 315, 316, -1, -1, -1,
+ -1, -1, 322, 323, 324, 325, 326, 327, 328, 329,
+ 330, 331, 332, -1, -1, 335, 336, 337, 338, -1,
+ -1, 341, 342, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 353, 354, 355, 356, 357, -1, -1,
+ -1, 361, 362, 363, 364, 257, 258, 259, 260, -1,
+ -1, 263, -1, 265, 266, 267, 268, 269, 270, 271,
+ 272, -1, -1, -1, -1, -1, -1, -1, -1, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
+ 292, 293, 294, 295, 296, 297, 298, 299, 0, -1,
+ -1, -1, -1, 305, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, -1, -1, -1, -1, -1,
+ 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, 33, -1, 335, 336, 337, 338, -1, 40, 341,
+ 342, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 353, 354, 355, 356, 357, -1, 59, -1, 361,
+ 362, 363, 364, -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, 93, -1, -1, 96, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 0, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 125, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 33,
+ -1, -1, -1, -1, -1, -1, 40, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 59, -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, -1, 93,
+ -1, -1, 96, -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, 125, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 257, 258, 259, 260, -1,
+ -1, 263, -1, 265, 266, 267, 268, 269, 270, 271,
+ 272, -1, -1, -1, -1, -1, -1, -1, -1, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
+ 292, 293, 294, 295, 296, 297, 298, 299, -1, -1,
+ -1, -1, -1, 305, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, -1, -1, -1, -1, -1,
+ 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, -1, -1, 335, 336, 337, 338, -1, -1, 341,
+ 342, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 353, 354, 355, 356, 357, -1, -1, -1, 361,
+ 362, 363, 364, 257, 258, 259, 260, -1, -1, 263,
+ -1, 265, 266, 267, 268, 269, 270, 271, 272, -1,
+ -1, -1, -1, -1, -1, -1, -1, 281, 282, 283,
+ 284, 285, 286, 287, 288, 289, 290, 291, 292, 293,
+ 294, 295, 296, 297, 298, 299, -1, -1, -1, -1,
+ -1, 305, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, -1, -1, -1, -1, -1, 322, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, 0,
+ -1, 335, 336, 337, 338, -1, -1, 341, 342, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 353,
+ 354, 355, 356, 357, -1, -1, -1, 361, 362, 363,
+ 364, -1, 33, -1, -1, -1, -1, -1, -1, 40,
+ 41, -1, 43, 44, 45, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 59, -1,
+ -1, 62, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 0, -1, -1, -1, -1,
+ -1, -1, 93, -1, -1, 96, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 33, -1,
+ -1, -1, -1, -1, 125, 40, 41, -1, 0, 44,
+ 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 59, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 33, -1, -1, -1, -1, -1, -1, 40, 41,
+ -1, -1, 44, -1, -1, -1, -1, -1, 93, -1,
+ -1, 96, -1, -1, -1, -1, -1, 59, 60, -1,
+ 62, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 125, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 93, -1, -1, 96, -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, 125, -1, -1, 257, 258, 259, 260,
+ -1, -1, 263, -1, 265, 266, 267, 268, 269, 270,
+ 271, 272, -1, -1, -1, -1, -1, -1, -1, -1,
+ 281, 282, 283, 284, 285, 286, 287, 288, 289, 290,
+ 291, 292, 293, 294, 295, 296, 297, 298, 299, 0,
+ -1, -1, -1, 304, 305, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 317, 318, 319, 320,
+ 321, 322, 323, 324, 325, 326, 327, 328, 329, 330,
+ 331, 332, 33, -1, -1, -1, -1, -1, -1, 40,
+ 341, 342, 257, 258, 259, 260, -1, -1, 263, -1,
+ 265, 266, 267, 268, 269, 270, -1, -1, 59, -1,
+ 361, 362, 363, 364, -1, -1, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 257, 258, 259, 260, -1,
+ 305, 263, 93, -1, -1, 96, 268, -1, -1, 271,
+ 272, -1, -1, -1, -1, -1, -1, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, -1, -1,
+ -1, -1, -1, -1, 125, -1, 341, 342, 0, -1,
+ -1, -1, -1, 305, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, -1, 361, 362, 363, 364,
+ 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, 33, -1, 335, 336, 337, 338, -1, 40, -1,
+ -1, -1, -1, -1, -1, 347, 348, 349, 350, 351,
+ 352, 353, 354, 355, 356, 357, -1, 59, -1, -1,
+ -1, -1, 364, -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, 93, -1, -1, 96, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 125, -1, -1, 257, 258, 259, 260,
+ -1, -1, 263, -1, -1, -1, -1, 268, -1, -1,
+ 271, 272, -1, -1, -1, -1, -1, -1, -1, -1,
+ 0, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 59, -1,
+ -1, -1, -1, -1, 305, 306, 307, 308, 309, 310,
+ 311, 312, 313, 314, 315, 316, -1, -1, -1, -1,
+ -1, 322, 323, 324, 325, 326, 327, 328, 329, 330,
+ 331, 332, 93, -1, 335, 336, 337, 338, -1, 59,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 353, 354, 355, 356, 357, -1, -1, -1,
+ -1, -1, -1, 364, 125, -1, -1, -1, 0, -1,
+ -1, -1, -1, 93, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 257, 258, 259, 260, -1,
+ -1, 263, -1, -1, -1, -1, 268, -1, -1, 271,
+ 272, -1, -1, -1, -1, 125, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 59, -1, -1,
+ -1, -1, -1, 305, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, -1, -1, -1, -1, -1,
+ 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, 93, -1, 335, 336, 337, 338, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 353, 354, 355, 356, 357, -1, -1, -1, 0,
+ -1, -1, 364, 125, -1, -1, -1, -1, -1, 260,
+ -1, -1, -1, -1, 265, 266, 267, -1, 269, 270,
+ 271, 272, -1, -1, -1, -1, -1, -1, -1, -1,
+ 281, 282, 283, 284, 285, 286, 287, 288, 289, 290,
+ 291, 292, 293, 294, 295, 296, 297, 298, 299, 300,
+ 260, -1, -1, -1, -1, 265, 266, 267, 59, 269,
+ 270, 271, 272, -1, -1, -1, -1, -1, -1, -1,
+ -1, 281, 282, 283, 284, 285, 286, 287, 288, 289,
+ 290, 291, 292, 293, 294, 295, 296, 297, 298, 299,
+ 341, 342, 93, -1, -1, -1, -1, -1, -1, 0,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 361, 362, 363, 364, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 125, -1, -1, -1, -1, -1,
+ -1, 341, 342, -1, -1, -1, -1, -1, 260, -1,
+ -1, -1, -1, 265, 266, 267, -1, 269, 270, 271,
+ 272, 361, 362, 363, 364, -1, -1, -1, 59, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
+ 292, 293, 294, 295, 296, 297, 298, 299, 300, -1,
+ -1, -1, -1, -1, 0, -1, 0, -1, -1, -1,
+ -1, -1, 93, -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, 341,
+ 342, -1, -1, -1, 125, -1, -1, -1, -1, 43,
+ -1, 45, 46, -1, -1, -1, -1, -1, -1, 361,
+ 362, 363, 364, 59, -1, 59, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 260,
+ -1, -1, -1, -1, 265, 266, 267, -1, 269, 270,
+ 271, 272, -1, -1, -1, -1, -1, 93, -1, 93,
+ 281, 282, 283, 284, 285, 286, 287, 288, 289, 290,
+ 291, 292, 293, 294, 295, 296, 297, 298, 299, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 0, 125,
+ -1, 125, -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,
+ 341, 342, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 260,
+ 361, 362, 363, 364, 265, 266, 267, 59, 269, 270,
+ 271, 272, -1, -1, -1, -1, -1, -1, -1, -1,
+ 281, 282, 283, 284, 285, 286, 287, 288, 289, 290,
+ 291, 292, 293, 294, 295, 296, 297, 298, 299, -1,
+ -1, 93, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 0, -1, -1, -1, -1,
+ -1, -1, -1, 125, -1, -1, -1, -1, -1, -1,
+ 341, 342, -1, -1, 260, -1, -1, -1, -1, 265,
+ 266, 267, -1, 269, 270, 271, 272, 271, 272, -1,
+ 361, 362, 363, 364, -1, 281, 282, 283, 284, 285,
+ 286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
+ 296, 297, 298, 299, 59, -1, -1, -1, -1, -1,
+ -1, -1, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, 317, 318, 319, 320, 321, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 93, -1,
+ -1, 335, 336, 337, 338, 341, 342, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 353,
+ 354, 355, 356, 357, -1, 361, 362, 363, 364, -1,
+ 125, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 260, -1,
+ -1, -1, -1, 265, 266, 267, -1, 269, 270, 271,
+ 272, -1, -1, -1, -1, -1, -1, -1, -1, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
+ 292, 293, 294, 295, 296, 297, 298, 299, 0, -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, 33, -1, -1, -1, -1, -1, -1, 40, 341,
+ 342, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 59, -1, 361,
+ 362, 363, 364, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 260, -1, -1, -1, -1,
+ 265, 266, 267, -1, 269, 270, 271, 272, -1, -1,
+ -1, 93, -1, -1, 96, -1, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, -1, -1, -1, -1, -1,
+ -1, -1, -1, 125, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 33, -1,
+ -1, -1, -1, -1, -1, 40, -1, -1, -1, -1,
+ 45, -1, -1, -1, -1, -1, 341, 342, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 361, 362, 363, 364,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 91, -1, -1, -1,
+ -1, 96, -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, 123, -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, 257, 258, 259, -1, -1,
+ -1, 263, -1, 265, 266, 267, 268, 269, 270, 271,
+ 272, -1, -1, -1, -1, -1, -1, -1, -1, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
+ 292, 293, 294, 295, 296, 297, 298, 299, -1, -1,
+ -1, -1, -1, 305, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, -1, -1, -1, -1, -1,
+ 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, -1, -1, 335, 336, 337, 338, -1, -1, 341,
+ 342, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 353, 354, 355, 356, 357, -1, -1, -1, 361,
+ 362, 363, 257, 258, 259, 260, 261, -1, 263, -1,
+ -1, -1, -1, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, -1, -1, 33, -1,
+ -1, -1, -1, -1, -1, 40, -1, -1, -1, -1,
+ 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, -1, -1, -1, -1, -1, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, -1,
+ 335, 336, 337, 338, 339, 340, 91, -1, 343, -1,
+ 345, 96, -1, -1, -1, -1, -1, -1, 353, 354,
+ 355, 356, 357, 358, -1, 360, -1, -1, -1, 364,
+ 365, -1, -1, -1, -1, -1, -1, -1, 123, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 33, -1, -1,
+ -1, -1, -1, -1, 40, -1, -1, -1, -1, 45,
+ -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, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 96, -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, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 257, 258, 259, 260, 261, -1, 263, -1,
+ -1, -1, -1, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 33, -1, -1, -1,
+ -1, -1, -1, 40, 41, -1, -1, -1, 45, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, -1, -1, -1, -1, -1, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, -1,
+ 335, 336, 337, 338, 339, 340, -1, -1, 343, 96,
+ 345, -1, -1, -1, -1, -1, -1, -1, 353, 354,
+ 355, 356, 357, 358, -1, 360, -1, -1, -1, 364,
+ 365, 257, 258, 259, 260, -1, -1, 263, -1, 265,
+ 266, 267, 268, 269, 270, 271, 272, -1, -1, -1,
+ -1, -1, -1, -1, -1, 281, 282, 283, 284, 285,
+ 286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
+ 296, 297, 298, 299, -1, -1, -1, -1, -1, 305,
+ 306, 307, 308, 309, 310, 311, 312, 313, 314, 315,
+ 316, -1, -1, -1, -1, -1, 322, 323, 324, 325,
+ 326, 327, 328, 329, 330, 331, 332, -1, -1, 335,
+ 336, 337, 338, -1, 33, 341, 342, -1, -1, -1,
+ -1, 40, -1, -1, -1, -1, 45, 353, 354, 355,
+ 356, 357, -1, -1, -1, 361, 362, 363, 364, -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,
+ 257, 258, 259, 260, -1, -1, 263, 96, -1, -1,
+ -1, 268, -1, -1, 271, 272, -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, 305, 306,
+ 307, 308, 309, 310, 311, 312, 313, 314, 315, 316,
+ -1, -1, -1, -1, -1, 322, 323, 324, 325, 326,
+ 327, 328, 329, 330, 331, 332, 33, -1, 335, 336,
+ 337, 338, -1, 40, -1, -1, -1, -1, 45, -1,
+ -1, -1, -1, -1, -1, -1, 353, 354, 355, 356,
+ 357, -1, -1, -1, -1, -1, -1, 364, -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, 96,
+ -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, 257, 258,
+ 259, 260, -1, -1, 263, -1, -1, -1, -1, 268,
+ -1, -1, 271, 272, -1, -1, -1, 33, -1, -1,
+ -1, -1, -1, -1, 40, -1, -1, -1, -1, 45,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 305, 306, 307, 308,
+ 309, 310, 311, 312, 313, 314, 315, 316, -1, -1,
+ -1, -1, -1, 322, 323, 324, 325, 326, 327, 328,
+ 329, 330, 331, 332, -1, -1, 335, 336, 337, 338,
+ 96, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 353, 354, 355, 356, 357, -1,
+ -1, -1, -1, -1, -1, 364, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 33, -1, -1,
+ 257, 258, 259, 260, 40, -1, 263, -1, -1, 45,
+ -1, 268, -1, -1, 271, 272, -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, 305, 306,
+ 307, 308, 309, 310, 311, 312, 313, 314, 315, 316,
+ 96, -1, -1, -1, -1, 322, 323, 324, 325, 326,
+ 327, 328, 329, 330, 331, 332, -1, -1, 335, 336,
+ 337, 338, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 353, 354, 355, 356,
+ 357, -1, -1, -1, -1, -1, -1, 364, -1, 33,
+ -1, 257, 258, 259, 260, -1, 40, 263, 42, -1,
+ -1, 45, 268, -1, -1, 271, 272, -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, 305,
+ 306, 307, 308, 309, 310, 311, 312, 313, 314, 315,
+ 316, -1, 96, -1, -1, -1, 322, 323, 324, 325,
+ 326, 327, 328, 329, 330, 331, 332, -1, -1, 335,
+ 336, 337, 338, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 353, 354, 355,
+ 356, 357, -1, -1, -1, -1, -1, -1, 364, 33,
+ -1, 257, 258, 259, 260, -1, 40, 263, -1, -1,
+ -1, 45, 268, -1, -1, 271, 272, -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, 305,
+ 306, 307, 308, 309, 310, 311, 312, 313, 314, 315,
+ 316, -1, 96, -1, -1, -1, 322, 323, 324, 325,
+ 326, 327, 328, 329, 330, 331, 332, -1, -1, 335,
+ 336, 337, 338, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 353, 354, 355,
+ 356, 357, -1, -1, -1, -1, -1, -1, 364, -1,
+ 33, -1, -1, 257, 258, 259, -1, 40, -1, 263,
+ -1, -1, 45, -1, 268, -1, -1, 271, 272, -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, 305, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, 96, -1, -1, -1, -1, 322, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, -1,
+ -1, 335, 336, 337, 338, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 353,
+ 354, 355, 356, 357, -1, -1, -1, -1, -1, -1,
+ 33, -1, -1, 257, 258, 259, -1, 40, -1, 263,
+ -1, -1, 45, -1, 268, -1, -1, 271, 272, -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, 305, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, 96, -1, -1, -1, -1, 322, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, -1,
+ -1, 335, 336, 337, 338, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 353,
+ 354, 355, 356, 357, -1, -1, -1, -1, -1, -1,
+ -1, 33, -1, -1, 257, 258, 259, -1, 40, -1,
+ 263, -1, -1, 45, -1, 268, -1, -1, 271, 272,
+ -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, 305, 306, 307, 308, 309, 310, 311, 312,
+ 313, 314, 315, 316, 96, -1, -1, -1, -1, 322,
+ 323, 324, 325, 326, 327, 328, 329, 330, 331, 332,
+ -1, -1, 335, 336, 337, 338, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 353, 354, 355, 356, 357, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 257, 258, 259, -1, -1, -1,
+ 263, -1, -1, -1, -1, 268, -1, -1, 271, 272,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 59, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 305, 306, 307, 308, 309, 310, 311, 312,
+ 313, 314, 315, 316, 91, -1, -1, -1, -1, 322,
+ 323, 324, 325, 326, 327, 328, 329, 330, 331, 332,
+ -1, -1, 335, 336, 337, 338, -1, -1, -1, -1,
+ -1, -1, 91, -1, -1, -1, 123, -1, -1, -1,
+ 353, 354, 355, 356, 357, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 257, 258, 259, -1, -1,
+ -1, 263, -1, -1, 123, -1, 268, -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, -1,
+ -1, -1, -1, 305, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, -1, -1, -1, -1, -1,
+ 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, -1, -1, 335, 336, 337, 338, -1, -1, -1,
+ -1, -1, -1, 91, -1, -1, -1, -1, -1, -1,
+ -1, 353, 354, 355, 356, 357, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 257, 258, -1, 260, 261, 123, -1, -1, -1, -1,
+ -1, -1, 269, 270, 271, 272, 273, 274, 275, 276,
+ 277, 278, 279, 280, -1, -1, -1, -1, 257, 258,
+ -1, 260, 261, -1, -1, -1, -1, -1, -1, -1,
+ 269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
+ 279, 280, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 333, -1, -1, -1,
+ -1, -1, 339, 340, -1, -1, 343, -1, 345, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 358, -1, 360, 333, -1, -1, 364, 365, -1,
+ 339, 340, -1, -1, 343, -1, 345, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 358,
+ -1, 360, -1, -1, -1, 364, 365, -1, -1, 257,
+ 258, -1, 260, 261, -1, -1, -1, -1, -1, -1,
+ -1, 269, 270, 271, 272, 273, 274, 275, 276, 277,
+ 278, 279, 280, -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, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 333, -1, -1, -1, -1,
+ -1, 339, 340, -1, -1, 343, -1, 345, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 358, -1, 360, -1, -1, -1, 364, 365,
+};
+#define YYFINAL 2
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#define YYMAXTOKEN 367
+#if YYDEBUG
+char *yyname[] = {
+"end-of-file",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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"LABEL","VARIABLE","NUMBER",
+"TEXT","COMMAND_LINE","DELIMITED","ORDINAL","TH","LEFT_ARROW_HEAD",
+"RIGHT_ARROW_HEAD","DOUBLE_ARROW_HEAD","LAST","UP","DOWN","LEFT","RIGHT","BOX",
+"CIRCLE","ELLIPSE","ARC","LINE","ARROW","MOVE","SPLINE","HEIGHT","RADIUS",
+"WIDTH","DIAMETER","FROM","TO","AT","WITH","BY","THEN","DOTTED","DASHED","CHOP",
+"SAME","INVISIBLE","LJUST","RJUST","ABOVE","BELOW","OF","THE","WAY","BETWEEN",
+"AND","HERE","DOT_N","DOT_E","DOT_W","DOT_S","DOT_NE","DOT_SE","DOT_NW",
+"DOT_SW","DOT_C","DOT_START","DOT_END","DOT_X","DOT_Y","DOT_HT","DOT_WID",
+"DOT_RAD","SIN","COS","ATAN2","LOG","EXP","SQRT","K_MAX","K_MIN","INT","RAND",
+"SRAND","COPY","THRU","TOP","BOTTOM","UPPER","LOWER","SH","PRINT","CW","CCW",
+"FOR","DO","IF","ELSE","ANDAND","OROR","NOTEQUAL","EQUALEQUAL","LESSEQUAL",
+"GREATEREQUAL","LEFT_CORNER","RIGHT_CORNER","CENTER","END","START","RESET",
+"UNTIL","PLOT","THICKNESS","FILL","ALIGNED","SPRINTF","COMMAND","DEFINE",
+"UNDEF",
+};
+char *yyrule[] = {
+"$accept : top",
+"top : optional_separator",
+"top : element_list",
+"element_list : optional_separator middle_element_list optional_separator",
+"middle_element_list : element",
+"middle_element_list : middle_element_list separator element",
+"optional_separator :",
+"optional_separator : separator",
+"separator : ';'",
+"separator : separator ';'",
+"placeless_element : VARIABLE '=' any_expr",
+"placeless_element : VARIABLE ':' '=' any_expr",
+"placeless_element : UP",
+"placeless_element : DOWN",
+"placeless_element : LEFT",
+"placeless_element : RIGHT",
+"placeless_element : COMMAND_LINE",
+"placeless_element : COMMAND print_args",
+"placeless_element : PRINT print_args",
+"$$1 :",
+"placeless_element : SH $$1 DELIMITED",
+"placeless_element : COPY TEXT",
+"$$2 :",
+"$$3 :",
+"placeless_element : COPY TEXT THRU $$2 DELIMITED $$3 until",
+"$$4 :",
+"$$5 :",
+"placeless_element : COPY THRU $$4 DELIMITED $$5 until",
+"$$6 :",
+"placeless_element : FOR VARIABLE '=' expr TO expr optional_by DO $$6 DELIMITED",
+"placeless_element : simple_if",
+"$$7 :",
+"placeless_element : simple_if ELSE $$7 DELIMITED",
+"placeless_element : reset_variables",
+"placeless_element : RESET",
+"reset_variables : RESET VARIABLE",
+"reset_variables : reset_variables VARIABLE",
+"reset_variables : reset_variables ',' VARIABLE",
+"print_args : print_arg",
+"print_args : print_args print_arg",
+"print_arg : expr",
+"print_arg : text",
+"print_arg : position",
+"$$8 :",
+"simple_if : IF any_expr THEN $$8 DELIMITED",
+"until :",
+"until : UNTIL TEXT",
+"any_expr : expr",
+"any_expr : text_expr",
+"text_expr : text EQUALEQUAL text",
+"text_expr : text NOTEQUAL text",
+"text_expr : text_expr ANDAND text_expr",
+"text_expr : text_expr ANDAND expr",
+"text_expr : expr ANDAND text_expr",
+"text_expr : text_expr OROR text_expr",
+"text_expr : text_expr OROR expr",
+"text_expr : expr OROR text_expr",
+"text_expr : '!' text_expr",
+"optional_by :",
+"optional_by : BY expr",
+"optional_by : BY '*' expr",
+"element : object_spec",
+"element : LABEL ':' optional_separator element",
+"element : LABEL ':' optional_separator position_not_place",
+"element : LABEL ':' optional_separator place",
+"$$9 :",
+"$$10 :",
+"element : '{' $$9 element_list '}' $$10 optional_element",
+"element : placeless_element",
+"optional_element :",
+"optional_element : element",
+"object_spec : BOX",
+"object_spec : CIRCLE",
+"object_spec : ELLIPSE",
+"object_spec : ARC",
+"object_spec : LINE",
+"object_spec : ARROW",
+"object_spec : MOVE",
+"object_spec : SPLINE",
+"object_spec : text",
+"object_spec : PLOT expr",
+"object_spec : PLOT expr text",
+"$$11 :",
+"object_spec : '[' $$11 element_list ']'",
+"object_spec : object_spec HEIGHT expr",
+"object_spec : object_spec RADIUS expr",
+"object_spec : object_spec WIDTH expr",
+"object_spec : object_spec DIAMETER expr",
+"object_spec : object_spec expr",
+"object_spec : object_spec UP",
+"object_spec : object_spec UP expr",
+"object_spec : object_spec DOWN",
+"object_spec : object_spec DOWN expr",
+"object_spec : object_spec RIGHT",
+"object_spec : object_spec RIGHT expr",
+"object_spec : object_spec LEFT",
+"object_spec : object_spec LEFT expr",
+"object_spec : object_spec FROM position",
+"object_spec : object_spec TO position",
+"object_spec : object_spec AT position",
+"object_spec : object_spec WITH path",
+"object_spec : object_spec BY expr_pair",
+"object_spec : object_spec THEN",
+"object_spec : object_spec DOTTED",
+"object_spec : object_spec DOTTED expr",
+"object_spec : object_spec DASHED",
+"object_spec : object_spec DASHED expr",
+"object_spec : object_spec FILL",
+"object_spec : object_spec FILL expr",
+"object_spec : object_spec CHOP",
+"object_spec : object_spec CHOP expr",
+"object_spec : object_spec SAME",
+"object_spec : object_spec INVISIBLE",
+"object_spec : object_spec LEFT_ARROW_HEAD",
+"object_spec : object_spec RIGHT_ARROW_HEAD",
+"object_spec : object_spec DOUBLE_ARROW_HEAD",
+"object_spec : object_spec CW",
+"object_spec : object_spec CCW",
+"object_spec : object_spec text",
+"object_spec : object_spec LJUST",
+"object_spec : object_spec RJUST",
+"object_spec : object_spec ABOVE",
+"object_spec : object_spec BELOW",
+"object_spec : object_spec THICKNESS expr",
+"object_spec : object_spec ALIGNED",
+"text : TEXT",
+"text : SPRINTF '(' TEXT sprintf_args ')'",
+"sprintf_args :",
+"sprintf_args : sprintf_args ',' expr",
+"position : position_not_place",
+"position : place",
+"position_not_place : expr_pair",
+"position_not_place : position '+' expr_pair",
+"position_not_place : position '-' expr_pair",
+"position_not_place : '(' position ',' position ')'",
+"position_not_place : expr between position AND position",
+"position_not_place : expr '<' position ',' position '>'",
+"between : BETWEEN",
+"between : OF THE WAY BETWEEN",
+"expr_pair : expr ',' expr",
+"expr_pair : '(' expr_pair ')'",
+"place : label",
+"place : label corner",
+"place : corner label",
+"place : corner OF label",
+"place : HERE",
+"label : LABEL",
+"label : nth_primitive",
+"label : label '.' LABEL",
+"ordinal : ORDINAL",
+"ordinal : '`' any_expr TH",
+"optional_ordinal_last : LAST",
+"optional_ordinal_last : ordinal LAST",
+"nth_primitive : ordinal object_type",
+"nth_primitive : optional_ordinal_last object_type",
+"object_type : BOX",
+"object_type : CIRCLE",
+"object_type : ELLIPSE",
+"object_type : ARC",
+"object_type : LINE",
+"object_type : ARROW",
+"object_type : SPLINE",
+"object_type : '[' ']'",
+"object_type : TEXT",
+"label_path : '.' LABEL",
+"label_path : label_path '.' LABEL",
+"relative_path : corner",
+"relative_path : label_path",
+"relative_path : label_path corner",
+"path : relative_path",
+"path : '(' relative_path ',' relative_path ')'",
+"path : ORDINAL LAST object_type relative_path",
+"path : LAST object_type relative_path",
+"path : ORDINAL object_type relative_path",
+"path : LABEL relative_path",
+"corner : DOT_N",
+"corner : DOT_E",
+"corner : DOT_W",
+"corner : DOT_S",
+"corner : DOT_NE",
+"corner : DOT_SE",
+"corner : DOT_NW",
+"corner : DOT_SW",
+"corner : DOT_C",
+"corner : DOT_START",
+"corner : DOT_END",
+"corner : TOP",
+"corner : BOTTOM",
+"corner : LEFT",
+"corner : RIGHT",
+"corner : UPPER LEFT",
+"corner : LOWER LEFT",
+"corner : UPPER RIGHT",
+"corner : LOWER RIGHT",
+"corner : LEFT_CORNER",
+"corner : RIGHT_CORNER",
+"corner : UPPER LEFT_CORNER",
+"corner : LOWER LEFT_CORNER",
+"corner : UPPER RIGHT_CORNER",
+"corner : LOWER RIGHT_CORNER",
+"corner : CENTER",
+"corner : START",
+"corner : END",
+"expr : VARIABLE",
+"expr : NUMBER",
+"expr : place DOT_X",
+"expr : place DOT_Y",
+"expr : place DOT_HT",
+"expr : place DOT_WID",
+"expr : place DOT_RAD",
+"expr : expr '+' expr",
+"expr : expr '-' expr",
+"expr : expr '*' expr",
+"expr : expr '/' expr",
+"expr : expr '%' expr",
+"expr : expr '^' expr",
+"expr : '-' expr",
+"expr : '(' any_expr ')'",
+"expr : SIN '(' any_expr ')'",
+"expr : COS '(' any_expr ')'",
+"expr : ATAN2 '(' any_expr ',' any_expr ')'",
+"expr : LOG '(' any_expr ')'",
+"expr : EXP '(' any_expr ')'",
+"expr : SQRT '(' any_expr ')'",
+"expr : K_MAX '(' any_expr ',' any_expr ')'",
+"expr : K_MIN '(' any_expr ',' any_expr ')'",
+"expr : INT '(' any_expr ')'",
+"expr : RAND '(' any_expr ')'",
+"expr : RAND '(' ')'",
+"expr : SRAND '(' any_expr ')'",
+"expr : expr '<' expr",
+"expr : expr LESSEQUAL expr",
+"expr : expr '>' expr",
+"expr : expr GREATEREQUAL expr",
+"expr : expr EQUALEQUAL expr",
+"expr : expr NOTEQUAL expr",
+"expr : expr ANDAND expr",
+"expr : expr OROR expr",
+"expr : '!' expr",
+};
+#endif
+#ifdef YYSTACKSIZE
+#undef YYMAXDEPTH
+#define YYMAXDEPTH YYSTACKSIZE
+#else
+#ifdef YYMAXDEPTH
+#define YYSTACKSIZE YYMAXDEPTH
+#else
+#define YYSTACKSIZE 500
+#define YYMAXDEPTH 500
+#endif
+#endif
+int yydebug;
+int yynerrs;
+int yyerrflag;
+int yychar;
+short *yyssp;
+YYSTYPE *yyvsp;
+YYSTYPE yyval;
+YYSTYPE yylval;
+short yyss[YYSTACKSIZE];
+YYSTYPE yyvs[YYSTACKSIZE];
+#define yystacksize YYSTACKSIZE
+#line 1537 "/home/cjk/groff/pic/pic.y"
+
+/* bison defines const to be empty unless __STDC__ is defined, which it
+isn't under cfront */
+
+#ifdef const
+#undef const
+#endif
+
+static struct {
+ const char *name;
+ double val;
+ int scaled; // non-zero if val should be multiplied by scale
+} defaults_table[] = {
+ { "arcrad", .25, 1 },
+ { "arrowht", .1, 1 },
+ { "arrowwid", .05, 1 },
+ { "circlerad", .25, 1 },
+ { "boxht", .5, 1 },
+ { "boxwid", .75, 1 },
+ { "boxrad", 0.0, 1 },
+ { "dashwid", .05, 1 },
+ { "ellipseht", .5, 1 },
+ { "ellipsewid", .75, 1 },
+ { "moveht", .5, 1 },
+ { "movewid", .5, 1 },
+ { "lineht", .5, 1 },
+ { "linewid", .5, 1 },
+ { "textht", 0.0, 1 },
+ { "textwid", 0.0, 1 },
+ { "scale", 1.0, 0 },
+ { "linethick", -1.0, 0 }, // in points
+ { "fillval", .5, 0 },
+ { "arrowhead", 1.0, 0 },
+ { "maxpswid", 8.5, 0 },
+ { "maxpsht", 11.0, 0 },
+};
+
+place *lookup_label(const char *label)
+{
+ saved_state *state = current_saved_state;
+ PTABLE(place) *tbl = current_table;
+ for (;;) {
+ place *pl = tbl->lookup(label);
+ if (pl)
+ return pl;
+ if (!state)
+ return 0;
+ tbl = state->tbl;
+ state = state->prev;
+ }
+}
+
+void define_label(const char *label, const place *pl)
+{
+ place *p = new place;
+ *p = *pl;
+ current_table->define(label, p);
+}
+
+int lookup_variable(const char *name, double *val)
+{
+ place *pl = lookup_label(name);
+ if (pl) {
+ *val = pl->x;
+ return 1;
+ }
+ return 0;
+}
+
+void define_variable(const char *name, double val)
+{
+ place *p = new place;
+ p->obj = 0;
+ p->x = val;
+ p->y = 0.0;
+ current_table->define(name, p);
+ if (strcmp(name, "scale") == 0) {
+ // When the scale changes, reset all scaled pre-defined variables to
+ // their default values.
+ for (int i = 0; i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++)
+ if (defaults_table[i].scaled)
+ define_variable(defaults_table[i].name, val*defaults_table[i].val);
+ }
+}
+
+// called once only (not once per parse)
+
+void parse_init()
+{
+ current_direction = RIGHT_DIRECTION;
+ current_position.x = 0.0;
+ current_position.y = 0.0;
+ // This resets everything to its default value.
+ reset_all();
+}
+
+void reset(const char *nm)
+{
+ for (int i = 0; i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++)
+ if (strcmp(nm, defaults_table[i].name) == 0) {
+ double val = defaults_table[i].val;
+ if (defaults_table[i].scaled) {
+ double scale;
+ lookup_variable("scale", &scale);
+ val *= scale;
+ }
+ define_variable(defaults_table[i].name, val);
+ return;
+ }
+ lex_error("`%1' is not a predefined variable", nm);
+}
+
+void reset_all()
+{
+ // We only have to explicitly reset the pre-defined variables that
+ // aren't scaled because `scale' is not scaled, and changing the
+ // value of `scale' will reset all the pre-defined variables that
+ // are scaled.
+ for (int i = 0; i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++)
+ if (!defaults_table[i].scaled)
+ define_variable(defaults_table[i].name, defaults_table[i].val);
+}
+
+// called after each parse
+
+void parse_cleanup()
+{
+ while (current_saved_state != 0) {
+ delete current_table;
+ current_table = current_saved_state->tbl;
+ saved_state *tem = current_saved_state;
+ current_saved_state = current_saved_state->prev;
+ delete tem;
+ }
+ assert(current_table == &top_table);
+ PTABLE_ITERATOR(place) iter(current_table);
+ const char *key;
+ place *pl;
+ while (iter.next(&key, &pl))
+ if (pl->obj != 0) {
+ position pos = pl->obj->origin();
+ pl->obj = 0;
+ pl->x = pos.x;
+ pl->y = pos.y;
+ }
+ while (olist.head != 0) {
+ object *tem = olist.head;
+ olist.head = olist.head->next;
+ delete tem;
+ }
+ olist.tail = 0;
+ current_direction = RIGHT_DIRECTION;
+ current_position.x = 0.0;
+ current_position.y = 0.0;
+}
+
+const char *ordinal_postfix(int n)
+{
+ if (n < 10 || n > 20)
+ switch (n % 10) {
+ case 1:
+ return "st";
+ case 2:
+ return "nd";
+ case 3:
+ return "rd";
+ }
+ return "th";
+}
+
+const char *object_type_name(object_type type)
+{
+ switch (type) {
+ case BOX_OBJECT:
+ return "box";
+ case CIRCLE_OBJECT:
+ return "circle";
+ case ELLIPSE_OBJECT:
+ return "ellipse";
+ case ARC_OBJECT:
+ return "arc";
+ case SPLINE_OBJECT:
+ return "spline";
+ case LINE_OBJECT:
+ return "line";
+ case ARROW_OBJECT:
+ return "arrow";
+ case MOVE_OBJECT:
+ return "move";
+ case TEXT_OBJECT:
+ return "\"\"";
+ case BLOCK_OBJECT:
+ return "[]";
+ case OTHER_OBJECT:
+ case MARK_OBJECT:
+ default:
+ break;
+ }
+ return "object";
+}
+
+static char sprintf_buf[1024];
+
+char *format_number(const char *form, double n)
+{
+ if (form == 0)
+ form = "%g";
+ else {
+ // this is a fairly feeble attempt at validation of the format
+ int nspecs = 0;
+ for (const char *p = form; *p != '\0'; p++)
+ if (*p == '%') {
+ if (p[1] == '%')
+ p++;
+ else
+ nspecs++;
+ }
+ if (nspecs > 1) {
+ lex_error("bad format `%1'", form);
+ return strsave(form);
+ }
+ }
+ sprintf(sprintf_buf, form, n);
+ return strsave(sprintf_buf);
+}
+
+char *do_sprintf(const char *form, const double *v, int nv)
+{
+ string result;
+ int i = 0;
+ string one_format;
+ while (*form) {
+ if (*form == '%') {
+ one_format += *form++;
+ for (; *form != '\0' && strchr("#-+ 0123456789.", *form) != 0; form++)
+ one_format += *form;
+ if (*form == '\0' || strchr("eEfgG%", *form) == 0) {
+ lex_error("bad sprintf format");
+ result += one_format;
+ result += form;
+ break;
+ }
+ if (*form == '%') {
+ one_format += *form++;
+ one_format += '\0';
+ sprintf(sprintf_buf, one_format.contents());
+ }
+ else {
+ if (i >= nv) {
+ lex_error("too few arguments to sprintf");
+ result += one_format;
+ result += form;
+ break;
+ }
+ one_format += *form++;
+ one_format += '\0';
+ sprintf(sprintf_buf, one_format.contents(), v[i++]);
+ }
+ one_format.clear();
+ result += sprintf_buf;
+ }
+ else
+ result += *form++;
+ }
+ result += '\0';
+ return strsave(result.contents());
+}
+#line 3419 "y.tab.c"
+#define YYABORT goto yyabort
+#define YYREJECT goto yyabort
+#define YYACCEPT goto yyaccept
+#define YYERROR goto yyerrlab
+int
+#if defined(__STDC__)
+yyparse(void)
+#else
+yyparse()
+#endif
+{
+ register int yym, yyn, yystate;
+#if YYDEBUG
+ register char *yys;
+ extern char *getenv();
+
+ if (yys = getenv("YYDEBUG"))
+ {
+ yyn = *yys;
+ if (yyn >= '0' && yyn <= '9')
+ yydebug = yyn - '0';
+ }
+#endif
+
+ yynerrs = 0;
+ yyerrflag = 0;
+ yychar = (-1);
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+ *yyssp = yystate = 0;
+
+yyloop:
+ if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
+ if (yychar < 0)
+ {
+ if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+ if (!yys) yys = "illegal-symbol";
+ printf("%sdebug: state %d, reading %d (%s)\n",
+ YYPREFIX, yystate, yychar, yys);
+ }
+#endif
+ }
+ if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: state %d, shifting to state %d\n",
+ YYPREFIX, yystate, yytable[yyn]);
+#endif
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ goto yyoverflow;
+ }
+ *++yyssp = yystate = yytable[yyn];
+ *++yyvsp = yylval;
+ yychar = (-1);
+ if (yyerrflag > 0) --yyerrflag;
+ goto yyloop;
+ }
+ if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+ {
+ yyn = yytable[yyn];
+ goto yyreduce;
+ }
+ if (yyerrflag) goto yyinrecovery;
+ yyerror("syntax error");
+#ifdef lint
+ goto yyerrlab;
+#endif
+yyerrlab:
+ ++yynerrs;
+yyinrecovery:
+ if (yyerrflag < 3)
+ {
+ yyerrflag = 3;
+ for (;;)
+ {
+ if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: state %d, error recovery shifting\
+ to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
+#endif
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ goto yyoverflow;
+ }
+ *++yyssp = yystate = yytable[yyn];
+ *++yyvsp = yylval;
+ goto yyloop;
+ }
+ else
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: error recovery discarding state %d\n",
+ YYPREFIX, *yyssp);
+#endif
+ if (yyssp <= yyss) goto yyabort;
+ --yyssp;
+ --yyvsp;
+ }
+ }
+ }
+ else
+ {
+ if (yychar == 0) goto yyabort;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+ if (!yys) yys = "illegal-symbol";
+ printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
+ YYPREFIX, yystate, yychar, yys);
+ }
+#endif
+ yychar = (-1);
+ goto yyloop;
+ }
+yyreduce:
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: state %d, reducing by rule %d (%s)\n",
+ YYPREFIX, yystate, yyn, yyrule[yyn]);
+#endif
+ yym = yylen[yyn];
+ yyval = yyvsp[1-yym];
+ switch (yyn)
+ {
+case 2:
+#line 278 "/home/cjk/groff/pic/pic.y"
+{
+ if (olist.head)
+ print_picture(olist.head);
+ }
+break;
+case 3:
+#line 287 "/home/cjk/groff/pic/pic.y"
+{ yyval.pl = yyvsp[-1].pl; }
+break;
+case 4:
+#line 292 "/home/cjk/groff/pic/pic.y"
+{ yyval.pl = yyvsp[0].pl; }
+break;
+case 5:
+#line 294 "/home/cjk/groff/pic/pic.y"
+{ yyval.pl = yyvsp[-2].pl; }
+break;
+case 10:
+#line 309 "/home/cjk/groff/pic/pic.y"
+{
+ define_variable(yyvsp[-2].str, yyvsp[0].x);
+ a_delete yyvsp[-2].str;
+ }
+break;
+case 11:
+#line 314 "/home/cjk/groff/pic/pic.y"
+{
+ place *p = lookup_label(yyvsp[-3].str);
+ if (!p) {
+ lex_error("variable `%1' not defined", yyvsp[-3].str);
+ YYABORT;
+ }
+ p->obj = 0;
+ p->x = yyvsp[0].x;
+ p->y = 0.0;
+ a_delete yyvsp[-3].str;
+ }
+break;
+case 12:
+#line 326 "/home/cjk/groff/pic/pic.y"
+{ current_direction = UP_DIRECTION; }
+break;
+case 13:
+#line 328 "/home/cjk/groff/pic/pic.y"
+{ current_direction = DOWN_DIRECTION; }
+break;
+case 14:
+#line 330 "/home/cjk/groff/pic/pic.y"
+{ current_direction = LEFT_DIRECTION; }
+break;
+case 15:
+#line 332 "/home/cjk/groff/pic/pic.y"
+{ current_direction = RIGHT_DIRECTION; }
+break;
+case 16:
+#line 334 "/home/cjk/groff/pic/pic.y"
+{
+ olist.append(make_command_object(yyvsp[0].lstr.str, yyvsp[0].lstr.filename,
+ yyvsp[0].lstr.lineno));
+ }
+break;
+case 17:
+#line 339 "/home/cjk/groff/pic/pic.y"
+{
+ olist.append(make_command_object(yyvsp[0].lstr.str, yyvsp[0].lstr.filename,
+ yyvsp[0].lstr.lineno));
+ }
+break;
+case 18:
+#line 344 "/home/cjk/groff/pic/pic.y"
+{
+ fprintf(stderr, "%s\n", yyvsp[0].lstr.str);
+ a_delete yyvsp[0].lstr.str;
+ fflush(stderr);
+ }
+break;
+case 19:
+#line 350 "/home/cjk/groff/pic/pic.y"
+{ delim_flag = 1; }
+break;
+case 20:
+#line 352 "/home/cjk/groff/pic/pic.y"
+{
+ delim_flag = 0;
+ if (safer_flag)
+ lex_error("unsafe to run command `%1'", yyvsp[0].str);
+ else
+ system(yyvsp[0].str);
+ a_delete yyvsp[0].str;
+ }
+break;
+case 21:
+#line 361 "/home/cjk/groff/pic/pic.y"
+{
+ if (yychar < 0)
+ do_lookahead();
+ do_copy(yyvsp[0].lstr.str);
+ /* do not delete the filename*/
+ }
+break;
+case 22:
+#line 368 "/home/cjk/groff/pic/pic.y"
+{ delim_flag = 2; }
+break;
+case 23:
+#line 370 "/home/cjk/groff/pic/pic.y"
+{ delim_flag = 0; }
+break;
+case 24:
+#line 372 "/home/cjk/groff/pic/pic.y"
+{
+ if (yychar < 0)
+ do_lookahead();
+ copy_file_thru(yyvsp[-5].lstr.str, yyvsp[-2].str, yyvsp[0].str);
+ /* do not delete the filename*/
+ a_delete yyvsp[-2].str;
+ a_delete yyvsp[0].str;
+ }
+break;
+case 25:
+#line 381 "/home/cjk/groff/pic/pic.y"
+{ delim_flag = 2; }
+break;
+case 26:
+#line 383 "/home/cjk/groff/pic/pic.y"
+{ delim_flag = 0; }
+break;
+case 27:
+#line 385 "/home/cjk/groff/pic/pic.y"
+{
+ if (yychar < 0)
+ do_lookahead();
+ copy_rest_thru(yyvsp[-2].str, yyvsp[0].str);
+ a_delete yyvsp[-2].str;
+ a_delete yyvsp[0].str;
+ }
+break;
+case 28:
+#line 393 "/home/cjk/groff/pic/pic.y"
+{ delim_flag = 1; }
+break;
+case 29:
+#line 395 "/home/cjk/groff/pic/pic.y"
+{
+ delim_flag = 0;
+ if (yychar < 0)
+ do_lookahead();
+ do_for(yyvsp[-8].str, yyvsp[-6].x, yyvsp[-4].x, yyvsp[-3].by.is_multiplicative, yyvsp[-3].by.val, yyvsp[0].str);
+ }
+break;
+case 30:
+#line 402 "/home/cjk/groff/pic/pic.y"
+{
+ if (yychar < 0)
+ do_lookahead();
+ if (yyvsp[0].if_data.x != 0.0)
+ push_body(yyvsp[0].if_data.body);
+ a_delete yyvsp[0].if_data.body;
+ }
+break;
+case 31:
+#line 410 "/home/cjk/groff/pic/pic.y"
+{ delim_flag = 1; }
+break;
+case 32:
+#line 412 "/home/cjk/groff/pic/pic.y"
+{
+ delim_flag = 0;
+ if (yychar < 0)
+ do_lookahead();
+ if (yyvsp[-3].if_data.x != 0.0)
+ push_body(yyvsp[-3].if_data.body);
+ else
+ push_body(yyvsp[0].str);
+ a_delete yyvsp[-3].if_data.body;
+ a_delete yyvsp[0].str;
+ }
+break;
+case 34:
+#line 425 "/home/cjk/groff/pic/pic.y"
+{ define_variable("scale", 1.0); }
+break;
+case 35:
+#line 430 "/home/cjk/groff/pic/pic.y"
+{ reset(yyvsp[0].str); a_delete yyvsp[0].str; }
+break;
+case 36:
+#line 432 "/home/cjk/groff/pic/pic.y"
+{ reset(yyvsp[0].str); a_delete yyvsp[0].str; }
+break;
+case 37:
+#line 434 "/home/cjk/groff/pic/pic.y"
+{ reset(yyvsp[0].str); a_delete yyvsp[0].str; }
+break;
+case 38:
+#line 439 "/home/cjk/groff/pic/pic.y"
+{ yyval.lstr = yyvsp[0].lstr; }
+break;
+case 39:
+#line 441 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.lstr.str = new char[strlen(yyvsp[-1].lstr.str) + strlen(yyvsp[0].lstr.str) + 1];
+ strcpy(yyval.lstr.str, yyvsp[-1].lstr.str);
+ strcat(yyval.lstr.str, yyvsp[0].lstr.str);
+ a_delete yyvsp[-1].lstr.str;
+ a_delete yyvsp[0].lstr.str;
+ if (yyvsp[-1].lstr.filename) {
+ yyval.lstr.filename = yyvsp[-1].lstr.filename;
+ yyval.lstr.lineno = yyvsp[-1].lstr.lineno;
+ }
+ else if (yyvsp[0].lstr.filename) {
+ yyval.lstr.filename = yyvsp[0].lstr.filename;
+ yyval.lstr.lineno = yyvsp[0].lstr.lineno;
+ }
+ }
+break;
+case 40:
+#line 460 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.lstr.str = new char[GDIGITS + 1];
+ sprintf(yyval.lstr.str, "%g", yyvsp[0].x);
+ yyval.lstr.filename = 0;
+ yyval.lstr.lineno = 0;
+ }
+break;
+case 41:
+#line 467 "/home/cjk/groff/pic/pic.y"
+{ yyval.lstr = yyvsp[0].lstr; }
+break;
+case 42:
+#line 469 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.lstr.str = new char[GDIGITS + 2 + GDIGITS + 1];
+ sprintf(yyval.lstr.str, "%g, %g", yyvsp[0].pair.x, yyvsp[0].pair.y);
+ yyval.lstr.filename = 0;
+ yyval.lstr.lineno = 0;
+ }
+break;
+case 43:
+#line 478 "/home/cjk/groff/pic/pic.y"
+{ delim_flag = 1; }
+break;
+case 44:
+#line 480 "/home/cjk/groff/pic/pic.y"
+{ delim_flag = 0; yyval.if_data.x = yyvsp[-3].x; yyval.if_data.body = yyvsp[0].str; }
+break;
+case 45:
+#line 485 "/home/cjk/groff/pic/pic.y"
+{ yyval.str = 0; }
+break;
+case 46:
+#line 487 "/home/cjk/groff/pic/pic.y"
+{ yyval.str = yyvsp[0].lstr.str; }
+break;
+case 47:
+#line 492 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = yyvsp[0].x; }
+break;
+case 48:
+#line 494 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = yyvsp[0].x; }
+break;
+case 49:
+#line 499 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.x = strcmp(yyvsp[-2].lstr.str, yyvsp[0].lstr.str) == 0;
+ a_delete yyvsp[-2].lstr.str;
+ a_delete yyvsp[0].lstr.str;
+ }
+break;
+case 50:
+#line 505 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.x = strcmp(yyvsp[-2].lstr.str, yyvsp[0].lstr.str) != 0;
+ a_delete yyvsp[-2].lstr.str;
+ a_delete yyvsp[0].lstr.str;
+ }
+break;
+case 51:
+#line 511 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x != 0.0 && yyvsp[0].x != 0.0); }
+break;
+case 52:
+#line 513 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x != 0.0 && yyvsp[0].x != 0.0); }
+break;
+case 53:
+#line 515 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x != 0.0 && yyvsp[0].x != 0.0); }
+break;
+case 54:
+#line 517 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x != 0.0 || yyvsp[0].x != 0.0); }
+break;
+case 55:
+#line 519 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x != 0.0 || yyvsp[0].x != 0.0); }
+break;
+case 56:
+#line 521 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x != 0.0 || yyvsp[0].x != 0.0); }
+break;
+case 57:
+#line 523 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = (yyvsp[0].x == 0.0); }
+break;
+case 58:
+#line 529 "/home/cjk/groff/pic/pic.y"
+{ yyval.by.val = 1.0; yyval.by.is_multiplicative = 0; }
+break;
+case 59:
+#line 531 "/home/cjk/groff/pic/pic.y"
+{ yyval.by.val = yyvsp[0].x; yyval.by.is_multiplicative = 0; }
+break;
+case 60:
+#line 533 "/home/cjk/groff/pic/pic.y"
+{ yyval.by.val = yyvsp[0].x; yyval.by.is_multiplicative = 1; }
+break;
+case 61:
+#line 538 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pl.obj = yyvsp[0].spec->make_object(&current_position,
+ &current_direction);
+ if (yyval.pl.obj == 0)
+ YYABORT;
+ delete yyvsp[0].spec;
+ if (yyval.pl.obj)
+ olist.append(yyval.pl.obj);
+ else {
+ yyval.pl.x = current_position.x;
+ yyval.pl.y = current_position.y;
+ }
+ }
+break;
+case 62:
+#line 552 "/home/cjk/groff/pic/pic.y"
+{ yyval.pl = yyvsp[0].pl; define_label(yyvsp[-3].str, & yyval.pl); a_delete yyvsp[-3].str; }
+break;
+case 63:
+#line 554 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pl.obj = 0;
+ yyval.pl.x = yyvsp[0].pair.x;
+ yyval.pl.y = yyvsp[0].pair.y;
+ define_label(yyvsp[-3].str, & yyval.pl);
+ a_delete yyvsp[-3].str;
+ }
+break;
+case 64:
+#line 562 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pl = yyvsp[0].pl;
+ define_label(yyvsp[-3].str, & yyval.pl);
+ a_delete yyvsp[-3].str;
+ }
+break;
+case 65:
+#line 568 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.state.x = current_position.x;
+ yyval.state.y = current_position.y;
+ yyval.state.dir = current_direction;
+ }
+break;
+case 66:
+#line 574 "/home/cjk/groff/pic/pic.y"
+{
+ current_position.x = yyvsp[-2].state.x;
+ current_position.y = yyvsp[-2].state.y;
+ current_direction = yyvsp[-2].state.dir;
+ }
+break;
+case 67:
+#line 580 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pl = yyvsp[-3].pl;
+ }
+break;
+case 68:
+#line 584 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pl.obj = 0;
+ yyval.pl.x = current_position.x;
+ yyval.pl.y = current_position.y;
+ }
+break;
+case 69:
+#line 593 "/home/cjk/groff/pic/pic.y"
+{}
+break;
+case 70:
+#line 595 "/home/cjk/groff/pic/pic.y"
+{}
+break;
+case 71:
+#line 600 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = new object_spec(BOX_OBJECT);
+ }
+break;
+case 72:
+#line 604 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = new object_spec(CIRCLE_OBJECT);
+ }
+break;
+case 73:
+#line 608 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = new object_spec(ELLIPSE_OBJECT);
+ }
+break;
+case 74:
+#line 612 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = new object_spec(ARC_OBJECT);
+ yyval.spec->dir = current_direction;
+ }
+break;
+case 75:
+#line 617 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = new object_spec(LINE_OBJECT);
+ lookup_variable("lineht", & yyval.spec->segment_height);
+ lookup_variable("linewid", & yyval.spec->segment_width);
+ yyval.spec->dir = current_direction;
+ }
+break;
+case 76:
+#line 624 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = new object_spec(ARROW_OBJECT);
+ lookup_variable("lineht", & yyval.spec->segment_height);
+ lookup_variable("linewid", & yyval.spec->segment_width);
+ yyval.spec->dir = current_direction;
+ }
+break;
+case 77:
+#line 631 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = new object_spec(MOVE_OBJECT);
+ lookup_variable("moveht", & yyval.spec->segment_height);
+ lookup_variable("movewid", & yyval.spec->segment_width);
+ yyval.spec->dir = current_direction;
+ }
+break;
+case 78:
+#line 638 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = new object_spec(SPLINE_OBJECT);
+ lookup_variable("lineht", & yyval.spec->segment_height);
+ lookup_variable("linewid", & yyval.spec->segment_width);
+ yyval.spec->dir = current_direction;
+ }
+break;
+case 79:
+#line 645 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = new object_spec(TEXT_OBJECT);
+ yyval.spec->text = new text_item(yyvsp[0].lstr.str, yyvsp[0].lstr.filename, yyvsp[0].lstr.lineno);
+ }
+break;
+case 80:
+#line 650 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = new object_spec(TEXT_OBJECT);
+ yyval.spec->text = new text_item(format_number(0, yyvsp[0].x), 0, -1);
+ }
+break;
+case 81:
+#line 655 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = new object_spec(TEXT_OBJECT);
+ yyval.spec->text = new text_item(format_number(yyvsp[0].lstr.str, yyvsp[-1].x),
+ yyvsp[0].lstr.filename, yyvsp[0].lstr.lineno);
+ a_delete yyvsp[0].lstr.str;
+ }
+break;
+case 82:
+#line 662 "/home/cjk/groff/pic/pic.y"
+{
+ saved_state *p = new saved_state;
+ yyval.pstate = p;
+ p->x = current_position.x;
+ p->y = current_position.y;
+ p->dir = current_direction;
+ p->tbl = current_table;
+ p->prev = current_saved_state;
+ current_position.x = 0.0;
+ current_position.y = 0.0;
+ current_table = new PTABLE(place);
+ current_saved_state = p;
+ olist.append(make_mark_object());
+ }
+break;
+case 83:
+#line 677 "/home/cjk/groff/pic/pic.y"
+{
+ current_position.x = yyvsp[-2].pstate->x;
+ current_position.y = yyvsp[-2].pstate->y;
+ current_direction = yyvsp[-2].pstate->dir;
+ yyval.spec = new object_spec(BLOCK_OBJECT);
+ olist.wrap_up_block(& yyval.spec->oblist);
+ yyval.spec->tbl = current_table;
+ current_table = yyvsp[-2].pstate->tbl;
+ current_saved_state = yyvsp[-2].pstate->prev;
+ delete yyvsp[-2].pstate;
+ }
+break;
+case 84:
+#line 689 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->height = yyvsp[0].x;
+ yyval.spec->flags |= HAS_HEIGHT;
+ }
+break;
+case 85:
+#line 695 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->radius = yyvsp[0].x;
+ yyval.spec->flags |= HAS_RADIUS;
+ }
+break;
+case 86:
+#line 701 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->width = yyvsp[0].x;
+ yyval.spec->flags |= HAS_WIDTH;
+ }
+break;
+case 87:
+#line 707 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->radius = yyvsp[0].x/2.0;
+ yyval.spec->flags |= HAS_RADIUS;
+ }
+break;
+case 88:
+#line 713 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= HAS_SEGMENT;
+ switch (yyval.spec->dir) {
+ case UP_DIRECTION:
+ yyval.spec->segment_pos.y += yyvsp[0].x;
+ break;
+ case DOWN_DIRECTION:
+ yyval.spec->segment_pos.y -= yyvsp[0].x;
+ break;
+ case RIGHT_DIRECTION:
+ yyval.spec->segment_pos.x += yyvsp[0].x;
+ break;
+ case LEFT_DIRECTION:
+ yyval.spec->segment_pos.x -= yyvsp[0].x;
+ break;
+ }
+ }
+break;
+case 89:
+#line 732 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->dir = UP_DIRECTION;
+ yyval.spec->flags |= HAS_SEGMENT;
+ yyval.spec->segment_pos.y += yyval.spec->segment_height;
+ }
+break;
+case 90:
+#line 739 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->dir = UP_DIRECTION;
+ yyval.spec->flags |= HAS_SEGMENT;
+ yyval.spec->segment_pos.y += yyvsp[0].x;
+ }
+break;
+case 91:
+#line 746 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->dir = DOWN_DIRECTION;
+ yyval.spec->flags |= HAS_SEGMENT;
+ yyval.spec->segment_pos.y -= yyval.spec->segment_height;
+ }
+break;
+case 92:
+#line 753 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->dir = DOWN_DIRECTION;
+ yyval.spec->flags |= HAS_SEGMENT;
+ yyval.spec->segment_pos.y -= yyvsp[0].x;
+ }
+break;
+case 93:
+#line 760 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->dir = RIGHT_DIRECTION;
+ yyval.spec->flags |= HAS_SEGMENT;
+ yyval.spec->segment_pos.x += yyval.spec->segment_width;
+ }
+break;
+case 94:
+#line 767 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->dir = RIGHT_DIRECTION;
+ yyval.spec->flags |= HAS_SEGMENT;
+ yyval.spec->segment_pos.x += yyvsp[0].x;
+ }
+break;
+case 95:
+#line 774 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->dir = LEFT_DIRECTION;
+ yyval.spec->flags |= HAS_SEGMENT;
+ yyval.spec->segment_pos.x -= yyval.spec->segment_width;
+ }
+break;
+case 96:
+#line 781 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->dir = LEFT_DIRECTION;
+ yyval.spec->flags |= HAS_SEGMENT;
+ yyval.spec->segment_pos.x -= yyvsp[0].x;
+ }
+break;
+case 97:
+#line 788 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->flags |= HAS_FROM;
+ yyval.spec->from.x = yyvsp[0].pair.x;
+ yyval.spec->from.y = yyvsp[0].pair.y;
+ }
+break;
+case 98:
+#line 795 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ if (yyval.spec->flags & HAS_SEGMENT)
+ yyval.spec->segment_list = new segment(yyval.spec->segment_pos,
+ yyval.spec->segment_is_absolute,
+ yyval.spec->segment_list);
+ yyval.spec->flags |= HAS_SEGMENT;
+ yyval.spec->segment_pos.x = yyvsp[0].pair.x;
+ yyval.spec->segment_pos.y = yyvsp[0].pair.y;
+ yyval.spec->segment_is_absolute = 1;
+ yyval.spec->flags |= HAS_TO;
+ yyval.spec->to.x = yyvsp[0].pair.x;
+ yyval.spec->to.y = yyvsp[0].pair.y;
+ }
+break;
+case 99:
+#line 810 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->flags |= HAS_AT;
+ yyval.spec->at.x = yyvsp[0].pair.x;
+ yyval.spec->at.y = yyvsp[0].pair.y;
+ if (yyval.spec->type != ARC_OBJECT) {
+ yyval.spec->flags |= HAS_FROM;
+ yyval.spec->from.x = yyvsp[0].pair.x;
+ yyval.spec->from.y = yyvsp[0].pair.y;
+ }
+ }
+break;
+case 100:
+#line 822 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->flags |= HAS_WITH;
+ yyval.spec->with = yyvsp[0].pth;
+ }
+break;
+case 101:
+#line 828 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->flags |= HAS_SEGMENT;
+ yyval.spec->segment_pos.x += yyvsp[0].pair.x;
+ yyval.spec->segment_pos.y += yyvsp[0].pair.y;
+ }
+break;
+case 102:
+#line 835 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ if (yyval.spec->flags & HAS_SEGMENT) {
+ yyval.spec->segment_list = new segment(yyval.spec->segment_pos,
+ yyval.spec->segment_is_absolute,
+ yyval.spec->segment_list);
+ yyval.spec->flags &= ~HAS_SEGMENT;
+ yyval.spec->segment_pos.x = yyval.spec->segment_pos.y = 0.0;
+ yyval.spec->segment_is_absolute = 0;
+ }
+ }
+break;
+case 103:
+#line 847 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= IS_DOTTED;
+ lookup_variable("dashwid", & yyval.spec->dash_width);
+ }
+break;
+case 104:
+#line 853 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->flags |= IS_DOTTED;
+ yyval.spec->dash_width = yyvsp[0].x;
+ }
+break;
+case 105:
+#line 859 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= IS_DASHED;
+ lookup_variable("dashwid", & yyval.spec->dash_width);
+ }
+break;
+case 106:
+#line 865 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->flags |= IS_DASHED;
+ yyval.spec->dash_width = yyvsp[0].x;
+ }
+break;
+case 107:
+#line 871 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= IS_DEFAULT_FILLED;
+ }
+break;
+case 108:
+#line 876 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->flags |= IS_FILLED;
+ yyval.spec->fill = yyvsp[0].x;
+ }
+break;
+case 109:
+#line 882 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ /* line chop chop means line chop 0 chop 0*/
+ if (yyval.spec->flags & IS_DEFAULT_CHOPPED) {
+ yyval.spec->flags |= IS_CHOPPED;
+ yyval.spec->flags &= ~IS_DEFAULT_CHOPPED;
+ yyval.spec->start_chop = yyval.spec->end_chop = 0.0;
+ }
+ else if (yyval.spec->flags & IS_CHOPPED) {
+ yyval.spec->end_chop = 0.0;
+ }
+ else {
+ yyval.spec->flags |= IS_DEFAULT_CHOPPED;
+ }
+ }
+break;
+case 110:
+#line 898 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ if (yyval.spec->flags & IS_DEFAULT_CHOPPED) {
+ yyval.spec->flags |= IS_CHOPPED;
+ yyval.spec->flags &= ~IS_DEFAULT_CHOPPED;
+ yyval.spec->start_chop = 0.0;
+ yyval.spec->end_chop = yyvsp[0].x;
+ }
+ else if (yyval.spec->flags & IS_CHOPPED) {
+ yyval.spec->end_chop = yyvsp[0].x;
+ }
+ else {
+ yyval.spec->start_chop = yyval.spec->end_chop = yyvsp[0].x;
+ yyval.spec->flags |= IS_CHOPPED;
+ }
+ }
+break;
+case 111:
+#line 915 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= IS_SAME;
+ }
+break;
+case 112:
+#line 920 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= IS_INVISIBLE;
+ }
+break;
+case 113:
+#line 925 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= HAS_LEFT_ARROW_HEAD;
+ }
+break;
+case 114:
+#line 930 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= HAS_RIGHT_ARROW_HEAD;
+ }
+break;
+case 115:
+#line 935 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD);
+ }
+break;
+case 116:
+#line 940 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= IS_CLOCKWISE;
+ }
+break;
+case 117:
+#line 945 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags &= ~IS_CLOCKWISE;
+ }
+break;
+case 118:
+#line 950 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ text_item **p;
+ for (p = & yyval.spec->text; *p; p = &(*p)->next)
+ ;
+ *p = new text_item(yyvsp[0].lstr.str, yyvsp[0].lstr.filename, yyvsp[0].lstr.lineno);
+ }
+break;
+case 119:
+#line 958 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ if (yyval.spec->text) {
+ text_item *p;
+ for (p = yyval.spec->text; p->next; p = p->next)
+ ;
+ p->adj.h = LEFT_ADJUST;
+ }
+ }
+break;
+case 120:
+#line 968 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ if (yyval.spec->text) {
+ text_item *p;
+ for (p = yyval.spec->text; p->next; p = p->next)
+ ;
+ p->adj.h = RIGHT_ADJUST;
+ }
+ }
+break;
+case 121:
+#line 978 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ if (yyval.spec->text) {
+ text_item *p;
+ for (p = yyval.spec->text; p->next; p = p->next)
+ ;
+ p->adj.v = ABOVE_ADJUST;
+ }
+ }
+break;
+case 122:
+#line 988 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ if (yyval.spec->text) {
+ text_item *p;
+ for (p = yyval.spec->text; p->next; p = p->next)
+ ;
+ p->adj.v = BELOW_ADJUST;
+ }
+ }
+break;
+case 123:
+#line 998 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->flags |= HAS_THICKNESS;
+ yyval.spec->thickness = yyvsp[0].x;
+ }
+break;
+case 124:
+#line 1004 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= IS_ALIGNED;
+ }
+break;
+case 125:
+#line 1012 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.lstr = yyvsp[0].lstr;
+ }
+break;
+case 126:
+#line 1016 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.lstr.filename = yyvsp[-2].lstr.filename;
+ yyval.lstr.lineno = yyvsp[-2].lstr.lineno;
+ yyval.lstr.str = do_sprintf(yyvsp[-2].lstr.str, yyvsp[-1].dv.v, yyvsp[-1].dv.nv);
+ a_delete yyvsp[-1].dv.v;
+ a_delete yyvsp[-2].lstr.str;
+ }
+break;
+case 127:
+#line 1027 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.dv.v = 0;
+ yyval.dv.nv = 0;
+ yyval.dv.maxv = 0;
+ }
+break;
+case 128:
+#line 1033 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.dv = yyvsp[-2].dv;
+ if (yyval.dv.nv >= yyval.dv.maxv) {
+ if (yyval.dv.nv == 0) {
+ yyval.dv.v = new double[4];
+ yyval.dv.maxv = 4;
+ }
+ else {
+ double *oldv = yyval.dv.v;
+ yyval.dv.maxv *= 2;
+ yyval.dv.v = new double[yyval.dv.maxv];
+ memcpy(yyval.dv.v, oldv, yyval.dv.nv*sizeof(double));
+ a_delete oldv;
+ }
+ }
+ yyval.dv.v[yyval.dv.nv] = yyvsp[0].x;
+ yyval.dv.nv += 1;
+ }
+break;
+case 129:
+#line 1055 "/home/cjk/groff/pic/pic.y"
+{ yyval.pair = yyvsp[0].pair; }
+break;
+case 130:
+#line 1057 "/home/cjk/groff/pic/pic.y"
+{
+ position pos = yyvsp[0].pl;
+ yyval.pair.x = pos.x;
+ yyval.pair.y = pos.y;
+ }
+break;
+case 131:
+#line 1066 "/home/cjk/groff/pic/pic.y"
+{ yyval.pair = yyvsp[0].pair; }
+break;
+case 132:
+#line 1068 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pair.x = yyvsp[-2].pair.x + yyvsp[0].pair.x;
+ yyval.pair.y = yyvsp[-2].pair.y + yyvsp[0].pair.y;
+ }
+break;
+case 133:
+#line 1073 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pair.x = yyvsp[-2].pair.x - yyvsp[0].pair.x;
+ yyval.pair.y = yyvsp[-2].pair.y - yyvsp[0].pair.y;
+ }
+break;
+case 134:
+#line 1078 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pair.x = yyvsp[-3].pair.x;
+ yyval.pair.y = yyvsp[-1].pair.y;
+ }
+break;
+case 135:
+#line 1083 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pair.x = (1.0 - yyvsp[-4].x)*yyvsp[-2].pair.x + yyvsp[-4].x*yyvsp[0].pair.x;
+ yyval.pair.y = (1.0 - yyvsp[-4].x)*yyvsp[-2].pair.y + yyvsp[-4].x*yyvsp[0].pair.y;
+ }
+break;
+case 136:
+#line 1088 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pair.x = (1.0 - yyvsp[-5].x)*yyvsp[-3].pair.x + yyvsp[-5].x*yyvsp[-1].pair.x;
+ yyval.pair.y = (1.0 - yyvsp[-5].x)*yyvsp[-3].pair.y + yyvsp[-5].x*yyvsp[-1].pair.y;
+ }
+break;
+case 139:
+#line 1101 "/home/cjk/groff/pic/pic.y"
+{ yyval.pair.x = yyvsp[-2].x; yyval.pair.y = yyvsp[0].x; }
+break;
+case 140:
+#line 1103 "/home/cjk/groff/pic/pic.y"
+{ yyval.pair = yyvsp[-1].pair; }
+break;
+case 141:
+#line 1108 "/home/cjk/groff/pic/pic.y"
+{ yyval.pl = yyvsp[0].pl; }
+break;
+case 142:
+#line 1110 "/home/cjk/groff/pic/pic.y"
+{
+ path pth(yyvsp[0].crn);
+ if (!pth.follow(yyvsp[-1].pl, & yyval.pl))
+ YYABORT;
+ }
+break;
+case 143:
+#line 1116 "/home/cjk/groff/pic/pic.y"
+{
+ path pth(yyvsp[-1].crn);
+ if (!pth.follow(yyvsp[0].pl, & yyval.pl))
+ YYABORT;
+ }
+break;
+case 144:
+#line 1122 "/home/cjk/groff/pic/pic.y"
+{
+ path pth(yyvsp[-2].crn);
+ if (!pth.follow(yyvsp[0].pl, & yyval.pl))
+ YYABORT;
+ }
+break;
+case 145:
+#line 1128 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pl.x = current_position.x;
+ yyval.pl.y = current_position.y;
+ yyval.pl.obj = 0;
+ }
+break;
+case 146:
+#line 1137 "/home/cjk/groff/pic/pic.y"
+{
+ place *p = lookup_label(yyvsp[0].str);
+ if (!p) {
+ lex_error("there is no place `%1'", yyvsp[0].str);
+ YYABORT;
+ }
+ yyval.pl = *p;
+ a_delete yyvsp[0].str;
+ }
+break;
+case 147:
+#line 1147 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pl.obj = yyvsp[0].obj;
+ }
+break;
+case 148:
+#line 1151 "/home/cjk/groff/pic/pic.y"
+{
+ path pth(yyvsp[0].str);
+ if (!pth.follow(yyvsp[-2].pl, & yyval.pl))
+ YYABORT;
+ }
+break;
+case 149:
+#line 1160 "/home/cjk/groff/pic/pic.y"
+{ yyval.n = yyvsp[0].n; }
+break;
+case 150:
+#line 1162 "/home/cjk/groff/pic/pic.y"
+{
+ /* XXX Check for overflow (and non-integers?).*/
+ yyval.n = (int)yyvsp[-1].x;
+ }
+break;
+case 151:
+#line 1170 "/home/cjk/groff/pic/pic.y"
+{ yyval.n = 1; }
+break;
+case 152:
+#line 1172 "/home/cjk/groff/pic/pic.y"
+{ yyval.n = yyvsp[-1].n; }
+break;
+case 153:
+#line 1177 "/home/cjk/groff/pic/pic.y"
+{
+ int count = 0;
+ object *p;
+ for (p = olist.head; p != 0; p = p->next)
+ if (p->type() == yyvsp[0].obtype && ++count == yyvsp[-1].n) {
+ yyval.obj = p;
+ break;
+ }
+ if (p == 0) {
+ lex_error("there is no %1%2 %3", yyvsp[-1].n, ordinal_postfix(yyvsp[-1].n),
+ object_type_name(yyvsp[0].obtype));
+ YYABORT;
+ }
+ }
+break;
+case 154:
+#line 1192 "/home/cjk/groff/pic/pic.y"
+{
+ int count = 0;
+ object *p;
+ for (p = olist.tail; p != 0; p = p->prev)
+ if (p->type() == yyvsp[0].obtype && ++count == yyvsp[-1].n) {
+ yyval.obj = p;
+ break;
+ }
+ if (p == 0) {
+ lex_error("there is no %1%2 last %3", yyvsp[-1].n,
+ ordinal_postfix(yyvsp[-1].n), object_type_name(yyvsp[0].obtype));
+ YYABORT;
+ }
+ }
+break;
+case 155:
+#line 1210 "/home/cjk/groff/pic/pic.y"
+{ yyval.obtype = BOX_OBJECT; }
+break;
+case 156:
+#line 1212 "/home/cjk/groff/pic/pic.y"
+{ yyval.obtype = CIRCLE_OBJECT; }
+break;
+case 157:
+#line 1214 "/home/cjk/groff/pic/pic.y"
+{ yyval.obtype = ELLIPSE_OBJECT; }
+break;
+case 158:
+#line 1216 "/home/cjk/groff/pic/pic.y"
+{ yyval.obtype = ARC_OBJECT; }
+break;
+case 159:
+#line 1218 "/home/cjk/groff/pic/pic.y"
+{ yyval.obtype = LINE_OBJECT; }
+break;
+case 160:
+#line 1220 "/home/cjk/groff/pic/pic.y"
+{ yyval.obtype = ARROW_OBJECT; }
+break;
+case 161:
+#line 1222 "/home/cjk/groff/pic/pic.y"
+{ yyval.obtype = SPLINE_OBJECT; }
+break;
+case 162:
+#line 1224 "/home/cjk/groff/pic/pic.y"
+{ yyval.obtype = BLOCK_OBJECT; }
+break;
+case 163:
+#line 1226 "/home/cjk/groff/pic/pic.y"
+{ yyval.obtype = TEXT_OBJECT; }
+break;
+case 164:
+#line 1231 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pth = new path(yyvsp[0].str);
+ }
+break;
+case 165:
+#line 1235 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pth = yyvsp[-2].pth;
+ yyval.pth->append(yyvsp[0].str);
+ }
+break;
+case 166:
+#line 1243 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pth = new path(yyvsp[0].crn);
+ }
+break;
+case 167:
+#line 1250 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pth = yyvsp[0].pth;
+ }
+break;
+case 168:
+#line 1254 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pth = yyvsp[-1].pth;
+ yyval.pth->append(yyvsp[0].crn);
+ }
+break;
+case 169:
+#line 1262 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pth = yyvsp[0].pth;
+ }
+break;
+case 170:
+#line 1266 "/home/cjk/groff/pic/pic.y"
+{
+ yyval.pth = yyvsp[-3].pth;
+ yyval.pth->set_ypath(yyvsp[-1].pth);
+ }
+break;
+case 171:
+#line 1272 "/home/cjk/groff/pic/pic.y"
+{
+ lex_warning("`%1%2 last %3' in `with' argument ignored",
+ yyvsp[-3].n, ordinal_postfix(yyvsp[-3].n), object_type_name(yyvsp[-1].obtype));
+ yyval.pth = yyvsp[0].pth;
+ }
+break;
+case 172:
+#line 1278 "/home/cjk/groff/pic/pic.y"
+{
+ lex_warning("`last %1' in `with' argument ignored",
+ object_type_name(yyvsp[-1].obtype));
+ yyval.pth = yyvsp[0].pth;
+ }
+break;
+case 173:
+#line 1284 "/home/cjk/groff/pic/pic.y"
+{
+ lex_warning("`%1%2 %3' in `with' argument ignored",
+ yyvsp[-2].n, ordinal_postfix(yyvsp[-2].n), object_type_name(yyvsp[-1].obtype));
+ yyval.pth = yyvsp[0].pth;
+ }
+break;
+case 174:
+#line 1290 "/home/cjk/groff/pic/pic.y"
+{
+ lex_warning("initial `%1' in `with' argument ignored", yyvsp[-1].str);
+ a_delete yyvsp[-1].str;
+ yyval.pth = yyvsp[0].pth;
+ }
+break;
+case 175:
+#line 1299 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::north; }
+break;
+case 176:
+#line 1301 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::east; }
+break;
+case 177:
+#line 1303 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::west; }
+break;
+case 178:
+#line 1305 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::south; }
+break;
+case 179:
+#line 1307 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::north_east; }
+break;
+case 180:
+#line 1309 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object:: south_east; }
+break;
+case 181:
+#line 1311 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::north_west; }
+break;
+case 182:
+#line 1313 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::south_west; }
+break;
+case 183:
+#line 1315 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::center; }
+break;
+case 184:
+#line 1317 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::start; }
+break;
+case 185:
+#line 1319 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::end; }
+break;
+case 186:
+#line 1321 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::north; }
+break;
+case 187:
+#line 1323 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::south; }
+break;
+case 188:
+#line 1325 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::west; }
+break;
+case 189:
+#line 1327 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::east; }
+break;
+case 190:
+#line 1329 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::north_west; }
+break;
+case 191:
+#line 1331 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::south_west; }
+break;
+case 192:
+#line 1333 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::north_east; }
+break;
+case 193:
+#line 1335 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::south_east; }
+break;
+case 194:
+#line 1337 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::west; }
+break;
+case 195:
+#line 1339 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::east; }
+break;
+case 196:
+#line 1341 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::north_west; }
+break;
+case 197:
+#line 1343 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::south_west; }
+break;
+case 198:
+#line 1345 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::north_east; }
+break;
+case 199:
+#line 1347 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::south_east; }
+break;
+case 200:
+#line 1349 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::center; }
+break;
+case 201:
+#line 1351 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::start; }
+break;
+case 202:
+#line 1353 "/home/cjk/groff/pic/pic.y"
+{ yyval.crn = &object::end; }
+break;
+case 203:
+#line 1358 "/home/cjk/groff/pic/pic.y"
+{
+ if (!lookup_variable(yyvsp[0].str, & yyval.x)) {
+ lex_error("there is no variable `%1'", yyvsp[0].str);
+ YYABORT;
+ }
+ a_delete yyvsp[0].str;
+ }
+break;
+case 204:
+#line 1366 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = yyvsp[0].x; }
+break;
+case 205:
+#line 1368 "/home/cjk/groff/pic/pic.y"
+{
+ if (yyvsp[-1].pl.obj != 0)
+ yyval.x = yyvsp[-1].pl.obj->origin().x;
+ else
+ yyval.x = yyvsp[-1].pl.x;
+ }
+break;
+case 206:
+#line 1375 "/home/cjk/groff/pic/pic.y"
+{
+ if (yyvsp[-1].pl.obj != 0)
+ yyval.x = yyvsp[-1].pl.obj->origin().y;
+ else
+ yyval.x = yyvsp[-1].pl.y;
+ }
+break;
+case 207:
+#line 1382 "/home/cjk/groff/pic/pic.y"
+{
+ if (yyvsp[-1].pl.obj != 0)
+ yyval.x = yyvsp[-1].pl.obj->height();
+ else
+ yyval.x = 0.0;
+ }
+break;
+case 208:
+#line 1389 "/home/cjk/groff/pic/pic.y"
+{
+ if (yyvsp[-1].pl.obj != 0)
+ yyval.x = yyvsp[-1].pl.obj->width();
+ else
+ yyval.x = 0.0;
+ }
+break;
+case 209:
+#line 1396 "/home/cjk/groff/pic/pic.y"
+{
+ if (yyvsp[-1].pl.obj != 0)
+ yyval.x = yyvsp[-1].pl.obj->radius();
+ else
+ yyval.x = 0.0;
+ }
+break;
+case 210:
+#line 1403 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = yyvsp[-2].x + yyvsp[0].x; }
+break;
+case 211:
+#line 1405 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = yyvsp[-2].x - yyvsp[0].x; }
+break;
+case 212:
+#line 1407 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = yyvsp[-2].x * yyvsp[0].x; }
+break;
+case 213:
+#line 1409 "/home/cjk/groff/pic/pic.y"
+{
+ if (yyvsp[0].x == 0.0) {
+ lex_error("division by zero");
+ YYABORT;
+ }
+ yyval.x = yyvsp[-2].x/yyvsp[0].x;
+ }
+break;
+case 214:
+#line 1417 "/home/cjk/groff/pic/pic.y"
+{
+ if (yyvsp[0].x == 0.0) {
+ lex_error("modulus by zero");
+ YYABORT;
+ }
+ yyval.x = fmod(yyvsp[-2].x, yyvsp[0].x);
+ }
+break;
+case 215:
+#line 1425 "/home/cjk/groff/pic/pic.y"
+{
+ errno = 0;
+ yyval.x = pow(yyvsp[-2].x, yyvsp[0].x);
+ if (errno == EDOM) {
+ lex_error("arguments to `^' operator out of domain");
+ YYABORT;
+ }
+ if (errno == ERANGE) {
+ lex_error("result of `^' operator out of range");
+ YYABORT;
+ }
+ }
+break;
+case 216:
+#line 1438 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = -yyvsp[0].x; }
+break;
+case 217:
+#line 1440 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = yyvsp[-1].x; }
+break;
+case 218:
+#line 1442 "/home/cjk/groff/pic/pic.y"
+{
+ errno = 0;
+ yyval.x = sin(yyvsp[-1].x);
+ if (errno == ERANGE) {
+ lex_error("sin result out of range");
+ YYABORT;
+ }
+ }
+break;
+case 219:
+#line 1451 "/home/cjk/groff/pic/pic.y"
+{
+ errno = 0;
+ yyval.x = cos(yyvsp[-1].x);
+ if (errno == ERANGE) {
+ lex_error("cos result out of range");
+ YYABORT;
+ }
+ }
+break;
+case 220:
+#line 1460 "/home/cjk/groff/pic/pic.y"
+{
+ errno = 0;
+ yyval.x = atan2(yyvsp[-3].x, yyvsp[-1].x);
+ if (errno == EDOM) {
+ lex_error("atan2 argument out of domain");
+ YYABORT;
+ }
+ if (errno == ERANGE) {
+ lex_error("atan2 result out of range");
+ YYABORT;
+ }
+ }
+break;
+case 221:
+#line 1473 "/home/cjk/groff/pic/pic.y"
+{
+ errno = 0;
+ yyval.x = log10(yyvsp[-1].x);
+ if (errno == ERANGE) {
+ lex_error("log result out of range");
+ YYABORT;
+ }
+ }
+break;
+case 222:
+#line 1482 "/home/cjk/groff/pic/pic.y"
+{
+ errno = 0;
+ yyval.x = pow(10.0, yyvsp[-1].x);
+ if (errno == ERANGE) {
+ lex_error("exp result out of range");
+ YYABORT;
+ }
+ }
+break;
+case 223:
+#line 1491 "/home/cjk/groff/pic/pic.y"
+{
+ errno = 0;
+ yyval.x = sqrt(yyvsp[-1].x);
+ if (errno == EDOM) {
+ lex_error("sqrt argument out of domain");
+ YYABORT;
+ }
+ }
+break;
+case 224:
+#line 1500 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = yyvsp[-3].x > yyvsp[-1].x ? yyvsp[-3].x : yyvsp[-1].x; }
+break;
+case 225:
+#line 1502 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = yyvsp[-3].x < yyvsp[-1].x ? yyvsp[-3].x : yyvsp[-1].x; }
+break;
+case 226:
+#line 1504 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = floor(yyvsp[-1].x); }
+break;
+case 227:
+#line 1506 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = 1.0 + floor(((rand()&0x7fff)/double(0x7fff))*yyvsp[-1].x); }
+break;
+case 228:
+#line 1508 "/home/cjk/groff/pic/pic.y"
+{
+ /* return a random number in the range [0,1) */
+ /* portable, but not very random */
+ yyval.x = (rand() & 0x7fff) / double(0x8000);
+ }
+break;
+case 229:
+#line 1514 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = 0; srand((unsigned int)yyvsp[-1].x); }
+break;
+case 230:
+#line 1516 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x < yyvsp[0].x); }
+break;
+case 231:
+#line 1518 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x <= yyvsp[0].x); }
+break;
+case 232:
+#line 1520 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x > yyvsp[0].x); }
+break;
+case 233:
+#line 1522 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x >= yyvsp[0].x); }
+break;
+case 234:
+#line 1524 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x == yyvsp[0].x); }
+break;
+case 235:
+#line 1526 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x != yyvsp[0].x); }
+break;
+case 236:
+#line 1528 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x != 0.0 && yyvsp[0].x != 0.0); }
+break;
+case 237:
+#line 1530 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x != 0.0 || yyvsp[0].x != 0.0); }
+break;
+case 238:
+#line 1532 "/home/cjk/groff/pic/pic.y"
+{ yyval.x = (yyvsp[0].x == 0.0); }
+break;
+#line 5165 "y.tab.c"
+ }
+ yyssp -= yym;
+ yystate = *yyssp;
+ yyvsp -= yym;
+ yym = yylhs[yyn];
+ if (yystate == 0 && yym == 0)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: after reduction, shifting from state 0 to\
+ state %d\n", YYPREFIX, YYFINAL);
+#endif
+ yystate = YYFINAL;
+ *++yyssp = YYFINAL;
+ *++yyvsp = yyval;
+ if (yychar < 0)
+ {
+ if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+ if (!yys) yys = "illegal-symbol";
+ printf("%sdebug: state %d, reading %d (%s)\n",
+ YYPREFIX, YYFINAL, yychar, yys);
+ }
+#endif
+ }
+ if (yychar == 0) goto yyaccept;
+ goto yyloop;
+ }
+ if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
+ yystate = yytable[yyn];
+ else
+ yystate = yydgoto[yym];
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: after reduction, shifting from state %d \
+to state %d\n", YYPREFIX, *yyssp, yystate);
+#endif
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ goto yyoverflow;
+ }
+ *++yyssp = yystate;
+ *++yyvsp = yyval;
+ goto yyloop;
+yyoverflow:
+ yyerror("yacc stack overflow");
+yyabort:
+ return (1);
+yyaccept:
+ return (0);
+}
diff --git a/src/preproc/pic/pic.h b/src/preproc/pic/pic.h
new file mode 100644
index 00000000..77e59c7e
--- /dev/null
+++ b/src/preproc/pic/pic.h
@@ -0,0 +1,104 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#ifndef MATH_H_DECLARES_HYPOT
+extern "C" {
+ double hypot(double, double);
+}
+#endif
+
+#include "assert.h"
+#include "cset.h"
+#include "lib.h"
+#include "stringclass.h"
+#include "errarg.h"
+#include "error.h"
+#include "position.h"
+#include "text.h"
+#include "output.h"
+
+#ifndef M_SQRT2
+#define M_SQRT2 1.41421356237309504880
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+class input {
+ input *next;
+public:
+ input();
+ virtual ~input();
+ virtual int get() = 0;
+ virtual int peek() = 0;
+ virtual int get_location(const char **, int *);
+ friend class input_stack;
+ friend class copy_rest_thru_input;
+};
+
+class file_input : public input {
+ FILE *fp;
+ const char *filename;
+ int lineno;
+ string line;
+ const char *ptr;
+ int read_line();
+public:
+ file_input(FILE *, const char *);
+ ~file_input();
+ int get();
+ int peek();
+ int get_location(const char **, int *);
+};
+
+void lex_init(input *);
+int get_location(char **, int *);
+
+void do_copy(const char *file);
+void parse_init();
+void parse_cleanup();
+
+void lex_error(const char *message,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+void lex_warning(const char *message,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+void lex_cleanup();
+
+extern int flyback_flag;
+extern int command_char;
+// zero_length_line_flag is non-zero if zero-length lines are drawn
+// as dots by the output device
+extern int zero_length_line_flag;
+extern int driver_extension_flag;
+extern int compatible_flag;
+extern int safer_flag;
diff --git a/src/preproc/pic/pic.man b/src/preproc/pic/pic.man
new file mode 100644
index 00000000..22481019
--- /dev/null
+++ b/src/preproc/pic/pic.man
@@ -0,0 +1,762 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1999 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X
+.el .ds tx TeX
+.ie \n(.g .ds ic \/
+.el .ds ic \^
+.\" The BSD man macros can't handle " in arguments to font change macros,
+.\" so use \(ts instead of ".
+.tr \(ts"
+.TH @G@PIC @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+@g@pic \- compile pictures for troff or TeX
+.SH SYNOPSIS
+.B @g@pic
+[
+.B \-nvCSU
+]
+[
+.I filename
+\&.\|.\|.
+]
+.br
+.B @g@pic
+.B \-t
+[
+.B \-cvzCSU
+]
+[
+.I filename
+\&.\|.\|.
+]
+.SH DESCRIPTION
+.LP
+This manual page describes the GNU version of
+.BR pic ,
+which is part of the groff document formatting system.
+.B pic
+compiles descriptions of pictures embedded within
+.B troff
+or \*(tx input files into commands that are understood by \*(tx or
+.BR troff .
+Each picture starts with a line beginning with
+.B .PS
+and ends with a line beginning with
+.BR .PE .
+Anything outside of
+.B .PS
+and
+.B .PE
+is passed through without change.
+.LP
+It is the user's responsibility to provide appropriate definitions of the
+.B PS
+and
+.B PE
+macros.
+When the macro package being used does not supply such definitions
+(for example, old versions of \-ms),
+appropriate definitions can be obtained with
+.BR \-mpic :
+these will center each picture.
+.SH OPTIONS
+.LP
+Options that do not take arguments may be grouped behind a single
+.BR \- .
+The special option
+.B \-\^\-
+can be used to mark the end of the options.
+A filename of
+.B \-
+refers to the standard input.
+.TP
+.B \-C
+Recognize
+.B .PS
+and
+.B .PE
+even when followed by a character other than space or newline.
+.TP
+.B \-S
+Safer mode; do not execute
+.B sh
+commands.
+This can be useful when operating on untrustworthy input.
+(enabled by default)
+.TP
+.B \-U
+Unsafe mode; revert the default option
+.BR \-S .
+.TP
+.B \-n
+Don't use the groff extensions to the troff drawing commands.
+You should use this if you are using a postprocessor that doesn't support
+these extensions.
+The extensions are described in
+.BR groff_out (@MAN5EXT@).
+The
+.B \-n
+option also causes pic
+not to use zero-length lines to draw dots in troff mode.
+.TP
+.B \-t
+\*(tx mode.
+.TP
+.B \-c
+Be more compatible with
+.BR tpic .
+Implies
+.BR \-t .
+Lines beginning with
+.B \e
+are not passed through transparently.
+Lines beginning with
+.B .
+are passed through with the initial
+.B .
+changed to
+.BR \e .
+A line beginning with
+.B .ps
+is given special treatment:
+it takes an optional integer argument specifying
+the line thickness (pen size) in milliinches;
+a missing argument restores the previous line thickness;
+the default line thickness is 8 milliinches.
+The line thickness thus specified takes effect only
+when a non-negative line thickness has not been
+specified by use of the
+.B thickness
+attribute or by setting the
+.B linethick
+variable.
+.TP
+.B \-v
+Print the version number.
+.TP
+.B \-z
+In \*(tx mode draw dots using zero-length lines.
+.LP
+The following options supported by other versions of
+.B pic
+are ignored:
+.TP
+.B \-D
+Draw all lines using the \eD escape sequence.
+.B pic
+always does this.
+.TP
+.BI \-T \ dev
+Generate output for the
+.B troff
+device
+.IR dev .
+This is unnecessary because the
+.B troff
+output generated by
+.B pic
+is device-independent.
+.SH USAGE
+This section describes only the differences between GNU pic and the original
+version of pic.
+Many of these differences also apply to newer versions of Unix pic.
+.SS \*(tx mode
+.LP
+\*(tx mode is enabled by the
+.B \-t
+option.
+In \*(tx mode, pic will define a vbox called
+.B \egraph
+for each picture.
+You must yourself print that vbox using, for example, the command
+.RS
+.LP
+.B
+\ecenterline{\ebox\egraph}
+.RE
+.LP
+Actually, since the vbox has a height of zero this will produce
+slightly more vertical space above the picture than below it;
+.RS
+.LP
+.B
+\ecenterline{\eraise 1em\ebox\egraph}
+.RE
+.LP
+would avoid this.
+.LP
+You must use a \*(tx driver that supports the
+.B tpic
+specials, version 2.
+.LP
+Lines beginning with
+.B \e
+are passed through transparently; a
+.B %
+is added to the end of the line to avoid unwanted spaces.
+You can safely use this feature to change fonts or to
+change the value of
+.BR \ebaselineskip .
+Anything else may well produce undesirable results; use at your own risk.
+Lines beginning with a period are not given any special treatment.
+.SS Commands
+.TP
+\fBfor\fR \fIvariable\fR \fB=\fR \fIexpr1\fR \fBto\fR \fIexpr2\fR \
+[\fBby\fR [\fB*\fR]\fIexpr3\fR] \fBdo\fR \fIX\fR \fIbody\fR \fIX\fR
+Set
+.I variable
+to
+.IR expr1 .
+While the value of
+.I variable
+is less than or equal to
+.IR expr2 ,
+do
+.I body
+and increment
+.I variable
+by
+.IR expr3 ;
+if
+.B by
+is not given, increment
+.I variable
+by 1.
+If
+.I expr3
+is prefixed by
+.B *
+then
+.I variable
+will instead be multiplied by
+.IR expr3 .
+.I X
+can be any character not occurring in
+.IR body .
+.TP
+\fBif\fR \fIexpr\fR \fBthen\fR \fIX\fR \fIif-true\fR \fIX\fR \
+[\fBelse\fR \fIY\fR \fIif-false\fR \fIY\fR]
+Evaluate
+.IR expr ;
+if it is non-zero then do
+.IR if-true ,
+otherwise do
+.IR if-false .
+.I X
+can be any character not occurring in
+.IR if-true .
+.I Y
+can be any character not occurring in
+.IR if-false .
+.TP
+\fBprint\fR \fIarg\fR\|.\|.\|.
+Concatenate the arguments and print as a line on stderr.
+Each
+.I arg
+must be an expression, a position, or text.
+This is useful for debugging.
+.TP
+\fBcommand\fR \fIarg\fR\|.\|.\|.
+Concatenate the arguments
+and pass them through as a line to troff or\*(tx.
+Each
+.I arg
+must be an expression, a position, or text.
+This has a similar effect to a line beginning with
+.B .
+or
+.BR \e ,
+but allows the values of variables to be passed through.
+.TP
+\fBsh\fR \fIX\fR \fIcommand\fR \fIX\fR
+Pass
+.I command
+to a shell.
+.I X
+can be any character not occurring in
+.IR command .
+.TP
+\fBcopy\fR \fB"\fIfilename\fB"\fR
+Include
+.I filename
+at this point in the file.
+.TP
+\fBcopy\fR [\fB"\fIfilename\fB"\fR] \fBthru\fR \fIX\fR \fIbody\fR \fIX\fR \
+[\fBuntil\fR \fB"\fIword\*(ic\fB"\fR]
+.ns
+.TP
+\fBcopy\fR [\fB"\fIfilename\fB"\fR] \fBthru\fR \fImacro\fR \
+[\fBuntil\fR \fB"\fIword\*(ic\fB"\fR]
+This construct does
+.I body
+once for each line of
+.IR filename ;
+the line is split into blank-delimited words,
+and occurrences of
+.BI $ i
+in
+.IR body ,
+for
+.I i
+between 1 and 9,
+are replaced by the
+.IR i -th
+word of the line.
+If
+.I filename
+is not given, lines are taken from the current input up to
+.BR .PE .
+If an
+.B until
+clause is specified,
+lines will be read only until a line the first word of which is
+.IR word ;
+that line will then be discarded.
+.I X
+can be any character not occurring in
+.IR body .
+For example,
+.RS
+.IP
+.ft B
+.nf
+\&.PS
+copy thru % circle at ($1,$2) % until "END"
+1 2
+3 4
+5 6
+END
+box
+\&.PE
+.ft
+.fi
+.RE
+.IP
+is equivalent to
+.RS
+.IP
+.ft B
+.nf
+\&.PS
+circle at (1,2)
+circle at (3,4)
+circle at (5,6)
+box
+\&.PE
+.ft
+.fi
+.RE
+.IP
+The commands to be performed for each line can also be taken
+from a macro defined earlier by giving the name of the macro
+as the argument to
+.BR thru .
+.LP
+.B reset
+.br
+.ns
+.TP
+\fBreset\fI variable1\fB,\fI variable2 .\^.\^.
+Reset pre-defined variables
+.IR variable1 ,
+.I variable2
+\&.\^.\^. to their default values.
+If no arguments are given, reset all pre-defined variables
+to their default values.
+Note that assigning a value to
+.B scale
+also causes all pre-defined variables that control dimensions
+to be reset to their default values times the new value of scale.
+.TP
+\fBplot\fR \fIexpr\fR [\fB"\fItext\*(ic\fB"\fR]
+This is a text object which is constructed by using
+.I text
+as a format string for sprintf
+with an argument of
+.IR expr .
+If
+.I text
+is omitted a format string of
+.B "\(ts%g\(ts"
+is used.
+Attributes can be specified in the same way as for a normal text
+object.
+Be very careful that you specify an appropriate format string;
+pic does only very limited checking of the string.
+This is deprecated in favour of
+.BR sprintf .
+.TP
+.IB variable := expr
+This is similar to
+.B =
+except
+.I variable
+must already be defined,
+and the value of
+.I variable
+will be changed only in the innermost block in which it is defined.
+(By contrast,
+.B =
+defines the variable in the current block if it is not already defined there,
+and then changes the value in the current block.)
+.LP
+Arguments of the form
+.IP
+.IR X\ anything\ X
+.LP
+are also allowed to be of the form
+.IP
+.BI {\ anything\ }
+.LP
+In this case
+.I anything
+can contain balanced occurrences of
+.B {
+and
+.BR } .
+Strings may contain
+.I X
+or imbalanced occurrences of
+.B {
+and
+.BR } .
+.SS Expressions
+The syntax for expressions has been significantly extended:
+.LP
+.IB x\ ^\ y
+(exponentiation)
+.br
+.BI sin( x )
+.br
+.BI cos( x )
+.br
+.BI atan2( y , \ x )
+.br
+.BI log( x )
+(base 10)
+.br
+.BI exp( x )
+(base 10, ie 10\v'-.4m'\fIx\*(ic\fR\v'.4m')
+.br
+.BI sqrt( x )
+.br
+.BI int( x )
+.br
+.B rand()
+(return a random number between 0 and 1)
+.br
+.BI rand( x )
+(return a random number between 1 and
+.IR x ;
+deprecated)
+.br
+.BI srand( x )
+(set the random number seed)
+.br
+.BI max( e1 , \ e2 )
+.br
+.BI min( e1 , \ e2 )
+.br
+.BI ! e
+.br
+\fIe1\fB && \fIe2\fR
+.br
+\fIe1\fB || \fIe2\fR
+.br
+\fIe1\fB == \fIe2\fR
+.br
+\fIe1\fB != \fIe2\fR
+.br
+\fIe1\fB >= \fIe2\fR
+.br
+\fIe1\fB > \fIe2\fR
+.br
+\fIe1\fB <= \fIe2\fR
+.br
+\fIe1\fB < \fIe2\fR
+.br
+\fB"\fIstr1\*(ic\fB" == "\fIstr2\*(ic\fB"\fR
+.br
+\fB"\fIstr1\*(ic\fB" != "\fIstr2\*(ic\fB"\fR
+.br
+.LP
+String comparison expressions must be parenthesised in some contexts
+to avoid ambiguity.
+.SS Other Changes
+.LP
+A bare expression,
+.IR expr ,
+is acceptable as an attribute;
+it is equivalent to
+.IR dir\ expr ,
+where
+.I dir
+is the current direction.
+For example
+.IP
+.B line 2i
+.LP
+means draw a line 2 inches long in the current direction.
+.LP
+The maximum width and height of the picture are taken from the variables
+.B maxpswid
+and
+.BR maxpsht .
+Initially these have values 8.5 and 11.
+.LP
+Scientific notation is allowed for numbers.
+For example
+.RS
+.B
+x = 5e\-2
+.RE
+.LP
+Text attributes can be compounded.
+For example,
+.RS
+.B
+"foo" above ljust
+.RE
+is legal.
+.LP
+There is no limit to the depth to which blocks can be examined.
+For example,
+.RS
+.B
+[A: [B: [C: box ]]] with .A.B.C.sw at 1,2
+.br
+.B
+circle at last [\^].A.B.C
+.RE
+is acceptable.
+.LP
+Arcs now have compass points
+determined by the circle of which the arc is a part.
+.LP
+Circles and arcs can be dotted or dashed.
+In \*(tx mode splines can be dotted or dashed.
+.LP
+Boxes can have rounded corners.
+The
+.B rad
+attribute specifies the radius of the quarter-circles at each corner.
+If no
+.B rad
+or
+.B diam
+attribute is given, a radius of
+.B boxrad
+is used.
+Initially,
+.B boxrad
+has a value of 0.
+A box with rounded corners can be dotted or dashed.
+.LP
+The
+.B .PS
+line can have a second argument specifying a maximum height for
+the picture.
+If the width of zero is specified the width will be ignored in computing
+the scaling factor for the picture.
+Note that GNU pic will always scale a picture by the same amount
+vertically as horizontally.
+This is different from the
+.SM DWB
+2.0 pic which may scale a picture by a
+different amount vertically than horizontally if a height is
+specified.
+.LP
+Each text object has an invisible box associated with it.
+The compass points of a text object are determined by this box.
+The implicit motion associated with the object is also determined
+by this box.
+The dimensions of this box are taken from the width and height attributes;
+if the width attribute is not supplied then the width will be taken to be
+.BR textwid ;
+if the height attribute is not supplied then the height will be taken to be
+the number of text strings associated with the object
+times
+.BR textht .
+Initially
+.B textwid
+and
+.B textht
+have a value of 0.
+.LP
+In places where a quoted text string can be used,
+an expression of the form
+.IP
+.BI sprintf(\(ts format \(ts,\ arg ,\fR.\|.\|.\fB)
+.LP
+can also be used;
+this will produce the arguments formatted according to
+.IR format ,
+which should be a string as described in
+.BR printf (3)
+appropriate for the number of arguments supplied,
+using only the
+.BR e ,
+.BR f ,
+.B g
+or
+.B %
+format characters.
+.LP
+The thickness of the lines used to draw objects is controlled by the
+.B linethick
+variable.
+This gives the thickness of lines in points.
+A negative value means use the default thickness:
+in \*(tx output mode, this means use a thickness of 8 milliinches;
+in \*(tx output mode with the
+.B -c
+option, this means use the line thickness specified by
+.B .ps
+lines;
+in troff output mode, this means use a thickness proportional
+to the pointsize.
+A zero value means draw the thinnest possible line supported by
+the output device.
+Initially it has a value of -1.
+There is also a
+.BR thick [ ness ]
+attribute.
+For example,
+.RS
+.LP
+.B circle thickness 1.5
+.RE
+.LP
+would draw a circle using a line with a thickness of 1.5 points.
+The thickness of lines is not affected by the
+value of the
+.B scale
+variable, nor by the width or height given in the
+.B .PS
+line.
+.LP
+Boxes (including boxes with rounded corners),
+circles and ellipses can be filled by giving then an attribute of
+.BR fill [ ed ].
+This takes an optional argument of an expression with a value between
+0 and 1; 0 will fill it with white, 1 with black, values in between
+with a proportionally gray shade.
+A value greater than 1 can also be used:
+this means fill with the
+shade of gray that is currently being used for text and lines.
+Normally this will be black, but output devices may provide
+a mechanism for changing this.
+Without an argument, then the value of the variable
+.B fillval
+will be used.
+Initially this has a value of 0.5.
+The invisible attribute does not affect the filling of objects.
+Any text associated with a filled object will be added after the
+object has been filled, so that the text will not be obscured
+by the filling.
+.LP
+Arrow heads will be drawn as solid triangles if the variable
+.B arrowhead
+is non-zero and either \*(tx mode is enabled or
+the
+.B \-x
+option has been given.
+Initially
+.B arrowhead
+has a value of 1.
+.LP
+The troff output of pic is device-independent.
+The
+.B \-T
+option is therefore redundant.
+All numbers are taken to be in inches; numbers are never interpreted
+to be in troff machine units.
+.LP
+Objects can have an
+.B aligned
+attribute.
+This will only work when the postprocessor is
+.BR grops .
+Any text associated with an object having the
+.B aligned
+attribute will be rotated about the center of the object
+so that it is aligned in the direction from the start point
+to the end point of the object.
+Note that this attribute will have no effect for objects whose start and
+end points are coincident.
+.LP
+In places where
+.IB n th
+is allowed
+.BI ` expr 'th
+is also allowed.
+Note that
+.B 'th
+is a single token: no space is allowed between the
+.B '
+and the
+.BR th .
+For example,
+.IP
+.B
+.nf
+for i = 1 to 4 do {
+ line from `i'th box.nw to `i+1'th box.se
+}
+.fi
+.SH FILES
+.Tp \w'\fB@MACRODIR@/tmac.pic'u+3n
+.B
+@MACRODIR@/tmac.pic
+Example definitions of the
+.B PS
+and
+.B PE
+macros.
+.SH "SEE ALSO"
+.BR @g@troff (@MAN1EXT@),
+.BR groff_out (@MAN5EXT@),
+.BR tex (1)
+.br
+Tpic: Pic for \*(tx
+.br
+Brian W. Kernighan,
+PIC \(em A Graphics Language for Typesetting (User Manual).
+AT&T Bell Laboratories, Computing Science Technical Report No.\ 116
+<URL:http://cm.bell-labs.com/cm/cs/cstr/116.ps.gz>
+(revised May, 1991).
+.SH BUGS
+.LP
+Input characters that are illegal for
+.B groff
+(ie those with
+.SM ASCII
+code 0 or between 013 and 037 octal or between 0200 and 0237 octal)
+are rejected even in \*(tx mode.
+.LP
+The interpretation of
+.B fillval
+is incompatible with the pic in 10th edition Unix,
+which interprets 0 as black and 1 as white.
diff --git a/src/preproc/pic/pic.tab.h b/src/preproc/pic/pic.tab.h
new file mode 100755
index 00000000..2a3f9d81
--- /dev/null
+++ b/src/preproc/pic/pic.tab.h
@@ -0,0 +1,130 @@
+#define LABEL 257
+#define VARIABLE 258
+#define NUMBER 259
+#define TEXT 260
+#define COMMAND_LINE 261
+#define DELIMITED 262
+#define ORDINAL 263
+#define TH 264
+#define LEFT_ARROW_HEAD 265
+#define RIGHT_ARROW_HEAD 266
+#define DOUBLE_ARROW_HEAD 267
+#define LAST 268
+#define UP 269
+#define DOWN 270
+#define LEFT 271
+#define RIGHT 272
+#define BOX 273
+#define CIRCLE 274
+#define ELLIPSE 275
+#define ARC 276
+#define LINE 277
+#define ARROW 278
+#define MOVE 279
+#define SPLINE 280
+#define HEIGHT 281
+#define RADIUS 282
+#define WIDTH 283
+#define DIAMETER 284
+#define FROM 285
+#define TO 286
+#define AT 287
+#define WITH 288
+#define BY 289
+#define THEN 290
+#define DOTTED 291
+#define DASHED 292
+#define CHOP 293
+#define SAME 294
+#define INVISIBLE 295
+#define LJUST 296
+#define RJUST 297
+#define ABOVE 298
+#define BELOW 299
+#define OF 300
+#define THE 301
+#define WAY 302
+#define BETWEEN 303
+#define AND 304
+#define HERE 305
+#define DOT_N 306
+#define DOT_E 307
+#define DOT_W 308
+#define DOT_S 309
+#define DOT_NE 310
+#define DOT_SE 311
+#define DOT_NW 312
+#define DOT_SW 313
+#define DOT_C 314
+#define DOT_START 315
+#define DOT_END 316
+#define DOT_X 317
+#define DOT_Y 318
+#define DOT_HT 319
+#define DOT_WID 320
+#define DOT_RAD 321
+#define SIN 322
+#define COS 323
+#define ATAN2 324
+#define LOG 325
+#define EXP 326
+#define SQRT 327
+#define K_MAX 328
+#define K_MIN 329
+#define INT 330
+#define RAND 331
+#define SRAND 332
+#define COPY 333
+#define THRU 334
+#define TOP 335
+#define BOTTOM 336
+#define UPPER 337
+#define LOWER 338
+#define SH 339
+#define PRINT 340
+#define CW 341
+#define CCW 342
+#define FOR 343
+#define DO 344
+#define IF 345
+#define ELSE 346
+#define ANDAND 347
+#define OROR 348
+#define NOTEQUAL 349
+#define EQUALEQUAL 350
+#define LESSEQUAL 351
+#define GREATEREQUAL 352
+#define LEFT_CORNER 353
+#define RIGHT_CORNER 354
+#define CENTER 355
+#define END 356
+#define START 357
+#define RESET 358
+#define UNTIL 359
+#define PLOT 360
+#define THICKNESS 361
+#define FILL 362
+#define ALIGNED 363
+#define SPRINTF 364
+#define COMMAND 365
+#define DEFINE 366
+#define UNDEF 367
+typedef union {
+ char *str;
+ int n;
+ double x;
+ struct { double x, y; } pair;
+ struct { double x; char *body; } if_data;
+ struct { char *str; const char *filename; int lineno; } lstr;
+ struct { double *v; int nv; int maxv; } dv;
+ struct { double val; int is_multiplicative; } by;
+ place pl;
+ object *obj;
+ corner crn;
+ path *pth;
+ object_spec *spec;
+ saved_state *pstate;
+ graphics_state state;
+ object_type obtype;
+} YYSTYPE;
+extern YYSTYPE yylval;
diff --git a/src/preproc/pic/pic.y b/src/preproc/pic/pic.y
new file mode 100644
index 00000000..2477085c
--- /dev/null
+++ b/src/preproc/pic/pic.y
@@ -0,0 +1,1803 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+%{
+#include "pic.h"
+#include "ptable.h"
+#include "object.h"
+
+extern int delim_flag;
+extern void do_copy(const char *);
+extern void copy_rest_thru(const char *, const char *);
+extern void copy_file_thru(const char *, const char *, const char *);
+extern void push_body(const char *);
+extern void do_for(char *var, double from, double to,
+ int by_is_multiplicative, double by, char *body);
+extern void do_lookahead();
+
+#ifndef HAVE_FMOD
+extern "C" {
+ double fmod(double, double);
+}
+#endif
+
+#undef rand
+#undef srand
+extern "C" {
+ int rand();
+ void srand(unsigned int);
+}
+
+/* Maximum number of characters produced by printf("%g") */
+#define GDIGITS 14
+
+int yylex();
+void yyerror(const char *);
+
+void reset(const char *nm);
+void reset_all();
+
+place *lookup_label(const char *);
+void define_label(const char *label, const place *pl);
+
+direction current_direction;
+position current_position;
+
+implement_ptable(place)
+
+PTABLE(place) top_table;
+
+PTABLE(place) *current_table = &top_table;
+saved_state *current_saved_state = 0;
+
+object_list olist;
+
+const char *ordinal_postfix(int n);
+const char *object_type_name(object_type type);
+char *format_number(const char *form, double n);
+char *do_sprintf(const char *form, const double *v, int nv);
+
+%}
+
+
+%union {
+ char *str;
+ int n;
+ double x;
+ struct { double x, y; } pair;
+ struct { double x; char *body; } if_data;
+ struct { char *str; const char *filename; int lineno; } lstr;
+ struct { double *v; int nv; int maxv; } dv;
+ struct { double val; int is_multiplicative; } by;
+ place pl;
+ object *obj;
+ corner crn;
+ path *pth;
+ object_spec *spec;
+ saved_state *pstate;
+ graphics_state state;
+ object_type obtype;
+}
+
+%token <str> LABEL
+%token <str> VARIABLE
+%token <x> NUMBER
+%token <lstr> TEXT
+%token <lstr> COMMAND_LINE
+%token <str> DELIMITED
+%token <n> ORDINAL
+%token TH
+%token LEFT_ARROW_HEAD
+%token RIGHT_ARROW_HEAD
+%token DOUBLE_ARROW_HEAD
+%token LAST
+%token UP
+%token DOWN
+%token LEFT
+%token RIGHT
+%token BOX
+%token CIRCLE
+%token ELLIPSE
+%token ARC
+%token LINE
+%token ARROW
+%token MOVE
+%token SPLINE
+%token HEIGHT
+%token RADIUS
+%token WIDTH
+%token DIAMETER
+%token UP
+%token DOWN
+%token RIGHT
+%token LEFT
+%token FROM
+%token TO
+%token AT
+%token WITH
+%token BY
+%token THEN
+%token DOTTED
+%token DASHED
+%token CHOP
+%token SAME
+%token INVISIBLE
+%token LJUST
+%token RJUST
+%token ABOVE
+%token BELOW
+%token OF
+%token THE
+%token WAY
+%token BETWEEN
+%token AND
+%token HERE
+%token DOT_N
+%token DOT_E
+%token DOT_W
+%token DOT_S
+%token DOT_NE
+%token DOT_SE
+%token DOT_NW
+%token DOT_SW
+%token DOT_C
+%token DOT_START
+%token DOT_END
+%token DOT_X
+%token DOT_Y
+%token DOT_HT
+%token DOT_WID
+%token DOT_RAD
+%token SIN
+%token COS
+%token ATAN2
+%token LOG
+%token EXP
+%token SQRT
+%token K_MAX
+%token K_MIN
+%token INT
+%token RAND
+%token SRAND
+%token COPY
+%token THRU
+%token TOP
+%token BOTTOM
+%token UPPER
+%token LOWER
+%token SH
+%token PRINT
+%token CW
+%token CCW
+%token FOR
+%token DO
+%token IF
+%token ELSE
+%token ANDAND
+%token OROR
+%token NOTEQUAL
+%token EQUALEQUAL
+%token LESSEQUAL
+%token GREATEREQUAL
+%token LEFT_CORNER
+%token RIGHT_CORNER
+%token CENTER
+%token END
+%token START
+%token RESET
+%token UNTIL
+%token PLOT
+%token THICKNESS
+%token FILL
+%token ALIGNED
+%token SPRINTF
+%token COMMAND
+
+%token DEFINE
+%token UNDEF
+
+/* this ensures that plot 17 "%g" parses as (plot 17 "%g") */
+%left PLOT
+%left TEXT SPRINTF
+
+/* give text adjustments higher precedence than TEXT, so that
+box "foo" above ljust == box ("foo" above ljust)
+*/
+
+%left LJUST RJUST ABOVE BELOW
+
+%left LEFT RIGHT
+/* Give attributes that take an optional expression a higher
+precedence than left and right, so that eg `line chop left'
+parses properly. */
+%left CHOP DASHED DOTTED UP DOWN FILL
+%left LABEL
+
+%left VARIABLE NUMBER '(' SIN COS ATAN2 LOG EXP SQRT K_MAX K_MIN INT RAND SRAND LAST
+%left ORDINAL HERE '`'
+
+/* these need to be lower than '-' */
+%left HEIGHT RADIUS WIDTH DIAMETER FROM TO AT THICKNESS
+
+/* these must have higher precedence than CHOP so that `label %prec CHOP'
+works */
+%left DOT_N DOT_E DOT_W DOT_S DOT_NE DOT_SE DOT_NW DOT_SW DOT_C
+%left DOT_START DOT_END TOP BOTTOM LEFT_CORNER RIGHT_CORNER
+%left UPPER LOWER CENTER START END
+
+%left ','
+%left OROR
+%left ANDAND
+%left EQUALEQUAL NOTEQUAL
+%left '<' '>' LESSEQUAL GREATEREQUAL
+
+%left BETWEEN OF
+%left AND
+
+%left '+' '-'
+%left '*' '/' '%'
+%right '!'
+%right '^'
+
+%type <x> expr any_expr text_expr
+%type <by> optional_by
+%type <pair> expr_pair position_not_place
+%type <if_data> simple_if
+%type <obj> nth_primitive
+%type <crn> corner
+%type <pth> path label_path relative_path
+%type <pl> place label element element_list middle_element_list
+%type <spec> object_spec
+%type <pair> position
+%type <obtype> object_type
+%type <n> optional_ordinal_last ordinal
+%type <str> until
+%type <dv> sprintf_args
+%type <lstr> text print_args print_arg
+
+%%
+
+top:
+ optional_separator
+ | element_list
+ {
+ if (olist.head)
+ print_picture(olist.head);
+ }
+ ;
+
+
+element_list:
+ optional_separator middle_element_list optional_separator
+ { $$ = $2; }
+ ;
+
+middle_element_list:
+ element
+ { $$ = $1; }
+ | middle_element_list separator element
+ { $$ = $1; }
+ ;
+
+optional_separator:
+ /* empty */
+ | separator
+ ;
+
+separator:
+ ';'
+ | separator ';'
+ ;
+
+placeless_element:
+ VARIABLE '=' any_expr
+ {
+ define_variable($1, $3);
+ a_delete $1;
+ }
+ | VARIABLE ':' '=' any_expr
+ {
+ place *p = lookup_label($1);
+ if (!p) {
+ lex_error("variable `%1' not defined", $1);
+ YYABORT;
+ }
+ p->obj = 0;
+ p->x = $4;
+ p->y = 0.0;
+ a_delete $1;
+ }
+ | UP
+ { current_direction = UP_DIRECTION; }
+ | DOWN
+ { current_direction = DOWN_DIRECTION; }
+ | LEFT
+ { current_direction = LEFT_DIRECTION; }
+ | RIGHT
+ { current_direction = RIGHT_DIRECTION; }
+ | COMMAND_LINE
+ {
+ olist.append(make_command_object($1.str, $1.filename,
+ $1.lineno));
+ }
+ | COMMAND print_args
+ {
+ olist.append(make_command_object($2.str, $2.filename,
+ $2.lineno));
+ }
+ | PRINT print_args
+ {
+ fprintf(stderr, "%s\n", $2.str);
+ a_delete $2.str;
+ fflush(stderr);
+ }
+ | SH
+ { delim_flag = 1; }
+ DELIMITED
+ {
+ delim_flag = 0;
+ if (safer_flag)
+ lex_error("unsafe to run command `%1'", $3);
+ else
+ system($3);
+ a_delete $3;
+ }
+ | COPY TEXT
+ {
+ if (yychar < 0)
+ do_lookahead();
+ do_copy($2.str);
+ // do not delete the filename
+ }
+ | COPY TEXT THRU
+ { delim_flag = 2; }
+ DELIMITED
+ { delim_flag = 0; }
+ until
+ {
+ if (yychar < 0)
+ do_lookahead();
+ copy_file_thru($2.str, $5, $7);
+ // do not delete the filename
+ a_delete $5;
+ a_delete $7;
+ }
+ | COPY THRU
+ { delim_flag = 2; }
+ DELIMITED
+ { delim_flag = 0; }
+ until
+ {
+ if (yychar < 0)
+ do_lookahead();
+ copy_rest_thru($4, $6);
+ a_delete $4;
+ a_delete $6;
+ }
+ | FOR VARIABLE '=' expr TO expr optional_by DO
+ { delim_flag = 1; }
+ DELIMITED
+ {
+ delim_flag = 0;
+ if (yychar < 0)
+ do_lookahead();
+ do_for($2, $4, $6, $7.is_multiplicative, $7.val, $10);
+ }
+ | simple_if
+ {
+ if (yychar < 0)
+ do_lookahead();
+ if ($1.x != 0.0)
+ push_body($1.body);
+ a_delete $1.body;
+ }
+ | simple_if ELSE
+ { delim_flag = 1; }
+ DELIMITED
+ {
+ delim_flag = 0;
+ if (yychar < 0)
+ do_lookahead();
+ if ($1.x != 0.0)
+ push_body($1.body);
+ else
+ push_body($4);
+ a_delete $1.body;
+ a_delete $4;
+ }
+ | reset_variables
+ | RESET
+ { define_variable("scale", 1.0); }
+ ;
+
+reset_variables:
+ RESET VARIABLE
+ { reset($2); a_delete $2; }
+ | reset_variables VARIABLE
+ { reset($2); a_delete $2; }
+ | reset_variables ',' VARIABLE
+ { reset($3); a_delete $3; }
+ ;
+
+print_args:
+ print_arg
+ { $$ = $1; }
+ | print_args print_arg
+ {
+ $$.str = new char[strlen($1.str) + strlen($2.str) + 1];
+ strcpy($$.str, $1.str);
+ strcat($$.str, $2.str);
+ a_delete $1.str;
+ a_delete $2.str;
+ if ($1.filename) {
+ $$.filename = $1.filename;
+ $$.lineno = $1.lineno;
+ }
+ else if ($2.filename) {
+ $$.filename = $2.filename;
+ $$.lineno = $2.lineno;
+ }
+ }
+ ;
+
+print_arg:
+ expr %prec ','
+ {
+ $$.str = new char[GDIGITS + 1];
+ sprintf($$.str, "%g", $1);
+ $$.filename = 0;
+ $$.lineno = 0;
+ }
+ | text
+ { $$ = $1; }
+ | position %prec ','
+ {
+ $$.str = new char[GDIGITS + 2 + GDIGITS + 1];
+ sprintf($$.str, "%g, %g", $1.x, $1.y);
+ $$.filename = 0;
+ $$.lineno = 0;
+ }
+
+simple_if:
+ IF any_expr THEN
+ { delim_flag = 1; }
+ DELIMITED
+ { delim_flag = 0; $$.x = $2; $$.body = $5; }
+ ;
+
+until:
+ /* empty */
+ { $$ = 0; }
+ | UNTIL TEXT
+ { $$ = $2.str; }
+ ;
+
+any_expr:
+ expr
+ { $$ = $1; }
+ | text_expr
+ { $$ = $1; }
+ ;
+
+text_expr:
+ text EQUALEQUAL text
+ {
+ $$ = strcmp($1.str, $3.str) == 0;
+ a_delete $1.str;
+ a_delete $3.str;
+ }
+ | text NOTEQUAL text
+ {
+ $$ = strcmp($1.str, $3.str) != 0;
+ a_delete $1.str;
+ a_delete $3.str;
+ }
+ | text_expr ANDAND text_expr
+ { $$ = ($1 != 0.0 && $3 != 0.0); }
+ | text_expr ANDAND expr
+ { $$ = ($1 != 0.0 && $3 != 0.0); }
+ | expr ANDAND text_expr
+ { $$ = ($1 != 0.0 && $3 != 0.0); }
+ | text_expr OROR text_expr
+ { $$ = ($1 != 0.0 || $3 != 0.0); }
+ | text_expr OROR expr
+ { $$ = ($1 != 0.0 || $3 != 0.0); }
+ | expr OROR text_expr
+ { $$ = ($1 != 0.0 || $3 != 0.0); }
+ | '!' text_expr
+ { $$ = ($2 == 0.0); }
+ ;
+
+
+optional_by:
+ /* empty */
+ { $$.val = 1.0; $$.is_multiplicative = 0; }
+ | BY expr
+ { $$.val = $2; $$.is_multiplicative = 0; }
+ | BY '*' expr
+ { $$.val = $3; $$.is_multiplicative = 1; }
+ ;
+
+element:
+ object_spec
+ {
+ $$.obj = $1->make_object(&current_position,
+ &current_direction);
+ if ($$.obj == 0)
+ YYABORT;
+ delete $1;
+ if ($$.obj)
+ olist.append($$.obj);
+ else {
+ $$.x = current_position.x;
+ $$.y = current_position.y;
+ }
+ }
+ | LABEL ':' optional_separator element
+ { $$ = $4; define_label($1, & $$); a_delete $1; }
+ | LABEL ':' optional_separator position_not_place
+ {
+ $$.obj = 0;
+ $$.x = $4.x;
+ $$.y = $4.y;
+ define_label($1, & $$);
+ a_delete $1;
+ }
+ | LABEL ':' optional_separator place
+ {
+ $$ = $4;
+ define_label($1, & $$);
+ a_delete $1;
+ }
+ | '{'
+ {
+ $<state>$.x = current_position.x;
+ $<state>$.y = current_position.y;
+ $<state>$.dir = current_direction;
+ }
+ element_list '}'
+ {
+ current_position.x = $<state>2.x;
+ current_position.y = $<state>2.y;
+ current_direction = $<state>2.dir;
+ }
+ optional_element
+ {
+ $$ = $3;
+ }
+ | placeless_element
+ {
+ $$.obj = 0;
+ $$.x = current_position.x;
+ $$.y = current_position.y;
+ }
+ ;
+
+optional_element:
+ /* empty */
+ {}
+ | element
+ {}
+ ;
+
+object_spec:
+ BOX
+ {
+ $$ = new object_spec(BOX_OBJECT);
+ }
+ | CIRCLE
+ {
+ $$ = new object_spec(CIRCLE_OBJECT);
+ }
+ | ELLIPSE
+ {
+ $$ = new object_spec(ELLIPSE_OBJECT);
+ }
+ | ARC
+ {
+ $$ = new object_spec(ARC_OBJECT);
+ $$->dir = current_direction;
+ }
+ | LINE
+ {
+ $$ = new object_spec(LINE_OBJECT);
+ lookup_variable("lineht", & $$->segment_height);
+ lookup_variable("linewid", & $$->segment_width);
+ $$->dir = current_direction;
+ }
+ | ARROW
+ {
+ $$ = new object_spec(ARROW_OBJECT);
+ lookup_variable("lineht", & $$->segment_height);
+ lookup_variable("linewid", & $$->segment_width);
+ $$->dir = current_direction;
+ }
+ | MOVE
+ {
+ $$ = new object_spec(MOVE_OBJECT);
+ lookup_variable("moveht", & $$->segment_height);
+ lookup_variable("movewid", & $$->segment_width);
+ $$->dir = current_direction;
+ }
+ | SPLINE
+ {
+ $$ = new object_spec(SPLINE_OBJECT);
+ lookup_variable("lineht", & $$->segment_height);
+ lookup_variable("linewid", & $$->segment_width);
+ $$->dir = current_direction;
+ }
+ | text %prec TEXT
+ {
+ $$ = new object_spec(TEXT_OBJECT);
+ $$->text = new text_item($1.str, $1.filename, $1.lineno);
+ }
+ | PLOT expr
+ {
+ $$ = new object_spec(TEXT_OBJECT);
+ $$->text = new text_item(format_number(0, $2), 0, -1);
+ }
+ | PLOT expr text
+ {
+ $$ = new object_spec(TEXT_OBJECT);
+ $$->text = new text_item(format_number($3.str, $2),
+ $3.filename, $3.lineno);
+ a_delete $3.str;
+ }
+ | '['
+ {
+ saved_state *p = new saved_state;
+ $<pstate>$ = p;
+ p->x = current_position.x;
+ p->y = current_position.y;
+ p->dir = current_direction;
+ p->tbl = current_table;
+ p->prev = current_saved_state;
+ current_position.x = 0.0;
+ current_position.y = 0.0;
+ current_table = new PTABLE(place);
+ current_saved_state = p;
+ olist.append(make_mark_object());
+ }
+ element_list ']'
+ {
+ current_position.x = $<pstate>2->x;
+ current_position.y = $<pstate>2->y;
+ current_direction = $<pstate>2->dir;
+ $$ = new object_spec(BLOCK_OBJECT);
+ olist.wrap_up_block(& $$->oblist);
+ $$->tbl = current_table;
+ current_table = $<pstate>2->tbl;
+ current_saved_state = $<pstate>2->prev;
+ delete $<pstate>2;
+ }
+ | object_spec HEIGHT expr
+ {
+ $$ = $1;
+ $$->height = $3;
+ $$->flags |= HAS_HEIGHT;
+ }
+ | object_spec RADIUS expr
+ {
+ $$ = $1;
+ $$->radius = $3;
+ $$->flags |= HAS_RADIUS;
+ }
+ | object_spec WIDTH expr
+ {
+ $$ = $1;
+ $$->width = $3;
+ $$->flags |= HAS_WIDTH;
+ }
+ | object_spec DIAMETER expr
+ {
+ $$ = $1;
+ $$->radius = $3/2.0;
+ $$->flags |= HAS_RADIUS;
+ }
+ | object_spec expr %prec HEIGHT
+ {
+ $$ = $1;
+ $$->flags |= HAS_SEGMENT;
+ switch ($$->dir) {
+ case UP_DIRECTION:
+ $$->segment_pos.y += $2;
+ break;
+ case DOWN_DIRECTION:
+ $$->segment_pos.y -= $2;
+ break;
+ case RIGHT_DIRECTION:
+ $$->segment_pos.x += $2;
+ break;
+ case LEFT_DIRECTION:
+ $$->segment_pos.x -= $2;
+ break;
+ }
+ }
+ | object_spec UP
+ {
+ $$ = $1;
+ $$->dir = UP_DIRECTION;
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.y += $$->segment_height;
+ }
+ | object_spec UP expr
+ {
+ $$ = $1;
+ $$->dir = UP_DIRECTION;
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.y += $3;
+ }
+ | object_spec DOWN
+ {
+ $$ = $1;
+ $$->dir = DOWN_DIRECTION;
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.y -= $$->segment_height;
+ }
+ | object_spec DOWN expr
+ {
+ $$ = $1;
+ $$->dir = DOWN_DIRECTION;
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.y -= $3;
+ }
+ | object_spec RIGHT
+ {
+ $$ = $1;
+ $$->dir = RIGHT_DIRECTION;
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.x += $$->segment_width;
+ }
+ | object_spec RIGHT expr
+ {
+ $$ = $1;
+ $$->dir = RIGHT_DIRECTION;
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.x += $3;
+ }
+ | object_spec LEFT
+ {
+ $$ = $1;
+ $$->dir = LEFT_DIRECTION;
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.x -= $$->segment_width;
+ }
+ | object_spec LEFT expr
+ {
+ $$ = $1;
+ $$->dir = LEFT_DIRECTION;
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.x -= $3;
+ }
+ | object_spec FROM position
+ {
+ $$ = $1;
+ $$->flags |= HAS_FROM;
+ $$->from.x = $3.x;
+ $$->from.y = $3.y;
+ }
+ | object_spec TO position
+ {
+ $$ = $1;
+ if ($$->flags & HAS_SEGMENT)
+ $$->segment_list = new segment($$->segment_pos,
+ $$->segment_is_absolute,
+ $$->segment_list);
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.x = $3.x;
+ $$->segment_pos.y = $3.y;
+ $$->segment_is_absolute = 1;
+ $$->flags |= HAS_TO;
+ $$->to.x = $3.x;
+ $$->to.y = $3.y;
+ }
+ | object_spec AT position
+ {
+ $$ = $1;
+ $$->flags |= HAS_AT;
+ $$->at.x = $3.x;
+ $$->at.y = $3.y;
+ if ($$->type != ARC_OBJECT) {
+ $$->flags |= HAS_FROM;
+ $$->from.x = $3.x;
+ $$->from.y = $3.y;
+ }
+ }
+ | object_spec WITH path
+ {
+ $$ = $1;
+ $$->flags |= HAS_WITH;
+ $$->with = $3;
+ }
+ | object_spec BY expr_pair
+ {
+ $$ = $1;
+ $$->flags |= HAS_SEGMENT;
+ $$->segment_pos.x += $3.x;
+ $$->segment_pos.y += $3.y;
+ }
+ | object_spec THEN
+ {
+ $$ = $1;
+ if ($$->flags & HAS_SEGMENT) {
+ $$->segment_list = new segment($$->segment_pos,
+ $$->segment_is_absolute,
+ $$->segment_list);
+ $$->flags &= ~HAS_SEGMENT;
+ $$->segment_pos.x = $$->segment_pos.y = 0.0;
+ $$->segment_is_absolute = 0;
+ }
+ }
+ | object_spec DOTTED
+ {
+ $$ = $1;
+ $$->flags |= IS_DOTTED;
+ lookup_variable("dashwid", & $$->dash_width);
+ }
+ | object_spec DOTTED expr
+ {
+ $$ = $1;
+ $$->flags |= IS_DOTTED;
+ $$->dash_width = $3;
+ }
+ | object_spec DASHED
+ {
+ $$ = $1;
+ $$->flags |= IS_DASHED;
+ lookup_variable("dashwid", & $$->dash_width);
+ }
+ | object_spec DASHED expr
+ {
+ $$ = $1;
+ $$->flags |= IS_DASHED;
+ $$->dash_width = $3;
+ }
+ | object_spec FILL
+ {
+ $$ = $1;
+ $$->flags |= IS_DEFAULT_FILLED;
+ }
+ | object_spec FILL expr
+ {
+ $$ = $1;
+ $$->flags |= IS_FILLED;
+ $$->fill = $3;
+ }
+ | object_spec CHOP
+ {
+ $$ = $1;
+ // line chop chop means line chop 0 chop 0
+ if ($$->flags & IS_DEFAULT_CHOPPED) {
+ $$->flags |= IS_CHOPPED;
+ $$->flags &= ~IS_DEFAULT_CHOPPED;
+ $$->start_chop = $$->end_chop = 0.0;
+ }
+ else if ($$->flags & IS_CHOPPED) {
+ $$->end_chop = 0.0;
+ }
+ else {
+ $$->flags |= IS_DEFAULT_CHOPPED;
+ }
+ }
+ | object_spec CHOP expr
+ {
+ $$ = $1;
+ if ($$->flags & IS_DEFAULT_CHOPPED) {
+ $$->flags |= IS_CHOPPED;
+ $$->flags &= ~IS_DEFAULT_CHOPPED;
+ $$->start_chop = 0.0;
+ $$->end_chop = $3;
+ }
+ else if ($$->flags & IS_CHOPPED) {
+ $$->end_chop = $3;
+ }
+ else {
+ $$->start_chop = $$->end_chop = $3;
+ $$->flags |= IS_CHOPPED;
+ }
+ }
+ | object_spec SAME
+ {
+ $$ = $1;
+ $$->flags |= IS_SAME;
+ }
+ | object_spec INVISIBLE
+ {
+ $$ = $1;
+ $$->flags |= IS_INVISIBLE;
+ }
+ | object_spec LEFT_ARROW_HEAD
+ {
+ $$ = $1;
+ $$->flags |= HAS_LEFT_ARROW_HEAD;
+ }
+ | object_spec RIGHT_ARROW_HEAD
+ {
+ $$ = $1;
+ $$->flags |= HAS_RIGHT_ARROW_HEAD;
+ }
+ | object_spec DOUBLE_ARROW_HEAD
+ {
+ $$ = $1;
+ $$->flags |= (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD);
+ }
+ | object_spec CW
+ {
+ $$ = $1;
+ $$->flags |= IS_CLOCKWISE;
+ }
+ | object_spec CCW
+ {
+ $$ = $1;
+ $$->flags &= ~IS_CLOCKWISE;
+ }
+ | object_spec text %prec TEXT
+ {
+ $$ = $1;
+ text_item **p;
+ for (p = & $$->text; *p; p = &(*p)->next)
+ ;
+ *p = new text_item($2.str, $2.filename, $2.lineno);
+ }
+ | object_spec LJUST
+ {
+ $$ = $1;
+ if ($$->text) {
+ text_item *p;
+ for (p = $$->text; p->next; p = p->next)
+ ;
+ p->adj.h = LEFT_ADJUST;
+ }
+ }
+ | object_spec RJUST
+ {
+ $$ = $1;
+ if ($$->text) {
+ text_item *p;
+ for (p = $$->text; p->next; p = p->next)
+ ;
+ p->adj.h = RIGHT_ADJUST;
+ }
+ }
+ | object_spec ABOVE
+ {
+ $$ = $1;
+ if ($$->text) {
+ text_item *p;
+ for (p = $$->text; p->next; p = p->next)
+ ;
+ p->adj.v = ABOVE_ADJUST;
+ }
+ }
+ | object_spec BELOW
+ {
+ $$ = $1;
+ if ($$->text) {
+ text_item *p;
+ for (p = $$->text; p->next; p = p->next)
+ ;
+ p->adj.v = BELOW_ADJUST;
+ }
+ }
+ | object_spec THICKNESS expr
+ {
+ $$ = $1;
+ $$->flags |= HAS_THICKNESS;
+ $$->thickness = $3;
+ }
+ | object_spec ALIGNED
+ {
+ $$ = $1;
+ $$->flags |= IS_ALIGNED;
+ }
+ ;
+
+text:
+ TEXT
+ {
+ $$ = $1;
+ }
+ | SPRINTF '(' TEXT sprintf_args ')'
+ {
+ $$.filename = $3.filename;
+ $$.lineno = $3.lineno;
+ $$.str = do_sprintf($3.str, $4.v, $4.nv);
+ a_delete $4.v;
+ a_delete $3.str;
+ }
+ ;
+
+sprintf_args:
+ /* empty */
+ {
+ $$.v = 0;
+ $$.nv = 0;
+ $$.maxv = 0;
+ }
+ | sprintf_args ',' expr
+ {
+ $$ = $1;
+ if ($$.nv >= $$.maxv) {
+ if ($$.nv == 0) {
+ $$.v = new double[4];
+ $$.maxv = 4;
+ }
+ else {
+ double *oldv = $$.v;
+ $$.maxv *= 2;
+ $$.v = new double[$$.maxv];
+ memcpy($$.v, oldv, $$.nv*sizeof(double));
+ a_delete oldv;
+ }
+ }
+ $$.v[$$.nv] = $3;
+ $$.nv += 1;
+ }
+ ;
+
+position:
+ position_not_place
+ { $$ = $1; }
+ | place
+ {
+ position pos = $1;
+ $$.x = pos.x;
+ $$.y = pos.y;
+ }
+ ;
+
+position_not_place:
+ expr_pair
+ { $$ = $1; }
+ | position '+' expr_pair
+ {
+ $$.x = $1.x + $3.x;
+ $$.y = $1.y + $3.y;
+ }
+ | position '-' expr_pair
+ {
+ $$.x = $1.x - $3.x;
+ $$.y = $1.y - $3.y;
+ }
+ | '(' position ',' position ')'
+ {
+ $$.x = $2.x;
+ $$.y = $4.y;
+ }
+ | expr between position AND position
+ {
+ $$.x = (1.0 - $1)*$3.x + $1*$5.x;
+ $$.y = (1.0 - $1)*$3.y + $1*$5.y;
+ }
+ | expr '<' position ',' position '>'
+ {
+ $$.x = (1.0 - $1)*$3.x + $1*$5.x;
+ $$.y = (1.0 - $1)*$3.y + $1*$5.y;
+ }
+ ;
+
+between:
+ BETWEEN
+ | OF THE WAY BETWEEN
+ ;
+
+expr_pair:
+ expr ',' expr
+ { $$.x = $1; $$.y = $3; }
+ | '(' expr_pair ')'
+ { $$ = $2; }
+ ;
+
+place:
+ label %prec CHOP /* line at A left == line (at A) left */
+ { $$ = $1; }
+ | label corner
+ {
+ path pth($2);
+ if (!pth.follow($1, & $$))
+ YYABORT;
+ }
+ | corner label
+ {
+ path pth($1);
+ if (!pth.follow($2, & $$))
+ YYABORT;
+ }
+ | corner OF label
+ {
+ path pth($1);
+ if (!pth.follow($3, & $$))
+ YYABORT;
+ }
+ | HERE
+ {
+ $$.x = current_position.x;
+ $$.y = current_position.y;
+ $$.obj = 0;
+ }
+ ;
+
+label:
+ LABEL
+ {
+ place *p = lookup_label($1);
+ if (!p) {
+ lex_error("there is no place `%1'", $1);
+ YYABORT;
+ }
+ $$ = *p;
+ a_delete $1;
+ }
+ | nth_primitive
+ {
+ $$.obj = $1;
+ }
+ | label '.' LABEL
+ {
+ path pth($3);
+ if (!pth.follow($1, & $$))
+ YYABORT;
+ }
+ ;
+
+ordinal:
+ ORDINAL
+ { $$ = $1; }
+ | '`' any_expr TH
+ {
+ // XXX Check for overflow (and non-integers?).
+ $$ = (int)$2;
+ }
+ ;
+
+optional_ordinal_last:
+ LAST
+ { $$ = 1; }
+ | ordinal LAST
+ { $$ = $1; }
+ ;
+
+nth_primitive:
+ ordinal object_type
+ {
+ int count = 0;
+ object *p;
+ for (p = olist.head; p != 0; p = p->next)
+ if (p->type() == $2 && ++count == $1) {
+ $$ = p;
+ break;
+ }
+ if (p == 0) {
+ lex_error("there is no %1%2 %3", $1, ordinal_postfix($1),
+ object_type_name($2));
+ YYABORT;
+ }
+ }
+ | optional_ordinal_last object_type
+ {
+ int count = 0;
+ object *p;
+ for (p = olist.tail; p != 0; p = p->prev)
+ if (p->type() == $2 && ++count == $1) {
+ $$ = p;
+ break;
+ }
+ if (p == 0) {
+ lex_error("there is no %1%2 last %3", $1,
+ ordinal_postfix($1), object_type_name($2));
+ YYABORT;
+ }
+ }
+ ;
+
+object_type:
+ BOX
+ { $$ = BOX_OBJECT; }
+ | CIRCLE
+ { $$ = CIRCLE_OBJECT; }
+ | ELLIPSE
+ { $$ = ELLIPSE_OBJECT; }
+ | ARC
+ { $$ = ARC_OBJECT; }
+ | LINE
+ { $$ = LINE_OBJECT; }
+ | ARROW
+ { $$ = ARROW_OBJECT; }
+ | SPLINE
+ { $$ = SPLINE_OBJECT; }
+ | '[' ']'
+ { $$ = BLOCK_OBJECT; }
+ | TEXT
+ { $$ = TEXT_OBJECT; }
+ ;
+
+label_path:
+ '.' LABEL
+ {
+ $$ = new path($2);
+ }
+ | label_path '.' LABEL
+ {
+ $$ = $1;
+ $$->append($3);
+ }
+ ;
+
+relative_path:
+ corner
+ {
+ $$ = new path($1);
+ }
+ /* give this a lower precedence than LEFT and RIGHT so that
+ [A: box] with .A left == [A: box] with (.A left) */
+
+ | label_path %prec TEXT
+ {
+ $$ = $1;
+ }
+ | label_path corner
+ {
+ $$ = $1;
+ $$->append($2);
+ }
+ ;
+
+path:
+ relative_path
+ {
+ $$ = $1;
+ }
+ | '(' relative_path ',' relative_path ')'
+ {
+ $$ = $2;
+ $$->set_ypath($4);
+ }
+ /* The rest of these rules are a compatibility sop. */
+ | ORDINAL LAST object_type relative_path
+ {
+ lex_warning("`%1%2 last %3' in `with' argument ignored",
+ $1, ordinal_postfix($1), object_type_name($3));
+ $$ = $4;
+ }
+ | LAST object_type relative_path
+ {
+ lex_warning("`last %1' in `with' argument ignored",
+ object_type_name($2));
+ $$ = $3;
+ }
+ | ORDINAL object_type relative_path
+ {
+ lex_warning("`%1%2 %3' in `with' argument ignored",
+ $1, ordinal_postfix($1), object_type_name($2));
+ $$ = $3;
+ }
+ | LABEL relative_path
+ {
+ lex_warning("initial `%1' in `with' argument ignored", $1);
+ a_delete $1;
+ $$ = $2;
+ }
+ ;
+
+corner:
+ DOT_N
+ { $$ = &object::north; }
+ | DOT_E
+ { $$ = &object::east; }
+ | DOT_W
+ { $$ = &object::west; }
+ | DOT_S
+ { $$ = &object::south; }
+ | DOT_NE
+ { $$ = &object::north_east; }
+ | DOT_SE
+ { $$ = &object:: south_east; }
+ | DOT_NW
+ { $$ = &object::north_west; }
+ | DOT_SW
+ { $$ = &object::south_west; }
+ | DOT_C
+ { $$ = &object::center; }
+ | DOT_START
+ { $$ = &object::start; }
+ | DOT_END
+ { $$ = &object::end; }
+ | TOP
+ { $$ = &object::north; }
+ | BOTTOM
+ { $$ = &object::south; }
+ | LEFT
+ { $$ = &object::west; }
+ | RIGHT
+ { $$ = &object::east; }
+ | UPPER LEFT
+ { $$ = &object::north_west; }
+ | LOWER LEFT
+ { $$ = &object::south_west; }
+ | UPPER RIGHT
+ { $$ = &object::north_east; }
+ | LOWER RIGHT
+ { $$ = &object::south_east; }
+ | LEFT_CORNER
+ { $$ = &object::west; }
+ | RIGHT_CORNER
+ { $$ = &object::east; }
+ | UPPER LEFT_CORNER
+ { $$ = &object::north_west; }
+ | LOWER LEFT_CORNER
+ { $$ = &object::south_west; }
+ | UPPER RIGHT_CORNER
+ { $$ = &object::north_east; }
+ | LOWER RIGHT_CORNER
+ { $$ = &object::south_east; }
+ | CENTER
+ { $$ = &object::center; }
+ | START
+ { $$ = &object::start; }
+ | END
+ { $$ = &object::end; }
+ ;
+
+expr:
+ VARIABLE
+ {
+ if (!lookup_variable($1, & $$)) {
+ lex_error("there is no variable `%1'", $1);
+ YYABORT;
+ }
+ a_delete $1;
+ }
+ | NUMBER
+ { $$ = $1; }
+ | place DOT_X
+ {
+ if ($1.obj != 0)
+ $$ = $1.obj->origin().x;
+ else
+ $$ = $1.x;
+ }
+ | place DOT_Y
+ {
+ if ($1.obj != 0)
+ $$ = $1.obj->origin().y;
+ else
+ $$ = $1.y;
+ }
+ | place DOT_HT
+ {
+ if ($1.obj != 0)
+ $$ = $1.obj->height();
+ else
+ $$ = 0.0;
+ }
+ | place DOT_WID
+ {
+ if ($1.obj != 0)
+ $$ = $1.obj->width();
+ else
+ $$ = 0.0;
+ }
+ | place DOT_RAD
+ {
+ if ($1.obj != 0)
+ $$ = $1.obj->radius();
+ else
+ $$ = 0.0;
+ }
+ | expr '+' expr
+ { $$ = $1 + $3; }
+ | expr '-' expr
+ { $$ = $1 - $3; }
+ | expr '*' expr
+ { $$ = $1 * $3; }
+ | expr '/' expr
+ {
+ if ($3 == 0.0) {
+ lex_error("division by zero");
+ YYABORT;
+ }
+ $$ = $1/$3;
+ }
+ | expr '%' expr
+ {
+ if ($3 == 0.0) {
+ lex_error("modulus by zero");
+ YYABORT;
+ }
+ $$ = fmod($1, $3);
+ }
+ | expr '^' expr
+ {
+ errno = 0;
+ $$ = pow($1, $3);
+ if (errno == EDOM) {
+ lex_error("arguments to `^' operator out of domain");
+ YYABORT;
+ }
+ if (errno == ERANGE) {
+ lex_error("result of `^' operator out of range");
+ YYABORT;
+ }
+ }
+ | '-' expr %prec '!'
+ { $$ = -$2; }
+ | '(' any_expr ')'
+ { $$ = $2; }
+ | SIN '(' any_expr ')'
+ {
+ errno = 0;
+ $$ = sin($3);
+ if (errno == ERANGE) {
+ lex_error("sin result out of range");
+ YYABORT;
+ }
+ }
+ | COS '(' any_expr ')'
+ {
+ errno = 0;
+ $$ = cos($3);
+ if (errno == ERANGE) {
+ lex_error("cos result out of range");
+ YYABORT;
+ }
+ }
+ | ATAN2 '(' any_expr ',' any_expr ')'
+ {
+ errno = 0;
+ $$ = atan2($3, $5);
+ if (errno == EDOM) {
+ lex_error("atan2 argument out of domain");
+ YYABORT;
+ }
+ if (errno == ERANGE) {
+ lex_error("atan2 result out of range");
+ YYABORT;
+ }
+ }
+ | LOG '(' any_expr ')'
+ {
+ errno = 0;
+ $$ = log10($3);
+ if (errno == ERANGE) {
+ lex_error("log result out of range");
+ YYABORT;
+ }
+ }
+ | EXP '(' any_expr ')'
+ {
+ errno = 0;
+ $$ = pow(10.0, $3);
+ if (errno == ERANGE) {
+ lex_error("exp result out of range");
+ YYABORT;
+ }
+ }
+ | SQRT '(' any_expr ')'
+ {
+ errno = 0;
+ $$ = sqrt($3);
+ if (errno == EDOM) {
+ lex_error("sqrt argument out of domain");
+ YYABORT;
+ }
+ }
+ | K_MAX '(' any_expr ',' any_expr ')'
+ { $$ = $3 > $5 ? $3 : $5; }
+ | K_MIN '(' any_expr ',' any_expr ')'
+ { $$ = $3 < $5 ? $3 : $5; }
+ | INT '(' any_expr ')'
+ { $$ = floor($3); }
+ | RAND '(' any_expr ')'
+ { $$ = 1.0 + floor(((rand()&0x7fff)/double(0x7fff))*$3); }
+ | RAND '(' ')'
+ {
+ /* return a random number in the range [0,1) */
+ /* portable, but not very random */
+ $$ = (rand() & 0x7fff) / double(0x8000);
+ }
+ | SRAND '(' any_expr ')'
+ { $$ = 0; srand((unsigned int)$3); }
+ | expr '<' expr
+ { $$ = ($1 < $3); }
+ | expr LESSEQUAL expr
+ { $$ = ($1 <= $3); }
+ | expr '>' expr
+ { $$ = ($1 > $3); }
+ | expr GREATEREQUAL expr
+ { $$ = ($1 >= $3); }
+ | expr EQUALEQUAL expr
+ { $$ = ($1 == $3); }
+ | expr NOTEQUAL expr
+ { $$ = ($1 != $3); }
+ | expr ANDAND expr
+ { $$ = ($1 != 0.0 && $3 != 0.0); }
+ | expr OROR expr
+ { $$ = ($1 != 0.0 || $3 != 0.0); }
+ | '!' expr
+ { $$ = ($2 == 0.0); }
+
+ ;
+
+%%
+
+/* bison defines const to be empty unless __STDC__ is defined, which it
+isn't under cfront */
+
+#ifdef const
+#undef const
+#endif
+
+static struct {
+ const char *name;
+ double val;
+ int scaled; // non-zero if val should be multiplied by scale
+} defaults_table[] = {
+ { "arcrad", .25, 1 },
+ { "arrowht", .1, 1 },
+ { "arrowwid", .05, 1 },
+ { "circlerad", .25, 1 },
+ { "boxht", .5, 1 },
+ { "boxwid", .75, 1 },
+ { "boxrad", 0.0, 1 },
+ { "dashwid", .05, 1 },
+ { "ellipseht", .5, 1 },
+ { "ellipsewid", .75, 1 },
+ { "moveht", .5, 1 },
+ { "movewid", .5, 1 },
+ { "lineht", .5, 1 },
+ { "linewid", .5, 1 },
+ { "textht", 0.0, 1 },
+ { "textwid", 0.0, 1 },
+ { "scale", 1.0, 0 },
+ { "linethick", -1.0, 0 }, // in points
+ { "fillval", .5, 0 },
+ { "arrowhead", 1.0, 0 },
+ { "maxpswid", 8.5, 0 },
+ { "maxpsht", 11.0, 0 },
+};
+
+place *lookup_label(const char *label)
+{
+ saved_state *state = current_saved_state;
+ PTABLE(place) *tbl = current_table;
+ for (;;) {
+ place *pl = tbl->lookup(label);
+ if (pl)
+ return pl;
+ if (!state)
+ return 0;
+ tbl = state->tbl;
+ state = state->prev;
+ }
+}
+
+void define_label(const char *label, const place *pl)
+{
+ place *p = new place;
+ *p = *pl;
+ current_table->define(label, p);
+}
+
+int lookup_variable(const char *name, double *val)
+{
+ place *pl = lookup_label(name);
+ if (pl) {
+ *val = pl->x;
+ return 1;
+ }
+ return 0;
+}
+
+void define_variable(const char *name, double val)
+{
+ place *p = new place;
+ p->obj = 0;
+ p->x = val;
+ p->y = 0.0;
+ current_table->define(name, p);
+ if (strcmp(name, "scale") == 0) {
+ // When the scale changes, reset all scaled pre-defined variables to
+ // their default values.
+ for (int i = 0; i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++)
+ if (defaults_table[i].scaled)
+ define_variable(defaults_table[i].name, val*defaults_table[i].val);
+ }
+}
+
+// called once only (not once per parse)
+
+void parse_init()
+{
+ current_direction = RIGHT_DIRECTION;
+ current_position.x = 0.0;
+ current_position.y = 0.0;
+ // This resets everything to its default value.
+ reset_all();
+}
+
+void reset(const char *nm)
+{
+ for (int i = 0; i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++)
+ if (strcmp(nm, defaults_table[i].name) == 0) {
+ double val = defaults_table[i].val;
+ if (defaults_table[i].scaled) {
+ double scale;
+ lookup_variable("scale", &scale);
+ val *= scale;
+ }
+ define_variable(defaults_table[i].name, val);
+ return;
+ }
+ lex_error("`%1' is not a predefined variable", nm);
+}
+
+void reset_all()
+{
+ // We only have to explicitly reset the pre-defined variables that
+ // aren't scaled because `scale' is not scaled, and changing the
+ // value of `scale' will reset all the pre-defined variables that
+ // are scaled.
+ for (int i = 0; i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++)
+ if (!defaults_table[i].scaled)
+ define_variable(defaults_table[i].name, defaults_table[i].val);
+}
+
+// called after each parse
+
+void parse_cleanup()
+{
+ while (current_saved_state != 0) {
+ delete current_table;
+ current_table = current_saved_state->tbl;
+ saved_state *tem = current_saved_state;
+ current_saved_state = current_saved_state->prev;
+ delete tem;
+ }
+ assert(current_table == &top_table);
+ PTABLE_ITERATOR(place) iter(current_table);
+ const char *key;
+ place *pl;
+ while (iter.next(&key, &pl))
+ if (pl->obj != 0) {
+ position pos = pl->obj->origin();
+ pl->obj = 0;
+ pl->x = pos.x;
+ pl->y = pos.y;
+ }
+ while (olist.head != 0) {
+ object *tem = olist.head;
+ olist.head = olist.head->next;
+ delete tem;
+ }
+ olist.tail = 0;
+ current_direction = RIGHT_DIRECTION;
+ current_position.x = 0.0;
+ current_position.y = 0.0;
+}
+
+const char *ordinal_postfix(int n)
+{
+ if (n < 10 || n > 20)
+ switch (n % 10) {
+ case 1:
+ return "st";
+ case 2:
+ return "nd";
+ case 3:
+ return "rd";
+ }
+ return "th";
+}
+
+const char *object_type_name(object_type type)
+{
+ switch (type) {
+ case BOX_OBJECT:
+ return "box";
+ case CIRCLE_OBJECT:
+ return "circle";
+ case ELLIPSE_OBJECT:
+ return "ellipse";
+ case ARC_OBJECT:
+ return "arc";
+ case SPLINE_OBJECT:
+ return "spline";
+ case LINE_OBJECT:
+ return "line";
+ case ARROW_OBJECT:
+ return "arrow";
+ case MOVE_OBJECT:
+ return "move";
+ case TEXT_OBJECT:
+ return "\"\"";
+ case BLOCK_OBJECT:
+ return "[]";
+ case OTHER_OBJECT:
+ case MARK_OBJECT:
+ default:
+ break;
+ }
+ return "object";
+}
+
+static char sprintf_buf[1024];
+
+char *format_number(const char *form, double n)
+{
+ if (form == 0)
+ form = "%g";
+ else {
+ // this is a fairly feeble attempt at validation of the format
+ int nspecs = 0;
+ for (const char *p = form; *p != '\0'; p++)
+ if (*p == '%') {
+ if (p[1] == '%')
+ p++;
+ else
+ nspecs++;
+ }
+ if (nspecs > 1) {
+ lex_error("bad format `%1'", form);
+ return strsave(form);
+ }
+ }
+ sprintf(sprintf_buf, form, n);
+ return strsave(sprintf_buf);
+}
+
+char *do_sprintf(const char *form, const double *v, int nv)
+{
+ string result;
+ int i = 0;
+ string one_format;
+ while (*form) {
+ if (*form == '%') {
+ one_format += *form++;
+ for (; *form != '\0' && strchr("#-+ 0123456789.", *form) != 0; form++)
+ one_format += *form;
+ if (*form == '\0' || strchr("eEfgG%", *form) == 0) {
+ lex_error("bad sprintf format");
+ result += one_format;
+ result += form;
+ break;
+ }
+ if (*form == '%') {
+ one_format += *form++;
+ one_format += '\0';
+ sprintf(sprintf_buf, one_format.contents());
+ }
+ else {
+ if (i >= nv) {
+ lex_error("too few arguments to sprintf");
+ result += one_format;
+ result += form;
+ break;
+ }
+ one_format += *form++;
+ one_format += '\0';
+ sprintf(sprintf_buf, one_format.contents(), v[i++]);
+ }
+ one_format.clear();
+ result += sprintf_buf;
+ }
+ else
+ result += *form++;
+ }
+ result += '\0';
+ return strsave(result.contents());
+}
diff --git a/src/preproc/pic/position.h b/src/preproc/pic/position.h
new file mode 100644
index 00000000..ab7d5469
--- /dev/null
+++ b/src/preproc/pic/position.h
@@ -0,0 +1,47 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+struct place;
+struct position {
+ double x;
+ double y;
+ position(double, double );
+ position();
+ position(const place &);
+ position &operator+=(const position &);
+ position &operator-=(const position &);
+ position &operator*=(double);
+ position &operator/=(double);
+};
+
+position operator-(const position &);
+position operator+(const position &, const position &);
+position operator-(const position &, const position &);
+position operator/(const position &, double);
+position operator*(const position &, double);
+// dot product
+double operator*(const position &, const position &);
+int operator==(const position &, const position &);
+int operator!=(const position &, const position &);
+
+double hypot(const position &a);
+
+typedef position distance;
+
diff --git a/src/preproc/pic/tex.cc b/src/preproc/pic/tex.cc
new file mode 100644
index 00000000..2a91b621
--- /dev/null
+++ b/src/preproc/pic/tex.cc
@@ -0,0 +1,412 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "pic.h"
+
+#ifdef TEX_SUPPORT
+
+#include "common.h"
+
+class tex_output : public common_output {
+public:
+ tex_output();
+ ~tex_output();
+ void start_picture(double, const position &ll, const position &ur);
+ void finish_picture();
+ void text(const position &, text_piece *, int, double);
+ void line(const position &, const position *, int n,
+ const line_type &);
+ void polygon(const position *, int n,
+ const line_type &, double);
+ void spline(const position &, const position *, int n,
+ const line_type &);
+ void arc(const position &, const position &, const position &,
+ const line_type &);
+ void circle(const position &, double rad, const line_type &, double);
+ void ellipse(const position &, const distance &, const line_type &, double);
+ void command(const char *, const char *, int);
+ int supports_filled_polygons();
+private:
+ position upper_left;
+ double height;
+ double width;
+ double scale;
+ double pen_size;
+
+ void point(const position &);
+ void dot(const position &, const line_type &);
+ void solid_arc(const position &cent, double rad, double start_angle,
+ double end_angle, const line_type &lt);
+ position transform(const position &);
+protected:
+ virtual void set_pen_size(double ps);
+};
+
+// convert inches to milliinches
+
+inline int milliinches(double x)
+{
+ return int(x*1000.0 + .5);
+}
+
+inline position tex_output::transform(const position &pos)
+{
+ return position((pos.x - upper_left.x)/scale,
+ (upper_left.y - pos.y)/scale);
+}
+
+output *make_tex_output()
+{
+ return new tex_output;
+}
+
+tex_output::tex_output()
+{
+}
+
+tex_output::~tex_output()
+{
+}
+
+const int DEFAULT_PEN_SIZE = 8;
+
+void tex_output::set_pen_size(double ps)
+{
+ if (ps < 0.0)
+ ps = -1.0;
+ if (ps != pen_size) {
+ pen_size = ps;
+ printf(" \\special{pn %d}%%\n",
+ ps < 0.0 ? DEFAULT_PEN_SIZE : int(ps*(1000.0/72.0) + .5));
+ }
+}
+
+void tex_output::start_picture(double sc, const position &ll,
+ const position &ur)
+{
+ upper_left.x = ll.x;
+ upper_left.y = ur.y;
+ scale = compute_scale(sc, ll, ur);
+ height = (ur.y - ll.y)/scale;
+ width = (ur.x - ll.x)/scale;
+ /* the point of \vskip 0pt is to ensure that the vtop gets
+ a height of 0 rather than the height of the hbox; this
+ might be non-zero if text from text attributes lies outside pic's
+ idea of the bounding box of the picture. */
+ fputs("\\expandafter\\ifx\\csname graph\\endcsname\\relax \\csname newbox\\endcsname\\graph\\fi\n"
+ "\\expandafter\\ifx\\csname graphtemp\\endcsname\\relax \\csname newdimen\\endcsname\\graphtemp\\fi\n"
+ "\\setbox\\graph=\\vtop{\\vskip 0pt\\hbox{%\n",
+ stdout);
+ pen_size = -2.0;
+}
+
+void tex_output::finish_picture()
+{
+ printf(" \\hbox{\\vrule depth%.3fin width0pt height 0pt}%%\n"
+ " \\kern %.3fin\n"
+ " }%%\n"
+ "}%%\n",
+ height, width);
+}
+
+void tex_output::text(const position &center, text_piece *v, int n, double)
+{
+ position c = transform(center);
+ for (int i = 0; i < n; i++)
+ if (v[i].text != 0 && *v[i].text != '\0') {
+ int j = 2*i - n + 1;
+ if (v[i].adj.v == ABOVE_ADJUST)
+ j--;
+ else if (v[i].adj.v == BELOW_ADJUST)
+ j++;
+ if (j == 0) {
+ printf(" \\graphtemp=.5ex\\advance\\graphtemp by %.3fin\n", c.y);
+ }
+ else {
+ printf(" \\graphtemp=\\baselineskip"
+ "\\multiply\\graphtemp by %d"
+ "\\divide\\graphtemp by 2\n"
+ " \\advance\\graphtemp by .5ex"
+ "\\advance\\graphtemp by %.3fin\n",
+ j, c.y);
+ }
+ printf(" \\rlap{\\kern %.3fin\\lower\\graphtemp", c.x);
+ fputs("\\hbox to 0pt{", stdout);
+ if (v[i].adj.h != LEFT_ADJUST)
+ fputs("\\hss ", stdout);
+ fputs(v[i].text, stdout);
+ if (v[i].adj.h != RIGHT_ADJUST)
+ fputs("\\hss", stdout);
+ fputs("}}%\n", stdout);
+ }
+}
+
+void tex_output::point(const position &pos)
+{
+ position p = transform(pos);
+ printf(" \\special{pa %d %d}%%\n", milliinches(p.x), milliinches(p.y));
+}
+
+void tex_output::line(const position &start, const position *v, int n,
+ const line_type &lt)
+{
+ set_pen_size(lt.thickness);
+ point(start);
+ for (int i = 0; i < n; i++)
+ point(v[i]);
+ fputs(" \\special{", stdout);
+ switch(lt.type) {
+ case line_type::invisible:
+ fputs("ip", stdout);
+ break;
+ case line_type::solid:
+ fputs("fp", stdout);
+ break;
+ case line_type::dotted:
+ printf("dt %.3f", lt.dash_width/scale);
+ break;
+ case line_type::dashed:
+ printf("da %.3f", lt.dash_width/scale);
+ break;
+ }
+ fputs("}%\n", stdout);
+}
+
+void tex_output::polygon(const position *v, int n,
+ const line_type &lt, double fill)
+{
+ if (fill >= 0.0) {
+ if (fill > 1.0)
+ fill = 1.0;
+ printf(" \\special{sh %.3f}%%\n", fill);
+ }
+ line(v[n-1], v, n, lt);
+}
+
+void tex_output::spline(const position &start, const position *v, int n,
+ const line_type &lt)
+{
+ if (lt.type == line_type::invisible)
+ return;
+ set_pen_size(lt.thickness);
+ point(start);
+ for (int i = 0; i < n; i++)
+ point(v[i]);
+ fputs(" \\special{sp", stdout);
+ switch(lt.type) {
+ case line_type::solid:
+ break;
+ case line_type::dotted:
+ printf(" %.3f", -lt.dash_width/scale);
+ break;
+ case line_type::dashed:
+ printf(" %.3f", lt.dash_width/scale);
+ break;
+ case line_type::invisible:
+ assert(0);
+ }
+ fputs("}%\n", stdout);
+}
+
+void tex_output::solid_arc(const position &cent, double rad,
+ double start_angle, double end_angle,
+ const line_type &lt)
+{
+ set_pen_size(lt.thickness);
+ position c = transform(cent);
+ printf(" \\special{ar %d %d %d %d %f %f}%%\n",
+ milliinches(c.x),
+ milliinches(c.y),
+ milliinches(rad/scale),
+ milliinches(rad/scale),
+ -end_angle,
+ (-end_angle > -start_angle) ? (double)M_PI * 2 - start_angle
+ : -start_angle);
+}
+
+void tex_output::arc(const position &start, const position &cent,
+ const position &end, const line_type &lt)
+{
+ switch (lt.type) {
+ case line_type::invisible:
+ break;
+ case line_type::dashed:
+ dashed_arc(start, cent, end, lt);
+ break;
+ case line_type::dotted:
+ dotted_arc(start, cent, end, lt);
+ break;
+ case line_type::solid:
+ {
+ position c;
+ if (!compute_arc_center(start, cent, end, &c)) {
+ line(start, &end, 1, lt);
+ break;
+ }
+ solid_arc(c,
+ hypot(cent - start),
+ atan2(start.y - c.y, start.x - c.x),
+ atan2(end.y - c.y, end.x - c.x),
+ lt);
+ break;
+ }
+ }
+}
+
+void tex_output::circle(const position &cent, double rad,
+ const line_type &lt, double fill)
+{
+ if (fill >= 0.0 && lt.type != line_type::solid) {
+ if (fill > 1.0)
+ fill = 1.0;
+ line_type ilt;
+ ilt.type = line_type::invisible;
+ ellipse(cent, position(rad*2.0, rad*2.0), ilt, fill);
+ }
+ switch (lt.type) {
+ case line_type::dashed:
+ dashed_circle(cent, rad, lt);
+ break;
+ case line_type::invisible:
+ break;
+ case line_type::solid:
+ ellipse(cent, position(rad*2.0,rad*2.0), lt, fill);
+ break;
+ case line_type::dotted:
+ dotted_circle(cent, rad, lt);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+void tex_output::ellipse(const position &cent, const distance &dim,
+ const line_type &lt, double fill)
+{
+ if (lt.type == line_type::invisible) {
+ if (fill < 0.0)
+ return;
+ }
+ else
+ set_pen_size(lt.thickness);
+ if (fill >= 0.0) {
+ if (fill > 1.0)
+ fill = 1.0;
+ printf(" \\special{sh %.3f}%%\n", fill);
+ }
+ position c = transform(cent);
+ printf(" \\special{%s %d %d %d %d 0 6.28319}%%\n",
+ (lt.type == line_type::invisible ? "ia" : "ar"),
+ milliinches(c.x),
+ milliinches(c.y),
+ milliinches(dim.x/(2.0*scale)),
+ milliinches(dim.y/(2.0*scale)));
+}
+
+void tex_output::command(const char *s, const char *, int)
+{
+ fputs(s, stdout);
+ putchar('%'); // avoid unwanted spaces
+ putchar('\n');
+}
+
+int tex_output::supports_filled_polygons()
+{
+ return 1;
+}
+
+void tex_output::dot(const position &pos, const line_type &lt)
+{
+ if (zero_length_line_flag) {
+ line_type slt = lt;
+ slt.type = line_type::solid;
+ line(pos, &pos, 1, slt);
+ }
+ else {
+ int dot_rad = int(lt.thickness*(1000.0/(72.0*2)) + .5);
+ if (dot_rad == 0)
+ dot_rad = 1;
+ position p = transform(pos);
+ printf(" \\special{sh 1}%%\n"
+ " \\special{ia %d %d %d %d 0 6.28319}%%\n",
+ milliinches(p.x), milliinches(p.y), dot_rad, dot_rad);
+ }
+}
+
+class tpic_output : public tex_output {
+public:
+ tpic_output();
+ void command(const char *, const char *, int);
+private:
+ void set_pen_size(double ps);
+ int default_pen_size;
+ int prev_default_pen_size;
+};
+
+tpic_output::tpic_output()
+: default_pen_size(DEFAULT_PEN_SIZE), prev_default_pen_size(DEFAULT_PEN_SIZE)
+{
+}
+
+void tpic_output::command(const char *s, const char *filename, int lineno)
+{
+ assert(s[0] == '.');
+ if (s[1] == 'p' && s[2] == 's' && (s[3] == '\0' || !csalpha(s[3]))) {
+ const char *p = s + 3;
+ while (csspace(*p))
+ p++;
+ if (*p == '\0') {
+ int temp = default_pen_size;
+ default_pen_size = prev_default_pen_size;
+ prev_default_pen_size = temp;
+ }
+ else {
+ char *ptr;
+ int temp = (int)strtol(p, &ptr, 10);
+ if (temp == 0 && ptr == p)
+ error_with_file_and_line(filename, lineno,
+ "argument to `.ps' not an integer");
+ else if (temp < 0)
+ error_with_file_and_line(filename, lineno,
+ "negative pen size");
+ else {
+ prev_default_pen_size = default_pen_size;
+ default_pen_size = temp;
+ }
+ }
+ }
+ else
+ printf("\\%s%%\n", s + 1);
+}
+
+void tpic_output::set_pen_size(double ps)
+{
+ if (ps < 0.0)
+ printf(" \\special{pn %d}%%\n", default_pen_size);
+ else
+ tex_output::set_pen_size(ps);
+}
+
+output *make_tpic_output()
+{
+ return new tpic_output;
+}
+
+#endif
diff --git a/src/preproc/pic/text.h b/src/preproc/pic/text.h
new file mode 100644
index 00000000..f9d34875
--- /dev/null
+++ b/src/preproc/pic/text.h
@@ -0,0 +1,28 @@
+// -*- C++ -*-
+
+enum hadjustment {
+ CENTER_ADJUST,
+ LEFT_ADJUST,
+ RIGHT_ADJUST
+ };
+
+enum vadjustment {
+ NONE_ADJUST,
+ ABOVE_ADJUST,
+ BELOW_ADJUST
+ };
+
+struct adjustment {
+ hadjustment h;
+ vadjustment v;
+};
+
+struct text_piece {
+ char *text;
+ adjustment adj;
+ const char *filename;
+ int lineno;
+
+ text_piece();
+ ~text_piece();
+};
diff --git a/src/preproc/pic/troff.cc b/src/preproc/pic/troff.cc
new file mode 100644
index 00000000..16568542
--- /dev/null
+++ b/src/preproc/pic/troff.cc
@@ -0,0 +1,502 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "pic.h"
+#include "common.h"
+
+
+const double RELATIVE_THICKNESS = -1.0;
+const double BAD_THICKNESS = -2.0;
+
+class simple_output : public common_output {
+ virtual void simple_line(const position &, const position &) = 0;
+ virtual void simple_spline(const position &, const position *, int n) = 0;
+ virtual void simple_arc(const position &, const position &,
+ const position &) = 0;
+ virtual void simple_circle(int, const position &, double rad) = 0;
+ virtual void simple_ellipse(int, const position &, const distance &) = 0;
+ virtual void simple_polygon(int, const position *, int) = 0;
+ virtual void line_thickness(double) = 0;
+ virtual void set_fill(double) = 0;
+ void dot(const position &, const line_type &) = 0;
+public:
+ void start_picture(double sc, const position &ll, const position &ur) = 0;
+ void finish_picture() = 0;
+ void text(const position &, text_piece *, int, double) = 0;
+ void line(const position &, const position *, int n,
+ const line_type &);
+ void polygon(const position *, int n,
+ const line_type &, double);
+ void spline(const position &, const position *, int n,
+ const line_type &);
+ void arc(const position &, const position &, const position &,
+ const line_type &);
+ void circle(const position &, double rad, const line_type &, double);
+ void ellipse(const position &, const distance &, const line_type &, double);
+ int supports_filled_polygons();
+};
+
+int simple_output::supports_filled_polygons()
+{
+ return driver_extension_flag != 0;
+}
+
+void simple_output::arc(const position &start, const position &cent,
+ const position &end, const line_type &lt)
+{
+ switch (lt.type) {
+ case line_type::solid:
+ line_thickness(lt.thickness);
+ simple_arc(start, cent, end);
+ break;
+ case line_type::invisible:
+ break;
+ case line_type::dashed:
+ dashed_arc(start, cent, end, lt);
+ break;
+ case line_type::dotted:
+ dotted_arc(start, cent, end, lt);
+ break;
+ }
+}
+
+void simple_output::line(const position &start, const position *v, int n,
+ const line_type &lt)
+{
+ position pos = start;
+ line_thickness(lt.thickness);
+ for (int i = 0; i < n; i++) {
+ switch (lt.type) {
+ case line_type::solid:
+ simple_line(pos, v[i]);
+ break;
+ case line_type::dotted:
+ {
+ distance vec(v[i] - pos);
+ double dist = hypot(vec);
+ int ndots = int(dist/lt.dash_width + .5);
+ if (ndots == 0)
+ dot(pos, lt);
+ else {
+ vec /= double(ndots);
+ for (int j = 0; j <= ndots; j++)
+ dot(pos + vec*j, lt);
+ }
+ }
+ break;
+ case line_type::dashed:
+ {
+ distance vec(v[i] - pos);
+ double dist = hypot(vec);
+ if (dist <= lt.dash_width*2.0)
+ simple_line(pos, v[i]);
+ else {
+ int ndashes = int((dist - lt.dash_width)/(lt.dash_width*2.0) + .5);
+ distance dash_vec = vec*(lt.dash_width/dist);
+ double dash_gap = (dist - lt.dash_width)/ndashes;
+ distance dash_gap_vec = vec*(dash_gap/dist);
+ for (int j = 0; j <= ndashes; j++) {
+ position s(pos + dash_gap_vec*j);
+ simple_line(s, s + dash_vec);
+ }
+ }
+ }
+ break;
+ case line_type::invisible:
+ break;
+ default:
+ assert(0);
+ }
+ pos = v[i];
+ }
+}
+
+void simple_output::spline(const position &start, const position *v, int n,
+ const line_type &lt)
+{
+ line_thickness(lt.thickness);
+ simple_spline(start, v, n);
+}
+
+void simple_output::polygon(const position *v, int n,
+ const line_type &lt, double fill)
+{
+ if (driver_extension_flag) {
+ if (fill >= 0.0) {
+ set_fill(fill);
+ simple_polygon(1, v, n);
+ }
+ }
+ if (lt.type == line_type::solid && driver_extension_flag) {
+ line_thickness(lt.thickness);
+ simple_polygon(0, v, n);
+ }
+ else if (lt.type != line_type::invisible) {
+ line_thickness(lt.thickness);
+ line(v[n - 1], v, n, lt);
+ }
+}
+
+void simple_output::circle(const position &cent, double rad,
+ const line_type &lt, double fill)
+{
+ if (driver_extension_flag && fill >= 0.0) {
+ set_fill(fill);
+ simple_circle(1, cent, rad);
+ }
+ line_thickness(lt.thickness);
+ switch (lt.type) {
+ case line_type::invisible:
+ break;
+ case line_type::dashed:
+ dashed_circle(cent, rad, lt);
+ break;
+ case line_type::dotted:
+ dotted_circle(cent, rad, lt);
+ break;
+ case line_type::solid:
+ simple_circle(0, cent, rad);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+void simple_output::ellipse(const position &cent, const distance &dim,
+ const line_type &lt, double fill)
+{
+ if (driver_extension_flag && fill >= 0.0) {
+ set_fill(fill);
+ simple_ellipse(1, cent, dim);
+ }
+ if (lt.type != line_type::invisible)
+ line_thickness(lt.thickness);
+ switch (lt.type) {
+ case line_type::invisible:
+ break;
+ case line_type::dotted:
+ case line_type::dashed:
+ case line_type::solid:
+ simple_ellipse(0, cent, dim);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+#define FILL_MAX 1000
+
+class troff_output : public simple_output {
+ const char *last_filename;
+ position upper_left;
+ double height;
+ double scale;
+ double last_line_thickness;
+ double last_fill;
+public:
+ troff_output();
+ ~troff_output();
+ void start_picture(double, const position &ll, const position &ur);
+ void finish_picture();
+ void text(const position &, text_piece *, int, double);
+ void dot(const position &, const line_type &);
+ void command(const char *, const char *, int);
+ void set_location(const char *, int);
+ void simple_line(const position &, const position &);
+ void simple_spline(const position &, const position *, int n);
+ void simple_arc(const position &, const position &, const position &);
+ void simple_circle(int, const position &, double rad);
+ void simple_ellipse(int, const position &, const distance &);
+ void simple_polygon(int, const position *, int);
+ void line_thickness(double p);
+ void set_fill(double);
+ position transform(const position &);
+};
+
+output *make_troff_output()
+{
+ return new troff_output;
+}
+
+troff_output::troff_output()
+: last_filename(0), last_line_thickness(BAD_THICKNESS), last_fill(-1.0)
+{
+}
+
+troff_output::~troff_output()
+{
+}
+
+inline position troff_output::transform(const position &pos)
+{
+ return position((pos.x - upper_left.x)/scale,
+ (upper_left.y - pos.y)/scale);
+}
+
+#define FILL_REG "00"
+
+// If this register > 0, then pic will generate \X'ps: ...' commands
+// if the aligned attribute is used.
+#define GROPS_REG "0p"
+
+// If this register is defined, geqn won't produce `\x's.
+#define EQN_NO_EXTRA_SPACE_REG "0x"
+
+void troff_output::start_picture(double sc,
+ const position &ll, const position &ur)
+{
+ upper_left.x = ll.x;
+ upper_left.y = ur.y;
+ scale = compute_scale(sc, ll, ur);
+ height = (ur.y - ll.y)/scale;
+ double width = (ur.x - ll.x)/scale;
+ printf(".PS %.3fi %.3fi", height, width);
+ if (args)
+ printf(" %s\n", args);
+ else
+ putchar('\n');
+ printf(".if '\\*(.T'html' \\X(graphic-start(\n");
+ printf(".\\\" %g %g %g %g\n", ll.x, ll.y, ur.x, ur.y);
+ printf(".\\\" %.3fi %.3fi %.3fi %.3fi\n", 0.0, height, width, 0.0);
+ printf(".nr " FILL_REG " \\n(.u\n.nf\n");
+ printf(".nr " EQN_NO_EXTRA_SPACE_REG " 1\n");
+ // This guarantees that if the picture is used in a diversion it will
+ // have the right width.
+ printf("\\h'%.3fi'\n.sp -1\n", width);
+}
+
+void troff_output::finish_picture()
+{
+ line_thickness(BAD_THICKNESS);
+ last_fill = -1.0; // force it to be reset for each picture
+ if (!flyback_flag)
+ printf(".sp %.3fi+1\n", height);
+ printf(".if \\n(" FILL_REG " .fi\n");
+ printf(".br\n");
+ printf(".nr " EQN_NO_EXTRA_SPACE_REG " 0\n");
+ printf(".if '\\*(.T'html' \\X(graphic-end(\n");
+ // this is a little gross
+ set_location(current_filename, current_lineno);
+ fputs(flyback_flag ? ".PF\n" : ".PE\n", stdout);
+}
+
+void troff_output::command(const char *s,
+ const char *filename, int lineno)
+{
+ if (filename != 0)
+ set_location(filename, lineno);
+ fputs(s, stdout);
+ putchar('\n');
+}
+
+void troff_output::simple_circle(int filled, const position &cent, double rad)
+{
+ position c = transform(cent);
+ printf("\\h'%.3fi'"
+ "\\v'%.3fi'"
+ "\\D'%c%.3fi'"
+ "\n.sp -1\n",
+ c.x - rad/scale,
+ c.y,
+ (filled ? 'C' : 'c'),
+ rad*2.0/scale);
+}
+
+void troff_output::simple_ellipse(int filled, const position &cent,
+ const distance &dim)
+{
+ position c = transform(cent);
+ printf("\\h'%.3fi'"
+ "\\v'%.3fi'"
+ "\\D'%c%.3fi %.3fi'"
+ "\n.sp -1\n",
+ c.x - dim.x/(2.0*scale),
+ c.y,
+ (filled ? 'E' : 'e'),
+ dim.x/scale, dim.y/scale);
+}
+
+void troff_output::simple_arc(const position &start, const distance &cent,
+ const distance &end)
+{
+ position s = transform(start);
+ position c = transform(cent);
+ distance cv = c - s;
+ distance ev = transform(end) - c;
+ printf("\\h'%.3fi'"
+ "\\v'%.3fi'"
+ "\\D'a%.3fi %.3fi %.3fi %.3fi'"
+ "\n.sp -1\n",
+ s.x, s.y, cv.x, cv.y, ev.x, ev.y);
+}
+
+void troff_output::simple_line(const position &start, const position &end)
+{
+ position s = transform(start);
+ distance ev = transform(end) - s;
+ printf("\\h'%.3fi'"
+ "\\v'%.3fi'"
+ "\\D'l%.3fi %.3fi'"
+ "\n.sp -1\n",
+ s.x, s.y, ev.x, ev.y);
+}
+
+void troff_output::simple_spline(const position &start,
+ const position *v, int n)
+{
+ position pos = transform(start);
+ printf("\\h'%.3fi'"
+ "\\v'%.3fi'",
+ pos.x, pos.y);
+ fputs("\\D'~", stdout);
+ for (int i = 0; i < n; i++) {
+ position temp = transform(v[i]);
+ distance d = temp - pos;
+ pos = temp;
+ if (i != 0)
+ putchar(' ');
+ printf("%.3fi %.3fi", d.x, d.y);
+ }
+ printf("'\n.sp -1\n");
+}
+
+// a solid polygon
+
+void troff_output::simple_polygon(int filled, const position *v, int n)
+{
+ position pos = transform(v[0]);
+ printf("\\h'%.3fi'"
+ "\\v'%.3fi'",
+ pos.x, pos.y);
+ printf("\\D'%c", (filled ? 'P' : 'p'));
+ for (int i = 1; i < n; i++) {
+ position temp = transform(v[i]);
+ distance d = temp - pos;
+ pos = temp;
+ if (i != 1)
+ putchar(' ');
+ printf("%.3fi %.3fi", d.x, d.y);
+ }
+ printf("'\n.sp -1\n");
+}
+
+const double TEXT_AXIS = 0.22; // in ems
+
+static const char *choose_delimiter(const char *text)
+{
+ if (strchr(text, '\'') == 0)
+ return "'";
+ else
+ return "\\(ts";
+}
+
+void troff_output::text(const position &center, text_piece *v, int n,
+ double ang)
+{
+ line_thickness(BAD_THICKNESS); // the text might use lines (eg in equations)
+ int rotate_flag = 0;
+ if (driver_extension_flag && ang != 0.0) {
+ rotate_flag = 1;
+ position c = transform(center);
+ printf(".if \\n(" GROPS_REG " \\{\\\n"
+ "\\h'%.3fi'"
+ "\\v'%.3fi'"
+ "\\X'ps: exec gsave currentpoint 2 copy translate %.4f rotate neg exch neg exch translate'"
+ "\n.sp -1\n"
+ ".\\}\n",
+ c.x, c.y, -ang*180.0/M_PI);
+ }
+ for (int i = 0; i < n; i++)
+ if (v[i].text != 0 && *v[i].text != '\0') {
+ position c = transform(center);
+ if (v[i].filename != 0)
+ set_location(v[i].filename, v[i].lineno);
+ printf("\\h'%.3fi", c.x);
+ const char *delim = choose_delimiter(v[i].text);
+ if (v[i].adj.h == RIGHT_ADJUST)
+ printf("-\\w%s%s%su", delim, v[i].text, delim);
+ else if (v[i].adj.h != LEFT_ADJUST)
+ printf("-(\\w%s%s%su/2u)", delim, v[i].text, delim);
+ putchar('\'');
+ printf("\\v'%.3fi-(%dv/2u)+%dv+%.2fm",
+ c.y,
+ n - 1,
+ i,
+ TEXT_AXIS);
+ if (v[i].adj.v == ABOVE_ADJUST)
+ printf("-.5v");
+ else if (v[i].adj.v == BELOW_ADJUST)
+ printf("+.5v");
+ putchar('\'');
+ fputs(v[i].text, stdout);
+ fputs("\n.sp -1\n", stdout);
+ }
+ if (rotate_flag)
+ printf(".if '\\*(.T'ps' \\{\\\n"
+ "\\X'ps: exec grestore'\n.sp -1\n"
+ ".\\}\n");
+}
+
+void troff_output::line_thickness(double p)
+{
+ if (p < 0.0)
+ p = RELATIVE_THICKNESS;
+ if (driver_extension_flag && p != last_line_thickness) {
+ printf("\\D't %.3fp'\\h'%.3fp'\n.sp -1\n", p, -p);
+ last_line_thickness = p;
+ }
+}
+
+void troff_output::set_fill(double f)
+{
+ if (driver_extension_flag && f != last_fill) {
+ printf("\\D'f %du'\\h'%du'\n.sp -1\n", int(f*FILL_MAX), -int(f*FILL_MAX));
+ last_fill = f;
+ }
+}
+
+const double DOT_AXIS = .044;
+
+void troff_output::dot(const position &cent, const line_type &lt)
+{
+ if (driver_extension_flag) {
+ line_thickness(lt.thickness);
+ simple_line(cent, cent);
+ }
+ else {
+ position c = transform(cent);
+ printf("\\h'%.3fi-(\\w'.'u/2u)'"
+ "\\v'%.3fi+%.2fm'"
+ ".\n.sp -1\n",
+ c.x,
+ c.y,
+ DOT_AXIS);
+ }
+}
+
+void troff_output::set_location(const char *s, int n)
+{
+ if (last_filename != 0 && strcmp(s, last_filename) == 0)
+ printf(".lf %d\n", n);
+ else {
+ printf(".lf %d %s\n", n, s);
+ last_filename = s;
+ }
+}
diff --git a/src/preproc/refer/Makefile.sub b/src/preproc/refer/Makefile.sub
new file mode 100644
index 00000000..1631b5e3
--- /dev/null
+++ b/src/preproc/refer/Makefile.sub
@@ -0,0 +1,23 @@
+PROG=refer
+MAN1=refer.n
+XLIBS=$(LIBBIB) $(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=\
+ command.o \
+ label.o \
+ ref.o \
+ refer.o \
+ token.o
+CCSRCS=\
+ $(srcdir)/command.cc \
+ $(srcdir)/ref.cc \
+ $(srcdir)/refer.cc \
+ $(srcdir)/token.cc
+HDRS=\
+ $(srcdir)/refer.h \
+ $(srcdir)/token.h \
+ $(srcdir)/command.h \
+ $(srcdir)/ref.h
+GRAM=$(srcdir)/label.y
+YTABC=$(srcdir)/label.cc
+NAMEPREFIX=$(g)
diff --git a/src/preproc/refer/TODO b/src/preproc/refer/TODO
new file mode 100644
index 00000000..5bbd9bff
--- /dev/null
+++ b/src/preproc/refer/TODO
@@ -0,0 +1,124 @@
+inline references
+
+Some sort of macro/subroutine that can cover several references.
+
+move-punctuation should ignore multiple punctuation characters.
+
+Make the index files machine independent.
+
+Allow search keys to be negated (with !) to indicate that the
+reference should not contain the key. Ignore negated keys during
+indexed searching.
+
+Provide an option with lkbib and lookbib that prints the location
+(filename, position) of each reference. Need to map filename_id's
+back to filenames.
+
+Rename join-authors to join-fields. Have a separate label-join-fields
+command used by @ and #.
+
+Have some sort of quantifier: eg $.n#A means execute `$.n' for each
+instance of an A field, setting $ to that field, and then join the
+results using the join-authors command.
+
+no-text-in-bracket command which says not to allow post_text and
+pre_text when the [] flags has been given. Useful for superscripted
+footnotes.
+
+Make it possible to translate - to \(en in page ranges.
+
+Trim eign a bit.
+
+In indexed searching discard all numeric keys except dates.
+
+Allow `\ ' to separate article from first word.
+
+%also
+
+Option automatically to supply [] flags in every reference.
+
+See if we can avoid requiring a comma before jr. and so on
+in find_last_name().
+
+Cache sortified authors in authors string during tentative evaluation of
+label specification.
+
+Possibly don't allow * and % expressions in the first part of ?:, | or
+& expressions.
+
+Handle better the case where <> occurs inside functions and in the
+first operand of ~. Or perhaps implement <> using some magic character
+in the string.
+
+Should special treatment be given to lines beginning with . in
+references? (Unix refer seems to treat them like `%').
+
+Add global flag to control whether all files should be stat-ed after
+loading, and whether they should be stat-ed before each search.
+Perhaps make this dependent on the number of files there are.
+
+Option to truncate keys to truncate_len in linear searching.
+
+Allow multiple -f options in indxbib.
+
+In indxbib, possibly store common words rather than common words
+filename. In this case store only words that are actually present in
+the file.
+
+Perhaps we should put out an obnoxious copyright message when lookbib
+starts up.
+
+Provide an option that writes a file containing just the references
+actually used. Useful if you want to distribute a document.
+
+Have a magic token such that
+%A <sort stuff><magic token><print stuff>
+will print as though it were
+%A <print stuff>
+but sort as though it were
+%A <sort stuff>
+Do we need this if we can specify author alternatives for sorting?
+No, provided we have separate alternatives for @.
+
+In consider_authors when last names are ambiguous we might be able to
+use just the first name and not Jr. bit. Or we might be able to
+abbreviate the author.
+
+It ought to be possible to specify an alternative field to sort on
+instead of date. (ie if there's a field giving the type of document --
+these references should sort after any years)
+
+Provide a way to execute a command using a command-line option.
+
+Option to set the label-spec as a command-line option (-L).
+
+Command to to specify which fields can occur multiple times:
+multiple AE
+
+Command to specify how various fields sort:
+aort-as-name A
+sort-as-date D
+sort-as-title T
+sort-as-other O
+
+Command to specify which fields are author fields:
+# if we don't have A use field Q
+author-fields AQ
+
+Commands to set properties of tokens.
+sortify-token \(ae ae
+uppercase-token \[ae] \[AE]
+
+Command to set the names of months:
+months january february march april may ...
+
+Perhaps provide some sort of macro capability:
+# perhaps a macro capability
+defmacro foo
+annotation-field $1
+endef
+
+Command to control strings used in capitalization
+capitalize-start \s+2
+capitalize-end \s-2
+(perhaps make these arguments to the capitalize command.)
diff --git a/src/preproc/refer/command.cc b/src/preproc/refer/command.cc
new file mode 100644
index 00000000..004189ee
--- /dev/null
+++ b/src/preproc/refer/command.cc
@@ -0,0 +1,807 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "refer.h"
+#include "refid.h"
+#include "search.h"
+#include "command.h"
+
+cset cs_field_name = csalpha;
+
+class input_item {
+ input_item *next;
+ char *filename;
+ int first_lineno;
+ string buffer;
+ const char *ptr;
+ const char *end;
+public:
+ input_item(string &, const char *, int = 1);
+ ~input_item();
+ int get_char();
+ int peek_char();
+ void skip_char();
+ int get_location(const char **, int *);
+
+ friend class input_stack;
+};
+
+input_item::input_item(string &s, const char *fn, int ln)
+: filename(strsave(fn)), first_lineno(ln)
+{
+ buffer.move(s);
+ ptr = buffer.contents();
+ end = ptr + buffer.length();
+}
+
+input_item::~input_item()
+{
+ a_delete filename;
+}
+
+inline int input_item::peek_char()
+{
+ if (ptr >= end)
+ return EOF;
+ else
+ return (unsigned char)*ptr;
+}
+
+inline int input_item::get_char()
+{
+ if (ptr >= end)
+ return EOF;
+ else
+ return (unsigned char)*ptr++;
+}
+
+inline void input_item::skip_char()
+{
+ ptr++;
+}
+
+int input_item::get_location(const char **filenamep, int *linenop)
+{
+ *filenamep = filename;
+ if (ptr == buffer.contents())
+ *linenop = first_lineno;
+ else {
+ int ln = first_lineno;
+ const char *e = ptr - 1;
+ for (const char *p = buffer.contents(); p < e; p++)
+ if (*p == '\n')
+ ln++;
+ *linenop = ln;
+ }
+ return 1;
+}
+
+class input_stack {
+ static input_item *top;
+public:
+ static void init();
+ static int get_char();
+ static int peek_char();
+ static void skip_char() { top->skip_char(); }
+ static void push_file(const char *);
+ static void push_string(string &, const char *, int);
+ static void error(const char *format,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+};
+
+input_item *input_stack::top = 0;
+
+void input_stack::init()
+{
+ while (top) {
+ input_item *tem = top;
+ top = top->next;
+ delete tem;
+ }
+}
+
+int input_stack::get_char()
+{
+ while (top) {
+ int c = top->get_char();
+ if (c >= 0)
+ return c;
+ input_item *tem = top;
+ top = top->next;
+ delete tem;
+ }
+ return -1;
+}
+
+int input_stack::peek_char()
+{
+ while (top) {
+ int c = top->peek_char();
+ if (c >= 0)
+ return c;
+ input_item *tem = top;
+ top = top->next;
+ delete tem;
+ }
+ return -1;
+}
+
+void input_stack::push_file(const char *fn)
+{
+ FILE *fp;
+ if (strcmp(fn, "-") == 0) {
+ fp = stdin;
+ fn = "<standard input>";
+ }
+ else {
+ errno = 0;
+ fp = fopen(fn, "r");
+ if (fp == 0) {
+ error("can't open `%1': %2", fn, strerror(errno));
+ return;
+ }
+ }
+ string buf;
+ int bol = 1;
+ int lineno = 1;
+ for (;;) {
+ int c = getc(fp);
+ if (bol && c == '.') {
+ // replace lines beginning with .R1 or .R2 with a blank line
+ c = getc(fp);
+ if (c == 'R') {
+ c = getc(fp);
+ if (c == '1' || c == '2') {
+ int cc = c;
+ c = getc(fp);
+ if (compatible_flag || c == ' ' || c == '\n' || c == EOF) {
+ while (c != '\n' && c != EOF)
+ c = getc(fp);
+ }
+ else {
+ buf += '.';
+ buf += 'R';
+ buf += cc;
+ }
+ }
+ else {
+ buf += '.';
+ buf += 'R';
+ }
+ }
+ else
+ buf += '.';
+ }
+ if (c == EOF)
+ break;
+ if (illegal_input_char(c))
+ error_with_file_and_line(fn, lineno,
+ "illegal input character code %1", int(c));
+ else {
+ buf += c;
+ if (c == '\n') {
+ bol = 1;
+ lineno++;
+ }
+ else
+ bol = 0;
+ }
+ }
+ if (fp != stdin)
+ fclose(fp);
+ if (buf.length() > 0 && buf[buf.length() - 1] != '\n')
+ buf += '\n';
+ input_item *it = new input_item(buf, fn);
+ it->next = top;
+ top = it;
+}
+
+void input_stack::push_string(string &s, const char *filename, int lineno)
+{
+ input_item *it = new input_item(s, filename, lineno);
+ it->next = top;
+ top = it;
+}
+
+void input_stack::error(const char *format, const errarg &arg1,
+ const errarg &arg2, const errarg &arg3)
+{
+ const char *filename;
+ int lineno;
+ for (input_item *it = top; it; it = it->next)
+ if (it->get_location(&filename, &lineno)) {
+ error_with_file_and_line(filename, lineno, format, arg1, arg2, arg3);
+ return;
+ }
+ ::error(format, arg1, arg2, arg3);
+}
+
+void command_error(const char *format, const errarg &arg1,
+ const errarg &arg2, const errarg &arg3)
+{
+ input_stack::error(format, arg1, arg2, arg3);
+}
+
+// # not recognized in ""
+// \<newline> is recognized in ""
+// # does not conceal newline
+// if missing closing quote, word extends to end of line
+// no special treatment of \ other than before newline
+// \<newline> not recognized after #
+// ; allowed as alternative to newline
+// ; not recognized in ""
+// don't clear word_buffer; just append on
+// return -1 for EOF, 0 for newline, 1 for word
+
+int get_word(string &word_buffer)
+{
+ int c = input_stack::get_char();
+ for (;;) {
+ if (c == '#') {
+ do {
+ c = input_stack::get_char();
+ } while (c != '\n' && c != EOF);
+ break;
+ }
+ if (c == '\\' && input_stack::peek_char() == '\n')
+ input_stack::skip_char();
+ else if (c != ' ' && c != '\t')
+ break;
+ c = input_stack::get_char();
+ }
+ if (c == EOF)
+ return -1;
+ if (c == '\n' || c == ';')
+ return 0;
+ if (c == '"') {
+ for (;;) {
+ c = input_stack::peek_char();
+ if (c == EOF || c == '\n')
+ break;
+ input_stack::skip_char();
+ if (c == '"') {
+ int d = input_stack::peek_char();
+ if (d == '"')
+ input_stack::skip_char();
+ else
+ break;
+ }
+ else if (c == '\\') {
+ int d = input_stack::peek_char();
+ if (d == '\n')
+ input_stack::skip_char();
+ else
+ word_buffer += '\\';
+ }
+ else
+ word_buffer += c;
+ }
+ return 1;
+ }
+ word_buffer += c;
+ for (;;) {
+ c = input_stack::peek_char();
+ if (c == ' ' || c == '\t' || c == '\n' || c == '#' || c == ';')
+ break;
+ input_stack::skip_char();
+ if (c == '\\') {
+ int d = input_stack::peek_char();
+ if (d == '\n')
+ input_stack::skip_char();
+ else
+ word_buffer += '\\';
+ }
+ else
+ word_buffer += c;
+ }
+ return 1;
+}
+
+union argument {
+ const char *s;
+ int n;
+};
+
+// This is for debugging.
+
+static void echo_command(int argc, argument *argv)
+{
+ for (int i = 0; i < argc; i++)
+ fprintf(stderr, "%s\n", argv[i].s);
+}
+
+static void include_command(int argc, argument *argv)
+{
+ assert(argc == 1);
+ input_stack::push_file(argv[0].s);
+}
+
+static void capitalize_command(int argc, argument *argv)
+{
+ if (argc > 0)
+ capitalize_fields = argv[0].s;
+ else
+ capitalize_fields.clear();
+}
+
+static void accumulate_command(int, argument *)
+{
+ accumulate = 1;
+}
+
+static void no_accumulate_command(int, argument *)
+{
+ accumulate = 0;
+}
+
+static void move_punctuation_command(int, argument *)
+{
+ move_punctuation = 1;
+}
+
+static void no_move_punctuation_command(int, argument *)
+{
+ move_punctuation = 0;
+}
+
+static void sort_command(int argc, argument *argv)
+{
+ if (argc == 0)
+ sort_fields = "AD";
+ else
+ sort_fields = argv[0].s;
+ accumulate = 1;
+}
+
+static void no_sort_command(int, argument *)
+{
+ sort_fields.clear();
+}
+
+static void articles_command(int argc, argument *argv)
+{
+ articles.clear();
+ int i;
+ for (i = 0; i < argc; i++) {
+ articles += argv[i].s;
+ articles += '\0';
+ }
+ int len = articles.length();
+ for (i = 0; i < len; i++)
+ articles[i] = cmlower(articles[i]);
+}
+
+static void database_command(int argc, argument *argv)
+{
+ for (int i = 0; i < argc; i++)
+ database_list.add_file(argv[i].s);
+}
+
+static void default_database_command(int, argument *)
+{
+ search_default = 1;
+}
+
+static void no_default_database_command(int, argument *)
+{
+ search_default = 0;
+}
+
+static void bibliography_command(int argc, argument *argv)
+{
+ const char *saved_filename = current_filename;
+ int saved_lineno = current_lineno;
+ int saved_label_in_text = label_in_text;
+ label_in_text = 0;
+ if (!accumulate)
+ fputs(".]<\n", stdout);
+ for (int i = 0; i < argc; i++)
+ do_bib(argv[i].s);
+ if (accumulate)
+ output_references();
+ else
+ fputs(".]>\n", stdout);
+ current_filename = saved_filename;
+ current_lineno = saved_lineno;
+ label_in_text = saved_label_in_text;
+}
+
+static void annotate_command(int argc, argument *argv)
+{
+ if (argc > 0)
+ annotation_field = argv[0].s[0];
+ else
+ annotation_field = 'X';
+ if (argc == 2)
+ annotation_macro = argv[1].s;
+ else
+ annotation_macro = "AP";
+}
+
+static void no_annotate_command(int, argument *)
+{
+ annotation_macro.clear();
+ annotation_field = -1;
+}
+
+static void reverse_command(int, argument *argv)
+{
+ reverse_fields = argv[0].s;
+}
+
+static void no_reverse_command(int, argument *)
+{
+ reverse_fields.clear();
+}
+
+static void abbreviate_command(int argc, argument *argv)
+{
+ abbreviate_fields = argv[0].s;
+ period_before_initial = argc > 1 ? argv[1].s : ". ";
+ period_before_last_name = argc > 2 ? argv[2].s : ". ";
+ period_before_other = argc > 3 ? argv[3].s : ". ";
+ period_before_hyphen = argc > 4 ? argv[4].s : ".";
+}
+
+static void no_abbreviate_command(int, argument *)
+{
+ abbreviate_fields.clear();
+}
+
+string search_ignore_fields;
+
+static void search_ignore_command(int argc, argument *argv)
+{
+ if (argc > 0)
+ search_ignore_fields = argv[0].s;
+ else
+ search_ignore_fields = "XYZ";
+ search_ignore_fields += '\0';
+ linear_ignore_fields = search_ignore_fields.contents();
+}
+
+static void no_search_ignore_command(int, argument *)
+{
+ linear_ignore_fields = "";
+}
+
+static void search_truncate_command(int argc, argument *argv)
+{
+ if (argc > 0)
+ linear_truncate_len = argv[0].n;
+ else
+ linear_truncate_len = 6;
+}
+
+static void no_search_truncate_command(int, argument *)
+{
+ linear_truncate_len = -1;
+}
+
+static void discard_command(int argc, argument *argv)
+{
+ if (argc == 0)
+ discard_fields = "XYZ";
+ else
+ discard_fields = argv[0].s;
+ accumulate = 1;
+}
+
+static void no_discard_command(int, argument *)
+{
+ discard_fields.clear();
+}
+
+static void label_command(int, argument *argv)
+{
+ set_label_spec(argv[0].s);
+}
+
+static void abbreviate_label_ranges_command(int argc, argument *argv)
+{
+ abbreviate_label_ranges = 1;
+ label_range_indicator = argc > 0 ? argv[0].s : "-";
+}
+
+static void no_abbreviate_label_ranges_command(int, argument *)
+{
+ abbreviate_label_ranges = 0;
+}
+
+static void label_in_reference_command(int, argument *)
+{
+ label_in_reference = 1;
+}
+
+static void no_label_in_reference_command(int, argument *)
+{
+ label_in_reference = 0;
+}
+
+static void label_in_text_command(int, argument *)
+{
+ label_in_text = 1;
+}
+
+static void no_label_in_text_command(int, argument *)
+{
+ label_in_text = 0;
+}
+
+static void sort_adjacent_labels_command(int, argument *)
+{
+ sort_adjacent_labels = 1;
+}
+
+static void no_sort_adjacent_labels_command(int, argument *)
+{
+ sort_adjacent_labels = 0;
+}
+
+static void date_as_label_command(int argc, argument *argv)
+{
+ if (set_date_label_spec(argc > 0 ? argv[0].s : "D%a*"))
+ date_as_label = 1;
+}
+
+static void no_date_as_label_command(int, argument *)
+{
+ date_as_label = 0;
+}
+
+static void short_label_command(int, argument *argv)
+{
+ if (set_short_label_spec(argv[0].s))
+ short_label_flag = 1;
+}
+
+static void no_short_label_command(int, argument *)
+{
+ short_label_flag = 0;
+}
+
+static void compatible_command(int, argument *)
+{
+ compatible_flag = 1;
+}
+
+static void no_compatible_command(int, argument *)
+{
+ compatible_flag = 0;
+}
+
+static void join_authors_command(int argc, argument *argv)
+{
+ join_authors_exactly_two = argv[0].s;
+ join_authors_default = argc > 1 ? argv[1].s : argv[0].s;
+ join_authors_last_two = argc == 3 ? argv[2].s : argv[0].s;
+}
+
+static void bracket_label_command(int, argument *argv)
+{
+ pre_label = argv[0].s;
+ post_label = argv[1].s;
+ sep_label = argv[2].s;
+}
+
+static void separate_label_second_parts_command(int, argument *argv)
+{
+ separate_label_second_parts = argv[0].s;
+}
+
+static void et_al_command(int argc, argument *argv)
+{
+ et_al = argv[0].s;
+ et_al_min_elide = argv[1].n;
+ if (et_al_min_elide < 1)
+ et_al_min_elide = 1;
+ et_al_min_total = argc >= 3 ? argv[2].n : 0;
+}
+
+static void no_et_al_command(int, argument *)
+{
+ et_al.clear();
+ et_al_min_elide = 0;
+}
+
+typedef void (*command_t)(int, argument *);
+
+/* arg_types is a string describing the numbers and types of arguments.
+s means a string, i means an integer, f is a list of fields, F is
+a single field,
+? means that the previous argument is optional, * means that the
+previous argument can occur any number of times. */
+
+struct {
+ const char *name;
+ command_t func;
+ const char *arg_types;
+} command_table[] = {
+ { "include", include_command, "s" },
+ { "echo", echo_command, "s*" },
+ { "capitalize", capitalize_command, "f?" },
+ { "accumulate", accumulate_command, "" },
+ { "no-accumulate", no_accumulate_command, "" },
+ { "move-punctuation", move_punctuation_command, "" },
+ { "no-move-punctuation", no_move_punctuation_command, "" },
+ { "sort", sort_command, "s?" },
+ { "no-sort", no_sort_command, "" },
+ { "articles", articles_command, "s*" },
+ { "database", database_command, "ss*" },
+ { "default-database", default_database_command, "" },
+ { "no-default-database", no_default_database_command, "" },
+ { "bibliography", bibliography_command, "ss*" },
+ { "annotate", annotate_command, "F?s?" },
+ { "no-annotate", no_annotate_command, "" },
+ { "reverse", reverse_command, "s" },
+ { "no-reverse", no_reverse_command, "" },
+ { "abbreviate", abbreviate_command, "ss?s?s?s?" },
+ { "no-abbreviate", no_abbreviate_command, "" },
+ { "search-ignore", search_ignore_command, "f?" },
+ { "no-search-ignore", no_search_ignore_command, "" },
+ { "search-truncate", search_truncate_command, "i?" },
+ { "no-search-truncate", no_search_truncate_command, "" },
+ { "discard", discard_command, "f?" },
+ { "no-discard", no_discard_command, "" },
+ { "label", label_command, "s" },
+ { "abbreviate-label-ranges", abbreviate_label_ranges_command, "s?" },
+ { "no-abbreviate-label-ranges", no_abbreviate_label_ranges_command, "" },
+ { "label-in-reference", label_in_reference_command, "" },
+ { "no-label-in-reference", no_label_in_reference_command, "" },
+ { "label-in-text", label_in_text_command, "" },
+ { "no-label-in-text", no_label_in_text_command, "" },
+ { "sort-adjacent-labels", sort_adjacent_labels_command, "" },
+ { "no-sort-adjacent-labels", no_sort_adjacent_labels_command, "" },
+ { "date-as-label", date_as_label_command, "s?" },
+ { "no-date-as-label", no_date_as_label_command, "" },
+ { "short-label", short_label_command, "s" },
+ { "no-short-label", no_short_label_command, "" },
+ { "compatible", compatible_command, "" },
+ { "no-compatible", no_compatible_command, "" },
+ { "join-authors", join_authors_command, "sss?" },
+ { "bracket-label", bracket_label_command, "sss" },
+ { "separate-label-second-parts", separate_label_second_parts_command, "s" },
+ { "et-al", et_al_command, "sii?" },
+ { "no-et-al", no_et_al_command, "" },
+};
+
+static int check_args(const char *types, const char *name,
+ int argc, argument *argv)
+{
+ int argno = 0;
+ while (*types) {
+ if (argc == 0) {
+ if (types[1] == '?')
+ break;
+ else if (types[1] == '*') {
+ assert(types[2] == '\0');
+ break;
+ }
+ else {
+ input_stack::error("missing argument for command `%1'", name);
+ return 0;
+ }
+ }
+ switch (*types) {
+ case 's':
+ break;
+ case 'i':
+ {
+ char *ptr;
+ long n = strtol(argv->s, &ptr, 10);
+ if ((n == 0 && ptr == argv->s)
+ || *ptr != '\0') {
+ input_stack::error("argument %1 for command `%2' must be an integer",
+ argno + 1, name);
+ return 0;
+ }
+ argv->n = (int)n;
+ break;
+ }
+ case 'f':
+ {
+ for (const char *ptr = argv->s; *ptr != '\0'; ptr++)
+ if (!cs_field_name(*ptr)) {
+ input_stack::error("argument %1 for command `%2' must be a list of fields",
+ argno + 1, name);
+ return 0;
+ }
+ break;
+ }
+ case 'F':
+ if (argv->s[0] == '\0' || argv->s[1] != '\0'
+ || !cs_field_name(argv->s[0])) {
+ input_stack::error("argument %1 for command `%2' must be a field name",
+ argno + 1, name);
+ return 0;
+ }
+ break;
+ default:
+ assert(0);
+ }
+ if (types[1] == '?')
+ types += 2;
+ else if (types[1] != '*')
+ types += 1;
+ --argc;
+ ++argv;
+ ++argno;
+ }
+ if (argc > 0) {
+ input_stack::error("too many arguments for command `%1'", name);
+ return 0;
+ }
+ return 1;
+}
+
+static void execute_command(const char *name, int argc, argument *argv)
+{
+ for (int i = 0; i < sizeof(command_table)/sizeof(command_table[0]); i++)
+ if (strcmp(name, command_table[i].name) == 0) {
+ if (check_args(command_table[i].arg_types, name, argc, argv))
+ (*command_table[i].func)(argc, argv);
+ return;
+ }
+ input_stack::error("unknown command `%1'", name);
+}
+
+static void command_loop()
+{
+ string command;
+ for (;;) {
+ command.clear();
+ int res = get_word(command);
+ if (res != 1) {
+ if (res == 0)
+ continue;
+ break;
+ }
+ int argc = 0;
+ command += '\0';
+ while ((res = get_word(command)) == 1) {
+ argc++;
+ command += '\0';
+ }
+ argument *argv = new argument[argc];
+ const char *ptr = command.contents();
+ for (int i = 0; i < argc; i++)
+ argv[i].s = ptr = strchr(ptr, '\0') + 1;
+ execute_command(command.contents(), argc, argv);
+ a_delete argv;
+ if (res == -1)
+ break;
+ }
+}
+
+void process_commands(const char *file)
+{
+ input_stack::init();
+ input_stack::push_file(file);
+ command_loop();
+}
+
+void process_commands(string &s, const char *file, int lineno)
+{
+ input_stack::init();
+ input_stack::push_string(s, file, lineno);
+ command_loop();
+}
diff --git a/src/preproc/refer/command.h b/src/preproc/refer/command.h
new file mode 100644
index 00000000..c7085db6
--- /dev/null
+++ b/src/preproc/refer/command.h
@@ -0,0 +1,36 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+void process_commands(const char *file);
+void process_commands(string &s, const char *file, int lineno);
+
+extern int accumulate;
+extern int move_punctuation;
+extern int search_default;
+extern search_list database_list;
+extern int label_in_text;
+extern int label_in_reference;
+extern int sort_adjacent_labels;
+extern string pre_label;
+extern string post_label;
+extern string sep_label;
+
+extern void do_bib(const char *);
+extern void output_references();
diff --git a/src/preproc/refer/label.cc b/src/preproc/refer/label.cc
new file mode 100755
index 00000000..206980f1
--- /dev/null
+++ b/src/preproc/refer/label.cc
@@ -0,0 +1,1602 @@
+#ifndef lint
+/*static char yysccsid[] = "from: @(#)yaccpar 1.9 (Berkeley) 02/21/93";*/
+static char yyrcsid[] = "$Id: label.cc,v 1.1 2000/02/06 09:38:34 wlemb Exp $";
+#endif
+#define YYBYACC 1
+#define YYMAJOR 1
+#define YYMINOR 9
+#define yyclearin (yychar=(-1))
+#define yyerrok (yyerrflag=0)
+#define YYRECOVERING (yyerrflag!=0)
+#define YYPREFIX "yy"
+#line 22 "label.y"
+
+#include "refer.h"
+#include "refid.h"
+#include "ref.h"
+#include "token.h"
+
+int yylex();
+void yyerror(const char *);
+int yyparse();
+
+static const char *format_serial(char c, int n);
+
+struct label_info {
+ int start;
+ int length;
+ int count;
+ int total;
+ label_info(const string &);
+};
+
+label_info *lookup_label(const string &label);
+
+struct expression {
+ enum {
+ /* Does the tentative label depend on the reference?*/
+ CONTAINS_VARIABLE = 01,
+ CONTAINS_STAR = 02,
+ CONTAINS_FORMAT = 04,
+ CONTAINS_AT = 010
+ };
+ virtual ~expression() { }
+ virtual void evaluate(int, const reference &, string &,
+ substring_position &) = 0;
+ virtual unsigned analyze() { return 0; }
+};
+
+class at_expr : public expression {
+public:
+ at_expr() { }
+ void evaluate(int, const reference &, string &, substring_position &);
+ unsigned analyze() { return CONTAINS_VARIABLE|CONTAINS_AT; }
+};
+
+class format_expr : public expression {
+ char type;
+ int width;
+ int first_number;
+public:
+ format_expr(char c, int w = 0, int f = 1)
+ : type(c), width(w), first_number(f) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+ unsigned analyze() { return CONTAINS_FORMAT; }
+};
+
+class field_expr : public expression {
+ int number;
+ char name;
+public:
+ field_expr(char nm, int num) : number(num), name(nm) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+ unsigned analyze() { return CONTAINS_VARIABLE; }
+};
+
+class literal_expr : public expression {
+ string s;
+public:
+ literal_expr(const char *ptr, int len) : s(ptr, len) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class unary_expr : public expression {
+protected:
+ expression *expr;
+public:
+ unary_expr(expression *e) : expr(e) { }
+ ~unary_expr() { delete expr; }
+ void evaluate(int, const reference &, string &, substring_position &) = 0;
+ unsigned analyze() { return expr ? expr->analyze() : 0; }
+};
+
+/* This caches the analysis of an expression.*/
+
+class analyzed_expr : public unary_expr {
+ unsigned flags;
+public:
+ analyzed_expr(expression *);
+ void evaluate(int, const reference &, string &, substring_position &);
+ unsigned analyze() { return flags; }
+};
+
+class star_expr : public unary_expr {
+public:
+ star_expr(expression *e) : unary_expr(e) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+ unsigned analyze() {
+ return ((expr ? (expr->analyze() & ~CONTAINS_VARIABLE) : 0)
+ | CONTAINS_STAR);
+ }
+};
+
+typedef void map_func(const char *, const char *, string &);
+
+class map_expr : public unary_expr {
+ map_func *func;
+public:
+ map_expr(expression *e, map_func *f) : unary_expr(e), func(f) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+typedef const char *extractor_func(const char *, const char *, const char **);
+
+class extractor_expr : public unary_expr {
+ int part;
+ extractor_func *func;
+public:
+ enum { BEFORE = +1, MATCH = 0, AFTER = -1 };
+ extractor_expr(expression *e, extractor_func *f, int pt)
+ : unary_expr(e), part(pt), func(f) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class truncate_expr : public unary_expr {
+ int n;
+public:
+ truncate_expr(expression *e, int i) : unary_expr(e), n(i) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class separator_expr : public unary_expr {
+public:
+ separator_expr(expression *e) : unary_expr(e) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class binary_expr : public expression {
+protected:
+ expression *expr1;
+ expression *expr2;
+public:
+ binary_expr(expression *e1, expression *e2) : expr1(e1), expr2(e2) { }
+ ~binary_expr() { delete expr1; delete expr2; }
+ void evaluate(int, const reference &, string &, substring_position &) = 0;
+ unsigned analyze() {
+ return (expr1 ? expr1->analyze() : 0) | (expr2 ? expr2->analyze() : 0);
+ }
+};
+
+class alternative_expr : public binary_expr {
+public:
+ alternative_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class list_expr : public binary_expr {
+public:
+ list_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class substitute_expr : public binary_expr {
+public:
+ substitute_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class ternary_expr : public expression {
+protected:
+ expression *expr1;
+ expression *expr2;
+ expression *expr3;
+public:
+ ternary_expr(expression *e1, expression *e2, expression *e3)
+ : expr1(e1), expr2(e2), expr3(e3) { }
+ ~ternary_expr() { delete expr1; delete expr2; delete expr3; }
+ void evaluate(int, const reference &, string &, substring_position &) = 0;
+ unsigned analyze() {
+ return ((expr1 ? expr1->analyze() : 0)
+ | (expr2 ? expr2->analyze() : 0)
+ | (expr3 ? expr3->analyze() : 0));
+ }
+};
+
+class conditional_expr : public ternary_expr {
+public:
+ conditional_expr(expression *e1, expression *e2, expression *e3)
+ : ternary_expr(e1, e2, e3) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+static expression *parsed_label = 0;
+static expression *parsed_date_label = 0;
+static expression *parsed_short_label = 0;
+
+static expression *parse_result;
+
+string literals;
+
+#line 221 "label.y"
+typedef union {
+ int num;
+ expression *expr;
+ struct { int ndigits; int val; } dig;
+ struct { int start; int len; } str;
+} YYSTYPE;
+#line 218 "y.tab.c"
+#define TOKEN_LETTER 257
+#define TOKEN_LITERAL 258
+#define TOKEN_DIGIT 259
+#define YYERRCODE 256
+short yylhs[] = { -1,
+ 0, 1, 1, 6, 6, 2, 2, 2, 3, 3,
+ 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 9, 9, 7, 7, 8, 8,
+ 10, 10, 10,
+};
+short yylen[] = { 2,
+ 1, 1, 5, 0, 1, 1, 3, 3, 1, 2,
+ 1, 3, 1, 1, 1, 2, 2, 2, 5, 3,
+ 3, 2, 3, 3, 0, 1, 1, 2, 1, 2,
+ 0, 1, 1,
+};
+short yydefred[] = { 0,
+ 0, 14, 13, 0, 0, 0, 0, 5, 0, 0,
+ 0, 0, 1, 27, 0, 17, 29, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 22, 0, 28,
+ 30, 23, 24, 0, 0, 0, 32, 33, 0, 0,
+ 0, 0, 0, 0, 3, 0, 19,
+};
+short yydgoto[] = { 7,
+ 8, 9, 10, 11, 12, 13, 15, 18, 47, 39,
+};
+short yysindex[] = { -32,
+ -257, 0, 0, -240, -32, -32, 0, 0, -18, -32,
+ -36, -114, 0, 0, -246, 0, 0, -241, -14, -39,
+ -32, -32, -32, -114, -21, -257, -257, 0, -32, 0,
+ 0, 0, 0, -25, -32, -32, 0, 0, -223, -246,
+ -246, -36, -32, -257, 0, -246, 0,
+};
+short yyrindex[] = { 35,
+ 1, 0, 0, 0, -5, -4, 0, 0, 14, 208,
+ 159, 224, 0, 0, 11, 0, 0, 40, 0, 0,
+ 2, 0, 0, 253, -220, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 263, 281, 0, 0, 0, 50,
+ 105, 214, 0, 115, 0, 149, 0,
+};
+short yygindex[] = { 0,
+ 19, 0, 7, 37, -10, 10, -23, 0, 0, 0,
+};
+#define YYTABLESIZE 511
+short yytable[] = { 24,
+ 15, 14, 40, 41, 4, 28, 26, 5, 27, 25,
+ 16, 29, 30, 2, 19, 20, 16, 31, 17, 23,
+ 46, 37, 33, 38, 24, 24, 32, 6, 35, 36,
+ 34, 3, 43, 44, 4, 4, 31, 15, 15, 18,
+ 15, 15, 15, 15, 21, 15, 15, 16, 16, 20,
+ 16, 16, 16, 16, 2, 16, 16, 4, 15, 4,
+ 15, 45, 15, 15, 15, 42, 0, 0, 16, 0,
+ 16, 2, 16, 16, 16, 2, 18, 18, 0, 18,
+ 18, 18, 18, 0, 18, 18, 20, 20, 0, 20,
+ 20, 20, 20, 0, 20, 20, 0, 18, 0, 18,
+ 0, 18, 18, 18, 21, 22, 0, 20, 0, 20,
+ 0, 20, 20, 20, 25, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 15, 0, 0, 0,
+ 0, 0, 0, 0, 16, 0, 16, 0, 0, 0,
+ 0, 21, 21, 0, 21, 21, 21, 21, 26, 21,
+ 21, 25, 25, 0, 25, 25, 25, 25, 11, 25,
+ 25, 0, 21, 18, 21, 18, 21, 21, 21, 0,
+ 0, 0, 25, 20, 25, 20, 25, 25, 25, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0, 26, 26,
+ 26, 26, 0, 26, 26, 11, 11, 0, 11, 11,
+ 0, 0, 0, 0, 0, 0, 26, 6, 26, 0,
+ 26, 26, 26, 12, 0, 0, 11, 0, 11, 0,
+ 11, 11, 11, 9, 1, 2, 0, 0, 21, 0,
+ 21, 0, 0, 0, 0, 0, 0, 0, 25, 0,
+ 25, 0, 0, 0, 0, 6, 0, 0, 6, 0,
+ 12, 12, 10, 12, 12, 0, 0, 15, 15, 0,
+ 9, 9, 7, 9, 9, 6, 0, 16, 16, 6,
+ 6, 12, 26, 12, 26, 12, 12, 12, 0, 0,
+ 8, 9, 11, 9, 11, 9, 9, 9, 0, 10,
+ 10, 0, 10, 10, 0, 0, 18, 18, 0, 0,
+ 7, 0, 0, 7, 0, 0, 20, 20, 0, 0,
+ 10, 0, 10, 0, 10, 10, 10, 0, 8, 0,
+ 7, 8, 0, 0, 7, 7, 0, 0, 0, 0,
+ 0, 6, 0, 0, 0, 0, 0, 12, 8, 12,
+ 0, 0, 8, 8, 0, 0, 0, 9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 21, 21, 0, 0, 0, 0, 0, 0, 0,
+ 0, 25, 25, 0, 0, 0, 10, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 8, 26, 26, 0, 0, 0,
+ 0, 0, 0, 0, 0, 11, 11, 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,
+ 12, 12, 0, 0, 0, 0, 0, 0, 0, 0,
+ 9, 9, 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, 10,
+ 10,
+};
+short yycheck[] = { 10,
+ 0, 259, 26, 27, 37, 42, 43, 40, 45, 46,
+ 0, 126, 259, 0, 5, 6, 257, 259, 259, 38,
+ 44, 43, 62, 45, 35, 36, 41, 60, 22, 23,
+ 21, 64, 58, 257, 0, 41, 257, 37, 38, 0,
+ 40, 41, 42, 43, 63, 45, 46, 37, 38, 0,
+ 40, 41, 42, 43, 41, 45, 46, 62, 58, 58,
+ 60, 43, 62, 63, 64, 29, -1, -1, 58, -1,
+ 60, 58, 62, 63, 64, 62, 37, 38, -1, 40,
+ 41, 42, 43, -1, 45, 46, 37, 38, -1, 40,
+ 41, 42, 43, -1, 45, 46, -1, 58, -1, 60,
+ -1, 62, 63, 64, 0, 124, -1, 58, -1, 60,
+ -1, 62, 63, 64, 0, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 124, -1, 126, -1, -1, -1,
+ -1, -1, -1, -1, 124, -1, 126, -1, -1, -1,
+ -1, 37, 38, -1, 40, 41, 42, 43, 0, 45,
+ 46, 37, 38, -1, 40, 41, 42, 43, 0, 45,
+ 46, -1, 58, 124, 60, 126, 62, 63, 64, -1,
+ -1, -1, 58, 124, 60, 126, 62, 63, 64, -1,
+ -1, -1, -1, -1, -1, 37, 38, -1, 40, 41,
+ 42, 43, -1, 45, 46, 37, 38, -1, 40, 41,
+ -1, -1, -1, -1, -1, -1, 58, 0, 60, -1,
+ 62, 63, 64, 0, -1, -1, 58, -1, 60, -1,
+ 62, 63, 64, 0, 257, 258, -1, -1, 124, -1,
+ 126, -1, -1, -1, -1, -1, -1, -1, 124, -1,
+ 126, -1, -1, -1, -1, 38, -1, -1, 41, -1,
+ 37, 38, 0, 40, 41, -1, -1, 257, 258, -1,
+ 37, 38, 0, 40, 41, 58, -1, 257, 258, 62,
+ 63, 58, 124, 60, 126, 62, 63, 64, -1, -1,
+ 0, 58, 124, 60, 126, 62, 63, 64, -1, 37,
+ 38, -1, 40, 41, -1, -1, 257, 258, -1, -1,
+ 38, -1, -1, 41, -1, -1, 257, 258, -1, -1,
+ 58, -1, 60, -1, 62, 63, 64, -1, 38, -1,
+ 58, 41, -1, -1, 62, 63, -1, -1, -1, -1,
+ -1, 124, -1, -1, -1, -1, -1, 124, 58, 126,
+ -1, -1, 62, 63, -1, -1, -1, 124, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 257, 258, -1, -1, -1, -1, -1, -1, -1,
+ -1, 257, 258, -1, -1, -1, 124, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 124, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 124, 257, 258, -1, -1, -1,
+ -1, -1, -1, -1, -1, 257, 258, -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, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 257, 258, -1, -1, -1, -1, -1, -1, -1, -1,
+ 257, 258, -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, 257,
+ 258,
+};
+#define YYFINAL 7
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#define YYMAXTOKEN 259
+#if YYDEBUG
+char *yyname[] = {
+"end-of-file",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,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,"'|'",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,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,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,"TOKEN_LETTER","TOKEN_LITERAL","TOKEN_DIGIT",
+};
+char *yyrule[] = {
+"$accept : expr",
+"expr : optional_conditional",
+"conditional : alternative",
+"conditional : alternative '?' optional_conditional ':' conditional",
+"optional_conditional :",
+"optional_conditional : conditional",
+"alternative : list",
+"alternative : alternative '|' list",
+"alternative : alternative '&' list",
+"list : substitute",
+"list : list substitute",
+"substitute : string",
+"substitute : substitute '~' string",
+"string : '@'",
+"string : TOKEN_LITERAL",
+"string : TOKEN_LETTER",
+"string : TOKEN_LETTER number",
+"string : '%' TOKEN_LETTER",
+"string : '%' digits",
+"string : string '.' flag TOKEN_LETTER optional_number",
+"string : string '+' number",
+"string : string '-' number",
+"string : string '*'",
+"string : '(' optional_conditional ')'",
+"string : '<' optional_conditional '>'",
+"optional_number :",
+"optional_number : number",
+"number : TOKEN_DIGIT",
+"number : number TOKEN_DIGIT",
+"digits : TOKEN_DIGIT",
+"digits : digits TOKEN_DIGIT",
+"flag :",
+"flag : '+'",
+"flag : '-'",
+};
+#endif
+#ifdef YYSTACKSIZE
+#undef YYMAXDEPTH
+#define YYMAXDEPTH YYSTACKSIZE
+#else
+#ifdef YYMAXDEPTH
+#define YYSTACKSIZE YYMAXDEPTH
+#else
+#define YYSTACKSIZE 500
+#define YYMAXDEPTH 500
+#endif
+#endif
+int yydebug;
+int yynerrs;
+int yyerrflag;
+int yychar;
+short *yyssp;
+YYSTYPE *yyvsp;
+YYSTYPE yyval;
+YYSTYPE yylval;
+short yyss[YYSTACKSIZE];
+YYSTYPE yyvs[YYSTACKSIZE];
+#define yystacksize YYSTACKSIZE
+#line 397 "label.y"
+
+/* bison defines const to be empty unless __STDC__ is defined, which it
+isn't under cfront */
+
+#ifdef const
+#undef const
+#endif
+
+const char *spec_ptr;
+const char *spec_end;
+const char *spec_cur;
+
+int yylex()
+{
+ while (spec_ptr < spec_end && csspace(*spec_ptr))
+ spec_ptr++;
+ spec_cur = spec_ptr;
+ if (spec_ptr >= spec_end)
+ return 0;
+ unsigned char c = *spec_ptr++;
+ if (csalpha(c)) {
+ yylval.num = c;
+ return TOKEN_LETTER;
+ }
+ if (csdigit(c)) {
+ yylval.num = c - '0';
+ return TOKEN_DIGIT;
+ }
+ if (c == '\'') {
+ yylval.str.start = literals.length();
+ for (; spec_ptr < spec_end; spec_ptr++) {
+ if (*spec_ptr == '\'') {
+ if (++spec_ptr < spec_end && *spec_ptr == '\'')
+ literals += '\'';
+ else {
+ yylval.str.len = literals.length() - yylval.str.start;
+ return TOKEN_LITERAL;
+ }
+ }
+ else
+ literals += *spec_ptr;
+ }
+ yylval.str.len = literals.length() - yylval.str.start;
+ return TOKEN_LITERAL;
+ }
+ return c;
+}
+
+int set_label_spec(const char *label_spec)
+{
+ spec_cur = spec_ptr = label_spec;
+ spec_end = strchr(label_spec, '\0');
+ literals.clear();
+ if (yyparse())
+ return 0;
+ delete parsed_label;
+ parsed_label = parse_result;
+ return 1;
+}
+
+int set_date_label_spec(const char *label_spec)
+{
+ spec_cur = spec_ptr = label_spec;
+ spec_end = strchr(label_spec, '\0');
+ literals.clear();
+ if (yyparse())
+ return 0;
+ delete parsed_date_label;
+ parsed_date_label = parse_result;
+ return 1;
+}
+
+int set_short_label_spec(const char *label_spec)
+{
+ spec_cur = spec_ptr = label_spec;
+ spec_end = strchr(label_spec, '\0');
+ literals.clear();
+ if (yyparse())
+ return 0;
+ delete parsed_short_label;
+ parsed_short_label = parse_result;
+ return 1;
+}
+
+void yyerror(const char *message)
+{
+ if (spec_cur < spec_end)
+ command_error("label specification %1 before `%2'", message, spec_cur);
+ else
+ command_error("label specification %1 at end of string",
+ message, spec_cur);
+}
+
+void at_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &)
+{
+ if (tentative)
+ ref.canonicalize_authors(result);
+ else {
+ const char *end, *start = ref.get_authors(&end);
+ if (start)
+ result.append(start, end - start);
+ }
+}
+
+void format_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &)
+{
+ if (tentative)
+ return;
+ const label_info *lp = ref.get_label_ptr();
+ int num = lp == 0 ? ref.get_number() : lp->count;
+ if (type != '0')
+ result += format_serial(type, num + 1);
+ else {
+ const char *ptr = itoa(num + first_number);
+ int pad = width - strlen(ptr);
+ while (--pad >= 0)
+ result += '0';
+ result += ptr;
+ }
+}
+
+static const char *format_serial(char c, int n)
+{
+ assert(n > 0);
+ static char buf[128]; // more than enough.
+ switch (c) {
+ case 'i':
+ case 'I':
+ {
+ char *p = buf;
+ // troff uses z and w to represent 10000 and 5000 in Roman
+ // numerals; I can find no historical basis for this usage
+ const char *s = c == 'i' ? "zwmdclxvi" : "ZWMDCLXVI";
+ if (n >= 40000)
+ return itoa(n);
+ while (n >= 10000) {
+ *p++ = s[0];
+ n -= 10000;
+ }
+ for (int i = 1000; i > 0; i /= 10, s += 2) {
+ int m = n/i;
+ n -= m*i;
+ switch (m) {
+ case 3:
+ *p++ = s[2];
+ /* falls through */
+ case 2:
+ *p++ = s[2];
+ /* falls through */
+ case 1:
+ *p++ = s[2];
+ break;
+ case 4:
+ *p++ = s[2];
+ *p++ = s[1];
+ break;
+ case 8:
+ *p++ = s[1];
+ *p++ = s[2];
+ *p++ = s[2];
+ *p++ = s[2];
+ break;
+ case 7:
+ *p++ = s[1];
+ *p++ = s[2];
+ *p++ = s[2];
+ break;
+ case 6:
+ *p++ = s[1];
+ *p++ = s[2];
+ break;
+ case 5:
+ *p++ = s[1];
+ break;
+ case 9:
+ *p++ = s[2];
+ *p++ = s[0];
+ }
+ }
+ *p = 0;
+ break;
+ }
+ case 'a':
+ case 'A':
+ {
+ char *p = buf;
+ // this is derived from troff/reg.c
+ while (n > 0) {
+ int d = n % 26;
+ if (d == 0)
+ d = 26;
+ n -= d;
+ n /= 26;
+ *p++ = c + d - 1; // ASCII dependent
+ }
+ *p-- = 0;
+ // Reverse it.
+ char *q = buf;
+ while (q < p) {
+ char temp = *q;
+ *q = *p;
+ *p = temp;
+ --p;
+ ++q;
+ }
+ break;
+ }
+ default:
+ assert(0);
+ }
+ return buf;
+}
+
+void field_expr::evaluate(int, const reference &ref,
+ string &result, substring_position &)
+{
+ const char *end;
+ const char *start = ref.get_field(name, &end);
+ if (start) {
+ start = nth_field(number, start, &end);
+ if (start)
+ result.append(start, end - start);
+ }
+}
+
+void literal_expr::evaluate(int, const reference &,
+ string &result, substring_position &)
+{
+ result += s;
+}
+
+analyzed_expr::analyzed_expr(expression *e)
+: unary_expr(e), flags(e ? e->analyze() : 0)
+{
+}
+
+void analyzed_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ if (expr)
+ expr->evaluate(tentative, ref, result, pos);
+}
+
+void star_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ const label_info *lp = ref.get_label_ptr();
+ if (!tentative
+ && (lp == 0 || lp->total > 1)
+ && expr)
+ expr->evaluate(tentative, ref, result, pos);
+}
+
+void separator_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ int start_length = result.length();
+ int is_first = pos.start < 0;
+ if (expr)
+ expr->evaluate(tentative, ref, result, pos);
+ if (is_first) {
+ pos.start = start_length;
+ pos.length = result.length() - start_length;
+ }
+}
+
+void map_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &)
+{
+ if (expr) {
+ string temp;
+ substring_position temp_pos;
+ expr->evaluate(tentative, ref, temp, temp_pos);
+ (*func)(temp.contents(), temp.contents() + temp.length(), result);
+ }
+}
+
+void extractor_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &)
+{
+ if (expr) {
+ string temp;
+ substring_position temp_pos;
+ expr->evaluate(tentative, ref, temp, temp_pos);
+ const char *end, *start = (*func)(temp.contents(),
+ temp.contents() + temp.length(),
+ &end);
+ switch (part) {
+ case BEFORE:
+ if (start)
+ result.append(temp.contents(), start - temp.contents());
+ else
+ result += temp;
+ break;
+ case MATCH:
+ if (start)
+ result.append(start, end - start);
+ break;
+ case AFTER:
+ if (start)
+ result.append(end, temp.contents() + temp.length() - end);
+ break;
+ default:
+ assert(0);
+ }
+ }
+}
+
+static void first_part(int len, const char *ptr, const char *end,
+ string &result)
+{
+ for (;;) {
+ const char *token_start = ptr;
+ if (!get_token(&ptr, end))
+ break;
+ const token_info *ti = lookup_token(token_start, ptr);
+ int counts = ti->sortify_non_empty(token_start, ptr);
+ if (counts && --len < 0)
+ break;
+ if (counts || ti->is_accent())
+ result.append(token_start, ptr - token_start);
+ }
+}
+
+static void last_part(int len, const char *ptr, const char *end,
+ string &result)
+{
+ const char *start = ptr;
+ int count = 0;
+ for (;;) {
+ const char *token_start = ptr;
+ if (!get_token(&ptr, end))
+ break;
+ const token_info *ti = lookup_token(token_start, ptr);
+ if (ti->sortify_non_empty(token_start, ptr))
+ count++;
+ }
+ ptr = start;
+ int skip = count - len;
+ if (skip > 0) {
+ for (;;) {
+ const char *token_start = ptr;
+ if (!get_token(&ptr, end))
+ assert(0);
+ const token_info *ti = lookup_token(token_start, ptr);
+ if (ti->sortify_non_empty(token_start, ptr) && --skip < 0) {
+ ptr = token_start;
+ break;
+ }
+ }
+ }
+ first_part(len, ptr, end, result);
+}
+
+void truncate_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &)
+{
+ if (expr) {
+ string temp;
+ substring_position temp_pos;
+ expr->evaluate(tentative, ref, temp, temp_pos);
+ const char *start = temp.contents();
+ const char *end = start + temp.length();
+ if (n > 0)
+ first_part(n, start, end, result);
+ else if (n < 0)
+ last_part(-n, start, end, result);
+ }
+}
+
+void alternative_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ int start_length = result.length();
+ if (expr1)
+ expr1->evaluate(tentative, ref, result, pos);
+ if (result.length() == start_length && expr2)
+ expr2->evaluate(tentative, ref, result, pos);
+}
+
+void list_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ if (expr1)
+ expr1->evaluate(tentative, ref, result, pos);
+ if (expr2)
+ expr2->evaluate(tentative, ref, result, pos);
+}
+
+void substitute_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ int start_length = result.length();
+ if (expr1)
+ expr1->evaluate(tentative, ref, result, pos);
+ if (result.length() > start_length && result[result.length() - 1] == '-') {
+ // ought to see if pos covers the -
+ result.set_length(result.length() - 1);
+ if (expr2)
+ expr2->evaluate(tentative, ref, result, pos);
+ }
+}
+
+void conditional_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ string temp;
+ substring_position temp_pos;
+ if (expr1)
+ expr1->evaluate(tentative, ref, temp, temp_pos);
+ if (temp.length() > 0) {
+ if (expr2)
+ expr2->evaluate(tentative, ref, result, pos);
+ }
+ else {
+ if (expr3)
+ expr3->evaluate(tentative, ref, result, pos);
+ }
+}
+
+void reference::pre_compute_label()
+{
+ if (parsed_label != 0
+ && (parsed_label->analyze() & expression::CONTAINS_VARIABLE)) {
+ label.clear();
+ substring_position temp_pos;
+ parsed_label->evaluate(1, *this, label, temp_pos);
+ label_ptr = lookup_label(label);
+ }
+}
+
+void reference::compute_label()
+{
+ label.clear();
+ if (parsed_label)
+ parsed_label->evaluate(0, *this, label, separator_pos);
+ if (short_label_flag && parsed_short_label)
+ parsed_short_label->evaluate(0, *this, short_label, short_separator_pos);
+ if (date_as_label) {
+ string new_date;
+ if (parsed_date_label) {
+ substring_position temp_pos;
+ parsed_date_label->evaluate(0, *this, new_date, temp_pos);
+ }
+ set_date(new_date);
+ }
+ if (label_ptr)
+ label_ptr->count += 1;
+}
+
+void reference::immediate_compute_label()
+{
+ if (label_ptr)
+ label_ptr->total = 2; // force use of disambiguator
+ compute_label();
+}
+
+int reference::merge_labels(reference **v, int n, label_type type,
+ string &result)
+{
+ if (abbreviate_label_ranges)
+ return merge_labels_by_number(v, n, type, result);
+ else
+ return merge_labels_by_parts(v, n, type, result);
+}
+
+int reference::merge_labels_by_number(reference **v, int n, label_type type,
+ string &result)
+{
+ if (n <= 1)
+ return 0;
+ int num = get_number();
+ // Only merge three or more labels.
+ if (v[0]->get_number() != num + 1
+ || v[1]->get_number() != num + 2)
+ return 0;
+ int i;
+ for (i = 2; i < n; i++)
+ if (v[i]->get_number() != num + i + 1)
+ break;
+ result = get_label(type);
+ result += label_range_indicator;
+ result += v[i - 1]->get_label(type);
+ return i;
+}
+
+const substring_position &reference::get_separator_pos(label_type type) const
+{
+ if (type == SHORT_LABEL && short_label_flag)
+ return short_separator_pos;
+ else
+ return separator_pos;
+}
+
+const string &reference::get_label(label_type type) const
+{
+ if (type == SHORT_LABEL && short_label_flag)
+ return short_label;
+ else
+ return label;
+}
+
+int reference::merge_labels_by_parts(reference **v, int n, label_type type,
+ string &result)
+{
+ if (n <= 0)
+ return 0;
+ const string &lb = get_label(type);
+ const substring_position &sp = get_separator_pos(type);
+ if (sp.start < 0
+ || sp.start != v[0]->get_separator_pos(type).start
+ || memcmp(lb.contents(), v[0]->get_label(type).contents(),
+ sp.start) != 0)
+ return 0;
+ result = lb;
+ int i = 0;
+ do {
+ result += separate_label_second_parts;
+ const substring_position &s = v[i]->get_separator_pos(type);
+ int sep_end_pos = s.start + s.length;
+ result.append(v[i]->get_label(type).contents() + sep_end_pos,
+ v[i]->get_label(type).length() - sep_end_pos);
+ } while (++i < n
+ && sp.start == v[i]->get_separator_pos(type).start
+ && memcmp(lb.contents(), v[i]->get_label(type).contents(),
+ sp.start) == 0);
+ return i;
+}
+
+string label_pool;
+
+label_info::label_info(const string &s)
+: start(label_pool.length()), length(s.length()), count(0), total(1)
+{
+ label_pool += s;
+}
+
+static label_info **label_table = 0;
+static int label_table_size = 0;
+static int label_table_used = 0;
+
+label_info *lookup_label(const string &label)
+{
+ if (label_table == 0) {
+ label_table = new label_info *[17];
+ label_table_size = 17;
+ for (int i = 0; i < 17; i++)
+ label_table[i] = 0;
+ }
+ unsigned h = hash_string(label.contents(), label.length()) % label_table_size;
+ label_info **ptr;
+ for (ptr = label_table + h;
+ *ptr != 0;
+ (ptr == label_table)
+ ? (ptr = label_table + label_table_size - 1)
+ : ptr--)
+ if ((*ptr)->length == label.length()
+ && memcmp(label_pool.contents() + (*ptr)->start, label.contents(),
+ label.length()) == 0) {
+ (*ptr)->total += 1;
+ return *ptr;
+ }
+ label_info *result = *ptr = new label_info(label);
+ if (++label_table_used * 2 > label_table_size) {
+ // Rehash the table.
+ label_info **old_table = label_table;
+ int old_size = label_table_size;
+ label_table_size = next_size(label_table_size);
+ label_table = new label_info *[label_table_size];
+ int i;
+ for (i = 0; i < label_table_size; i++)
+ label_table[i] = 0;
+ for (i = 0; i < old_size; i++)
+ if (old_table[i]) {
+ unsigned h = hash_string(label_pool.contents() + old_table[i]->start,
+ old_table[i]->length);
+ label_info **p;
+ for (p = label_table + (h % label_table_size);
+ *p != 0;
+ (p == label_table)
+ ? (p = label_table + label_table_size - 1)
+ : --p)
+ ;
+ *p = old_table[i];
+ }
+ a_delete old_table;
+ }
+ return result;
+}
+
+void clear_labels()
+{
+ for (int i = 0; i < label_table_size; i++) {
+ delete label_table[i];
+ label_table[i] = 0;
+ }
+ label_table_used = 0;
+ label_pool.clear();
+}
+
+static void consider_authors(reference **start, reference **end, int i);
+
+void compute_labels(reference **v, int n)
+{
+ if (parsed_label
+ && (parsed_label->analyze() & expression::CONTAINS_AT)
+ && sort_fields.length() >= 2
+ && sort_fields[0] == 'A'
+ && sort_fields[1] == '+')
+ consider_authors(v, v + n, 0);
+ for (int i = 0; i < n; i++)
+ v[i]->compute_label();
+}
+
+
+/* A reference with a list of authors <A0,A1,...,AN> _needs_ author i
+where 0 <= i <= N if there exists a reference with a list of authors
+<B0,B1,...,BM> such that <A0,A1,...,AN> != <B0,B1,...,BM> and M >= i
+and Aj = Bj for 0 <= j < i. In this case if we can't say ``A0,
+A1,...,A(i-1) et al'' because this would match both <A0,A1,...,AN> and
+<B0,B1,...,BM>. If a reference needs author i we only have to call
+need_author(j) for some j >= i such that the reference also needs
+author j. */
+
+/* This function handles 2 tasks:
+determine which authors are needed (cannot be elided with et al.);
+determine which authors can have only last names in the labels.
+
+References >= start and < end have the same first i author names.
+Also they're sorted by A+. */
+
+static void consider_authors(reference **start, reference **end, int i)
+{
+ if (start >= end)
+ return;
+ reference **p = start;
+ if (i >= (*p)->get_nauthors()) {
+ for (++p; p < end && i >= (*p)->get_nauthors(); p++)
+ ;
+ if (p < end && i > 0) {
+ // If we have an author list <A B C> and an author list <A B C D>,
+ // then both lists need C.
+ for (reference **q = start; q < end; q++)
+ (*q)->need_author(i - 1);
+ }
+ start = p;
+ }
+ while (p < end) {
+ reference **last_name_start = p;
+ reference **name_start = p;
+ for (++p;
+ p < end && i < (*p)->get_nauthors()
+ && same_author_last_name(**last_name_start, **p, i);
+ p++) {
+ if (!same_author_name(**name_start, **p, i)) {
+ consider_authors(name_start, p, i + 1);
+ name_start = p;
+ }
+ }
+ consider_authors(name_start, p, i + 1);
+ if (last_name_start == name_start) {
+ for (reference **q = last_name_start; q < p; q++)
+ (*q)->set_last_name_unambiguous(i);
+ }
+ // If we have an author list <A B C D> and <A B C E>, then the lists
+ // need author D and E respectively.
+ if (name_start > start || p < end) {
+ for (reference **q = last_name_start; q < p; q++)
+ (*q)->need_author(i);
+ }
+ }
+}
+
+int same_author_last_name(const reference &r1, const reference &r2, int n)
+{
+ const char *ae1;
+ const char *as1 = r1.get_sort_field(0, n, 0, &ae1);
+ assert(as1 != 0);
+ const char *ae2;
+ const char *as2 = r2.get_sort_field(0, n, 0, &ae2);
+ assert(as2 != 0);
+ return ae1 - as1 == ae2 - as2 && memcmp(as1, as2, ae1 - as1) == 0;
+}
+
+int same_author_name(const reference &r1, const reference &r2, int n)
+{
+ const char *ae1;
+ const char *as1 = r1.get_sort_field(0, n, -1, &ae1);
+ assert(as1 != 0);
+ const char *ae2;
+ const char *as2 = r2.get_sort_field(0, n, -1, &ae2);
+ assert(as2 != 0);
+ return ae1 - as1 == ae2 - as2 && memcmp(as1, as2, ae1 - as1) == 0;
+}
+
+
+void int_set::set(int i)
+{
+ assert(i >= 0);
+ int bytei = i >> 3;
+ if (bytei >= v.length()) {
+ int old_length = v.length();
+ v.set_length(bytei + 1);
+ for (int j = old_length; j <= bytei; j++)
+ v[j] = 0;
+ }
+ v[bytei] |= 1 << (i & 7);
+}
+
+int int_set::get(int i) const
+{
+ assert(i >= 0);
+ int bytei = i >> 3;
+ return bytei >= v.length() ? 0 : (v[bytei] & (1 << (i & 7))) != 0;
+}
+
+void reference::set_last_name_unambiguous(int i)
+{
+ last_name_unambiguous.set(i);
+}
+
+void reference::need_author(int n)
+{
+ if (n > last_needed_author)
+ last_needed_author = n;
+}
+
+const char *reference::get_authors(const char **end) const
+{
+ if (!computed_authors) {
+ ((reference *)this)->computed_authors = 1;
+ string &result = ((reference *)this)->authors;
+ int na = get_nauthors();
+ result.clear();
+ for (int i = 0; i < na; i++) {
+ if (last_name_unambiguous.get(i)) {
+ const char *e, *start = get_author_last_name(i, &e);
+ assert(start != 0);
+ result.append(start, e - start);
+ }
+ else {
+ const char *e, *start = get_author(i, &e);
+ assert(start != 0);
+ result.append(start, e - start);
+ }
+ if (i == last_needed_author
+ && et_al.length() > 0
+ && et_al_min_elide > 0
+ && last_needed_author + et_al_min_elide < na
+ && na >= et_al_min_total) {
+ result += et_al;
+ break;
+ }
+ if (i < na - 1) {
+ if (na == 2)
+ result += join_authors_exactly_two;
+ else if (i < na - 2)
+ result += join_authors_default;
+ else
+ result += join_authors_last_two;
+ }
+ }
+ }
+ const char *start = authors.contents();
+ *end = start + authors.length();
+ return start;
+}
+
+int reference::get_nauthors() const
+{
+ if (nauthors < 0) {
+ const char *dummy;
+ int na;
+ for (na = 0; get_author(na, &dummy) != 0; na++)
+ ;
+ ((reference *)this)->nauthors = na;
+ }
+ return nauthors;
+}
+#line 1228 "y.tab.c"
+#define YYABORT goto yyabort
+#define YYREJECT goto yyabort
+#define YYACCEPT goto yyaccept
+#define YYERROR goto yyerrlab
+int
+#if defined(__STDC__)
+yyparse(void)
+#else
+yyparse()
+#endif
+{
+ register int yym, yyn, yystate;
+#if YYDEBUG
+ register char *yys;
+ extern char *getenv();
+
+ if (yys = getenv("YYDEBUG"))
+ {
+ yyn = *yys;
+ if (yyn >= '0' && yyn <= '9')
+ yydebug = yyn - '0';
+ }
+#endif
+
+ yynerrs = 0;
+ yyerrflag = 0;
+ yychar = (-1);
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+ *yyssp = yystate = 0;
+
+yyloop:
+ if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
+ if (yychar < 0)
+ {
+ if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+ if (!yys) yys = "illegal-symbol";
+ printf("%sdebug: state %d, reading %d (%s)\n",
+ YYPREFIX, yystate, yychar, yys);
+ }
+#endif
+ }
+ if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: state %d, shifting to state %d\n",
+ YYPREFIX, yystate, yytable[yyn]);
+#endif
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ goto yyoverflow;
+ }
+ *++yyssp = yystate = yytable[yyn];
+ *++yyvsp = yylval;
+ yychar = (-1);
+ if (yyerrflag > 0) --yyerrflag;
+ goto yyloop;
+ }
+ if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+ {
+ yyn = yytable[yyn];
+ goto yyreduce;
+ }
+ if (yyerrflag) goto yyinrecovery;
+ yyerror("syntax error");
+#ifdef lint
+ goto yyerrlab;
+#endif
+yyerrlab:
+ ++yynerrs;
+yyinrecovery:
+ if (yyerrflag < 3)
+ {
+ yyerrflag = 3;
+ for (;;)
+ {
+ if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: state %d, error recovery shifting\
+ to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
+#endif
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ goto yyoverflow;
+ }
+ *++yyssp = yystate = yytable[yyn];
+ *++yyvsp = yylval;
+ goto yyloop;
+ }
+ else
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: error recovery discarding state %d\n",
+ YYPREFIX, *yyssp);
+#endif
+ if (yyssp <= yyss) goto yyabort;
+ --yyssp;
+ --yyvsp;
+ }
+ }
+ }
+ else
+ {
+ if (yychar == 0) goto yyabort;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+ if (!yys) yys = "illegal-symbol";
+ printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
+ YYPREFIX, yystate, yychar, yys);
+ }
+#endif
+ yychar = (-1);
+ goto yyloop;
+ }
+yyreduce:
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: state %d, reducing by rule %d (%s)\n",
+ YYPREFIX, yystate, yyn, yyrule[yyn]);
+#endif
+ yym = yylen[yyn];
+ yyval = yyvsp[1-yym];
+ switch (yyn)
+ {
+case 1:
+#line 250 "label.y"
+{ parse_result = (yyvsp[0].expr ? new analyzed_expr(yyvsp[0].expr) : 0); }
+break;
+case 2:
+#line 255 "label.y"
+{ yyval.expr = yyvsp[0].expr; }
+break;
+case 3:
+#line 257 "label.y"
+{ yyval.expr = new conditional_expr(yyvsp[-4].expr, yyvsp[-2].expr, yyvsp[0].expr); }
+break;
+case 4:
+#line 262 "label.y"
+{ yyval.expr = 0; }
+break;
+case 5:
+#line 264 "label.y"
+{ yyval.expr = yyvsp[0].expr; }
+break;
+case 6:
+#line 269 "label.y"
+{ yyval.expr = yyvsp[0].expr; }
+break;
+case 7:
+#line 271 "label.y"
+{ yyval.expr = new alternative_expr(yyvsp[-2].expr, yyvsp[0].expr); }
+break;
+case 8:
+#line 273 "label.y"
+{ yyval.expr = new conditional_expr(yyvsp[-2].expr, yyvsp[0].expr, 0); }
+break;
+case 9:
+#line 278 "label.y"
+{ yyval.expr = yyvsp[0].expr; }
+break;
+case 10:
+#line 280 "label.y"
+{ yyval.expr = new list_expr(yyvsp[-1].expr, yyvsp[0].expr); }
+break;
+case 11:
+#line 285 "label.y"
+{ yyval.expr = yyvsp[0].expr; }
+break;
+case 12:
+#line 287 "label.y"
+{ yyval.expr = new substitute_expr(yyvsp[-2].expr, yyvsp[0].expr); }
+break;
+case 13:
+#line 292 "label.y"
+{ yyval.expr = new at_expr; }
+break;
+case 14:
+#line 294 "label.y"
+{
+ yyval.expr = new literal_expr(literals.contents() + yyvsp[0].str.start,
+ yyvsp[0].str.len);
+ }
+break;
+case 15:
+#line 299 "label.y"
+{ yyval.expr = new field_expr(yyvsp[0].num, 0); }
+break;
+case 16:
+#line 301 "label.y"
+{ yyval.expr = new field_expr(yyvsp[-1].num, yyvsp[0].num - 1); }
+break;
+case 17:
+#line 303 "label.y"
+{
+ switch (yyvsp[0].num) {
+ case 'I':
+ case 'i':
+ case 'A':
+ case 'a':
+ yyval.expr = new format_expr(yyvsp[0].num);
+ break;
+ default:
+ command_error("unrecognized format `%1'", char(yyvsp[0].num));
+ yyval.expr = new format_expr('a');
+ break;
+ }
+ }
+break;
+case 18:
+#line 319 "label.y"
+{
+ yyval.expr = new format_expr('0', yyvsp[0].dig.ndigits, yyvsp[0].dig.val);
+ }
+break;
+case 19:
+#line 323 "label.y"
+{
+ switch (yyvsp[-1].num) {
+ case 'l':
+ yyval.expr = new map_expr(yyvsp[-4].expr, lowercase);
+ break;
+ case 'u':
+ yyval.expr = new map_expr(yyvsp[-4].expr, uppercase);
+ break;
+ case 'c':
+ yyval.expr = new map_expr(yyvsp[-4].expr, capitalize);
+ break;
+ case 'r':
+ yyval.expr = new map_expr(yyvsp[-4].expr, reverse_name);
+ break;
+ case 'a':
+ yyval.expr = new map_expr(yyvsp[-4].expr, abbreviate_name);
+ break;
+ case 'y':
+ yyval.expr = new extractor_expr(yyvsp[-4].expr, find_year, yyvsp[-2].num);
+ break;
+ case 'n':
+ yyval.expr = new extractor_expr(yyvsp[-4].expr, find_last_name, yyvsp[-2].num);
+ break;
+ default:
+ yyval.expr = yyvsp[-4].expr;
+ command_error("unknown function `%1'", char(yyvsp[-1].num));
+ break;
+ }
+ }
+break;
+case 20:
+#line 354 "label.y"
+{ yyval.expr = new truncate_expr(yyvsp[-2].expr, yyvsp[0].num); }
+break;
+case 21:
+#line 356 "label.y"
+{ yyval.expr = new truncate_expr(yyvsp[-2].expr, -yyvsp[0].num); }
+break;
+case 22:
+#line 358 "label.y"
+{ yyval.expr = new star_expr(yyvsp[-1].expr); }
+break;
+case 23:
+#line 360 "label.y"
+{ yyval.expr = yyvsp[-1].expr; }
+break;
+case 24:
+#line 362 "label.y"
+{ yyval.expr = new separator_expr(yyvsp[-1].expr); }
+break;
+case 25:
+#line 367 "label.y"
+{ yyval.num = -1; }
+break;
+case 26:
+#line 369 "label.y"
+{ yyval.num = yyvsp[0].num; }
+break;
+case 27:
+#line 374 "label.y"
+{ yyval.num = yyvsp[0].num; }
+break;
+case 28:
+#line 376 "label.y"
+{ yyval.num = yyvsp[-1].num*10 + yyvsp[0].num; }
+break;
+case 29:
+#line 381 "label.y"
+{ yyval.dig.ndigits = 1; yyval.dig.val = yyvsp[0].num; }
+break;
+case 30:
+#line 383 "label.y"
+{ yyval.dig.ndigits = yyvsp[-1].dig.ndigits + 1; yyval.dig.val = yyvsp[-1].dig.val*10 + yyvsp[0].num; }
+break;
+case 31:
+#line 389 "label.y"
+{ yyval.num = 0; }
+break;
+case 32:
+#line 391 "label.y"
+{ yyval.num = 1; }
+break;
+case 33:
+#line 393 "label.y"
+{ yyval.num = -1; }
+break;
+#line 1547 "y.tab.c"
+ }
+ yyssp -= yym;
+ yystate = *yyssp;
+ yyvsp -= yym;
+ yym = yylhs[yyn];
+ if (yystate == 0 && yym == 0)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: after reduction, shifting from state 0 to\
+ state %d\n", YYPREFIX, YYFINAL);
+#endif
+ yystate = YYFINAL;
+ *++yyssp = YYFINAL;
+ *++yyvsp = yyval;
+ if (yychar < 0)
+ {
+ if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+ if (!yys) yys = "illegal-symbol";
+ printf("%sdebug: state %d, reading %d (%s)\n",
+ YYPREFIX, YYFINAL, yychar, yys);
+ }
+#endif
+ }
+ if (yychar == 0) goto yyaccept;
+ goto yyloop;
+ }
+ if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
+ yystate = yytable[yyn];
+ else
+ yystate = yydgoto[yym];
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: after reduction, shifting from state %d \
+to state %d\n", YYPREFIX, *yyssp, yystate);
+#endif
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ goto yyoverflow;
+ }
+ *++yyssp = yystate;
+ *++yyvsp = yyval;
+ goto yyloop;
+yyoverflow:
+ yyerror("yacc stack overflow");
+yyabort:
+ return (1);
+yyaccept:
+ return (0);
+}
diff --git a/src/preproc/refer/label.y b/src/preproc/refer/label.y
new file mode 100644
index 00000000..6bc12c18
--- /dev/null
+++ b/src/preproc/refer/label.y
@@ -0,0 +1,1177 @@
+/* -*- C++ -*-
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+%{
+
+#include "refer.h"
+#include "refid.h"
+#include "ref.h"
+#include "token.h"
+
+int yylex();
+void yyerror(const char *);
+int yyparse();
+
+static const char *format_serial(char c, int n);
+
+struct label_info {
+ int start;
+ int length;
+ int count;
+ int total;
+ label_info(const string &);
+};
+
+label_info *lookup_label(const string &label);
+
+struct expression {
+ enum {
+ // Does the tentative label depend on the reference?
+ CONTAINS_VARIABLE = 01,
+ CONTAINS_STAR = 02,
+ CONTAINS_FORMAT = 04,
+ CONTAINS_AT = 010
+ };
+ virtual ~expression() { }
+ virtual void evaluate(int, const reference &, string &,
+ substring_position &) = 0;
+ virtual unsigned analyze() { return 0; }
+};
+
+class at_expr : public expression {
+public:
+ at_expr() { }
+ void evaluate(int, const reference &, string &, substring_position &);
+ unsigned analyze() { return CONTAINS_VARIABLE|CONTAINS_AT; }
+};
+
+class format_expr : public expression {
+ char type;
+ int width;
+ int first_number;
+public:
+ format_expr(char c, int w = 0, int f = 1)
+ : type(c), width(w), first_number(f) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+ unsigned analyze() { return CONTAINS_FORMAT; }
+};
+
+class field_expr : public expression {
+ int number;
+ char name;
+public:
+ field_expr(char nm, int num) : number(num), name(nm) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+ unsigned analyze() { return CONTAINS_VARIABLE; }
+};
+
+class literal_expr : public expression {
+ string s;
+public:
+ literal_expr(const char *ptr, int len) : s(ptr, len) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class unary_expr : public expression {
+protected:
+ expression *expr;
+public:
+ unary_expr(expression *e) : expr(e) { }
+ ~unary_expr() { delete expr; }
+ void evaluate(int, const reference &, string &, substring_position &) = 0;
+ unsigned analyze() { return expr ? expr->analyze() : 0; }
+};
+
+// This caches the analysis of an expression.
+
+class analyzed_expr : public unary_expr {
+ unsigned flags;
+public:
+ analyzed_expr(expression *);
+ void evaluate(int, const reference &, string &, substring_position &);
+ unsigned analyze() { return flags; }
+};
+
+class star_expr : public unary_expr {
+public:
+ star_expr(expression *e) : unary_expr(e) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+ unsigned analyze() {
+ return ((expr ? (expr->analyze() & ~CONTAINS_VARIABLE) : 0)
+ | CONTAINS_STAR);
+ }
+};
+
+typedef void map_func(const char *, const char *, string &);
+
+class map_expr : public unary_expr {
+ map_func *func;
+public:
+ map_expr(expression *e, map_func *f) : unary_expr(e), func(f) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+typedef const char *extractor_func(const char *, const char *, const char **);
+
+class extractor_expr : public unary_expr {
+ int part;
+ extractor_func *func;
+public:
+ enum { BEFORE = +1, MATCH = 0, AFTER = -1 };
+ extractor_expr(expression *e, extractor_func *f, int pt)
+ : unary_expr(e), part(pt), func(f) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class truncate_expr : public unary_expr {
+ int n;
+public:
+ truncate_expr(expression *e, int i) : unary_expr(e), n(i) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class separator_expr : public unary_expr {
+public:
+ separator_expr(expression *e) : unary_expr(e) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class binary_expr : public expression {
+protected:
+ expression *expr1;
+ expression *expr2;
+public:
+ binary_expr(expression *e1, expression *e2) : expr1(e1), expr2(e2) { }
+ ~binary_expr() { delete expr1; delete expr2; }
+ void evaluate(int, const reference &, string &, substring_position &) = 0;
+ unsigned analyze() {
+ return (expr1 ? expr1->analyze() : 0) | (expr2 ? expr2->analyze() : 0);
+ }
+};
+
+class alternative_expr : public binary_expr {
+public:
+ alternative_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class list_expr : public binary_expr {
+public:
+ list_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class substitute_expr : public binary_expr {
+public:
+ substitute_expr(expression *e1, expression *e2) : binary_expr(e1, e2) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+class ternary_expr : public expression {
+protected:
+ expression *expr1;
+ expression *expr2;
+ expression *expr3;
+public:
+ ternary_expr(expression *e1, expression *e2, expression *e3)
+ : expr1(e1), expr2(e2), expr3(e3) { }
+ ~ternary_expr() { delete expr1; delete expr2; delete expr3; }
+ void evaluate(int, const reference &, string &, substring_position &) = 0;
+ unsigned analyze() {
+ return ((expr1 ? expr1->analyze() : 0)
+ | (expr2 ? expr2->analyze() : 0)
+ | (expr3 ? expr3->analyze() : 0));
+ }
+};
+
+class conditional_expr : public ternary_expr {
+public:
+ conditional_expr(expression *e1, expression *e2, expression *e3)
+ : ternary_expr(e1, e2, e3) { }
+ void evaluate(int, const reference &, string &, substring_position &);
+};
+
+static expression *parsed_label = 0;
+static expression *parsed_date_label = 0;
+static expression *parsed_short_label = 0;
+
+static expression *parse_result;
+
+string literals;
+
+%}
+
+%union {
+ int num;
+ expression *expr;
+ struct { int ndigits; int val; } dig;
+ struct { int start; int len; } str;
+}
+
+/* uppercase or lowercase letter */
+%token <num> TOKEN_LETTER
+/* literal characters */
+%token <str> TOKEN_LITERAL
+/* digit */
+%token <num> TOKEN_DIGIT
+
+%type <expr> conditional
+%type <expr> alternative
+%type <expr> list
+%type <expr> string
+%type <expr> substitute
+%type <expr> optional_conditional
+%type <num> number
+%type <dig> digits
+%type <num> optional_number
+%type <num> flag
+
+%%
+
+expr:
+ optional_conditional
+ { parse_result = ($1 ? new analyzed_expr($1) : 0); }
+ ;
+
+conditional:
+ alternative
+ { $$ = $1; }
+ | alternative '?' optional_conditional ':' conditional
+ { $$ = new conditional_expr($1, $3, $5); }
+ ;
+
+optional_conditional:
+ /* empty */
+ { $$ = 0; }
+ | conditional
+ { $$ = $1; }
+ ;
+
+alternative:
+ list
+ { $$ = $1; }
+ | alternative '|' list
+ { $$ = new alternative_expr($1, $3); }
+ | alternative '&' list
+ { $$ = new conditional_expr($1, $3, 0); }
+ ;
+
+list:
+ substitute
+ { $$ = $1; }
+ | list substitute
+ { $$ = new list_expr($1, $2); }
+ ;
+
+substitute:
+ string
+ { $$ = $1; }
+ | substitute '~' string
+ { $$ = new substitute_expr($1, $3); }
+ ;
+
+string:
+ '@'
+ { $$ = new at_expr; }
+ | TOKEN_LITERAL
+ {
+ $$ = new literal_expr(literals.contents() + $1.start,
+ $1.len);
+ }
+ | TOKEN_LETTER
+ { $$ = new field_expr($1, 0); }
+ | TOKEN_LETTER number
+ { $$ = new field_expr($1, $2 - 1); }
+ | '%' TOKEN_LETTER
+ {
+ switch ($2) {
+ case 'I':
+ case 'i':
+ case 'A':
+ case 'a':
+ $$ = new format_expr($2);
+ break;
+ default:
+ command_error("unrecognized format `%1'", char($2));
+ $$ = new format_expr('a');
+ break;
+ }
+ }
+
+ | '%' digits
+ {
+ $$ = new format_expr('0', $2.ndigits, $2.val);
+ }
+ | string '.' flag TOKEN_LETTER optional_number
+ {
+ switch ($4) {
+ case 'l':
+ $$ = new map_expr($1, lowercase);
+ break;
+ case 'u':
+ $$ = new map_expr($1, uppercase);
+ break;
+ case 'c':
+ $$ = new map_expr($1, capitalize);
+ break;
+ case 'r':
+ $$ = new map_expr($1, reverse_name);
+ break;
+ case 'a':
+ $$ = new map_expr($1, abbreviate_name);
+ break;
+ case 'y':
+ $$ = new extractor_expr($1, find_year, $3);
+ break;
+ case 'n':
+ $$ = new extractor_expr($1, find_last_name, $3);
+ break;
+ default:
+ $$ = $1;
+ command_error("unknown function `%1'", char($4));
+ break;
+ }
+ }
+
+ | string '+' number
+ { $$ = new truncate_expr($1, $3); }
+ | string '-' number
+ { $$ = new truncate_expr($1, -$3); }
+ | string '*'
+ { $$ = new star_expr($1); }
+ | '(' optional_conditional ')'
+ { $$ = $2; }
+ | '<' optional_conditional '>'
+ { $$ = new separator_expr($2); }
+ ;
+
+optional_number:
+ /* empty */
+ { $$ = -1; }
+ | number
+ { $$ = $1; }
+ ;
+
+number:
+ TOKEN_DIGIT
+ { $$ = $1; }
+ | number TOKEN_DIGIT
+ { $$ = $1*10 + $2; }
+ ;
+
+digits:
+ TOKEN_DIGIT
+ { $$.ndigits = 1; $$.val = $1; }
+ | digits TOKEN_DIGIT
+ { $$.ndigits = $1.ndigits + 1; $$.val = $1.val*10 + $2; }
+ ;
+
+
+flag:
+ /* empty */
+ { $$ = 0; }
+ | '+'
+ { $$ = 1; }
+ | '-'
+ { $$ = -1; }
+ ;
+
+%%
+
+/* bison defines const to be empty unless __STDC__ is defined, which it
+isn't under cfront */
+
+#ifdef const
+#undef const
+#endif
+
+const char *spec_ptr;
+const char *spec_end;
+const char *spec_cur;
+
+int yylex()
+{
+ while (spec_ptr < spec_end && csspace(*spec_ptr))
+ spec_ptr++;
+ spec_cur = spec_ptr;
+ if (spec_ptr >= spec_end)
+ return 0;
+ unsigned char c = *spec_ptr++;
+ if (csalpha(c)) {
+ yylval.num = c;
+ return TOKEN_LETTER;
+ }
+ if (csdigit(c)) {
+ yylval.num = c - '0';
+ return TOKEN_DIGIT;
+ }
+ if (c == '\'') {
+ yylval.str.start = literals.length();
+ for (; spec_ptr < spec_end; spec_ptr++) {
+ if (*spec_ptr == '\'') {
+ if (++spec_ptr < spec_end && *spec_ptr == '\'')
+ literals += '\'';
+ else {
+ yylval.str.len = literals.length() - yylval.str.start;
+ return TOKEN_LITERAL;
+ }
+ }
+ else
+ literals += *spec_ptr;
+ }
+ yylval.str.len = literals.length() - yylval.str.start;
+ return TOKEN_LITERAL;
+ }
+ return c;
+}
+
+int set_label_spec(const char *label_spec)
+{
+ spec_cur = spec_ptr = label_spec;
+ spec_end = strchr(label_spec, '\0');
+ literals.clear();
+ if (yyparse())
+ return 0;
+ delete parsed_label;
+ parsed_label = parse_result;
+ return 1;
+}
+
+int set_date_label_spec(const char *label_spec)
+{
+ spec_cur = spec_ptr = label_spec;
+ spec_end = strchr(label_spec, '\0');
+ literals.clear();
+ if (yyparse())
+ return 0;
+ delete parsed_date_label;
+ parsed_date_label = parse_result;
+ return 1;
+}
+
+int set_short_label_spec(const char *label_spec)
+{
+ spec_cur = spec_ptr = label_spec;
+ spec_end = strchr(label_spec, '\0');
+ literals.clear();
+ if (yyparse())
+ return 0;
+ delete parsed_short_label;
+ parsed_short_label = parse_result;
+ return 1;
+}
+
+void yyerror(const char *message)
+{
+ if (spec_cur < spec_end)
+ command_error("label specification %1 before `%2'", message, spec_cur);
+ else
+ command_error("label specification %1 at end of string",
+ message, spec_cur);
+}
+
+void at_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &)
+{
+ if (tentative)
+ ref.canonicalize_authors(result);
+ else {
+ const char *end, *start = ref.get_authors(&end);
+ if (start)
+ result.append(start, end - start);
+ }
+}
+
+void format_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &)
+{
+ if (tentative)
+ return;
+ const label_info *lp = ref.get_label_ptr();
+ int num = lp == 0 ? ref.get_number() : lp->count;
+ if (type != '0')
+ result += format_serial(type, num + 1);
+ else {
+ const char *ptr = itoa(num + first_number);
+ int pad = width - strlen(ptr);
+ while (--pad >= 0)
+ result += '0';
+ result += ptr;
+ }
+}
+
+static const char *format_serial(char c, int n)
+{
+ assert(n > 0);
+ static char buf[128]; // more than enough.
+ switch (c) {
+ case 'i':
+ case 'I':
+ {
+ char *p = buf;
+ // troff uses z and w to represent 10000 and 5000 in Roman
+ // numerals; I can find no historical basis for this usage
+ const char *s = c == 'i' ? "zwmdclxvi" : "ZWMDCLXVI";
+ if (n >= 40000)
+ return itoa(n);
+ while (n >= 10000) {
+ *p++ = s[0];
+ n -= 10000;
+ }
+ for (int i = 1000; i > 0; i /= 10, s += 2) {
+ int m = n/i;
+ n -= m*i;
+ switch (m) {
+ case 3:
+ *p++ = s[2];
+ /* falls through */
+ case 2:
+ *p++ = s[2];
+ /* falls through */
+ case 1:
+ *p++ = s[2];
+ break;
+ case 4:
+ *p++ = s[2];
+ *p++ = s[1];
+ break;
+ case 8:
+ *p++ = s[1];
+ *p++ = s[2];
+ *p++ = s[2];
+ *p++ = s[2];
+ break;
+ case 7:
+ *p++ = s[1];
+ *p++ = s[2];
+ *p++ = s[2];
+ break;
+ case 6:
+ *p++ = s[1];
+ *p++ = s[2];
+ break;
+ case 5:
+ *p++ = s[1];
+ break;
+ case 9:
+ *p++ = s[2];
+ *p++ = s[0];
+ }
+ }
+ *p = 0;
+ break;
+ }
+ case 'a':
+ case 'A':
+ {
+ char *p = buf;
+ // this is derived from troff/reg.c
+ while (n > 0) {
+ int d = n % 26;
+ if (d == 0)
+ d = 26;
+ n -= d;
+ n /= 26;
+ *p++ = c + d - 1; // ASCII dependent
+ }
+ *p-- = 0;
+ // Reverse it.
+ char *q = buf;
+ while (q < p) {
+ char temp = *q;
+ *q = *p;
+ *p = temp;
+ --p;
+ ++q;
+ }
+ break;
+ }
+ default:
+ assert(0);
+ }
+ return buf;
+}
+
+void field_expr::evaluate(int, const reference &ref,
+ string &result, substring_position &)
+{
+ const char *end;
+ const char *start = ref.get_field(name, &end);
+ if (start) {
+ start = nth_field(number, start, &end);
+ if (start)
+ result.append(start, end - start);
+ }
+}
+
+void literal_expr::evaluate(int, const reference &,
+ string &result, substring_position &)
+{
+ result += s;
+}
+
+analyzed_expr::analyzed_expr(expression *e)
+: unary_expr(e), flags(e ? e->analyze() : 0)
+{
+}
+
+void analyzed_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ if (expr)
+ expr->evaluate(tentative, ref, result, pos);
+}
+
+void star_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ const label_info *lp = ref.get_label_ptr();
+ if (!tentative
+ && (lp == 0 || lp->total > 1)
+ && expr)
+ expr->evaluate(tentative, ref, result, pos);
+}
+
+void separator_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ int start_length = result.length();
+ int is_first = pos.start < 0;
+ if (expr)
+ expr->evaluate(tentative, ref, result, pos);
+ if (is_first) {
+ pos.start = start_length;
+ pos.length = result.length() - start_length;
+ }
+}
+
+void map_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &)
+{
+ if (expr) {
+ string temp;
+ substring_position temp_pos;
+ expr->evaluate(tentative, ref, temp, temp_pos);
+ (*func)(temp.contents(), temp.contents() + temp.length(), result);
+ }
+}
+
+void extractor_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &)
+{
+ if (expr) {
+ string temp;
+ substring_position temp_pos;
+ expr->evaluate(tentative, ref, temp, temp_pos);
+ const char *end, *start = (*func)(temp.contents(),
+ temp.contents() + temp.length(),
+ &end);
+ switch (part) {
+ case BEFORE:
+ if (start)
+ result.append(temp.contents(), start - temp.contents());
+ else
+ result += temp;
+ break;
+ case MATCH:
+ if (start)
+ result.append(start, end - start);
+ break;
+ case AFTER:
+ if (start)
+ result.append(end, temp.contents() + temp.length() - end);
+ break;
+ default:
+ assert(0);
+ }
+ }
+}
+
+static void first_part(int len, const char *ptr, const char *end,
+ string &result)
+{
+ for (;;) {
+ const char *token_start = ptr;
+ if (!get_token(&ptr, end))
+ break;
+ const token_info *ti = lookup_token(token_start, ptr);
+ int counts = ti->sortify_non_empty(token_start, ptr);
+ if (counts && --len < 0)
+ break;
+ if (counts || ti->is_accent())
+ result.append(token_start, ptr - token_start);
+ }
+}
+
+static void last_part(int len, const char *ptr, const char *end,
+ string &result)
+{
+ const char *start = ptr;
+ int count = 0;
+ for (;;) {
+ const char *token_start = ptr;
+ if (!get_token(&ptr, end))
+ break;
+ const token_info *ti = lookup_token(token_start, ptr);
+ if (ti->sortify_non_empty(token_start, ptr))
+ count++;
+ }
+ ptr = start;
+ int skip = count - len;
+ if (skip > 0) {
+ for (;;) {
+ const char *token_start = ptr;
+ if (!get_token(&ptr, end))
+ assert(0);
+ const token_info *ti = lookup_token(token_start, ptr);
+ if (ti->sortify_non_empty(token_start, ptr) && --skip < 0) {
+ ptr = token_start;
+ break;
+ }
+ }
+ }
+ first_part(len, ptr, end, result);
+}
+
+void truncate_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &)
+{
+ if (expr) {
+ string temp;
+ substring_position temp_pos;
+ expr->evaluate(tentative, ref, temp, temp_pos);
+ const char *start = temp.contents();
+ const char *end = start + temp.length();
+ if (n > 0)
+ first_part(n, start, end, result);
+ else if (n < 0)
+ last_part(-n, start, end, result);
+ }
+}
+
+void alternative_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ int start_length = result.length();
+ if (expr1)
+ expr1->evaluate(tentative, ref, result, pos);
+ if (result.length() == start_length && expr2)
+ expr2->evaluate(tentative, ref, result, pos);
+}
+
+void list_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ if (expr1)
+ expr1->evaluate(tentative, ref, result, pos);
+ if (expr2)
+ expr2->evaluate(tentative, ref, result, pos);
+}
+
+void substitute_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ int start_length = result.length();
+ if (expr1)
+ expr1->evaluate(tentative, ref, result, pos);
+ if (result.length() > start_length && result[result.length() - 1] == '-') {
+ // ought to see if pos covers the -
+ result.set_length(result.length() - 1);
+ if (expr2)
+ expr2->evaluate(tentative, ref, result, pos);
+ }
+}
+
+void conditional_expr::evaluate(int tentative, const reference &ref,
+ string &result, substring_position &pos)
+{
+ string temp;
+ substring_position temp_pos;
+ if (expr1)
+ expr1->evaluate(tentative, ref, temp, temp_pos);
+ if (temp.length() > 0) {
+ if (expr2)
+ expr2->evaluate(tentative, ref, result, pos);
+ }
+ else {
+ if (expr3)
+ expr3->evaluate(tentative, ref, result, pos);
+ }
+}
+
+void reference::pre_compute_label()
+{
+ if (parsed_label != 0
+ && (parsed_label->analyze() & expression::CONTAINS_VARIABLE)) {
+ label.clear();
+ substring_position temp_pos;
+ parsed_label->evaluate(1, *this, label, temp_pos);
+ label_ptr = lookup_label(label);
+ }
+}
+
+void reference::compute_label()
+{
+ label.clear();
+ if (parsed_label)
+ parsed_label->evaluate(0, *this, label, separator_pos);
+ if (short_label_flag && parsed_short_label)
+ parsed_short_label->evaluate(0, *this, short_label, short_separator_pos);
+ if (date_as_label) {
+ string new_date;
+ if (parsed_date_label) {
+ substring_position temp_pos;
+ parsed_date_label->evaluate(0, *this, new_date, temp_pos);
+ }
+ set_date(new_date);
+ }
+ if (label_ptr)
+ label_ptr->count += 1;
+}
+
+void reference::immediate_compute_label()
+{
+ if (label_ptr)
+ label_ptr->total = 2; // force use of disambiguator
+ compute_label();
+}
+
+int reference::merge_labels(reference **v, int n, label_type type,
+ string &result)
+{
+ if (abbreviate_label_ranges)
+ return merge_labels_by_number(v, n, type, result);
+ else
+ return merge_labels_by_parts(v, n, type, result);
+}
+
+int reference::merge_labels_by_number(reference **v, int n, label_type type,
+ string &result)
+{
+ if (n <= 1)
+ return 0;
+ int num = get_number();
+ // Only merge three or more labels.
+ if (v[0]->get_number() != num + 1
+ || v[1]->get_number() != num + 2)
+ return 0;
+ int i;
+ for (i = 2; i < n; i++)
+ if (v[i]->get_number() != num + i + 1)
+ break;
+ result = get_label(type);
+ result += label_range_indicator;
+ result += v[i - 1]->get_label(type);
+ return i;
+}
+
+const substring_position &reference::get_separator_pos(label_type type) const
+{
+ if (type == SHORT_LABEL && short_label_flag)
+ return short_separator_pos;
+ else
+ return separator_pos;
+}
+
+const string &reference::get_label(label_type type) const
+{
+ if (type == SHORT_LABEL && short_label_flag)
+ return short_label;
+ else
+ return label;
+}
+
+int reference::merge_labels_by_parts(reference **v, int n, label_type type,
+ string &result)
+{
+ if (n <= 0)
+ return 0;
+ const string &lb = get_label(type);
+ const substring_position &sp = get_separator_pos(type);
+ if (sp.start < 0
+ || sp.start != v[0]->get_separator_pos(type).start
+ || memcmp(lb.contents(), v[0]->get_label(type).contents(),
+ sp.start) != 0)
+ return 0;
+ result = lb;
+ int i = 0;
+ do {
+ result += separate_label_second_parts;
+ const substring_position &s = v[i]->get_separator_pos(type);
+ int sep_end_pos = s.start + s.length;
+ result.append(v[i]->get_label(type).contents() + sep_end_pos,
+ v[i]->get_label(type).length() - sep_end_pos);
+ } while (++i < n
+ && sp.start == v[i]->get_separator_pos(type).start
+ && memcmp(lb.contents(), v[i]->get_label(type).contents(),
+ sp.start) == 0);
+ return i;
+}
+
+string label_pool;
+
+label_info::label_info(const string &s)
+: start(label_pool.length()), length(s.length()), count(0), total(1)
+{
+ label_pool += s;
+}
+
+static label_info **label_table = 0;
+static int label_table_size = 0;
+static int label_table_used = 0;
+
+label_info *lookup_label(const string &label)
+{
+ if (label_table == 0) {
+ label_table = new label_info *[17];
+ label_table_size = 17;
+ for (int i = 0; i < 17; i++)
+ label_table[i] = 0;
+ }
+ unsigned h = hash_string(label.contents(), label.length()) % label_table_size;
+ label_info **ptr;
+ for (ptr = label_table + h;
+ *ptr != 0;
+ (ptr == label_table)
+ ? (ptr = label_table + label_table_size - 1)
+ : ptr--)
+ if ((*ptr)->length == label.length()
+ && memcmp(label_pool.contents() + (*ptr)->start, label.contents(),
+ label.length()) == 0) {
+ (*ptr)->total += 1;
+ return *ptr;
+ }
+ label_info *result = *ptr = new label_info(label);
+ if (++label_table_used * 2 > label_table_size) {
+ // Rehash the table.
+ label_info **old_table = label_table;
+ int old_size = label_table_size;
+ label_table_size = next_size(label_table_size);
+ label_table = new label_info *[label_table_size];
+ int i;
+ for (i = 0; i < label_table_size; i++)
+ label_table[i] = 0;
+ for (i = 0; i < old_size; i++)
+ if (old_table[i]) {
+ unsigned h = hash_string(label_pool.contents() + old_table[i]->start,
+ old_table[i]->length);
+ label_info **p;
+ for (p = label_table + (h % label_table_size);
+ *p != 0;
+ (p == label_table)
+ ? (p = label_table + label_table_size - 1)
+ : --p)
+ ;
+ *p = old_table[i];
+ }
+ a_delete old_table;
+ }
+ return result;
+}
+
+void clear_labels()
+{
+ for (int i = 0; i < label_table_size; i++) {
+ delete label_table[i];
+ label_table[i] = 0;
+ }
+ label_table_used = 0;
+ label_pool.clear();
+}
+
+static void consider_authors(reference **start, reference **end, int i);
+
+void compute_labels(reference **v, int n)
+{
+ if (parsed_label
+ && (parsed_label->analyze() & expression::CONTAINS_AT)
+ && sort_fields.length() >= 2
+ && sort_fields[0] == 'A'
+ && sort_fields[1] == '+')
+ consider_authors(v, v + n, 0);
+ for (int i = 0; i < n; i++)
+ v[i]->compute_label();
+}
+
+
+/* A reference with a list of authors <A0,A1,...,AN> _needs_ author i
+where 0 <= i <= N if there exists a reference with a list of authors
+<B0,B1,...,BM> such that <A0,A1,...,AN> != <B0,B1,...,BM> and M >= i
+and Aj = Bj for 0 <= j < i. In this case if we can't say ``A0,
+A1,...,A(i-1) et al'' because this would match both <A0,A1,...,AN> and
+<B0,B1,...,BM>. If a reference needs author i we only have to call
+need_author(j) for some j >= i such that the reference also needs
+author j. */
+
+/* This function handles 2 tasks:
+determine which authors are needed (cannot be elided with et al.);
+determine which authors can have only last names in the labels.
+
+References >= start and < end have the same first i author names.
+Also they're sorted by A+. */
+
+static void consider_authors(reference **start, reference **end, int i)
+{
+ if (start >= end)
+ return;
+ reference **p = start;
+ if (i >= (*p)->get_nauthors()) {
+ for (++p; p < end && i >= (*p)->get_nauthors(); p++)
+ ;
+ if (p < end && i > 0) {
+ // If we have an author list <A B C> and an author list <A B C D>,
+ // then both lists need C.
+ for (reference **q = start; q < end; q++)
+ (*q)->need_author(i - 1);
+ }
+ start = p;
+ }
+ while (p < end) {
+ reference **last_name_start = p;
+ reference **name_start = p;
+ for (++p;
+ p < end && i < (*p)->get_nauthors()
+ && same_author_last_name(**last_name_start, **p, i);
+ p++) {
+ if (!same_author_name(**name_start, **p, i)) {
+ consider_authors(name_start, p, i + 1);
+ name_start = p;
+ }
+ }
+ consider_authors(name_start, p, i + 1);
+ if (last_name_start == name_start) {
+ for (reference **q = last_name_start; q < p; q++)
+ (*q)->set_last_name_unambiguous(i);
+ }
+ // If we have an author list <A B C D> and <A B C E>, then the lists
+ // need author D and E respectively.
+ if (name_start > start || p < end) {
+ for (reference **q = last_name_start; q < p; q++)
+ (*q)->need_author(i);
+ }
+ }
+}
+
+int same_author_last_name(const reference &r1, const reference &r2, int n)
+{
+ const char *ae1;
+ const char *as1 = r1.get_sort_field(0, n, 0, &ae1);
+ assert(as1 != 0);
+ const char *ae2;
+ const char *as2 = r2.get_sort_field(0, n, 0, &ae2);
+ assert(as2 != 0);
+ return ae1 - as1 == ae2 - as2 && memcmp(as1, as2, ae1 - as1) == 0;
+}
+
+int same_author_name(const reference &r1, const reference &r2, int n)
+{
+ const char *ae1;
+ const char *as1 = r1.get_sort_field(0, n, -1, &ae1);
+ assert(as1 != 0);
+ const char *ae2;
+ const char *as2 = r2.get_sort_field(0, n, -1, &ae2);
+ assert(as2 != 0);
+ return ae1 - as1 == ae2 - as2 && memcmp(as1, as2, ae1 - as1) == 0;
+}
+
+
+void int_set::set(int i)
+{
+ assert(i >= 0);
+ int bytei = i >> 3;
+ if (bytei >= v.length()) {
+ int old_length = v.length();
+ v.set_length(bytei + 1);
+ for (int j = old_length; j <= bytei; j++)
+ v[j] = 0;
+ }
+ v[bytei] |= 1 << (i & 7);
+}
+
+int int_set::get(int i) const
+{
+ assert(i >= 0);
+ int bytei = i >> 3;
+ return bytei >= v.length() ? 0 : (v[bytei] & (1 << (i & 7))) != 0;
+}
+
+void reference::set_last_name_unambiguous(int i)
+{
+ last_name_unambiguous.set(i);
+}
+
+void reference::need_author(int n)
+{
+ if (n > last_needed_author)
+ last_needed_author = n;
+}
+
+const char *reference::get_authors(const char **end) const
+{
+ if (!computed_authors) {
+ ((reference *)this)->computed_authors = 1;
+ string &result = ((reference *)this)->authors;
+ int na = get_nauthors();
+ result.clear();
+ for (int i = 0; i < na; i++) {
+ if (last_name_unambiguous.get(i)) {
+ const char *e, *start = get_author_last_name(i, &e);
+ assert(start != 0);
+ result.append(start, e - start);
+ }
+ else {
+ const char *e, *start = get_author(i, &e);
+ assert(start != 0);
+ result.append(start, e - start);
+ }
+ if (i == last_needed_author
+ && et_al.length() > 0
+ && et_al_min_elide > 0
+ && last_needed_author + et_al_min_elide < na
+ && na >= et_al_min_total) {
+ result += et_al;
+ break;
+ }
+ if (i < na - 1) {
+ if (na == 2)
+ result += join_authors_exactly_two;
+ else if (i < na - 2)
+ result += join_authors_default;
+ else
+ result += join_authors_last_two;
+ }
+ }
+ }
+ const char *start = authors.contents();
+ *end = start + authors.length();
+ return start;
+}
+
+int reference::get_nauthors() const
+{
+ if (nauthors < 0) {
+ const char *dummy;
+ int na;
+ for (na = 0; get_author(na, &dummy) != 0; na++)
+ ;
+ ((reference *)this)->nauthors = na;
+ }
+ return nauthors;
+}
diff --git a/src/preproc/refer/ref.cc b/src/preproc/refer/ref.cc
new file mode 100644
index 00000000..c3517b19
--- /dev/null
+++ b/src/preproc/refer/ref.cc
@@ -0,0 +1,1160 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "refer.h"
+#include "refid.h"
+#include "ref.h"
+#include "token.h"
+
+static const char *find_day(const char *, const char *, const char **);
+static int find_month(const char *start, const char *end);
+static void abbreviate_names(string &);
+
+#define DEFAULT_ARTICLES "the\000a\000an"
+
+string articles(DEFAULT_ARTICLES, sizeof(DEFAULT_ARTICLES));
+
+// Multiple occurrences of fields are separated by FIELD_SEPARATOR.
+const char FIELD_SEPARATOR = '\0';
+
+const char MULTI_FIELD_NAMES[] = "AE";
+const char *AUTHOR_FIELDS = "AQ";
+
+enum { OTHER, JOURNAL_ARTICLE, BOOK, ARTICLE_IN_BOOK, TECH_REPORT, BELL_TM };
+
+const char *reference_types[] = {
+ "other",
+ "journal-article",
+ "book",
+ "article-in-book",
+ "tech-report",
+ "bell-tm",
+};
+
+static string temp_fields[256];
+
+reference::reference(const char *start, int len, reference_id *ridp)
+: h(0), merged(0), no(-1), field(0), nfields(0), label_ptr(0),
+ computed_authors(0), last_needed_author(-1), nauthors(-1)
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ field_index[i] = NULL_FIELD_INDEX;
+ if (ridp)
+ rid = *ridp;
+ if (start == 0)
+ return;
+ if (len <= 0)
+ return;
+ const char *end = start + len;
+ const char *ptr = start;
+ assert(*ptr == '%');
+ while (ptr < end) {
+ if (ptr + 1 < end && ptr[1] != '\0'
+ && ((ptr[1] != '%' && ptr[1] == annotation_field)
+ || (ptr + 2 < end && ptr[1] == '%' && ptr[2] != '\0'
+ && discard_fields.search(ptr[2]) < 0))) {
+ if (ptr[1] == '%')
+ ptr++;
+ string &f = temp_fields[(unsigned char)ptr[1]];
+ ptr += 2;
+ while (ptr < end && csspace(*ptr))
+ ptr++;
+ for (;;) {
+ for (;;) {
+ if (ptr >= end) {
+ f += '\n';
+ break;
+ }
+ f += *ptr;
+ if (*ptr++ == '\n')
+ break;
+ }
+ if (ptr >= end || *ptr == '%')
+ break;
+ }
+ }
+ else if (ptr + 1 < end && ptr[1] != '\0' && ptr[1] != '%'
+ && discard_fields.search(ptr[1]) < 0) {
+ string &f = temp_fields[(unsigned char)ptr[1]];
+ if (f.length() > 0) {
+ if (strchr(MULTI_FIELD_NAMES, ptr[1]) != 0)
+ f += FIELD_SEPARATOR;
+ else
+ f.clear();
+ }
+ ptr += 2;
+ if (ptr < end) {
+ if (*ptr == ' ')
+ ptr++;
+ for (;;) {
+ const char *p = ptr;
+ while (ptr < end && *ptr != '\n')
+ ptr++;
+ // strip trailing white space
+ const char *q = ptr;
+ while (q > p && q[-1] != '\n' && csspace(q[-1]))
+ q--;
+ while (p < q)
+ f += *p++;
+ if (ptr >= end)
+ break;
+ ptr++;
+ if (ptr >= end)
+ break;
+ if (*ptr == '%')
+ break;
+ f += ' ';
+ }
+ }
+ }
+ else {
+ // skip this field
+ for (;;) {
+ while (ptr < end && *ptr++ != '\n')
+ ;
+ if (ptr >= end || *ptr == '%')
+ break;
+ }
+ }
+ }
+ for (i = 0; i < 256; i++)
+ if (temp_fields[i].length() > 0)
+ nfields++;
+ field = new string[nfields];
+ int j = 0;
+ for (i = 0; i < 256; i++)
+ if (temp_fields[i].length() > 0) {
+ field[j].move(temp_fields[i]);
+ if (abbreviate_fields.search(i) >= 0)
+ abbreviate_names(field[j]);
+ field_index[i] = j;
+ j++;
+ }
+}
+
+reference::~reference()
+{
+ if (nfields > 0)
+ ad_delete(nfields) field;
+}
+
+// ref is the inline, this is the database ref
+
+void reference::merge(reference &ref)
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (field_index[i] != NULL_FIELD_INDEX)
+ temp_fields[i].move(field[field_index[i]]);
+ for (i = 0; i < 256; i++)
+ if (ref.field_index[i] != NULL_FIELD_INDEX)
+ temp_fields[i].move(ref.field[ref.field_index[i]]);
+ for (i = 0; i < 256; i++)
+ field_index[i] = NULL_FIELD_INDEX;
+ int old_nfields = nfields;
+ nfields = 0;
+ for (i = 0; i < 256; i++)
+ if (temp_fields[i].length() > 0)
+ nfields++;
+ if (nfields != old_nfields) {
+ if (old_nfields > 0)
+ ad_delete(old_nfields) field;
+ field = new string[nfields];
+ }
+ int j = 0;
+ for (i = 0; i < 256; i++)
+ if (temp_fields[i].length() > 0) {
+ field[j].move(temp_fields[i]);
+ field_index[i] = j;
+ j++;
+ }
+ merged = 1;
+}
+
+void reference::insert_field(unsigned char c, string &s)
+{
+ assert(s.length() > 0);
+ if (field_index[c] != NULL_FIELD_INDEX) {
+ field[field_index[c]].move(s);
+ return;
+ }
+ assert(field_index[c] == NULL_FIELD_INDEX);
+ string *old_field = field;
+ field = new string[nfields + 1];
+ int pos = 0;
+ int i;
+ for (i = 0; i < int(c); i++)
+ if (field_index[i] != NULL_FIELD_INDEX)
+ pos++;
+ for (i = 0; i < pos; i++)
+ field[i].move(old_field[i]);
+ field[pos].move(s);
+ for (i = pos; i < nfields; i++)
+ field[i + 1].move(old_field[i]);
+ if (nfields > 0)
+ ad_delete(nfields) old_field;
+ nfields++;
+ field_index[c] = pos;
+ for (i = c + 1; i < 256; i++)
+ if (field_index[i] != NULL_FIELD_INDEX)
+ field_index[i] += 1;
+}
+
+void reference::delete_field(unsigned char c)
+{
+ if (field_index[c] == NULL_FIELD_INDEX)
+ return;
+ string *old_field = field;
+ field = new string[nfields - 1];
+ int i;
+ for (i = 0; i < int(field_index[c]); i++)
+ field[i].move(old_field[i]);
+ for (i = field_index[c]; i < nfields - 1; i++)
+ field[i].move(old_field[i + 1]);
+ if (nfields > 0)
+ ad_delete(nfields) old_field;
+ nfields--;
+ field_index[c] = NULL_FIELD_INDEX;
+ for (i = c + 1; i < 256; i++)
+ if (field_index[i] != NULL_FIELD_INDEX)
+ field_index[i] -= 1;
+}
+
+void reference::compute_hash_code()
+{
+ if (!rid.is_null())
+ h = rid.hash();
+ else {
+ h = 0;
+ for (int i = 0; i < nfields; i++)
+ if (field[i].length() > 0) {
+ h <<= 4;
+ h ^= hash_string(field[i].contents(), field[i].length());
+ }
+ }
+}
+
+void reference::set_number(int n)
+{
+ no = n;
+}
+
+const char SORT_SEP = '\001';
+const char SORT_SUB_SEP = '\002';
+const char SORT_SUB_SUB_SEP = '\003';
+
+// sep specifies additional word separators
+
+void sortify_words(const char *s, const char *end, const char *sep,
+ string &result)
+{
+ int non_empty = 0;
+ int need_separator = 0;
+ for (;;) {
+ const char *token_start = s;
+ if (!get_token(&s, end))
+ break;
+ if ((s - token_start == 1
+ && (*token_start == ' '
+ || *token_start == '\n'
+ || (sep && *token_start != '\0'
+ && strchr(sep, *token_start) != 0)))
+ || (s - token_start == 2
+ && token_start[0] == '\\' && token_start[1] == ' ')) {
+ if (non_empty)
+ need_separator = 1;
+ }
+ else {
+ const token_info *ti = lookup_token(token_start, s);
+ if (ti->sortify_non_empty(token_start, s)) {
+ if (need_separator) {
+ result += ' ';
+ need_separator = 0;
+ }
+ ti->sortify(token_start, s, result);
+ non_empty = 1;
+ }
+ }
+ }
+}
+
+void sortify_word(const char *s, const char *end, string &result)
+{
+ for (;;) {
+ const char *token_start = s;
+ if (!get_token(&s, end))
+ break;
+ const token_info *ti = lookup_token(token_start, s);
+ ti->sortify(token_start, s, result);
+ }
+}
+
+void sortify_other(const char *s, int len, string &key)
+{
+ sortify_words(s, s + len, 0, key);
+}
+
+void sortify_title(const char *s, int len, string &key)
+{
+ const char *end = s + len;
+ for (; s < end && (*s == ' ' || *s == '\n'); s++)
+ ;
+ const char *ptr = s;
+ for (;;) {
+ const char *token_start = ptr;
+ if (!get_token(&ptr, end))
+ break;
+ if (ptr - token_start == 1
+ && (*token_start == ' ' || *token_start == '\n'))
+ break;
+ }
+ if (ptr < end) {
+ int first_word_len = ptr - s - 1;
+ const char *ae = articles.contents() + articles.length();
+ for (const char *a = articles.contents();
+ a < ae;
+ a = strchr(a, '\0') + 1)
+ if (first_word_len == strlen(a)) {
+ int j;
+ for (j = 0; j < first_word_len; j++)
+ if (a[j] != cmlower(s[j]))
+ break;
+ if (j >= first_word_len) {
+ s = ptr;
+ for (; s < end && (*s == ' ' || *s == '\n'); s++)
+ ;
+ break;
+ }
+ }
+ }
+ sortify_words(s, end, 0, key);
+}
+
+void sortify_name(const char *s, int len, string &key)
+{
+ const char *last_name_end;
+ const char *last_name = find_last_name(s, s + len, &last_name_end);
+ sortify_word(last_name, last_name_end, key);
+ key += SORT_SUB_SUB_SEP;
+ if (last_name > s)
+ sortify_words(s, last_name, ".", key);
+ key += SORT_SUB_SUB_SEP;
+ if (last_name_end < s + len)
+ sortify_words(last_name_end, s + len, ".,", key);
+}
+
+void sortify_date(const char *s, int len, string &key)
+{
+ const char *year_end;
+ const char *year_start = find_year(s, s + len, &year_end);
+ if (!year_start) {
+ // Things without years are often `forthcoming', so it makes sense
+ // that they sort after things with explicit years.
+ key += 'A';
+ sortify_words(s, s + len, 0, key);
+ return;
+ }
+ int n = year_end - year_start;
+ while (n < 4) {
+ key += '0';
+ n++;
+ }
+ while (year_start < year_end)
+ key += *year_start++;
+ int m = find_month(s, s + len);
+ if (m < 0)
+ return;
+ key += 'A' + m;
+ const char *day_end;
+ const char *day_start = find_day(s, s + len, &day_end);
+ if (!day_start)
+ return;
+ if (day_end - day_start == 1)
+ key += '0';
+ while (day_start < day_end)
+ key += *day_start++;
+}
+
+// SORT_{SUB,SUB_SUB}_SEP can creep in from use of @ in label specification.
+
+void sortify_label(const char *s, int len, string &key)
+{
+ const char *end = s + len;
+ for (;;) {
+ const char *ptr;
+ for (ptr = s;
+ ptr < end && *ptr != SORT_SUB_SEP && *ptr != SORT_SUB_SUB_SEP;
+ ptr++)
+ ;
+ if (ptr > s)
+ sortify_words(s, ptr, 0, key);
+ s = ptr;
+ if (s >= end)
+ break;
+ key += *s++;
+ }
+}
+
+void reference::compute_sort_key()
+{
+ if (sort_fields.length() == 0)
+ return;
+ sort_fields += '\0';
+ const char *sf = sort_fields.contents();
+ while (*sf != '\0') {
+ if (sf > sort_fields)
+ sort_key += SORT_SEP;
+ char f = *sf++;
+ int n = 1;
+ if (*sf == '+') {
+ n = INT_MAX;
+ sf++;
+ }
+ else if (csdigit(*sf)) {
+ char *ptr;
+ long l = strtol(sf, &ptr, 10);
+ if (l == 0 && ptr == sf)
+ ;
+ else {
+ sf = ptr;
+ if (l < 0) {
+ n = 1;
+ }
+ else {
+ n = int(l);
+ }
+ }
+ }
+ if (f == '.')
+ sortify_label(label.contents(), label.length(), sort_key);
+ else if (f == AUTHOR_FIELDS[0])
+ sortify_authors(n, sort_key);
+ else
+ sortify_field(f, n, sort_key);
+ }
+ sort_fields.set_length(sort_fields.length() - 1);
+}
+
+void reference::sortify_authors(int n, string &result) const
+{
+ for (const char *p = AUTHOR_FIELDS; *p != '\0'; p++)
+ if (contains_field(*p)) {
+ sortify_field(*p, n, result);
+ return;
+ }
+ sortify_field(AUTHOR_FIELDS[0], n, result);
+}
+
+void reference::canonicalize_authors(string &result) const
+{
+ int len = result.length();
+ sortify_authors(INT_MAX, result);
+ if (result.length() > len)
+ result += SORT_SUB_SEP;
+}
+
+void reference::sortify_field(unsigned char f, int n, string &result) const
+{
+ typedef void (*sortify_t)(const char *, int, string &);
+ sortify_t sortifier = sortify_other;
+ switch (f) {
+ case 'A':
+ case 'E':
+ sortifier = sortify_name;
+ break;
+ case 'D':
+ sortifier = sortify_date;
+ break;
+ case 'B':
+ case 'J':
+ case 'T':
+ sortifier = sortify_title;
+ break;
+ }
+ int fi = field_index[(unsigned char)f];
+ if (fi != NULL_FIELD_INDEX) {
+ string &str = field[fi];
+ const char *start = str.contents();
+ const char *end = start + str.length();
+ for (int i = 0; i < n && start < end; i++) {
+ const char *p = start;
+ while (start < end && *start != FIELD_SEPARATOR)
+ start++;
+ if (i > 0)
+ result += SORT_SUB_SEP;
+ (*sortifier)(p, start - p, result);
+ if (start < end)
+ start++;
+ }
+ }
+}
+
+int compare_reference(const reference &r1, const reference &r2)
+{
+ assert(r1.no >= 0);
+ assert(r2.no >= 0);
+ const char *s1 = r1.sort_key.contents();
+ int n1 = r1.sort_key.length();
+ const char *s2 = r2.sort_key.contents();
+ int n2 = r2.sort_key.length();
+ for (; n1 > 0 && n2 > 0; --n1, --n2, ++s1, ++s2)
+ if (*s1 != *s2)
+ return (int)(unsigned char)*s1 - (int)(unsigned char)*s2;
+ if (n2 > 0)
+ return -1;
+ if (n1 > 0)
+ return 1;
+ return r1.no - r2.no;
+}
+
+int same_reference(const reference &r1, const reference &r2)
+{
+ if (!r1.rid.is_null() && r1.rid == r2.rid)
+ return 1;
+ if (r1.h != r2.h)
+ return 0;
+ if (r1.nfields != r2.nfields)
+ return 0;
+ int i = 0;
+ for (i = 0; i < 256; i++)
+ if (r1.field_index != r2.field_index)
+ return 0;
+ for (i = 0; i < r1.nfields; i++)
+ if (r1.field[i] != r2.field[i])
+ return 0;
+ return 1;
+}
+
+const char *find_last_name(const char *start, const char *end,
+ const char **endp)
+{
+ const char *ptr = start;
+ const char *last_word = start;
+ for (;;) {
+ const char *token_start = ptr;
+ if (!get_token(&ptr, end))
+ break;
+ if (ptr - token_start == 1) {
+ if (*token_start == ',') {
+ *endp = token_start;
+ return last_word;
+ }
+ else if (*token_start == ' ' || *token_start == '\n') {
+ if (ptr < end && *ptr != ' ' && *ptr != '\n')
+ last_word = ptr;
+ }
+ }
+ }
+ *endp = end;
+ return last_word;
+}
+
+void abbreviate_name(const char *ptr, const char *end, string &result)
+{
+ const char *last_name_end;
+ const char *last_name_start = find_last_name(ptr, end, &last_name_end);
+ int need_period = 0;
+ for (;;) {
+ const char *token_start = ptr;
+ if (!get_token(&ptr, last_name_start))
+ break;
+ const token_info *ti = lookup_token(token_start, ptr);
+ if (need_period) {
+ if ((ptr - token_start == 1 && *token_start == ' ')
+ || (ptr - token_start == 2 && token_start[0] == '\\'
+ && token_start[1] == ' '))
+ continue;
+ if (ti->is_upper())
+ result += period_before_initial;
+ else
+ result += period_before_other;
+ need_period = 0;
+ }
+ result.append(token_start, ptr - token_start);
+ if (ti->is_upper()) {
+ const char *lower_ptr = ptr;
+ int first_token = 1;
+ for (;;) {
+ token_start = ptr;
+ if (!get_token(&ptr, last_name_start))
+ break;
+ if ((ptr - token_start == 1 && *token_start == ' ')
+ || (ptr - token_start == 2 && token_start[0] == '\\'
+ && token_start[1] == ' '))
+ break;
+ ti = lookup_token(token_start, ptr);
+ if (ti->is_hyphen()) {
+ const char *ptr1 = ptr;
+ if (get_token(&ptr1, last_name_start)) {
+ ti = lookup_token(ptr, ptr1);
+ if (ti->is_upper()) {
+ result += period_before_hyphen;
+ result.append(token_start, ptr1 - token_start);
+ ptr = ptr1;
+ }
+ }
+ }
+ else if (ti->is_upper()) {
+ // MacDougal -> MacD.
+ result.append(lower_ptr, ptr - lower_ptr);
+ lower_ptr = ptr;
+ first_token = 1;
+ }
+ else if (first_token && ti->is_accent()) {
+ result.append(token_start, ptr - token_start);
+ lower_ptr = ptr;
+ }
+ first_token = 0;
+ }
+ need_period = 1;
+ }
+ }
+ if (need_period)
+ result += period_before_last_name;
+ result.append(last_name_start, end - last_name_start);
+}
+
+static void abbreviate_names(string &result)
+{
+ string str;
+ str.move(result);
+ const char *ptr = str.contents();
+ const char *end = ptr + str.length();
+ while (ptr < end) {
+ const char *name_end = (char *)memchr(ptr, FIELD_SEPARATOR, end - ptr);
+ if (name_end == 0)
+ name_end = end;
+ abbreviate_name(ptr, name_end, result);
+ if (name_end >= end)
+ break;
+ ptr = name_end + 1;
+ result += FIELD_SEPARATOR;
+ }
+}
+
+void reverse_name(const char *ptr, const char *name_end, string &result)
+{
+ const char *last_name_end;
+ const char *last_name_start = find_last_name(ptr, name_end, &last_name_end);
+ result.append(last_name_start, last_name_end - last_name_start);
+ while (last_name_start > ptr
+ && (last_name_start[-1] == ' ' || last_name_start[-1] == '\n'))
+ last_name_start--;
+ if (last_name_start > ptr) {
+ result += ", ";
+ result.append(ptr, last_name_start - ptr);
+ }
+ if (last_name_end < name_end)
+ result.append(last_name_end, name_end - last_name_end);
+}
+
+void reverse_names(string &result, int n)
+{
+ if (n <= 0)
+ return;
+ string str;
+ str.move(result);
+ const char *ptr = str.contents();
+ const char *end = ptr + str.length();
+ while (ptr < end) {
+ if (--n < 0) {
+ result.append(ptr, end - ptr);
+ break;
+ }
+ const char *name_end = (char *)memchr(ptr, FIELD_SEPARATOR, end - ptr);
+ if (name_end == 0)
+ name_end = end;
+ reverse_name(ptr, name_end, result);
+ if (name_end >= end)
+ break;
+ ptr = name_end + 1;
+ result += FIELD_SEPARATOR;
+ }
+}
+
+// Return number of field separators.
+
+int join_fields(string &f)
+{
+ const char *ptr = f.contents();
+ int len = f.length();
+ int nfield_seps = 0;
+ int j;
+ for (j = 0; j < len; j++)
+ if (ptr[j] == FIELD_SEPARATOR)
+ nfield_seps++;
+ if (nfield_seps == 0)
+ return 0;
+ string temp;
+ int field_seps_left = nfield_seps;
+ for (j = 0; j < len; j++) {
+ if (ptr[j] == FIELD_SEPARATOR) {
+ if (nfield_seps == 1)
+ temp += join_authors_exactly_two;
+ else if (--field_seps_left == 0)
+ temp += join_authors_last_two;
+ else
+ temp += join_authors_default;
+ }
+ else
+ temp += ptr[j];
+ }
+ f = temp;
+ return nfield_seps;
+}
+
+void uppercase(const char *start, const char *end, string &result)
+{
+ for (;;) {
+ const char *token_start = start;
+ if (!get_token(&start, end))
+ break;
+ const token_info *ti = lookup_token(token_start, start);
+ ti->upper_case(token_start, start, result);
+ }
+}
+
+void lowercase(const char *start, const char *end, string &result)
+{
+ for (;;) {
+ const char *token_start = start;
+ if (!get_token(&start, end))
+ break;
+ const token_info *ti = lookup_token(token_start, start);
+ ti->lower_case(token_start, start, result);
+ }
+}
+
+void capitalize(const char *ptr, const char *end, string &result)
+{
+ int in_small_point_size = 0;
+ for (;;) {
+ const char *start = ptr;
+ if (!get_token(&ptr, end))
+ break;
+ const token_info *ti = lookup_token(start, ptr);
+ const char *char_end = ptr;
+ int is_lower = ti->is_lower();
+ if ((is_lower || ti->is_upper()) && get_token(&ptr, end)) {
+ const token_info *ti2 = lookup_token(char_end, ptr);
+ if (!ti2->is_accent())
+ ptr = char_end;
+ }
+ if (is_lower) {
+ if (!in_small_point_size) {
+ result += "\\s-2";
+ in_small_point_size = 1;
+ }
+ ti->upper_case(start, char_end, result);
+ result.append(char_end, ptr - char_end);
+ }
+ else {
+ if (in_small_point_size) {
+ result += "\\s+2";
+ in_small_point_size = 0;
+ }
+ result.append(start, ptr - start);
+ }
+ }
+ if (in_small_point_size)
+ result += "\\s+2";
+}
+
+void capitalize_field(string &str)
+{
+ string temp;
+ capitalize(str.contents(), str.contents() + str.length(), temp);
+ str.move(temp);
+}
+
+int is_terminated(const char *ptr, const char *end)
+{
+ const char *last_token = end;
+ for (;;) {
+ const char *p = ptr;
+ if (!get_token(&ptr, end))
+ break;
+ last_token = p;
+ }
+ return end - last_token == 1
+ && (*last_token == '.' || *last_token == '!' || *last_token == '?');
+}
+
+void reference::output(FILE *fp)
+{
+ fputs(".]-\n", fp);
+ for (int i = 0; i < 256; i++)
+ if (field_index[i] != NULL_FIELD_INDEX && i != annotation_field) {
+ string &f = field[field_index[i]];
+ if (!csdigit(i)) {
+ int j = reverse_fields.search(i);
+ if (j >= 0) {
+ int n;
+ int len = reverse_fields.length();
+ if (++j < len && csdigit(reverse_fields[j])) {
+ n = reverse_fields[j] - '0';
+ for (++j; j < len && csdigit(reverse_fields[j]); j++)
+ // should check for overflow
+ n = n*10 + reverse_fields[j] - '0';
+ }
+ else
+ n = INT_MAX;
+ reverse_names(f, n);
+ }
+ }
+ int is_multiple = join_fields(f) > 0;
+ if (capitalize_fields.search(i) >= 0)
+ capitalize_field(f);
+ if (memchr(f.contents(), '\n', f.length()) == 0) {
+ fprintf(fp, ".ds [%c ", i);
+ if (f[0] == ' ' || f[0] == '\\' || f[0] == '"')
+ putc('"', fp);
+ put_string(f, fp);
+ putc('\n', fp);
+ }
+ else {
+ fprintf(fp, ".de [%c\n", i);
+ put_string(f, fp);
+ fputs("..\n", fp);
+ }
+ if (i == 'P') {
+ int multiple_pages = 0;
+ const char *s = f.contents();
+ const char *end = f.contents() + f.length();
+ for (;;) {
+ const char *token_start = s;
+ if (!get_token(&s, end))
+ break;
+ const token_info *ti = lookup_token(token_start, s);
+ if (ti->is_hyphen() || ti->is_range_sep()) {
+ multiple_pages = 1;
+ break;
+ }
+ }
+ fprintf(fp, ".nr [P %d\n", multiple_pages);
+ }
+ else if (i == 'E')
+ fprintf(fp, ".nr [E %d\n", is_multiple);
+ }
+ for (const char *p = "TAO"; *p; p++) {
+ int fi = field_index[(unsigned char)*p];
+ if (fi != NULL_FIELD_INDEX) {
+ string &f = field[fi];
+ fprintf(fp, ".nr [%c %d\n", *p,
+ is_terminated(f.contents(), f.contents() + f.length()));
+ }
+ }
+ int t = classify();
+ fprintf(fp, ".][ %d %s\n", t, reference_types[t]);
+ if (annotation_macro.length() > 0 && annotation_field >= 0
+ && field_index[annotation_field] != NULL_FIELD_INDEX) {
+ putc('.', fp);
+ put_string(annotation_macro, fp);
+ putc('\n', fp);
+ put_string(field[field_index[annotation_field]], fp);
+ }
+}
+
+void reference::print_sort_key_comment(FILE *fp)
+{
+ fputs(".\\\"", fp);
+ put_string(sort_key, fp);
+ putc('\n', fp);
+}
+
+const char *find_year(const char *start, const char *end, const char **endp)
+{
+ for (;;) {
+ while (start < end && !csdigit(*start))
+ start++;
+ const char *ptr = start;
+ if (start == end)
+ break;
+ while (ptr < end && csdigit(*ptr))
+ ptr++;
+ if (ptr - start == 4 || ptr - start == 3
+ || (ptr - start == 2
+ && (start[0] >= '4' || (start[0] == '3' && start[1] >= '2')))) {
+ *endp = ptr;
+ return start;
+ }
+ start = ptr;
+ }
+ return 0;
+}
+
+static const char *find_day(const char *start, const char *end,
+ const char **endp)
+{
+ for (;;) {
+ while (start < end && !csdigit(*start))
+ start++;
+ const char *ptr = start;
+ if (start == end)
+ break;
+ while (ptr < end && csdigit(*ptr))
+ ptr++;
+ if ((ptr - start == 1 && start[0] != '0')
+ || (ptr - start == 2 &&
+ (start[0] == '1'
+ || start[0] == '2'
+ || (start[0] == '3' && start[1] <= '1')
+ || (start[0] == '0' && start[1] != '0')))) {
+ *endp = ptr;
+ return start;
+ }
+ start = ptr;
+ }
+ return 0;
+}
+
+static int find_month(const char *start, const char *end)
+{
+ static const char *months[] = {
+ "january",
+ "february",
+ "march",
+ "april",
+ "may",
+ "june",
+ "july",
+ "august",
+ "september",
+ "october",
+ "november",
+ "december",
+ };
+ for (;;) {
+ while (start < end && !csalpha(*start))
+ start++;
+ const char *ptr = start;
+ if (start == end)
+ break;
+ while (ptr < end && csalpha(*ptr))
+ ptr++;
+ if (ptr - start >= 3) {
+ for (int i = 0; i < sizeof(months)/sizeof(months[0]); i++) {
+ const char *q = months[i];
+ const char *p = start;
+ for (; p < ptr; p++, q++)
+ if (cmlower(*p) != *q)
+ break;
+ if (p >= ptr)
+ return i;
+ }
+ }
+ start = ptr;
+ }
+ return -1;
+}
+
+int reference::contains_field(char c) const
+{
+ return field_index[(unsigned char)c] != NULL_FIELD_INDEX;
+}
+
+int reference::classify()
+{
+ if (contains_field('J'))
+ return JOURNAL_ARTICLE;
+ if (contains_field('B'))
+ return ARTICLE_IN_BOOK;
+ if (contains_field('G'))
+ return TECH_REPORT;
+ if (contains_field('R'))
+ return TECH_REPORT;
+ if (contains_field('I'))
+ return BOOK;
+ if (contains_field('M'))
+ return BELL_TM;
+ return OTHER;
+}
+
+const char *reference::get_year(const char **endp) const
+{
+ if (field_index['D'] != NULL_FIELD_INDEX) {
+ string &date = field[field_index['D']];
+ const char *start = date.contents();
+ const char *end = start + date.length();
+ return find_year(start, end, endp);
+ }
+ else
+ return 0;
+}
+
+const char *reference::get_field(unsigned char c, const char **endp) const
+{
+ if (field_index[c] != NULL_FIELD_INDEX) {
+ string &f = field[field_index[c]];
+ const char *start = f.contents();
+ *endp = start + f.length();
+ return start;
+ }
+ else
+ return 0;
+}
+
+const char *reference::get_date(const char **endp) const
+{
+ return get_field('D', endp);
+}
+
+const char *nth_field(int i, const char *start, const char **endp)
+{
+ while (--i >= 0) {
+ start = (char *)memchr(start, FIELD_SEPARATOR, *endp - start);
+ if (!start)
+ return 0;
+ start++;
+ }
+ const char *e = (char *)memchr(start, FIELD_SEPARATOR, *endp - start);
+ if (e)
+ *endp = e;
+ return start;
+}
+
+const char *reference::get_author(int i, const char **endp) const
+{
+ for (const char *f = AUTHOR_FIELDS; *f != '\0'; f++) {
+ const char *start = get_field(*f, endp);
+ if (start) {
+ if (strchr(MULTI_FIELD_NAMES, *f) != 0)
+ return nth_field(i, start, endp);
+ else if (i == 0)
+ return start;
+ else
+ return 0;
+ }
+ }
+ return 0;
+}
+
+const char *reference::get_author_last_name(int i, const char **endp) const
+{
+ for (const char *f = AUTHOR_FIELDS; *f != '\0'; f++) {
+ const char *start = get_field(*f, endp);
+ if (start) {
+ if (strchr(MULTI_FIELD_NAMES, *f) != 0) {
+ start = nth_field(i, start, endp);
+ if (!start)
+ return 0;
+ }
+ if (*f == 'A')
+ return find_last_name(start, *endp, endp);
+ else
+ return start;
+ }
+ }
+ return 0;
+}
+
+void reference::set_date(string &d)
+{
+ if (d.length() == 0)
+ delete_field('D');
+ else
+ insert_field('D', d);
+}
+
+int same_year(const reference &r1, const reference &r2)
+{
+ const char *ye1;
+ const char *ys1 = r1.get_year(&ye1);
+ const char *ye2;
+ const char *ys2 = r2.get_year(&ye2);
+ if (ys1 == 0) {
+ if (ys2 == 0)
+ return same_date(r1, r2);
+ else
+ return 0;
+ }
+ else if (ys2 == 0)
+ return 0;
+ else if (ye1 - ys1 != ye2 - ys2)
+ return 0;
+ else
+ return memcmp(ys1, ys2, ye1 - ys1) == 0;
+}
+
+int same_date(const reference &r1, const reference &r2)
+{
+ const char *e1;
+ const char *s1 = r1.get_date(&e1);
+ const char *e2;
+ const char *s2 = r2.get_date(&e2);
+ if (s1 == 0)
+ return s2 == 0;
+ else if (s2 == 0)
+ return 0;
+ else if (e1 - s1 != e2 - s2)
+ return 0;
+ else
+ return memcmp(s1, s2, e1 - s1) == 0;
+}
+
+const char *reference::get_sort_field(int i, int si, int ssi,
+ const char **endp) const
+{
+ const char *start = sort_key.contents();
+ const char *end = start + sort_key.length();
+ if (i < 0) {
+ *endp = end;
+ return start;
+ }
+ while (--i >= 0) {
+ start = (char *)memchr(start, SORT_SEP, end - start);
+ if (!start)
+ return 0;
+ start++;
+ }
+ const char *e = (char *)memchr(start, SORT_SEP, end - start);
+ if (e)
+ end = e;
+ if (si < 0) {
+ *endp = end;
+ return start;
+ }
+ while (--si >= 0) {
+ start = (char *)memchr(start, SORT_SUB_SEP, end - start);
+ if (!start)
+ return 0;
+ start++;
+ }
+ e = (char *)memchr(start, SORT_SUB_SEP, end - start);
+ if (e)
+ end = e;
+ if (ssi < 0) {
+ *endp = end;
+ return start;
+ }
+ while (--ssi >= 0) {
+ start = (char *)memchr(start, SORT_SUB_SUB_SEP, end - start);
+ if (!start)
+ return 0;
+ start++;
+ }
+ e = (char *)memchr(start, SORT_SUB_SUB_SEP, end - start);
+ if (e)
+ end = e;
+ *endp = end;
+ return start;
+}
+
diff --git a/src/preproc/refer/ref.h b/src/preproc/refer/ref.h
new file mode 100644
index 00000000..13a984a4
--- /dev/null
+++ b/src/preproc/refer/ref.h
@@ -0,0 +1,120 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+struct label_info;
+
+enum label_type { NORMAL_LABEL, SHORT_LABEL };
+const int N_LABEL_TYPES = 2;
+
+struct substring_position {
+ int start;
+ int length;
+ substring_position() : start(-1) { }
+};
+
+class int_set {
+ string v;
+public:
+ int_set() { }
+ void set(int i);
+ int get(int i) const;
+};
+
+class reference {
+private:
+ unsigned h;
+ reference_id rid;
+ int merged;
+ string sort_key;
+ int no;
+ string *field;
+ int nfields;
+ unsigned char field_index[256];
+ enum { NULL_FIELD_INDEX = 255 };
+ string label;
+ substring_position separator_pos;
+ string short_label;
+ substring_position short_separator_pos;
+ label_info *label_ptr;
+ string authors;
+ int computed_authors;
+ int last_needed_author;
+ int nauthors;
+ int_set last_name_unambiguous;
+
+ int contains_field(char) const;
+ void insert_field(unsigned char, string &s);
+ void delete_field(unsigned char);
+ void set_date(string &);
+ const char *get_sort_field(int i, int si, int ssi, const char **endp) const;
+ int merge_labels_by_parts(reference **, int, label_type, string &);
+ int merge_labels_by_number(reference **, int, label_type, string &);
+public:
+ reference(const char * = 0, int = -1, reference_id * = 0);
+ ~reference();
+ void output(FILE *);
+ void print_sort_key_comment(FILE *);
+ void set_number(int);
+ int get_number() const { return no; }
+ unsigned hash() const { return h; }
+ const string &get_label(label_type type) const;
+ const substring_position &get_separator_pos(label_type) const;
+ int is_merged() const { return merged; }
+ void compute_sort_key();
+ void compute_hash_code();
+ void pre_compute_label();
+ void compute_label();
+ void immediate_compute_label();
+ int classify();
+ void merge(reference &);
+ int merge_labels(reference **, int, label_type, string &);
+ int get_nauthors() const;
+ void need_author(int);
+ void set_last_name_unambiguous(int);
+ void sortify_authors(int, string &) const;
+ void canonicalize_authors(string &) const;
+ void sortify_field(unsigned char, int, string &) const;
+ const char *get_author(int, const char **) const;
+ const char *get_author_last_name(int, const char **) const;
+ const char *get_date(const char **) const;
+ const char *get_year(const char **) const;
+ const char *get_field(unsigned char, const char **) const;
+ const label_info *get_label_ptr() const { return label_ptr; }
+ const char *get_authors(const char **) const;
+ // for sorting
+ friend int compare_reference(const reference &r1, const reference &r2);
+ // for merging
+ friend int same_reference(const reference &, const reference &);
+ friend int same_year(const reference &, const reference &);
+ friend int same_date(const reference &, const reference &);
+ friend int same_author_last_name(const reference &, const reference &, int);
+ friend int same_author_name(const reference &, const reference &, int);
+};
+
+const char *find_year(const char *, const char *, const char **);
+const char *find_last_name(const char *, const char *, const char **);
+
+const char *nth_field(int i, const char *start, const char **endp);
+
+void capitalize(const char *ptr, const char *end, string &result);
+void reverse_name(const char *ptr, const char *end, string &result);
+void uppercase(const char *ptr, const char *end, string &result);
+void lowercase(const char *ptr, const char *end, string &result);
+void abbreviate_name(const char *ptr, const char *end, string &result);
diff --git a/src/preproc/refer/refer.cc b/src/preproc/refer/refer.cc
new file mode 100644
index 00000000..cc8febe4
--- /dev/null
+++ b/src/preproc/refer/refer.cc
@@ -0,0 +1,1228 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "refer.h"
+#include "refid.h"
+#include "ref.h"
+#include "token.h"
+#include "search.h"
+#include "command.h"
+
+const char PRE_LABEL_MARKER = '\013';
+const char POST_LABEL_MARKER = '\014';
+const char LABEL_MARKER = '\015'; // label_type is added on
+
+#define FORCE_LEFT_BRACKET 04
+#define FORCE_RIGHT_BRACKET 010
+
+static FILE *outfp = stdout;
+
+string capitalize_fields;
+string reverse_fields;
+string abbreviate_fields;
+string period_before_last_name = ". ";
+string period_before_initial = ".";
+string period_before_hyphen = "";
+string period_before_other = ". ";
+string sort_fields;
+int annotation_field = -1;
+string annotation_macro;
+string discard_fields = "XYZ";
+string pre_label = "\\*([.";
+string post_label = "\\*(.]";
+string sep_label = ", ";
+int accumulate = 0;
+int move_punctuation = 0;
+int abbreviate_label_ranges = 0;
+string label_range_indicator;
+int label_in_text = 1;
+int label_in_reference = 1;
+int date_as_label = 0;
+int sort_adjacent_labels = 0;
+// Join exactly two authors with this.
+string join_authors_exactly_two = " and ";
+// When there are more than two authors join the last two with this.
+string join_authors_last_two = ", and ";
+// Otherwise join authors with this.
+string join_authors_default = ", ";
+string separate_label_second_parts = ", ";
+// Use this string to represent that there are other authors.
+string et_al = " et al";
+// Use et al only if it can replace at least this many authors.
+int et_al_min_elide = 2;
+// Use et al only if the total number of authors is at least this.
+int et_al_min_total = 3;
+
+
+int compatible_flag = 0;
+
+int short_label_flag = 0;
+
+static int recognize_R1_R2 = 1;
+
+search_list database_list;
+int search_default = 1;
+static int default_database_loaded = 0;
+
+static reference **citation = 0;
+static int ncitations = 0;
+static int citation_max = 0;
+
+static reference **reference_hash_table = 0;
+static int hash_table_size;
+static int nreferences = 0;
+
+static int need_syncing = 0;
+string pending_line;
+string pending_lf_lines;
+
+static void output_pending_line();
+static unsigned immediately_handle_reference(const string &);
+static void immediately_output_references();
+static unsigned store_reference(const string &);
+static void divert_to_temporary_file();
+static reference *make_reference(const string &, unsigned *);
+static void usage();
+static void do_file(const char *);
+static void split_punct(string &line, string &punct);
+static void output_citation_group(reference **v, int n, label_type, FILE *fp);
+static void possibly_load_default_database();
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ outfp = stdout;
+ int finished_options = 0;
+ int bib_flag = 0;
+ int done_spec = 0;
+
+ for (--argc, ++argv;
+ !finished_options && argc > 0 && argv[0][0] == '-'
+ && argv[0][1] != '\0';
+ argv++, argc--) {
+ const char *opt = argv[0] + 1;
+ while (opt != 0 && *opt != '\0') {
+ switch (*opt) {
+ case 'C':
+ compatible_flag = 1;
+ opt++;
+ break;
+ case 'B':
+ bib_flag = 1;
+ label_in_reference = 0;
+ label_in_text = 0;
+ ++opt;
+ if (*opt == '\0') {
+ annotation_field = 'X';
+ annotation_macro = "AP";
+ }
+ else if (csalnum(opt[0]) && opt[1] == '.' && opt[2] != '\0') {
+ annotation_field = opt[0];
+ annotation_macro = opt + 2;
+ }
+ opt = 0;
+ break;
+ case 'P':
+ move_punctuation = 1;
+ opt++;
+ break;
+ case 'R':
+ recognize_R1_R2 = 0;
+ opt++;
+ break;
+ case 'S':
+ // Not a very useful spec.
+ set_label_spec("(A.n|Q)', '(D.y|D)");
+ done_spec = 1;
+ pre_label = " (";
+ post_label = ")";
+ sep_label = "; ";
+ opt++;
+ break;
+ case 'V':
+ verify_flag = 1;
+ opt++;
+ break;
+ case 'f':
+ {
+ const char *num = 0;
+ if (*++opt == '\0') {
+ if (argc > 1) {
+ num = *++argv;
+ --argc;
+ }
+ else {
+ error("option `f' requires an argument");
+ usage();
+ }
+ }
+ else {
+ num = opt;
+ opt = 0;
+ }
+ const char *ptr;
+ for (ptr = num; *ptr; ptr++)
+ if (!csdigit(*ptr)) {
+ error("bad character `%1' in argument to -f option", *ptr);
+ break;
+ }
+ if (*ptr == '\0') {
+ string spec;
+ spec = '%';
+ spec += num;
+ spec += '\0';
+ set_label_spec(spec.contents());
+ done_spec = 1;
+ }
+ break;
+ }
+ case 'b':
+ label_in_text = 0;
+ label_in_reference = 0;
+ opt++;
+ break;
+ case 'e':
+ accumulate = 1;
+ opt++;
+ break;
+ case 'c':
+ capitalize_fields = ++opt;
+ opt = 0;
+ break;
+ case 'k':
+ {
+ char buf[5];
+ if (csalpha(*++opt))
+ buf[0] = *opt++;
+ else {
+ if (*opt != '\0')
+ error("bad field name `%1'", *opt++);
+ buf[0] = 'L';
+ }
+ buf[1] = '~';
+ buf[2] = '%';
+ buf[3] = 'a';
+ buf[4] = '\0';
+ set_label_spec(buf);
+ done_spec = 1;
+ }
+ break;
+ case 'a':
+ {
+ const char *ptr;
+ for (ptr = ++opt; *ptr; ptr++)
+ if (!csdigit(*ptr)) {
+ error("argument to `a' option not a number");
+ break;
+ }
+ if (*ptr == '\0') {
+ reverse_fields = 'A';
+ reverse_fields += opt;
+ }
+ opt = 0;
+ }
+ break;
+ case 'i':
+ linear_ignore_fields = ++opt;
+ opt = 0;
+ break;
+ case 'l':
+ {
+ char buf[INT_DIGITS*2 + 11]; // A.n+2D.y-3%a
+ strcpy(buf, "A.n");
+ if (*++opt != '\0' && *opt != ',') {
+ char *ptr;
+ long n = strtol(opt, &ptr, 10);
+ if (n == 0 && ptr == opt) {
+ error("bad integer `%1' in `l' option", opt);
+ opt = 0;
+ break;
+ }
+ if (n < 0)
+ n = 0;
+ opt = ptr;
+ sprintf(strchr(buf, '\0'), "+%ld", n);
+ }
+ strcat(buf, "D.y");
+ if (*opt == ',')
+ opt++;
+ if (*opt != '\0') {
+ char *ptr;
+ long n = strtol(opt, &ptr, 10);
+ if (n == 0 && ptr == opt) {
+ error("bad integer `%1' in `l' option", opt);
+ opt = 0;
+ break;
+ }
+ if (n < 0)
+ n = 0;
+ sprintf(strchr(buf, '\0'), "-%ld", n);
+ opt = ptr;
+ if (*opt != '\0')
+ error("argument to `l' option not of form `m,n'");
+ }
+ strcat(buf, "%a");
+ if (!set_label_spec(buf))
+ assert(0);
+ done_spec = 1;
+ }
+ break;
+ case 'n':
+ search_default = 0;
+ opt++;
+ break;
+ case 'p':
+ {
+ const char *filename = 0;
+ if (*++opt == '\0') {
+ if (argc > 1) {
+ filename = *++argv;
+ argc--;
+ }
+ else {
+ error("option `p' requires an argument");
+ usage();
+ }
+ }
+ else {
+ filename = opt;
+ opt = 0;
+ }
+ database_list.add_file(filename);
+ }
+ break;
+ case 's':
+ if (*++opt == '\0')
+ sort_fields = "AD";
+ else {
+ sort_fields = opt;
+ opt = 0;
+ }
+ accumulate = 1;
+ break;
+ case 't':
+ {
+ char *ptr;
+ long n = strtol(opt, &ptr, 10);
+ if (n == 0 && ptr == opt) {
+ error("bad integer `%1' in `t' option", opt);
+ opt = 0;
+ break;
+ }
+ if (n < 1)
+ n = 1;
+ linear_truncate_len = int(n);
+ opt = ptr;
+ break;
+ }
+ case 'v':
+ {
+ extern const char *Version_string;
+ fprintf(stderr, "GNU refer version %s\n", Version_string);
+ fflush(stderr);
+ opt++;
+ break;
+ }
+ case '-':
+ if (opt[1] == '\0') {
+ finished_options = 1;
+ opt++;
+ break;
+ }
+ // fall through
+ default:
+ error("unrecognized option `%1'", *opt);
+ usage();
+ break;
+ }
+ }
+ }
+ if (!done_spec)
+ set_label_spec("%1");
+ if (argc <= 0) {
+ if (bib_flag)
+ do_bib("-");
+ else
+ do_file("-");
+ }
+ else {
+ for (int i = 0; i < argc; i++) {
+ if (bib_flag)
+ do_bib(argv[i]);
+ else
+ do_file(argv[i]);
+ }
+ }
+ if (accumulate)
+ output_references();
+ if (fflush(stdout) < 0)
+ fatal("output error");
+ return 0;
+}
+
+static void usage()
+{
+ fprintf(stderr,
+"usage: %s [-benvCPRS] [-aN] [-cXYZ] [-fN] [-iXYZ] [-kX] [-lM,N] [-p file]\n"
+" [-sXYZ] [-tN] [-BL.M] [files ...]\n",
+ program_name);
+ exit(1);
+}
+
+static void possibly_load_default_database()
+{
+ if (search_default && !default_database_loaded) {
+ char *filename = getenv("REFER");
+ if (filename)
+ database_list.add_file(filename);
+ else
+ database_list.add_file(DEFAULT_INDEX, 1);
+ default_database_loaded = 1;
+ }
+}
+
+static int is_list(const string &str)
+{
+ const char *start = str.contents();
+ const char *end = start + str.length();
+ while (end > start && csspace(end[-1]))
+ end--;
+ while (start < end && csspace(*start))
+ start++;
+ return end - start == 6 && memcmp(start, "$LIST$", 6) == 0;
+}
+
+static void do_file(const char *filename)
+{
+ FILE *fp;
+ if (strcmp(filename, "-") == 0) {
+ fp = stdin;
+ }
+ else {
+ errno = 0;
+ fp = fopen(filename, "r");
+ if (fp == 0) {
+ error("can't open `%1': %2", filename, strerror(errno));
+ return;
+ }
+ }
+ current_filename = filename;
+ fprintf(outfp, ".lf 1 %s\n", filename);
+ string line;
+ current_lineno = 0;
+ for (;;) {
+ line.clear();
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF) {
+ if (line.length() > 0)
+ line += '\n';
+ break;
+ }
+ if (illegal_input_char(c))
+ error("illegal input character code %1", c);
+ else {
+ line += c;
+ if (c == '\n')
+ break;
+ }
+ }
+ int len = line.length();
+ if (len == 0)
+ break;
+ current_lineno++;
+ if (len >= 2 && line[0] == '.' && line[1] == '[') {
+ int start_lineno = current_lineno;
+ int start_of_line = 1;
+ string str;
+ string post;
+ string pre(line.contents() + 2, line.length() - 3);
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF) {
+ error_with_file_and_line(current_filename, start_lineno,
+ "missing `.]' line");
+ break;
+ }
+ if (start_of_line)
+ current_lineno++;
+ if (start_of_line && c == '.') {
+ int d = getc(fp);
+ if (d == ']') {
+ while ((d = getc(fp)) != '\n' && d != EOF) {
+ if (illegal_input_char(d))
+ error("illegal input character code %1", d);
+ else
+ post += d;
+ }
+ break;
+ }
+ if (d != EOF)
+ ungetc(d, fp);
+ }
+ if (illegal_input_char(c))
+ error("illegal input character code %1", c);
+ else
+ str += c;
+ start_of_line = (c == '\n');
+ }
+ if (is_list(str)) {
+ output_pending_line();
+ if (accumulate)
+ output_references();
+ else
+ error("found `$LIST$' but not accumulating references");
+ }
+ else {
+ unsigned flags = (accumulate
+ ? store_reference(str)
+ : immediately_handle_reference(str));
+ if (label_in_text) {
+ if (accumulate && outfp == stdout)
+ divert_to_temporary_file();
+ if (pending_line.length() == 0) {
+ warning("can't attach citation to previous line");
+ }
+ else
+ pending_line.set_length(pending_line.length() - 1);
+ string punct;
+ if (move_punctuation)
+ split_punct(pending_line, punct);
+ int have_text = pre.length() > 0 || post.length() > 0;
+ label_type lt = label_type(flags & ~(FORCE_LEFT_BRACKET
+ |FORCE_RIGHT_BRACKET));
+ if ((flags & FORCE_LEFT_BRACKET) || !have_text)
+ pending_line += PRE_LABEL_MARKER;
+ pending_line += pre;
+ char lm = LABEL_MARKER + lt;
+ pending_line += lm;
+ pending_line += post;
+ if ((flags & FORCE_RIGHT_BRACKET) || !have_text)
+ pending_line += POST_LABEL_MARKER;
+ pending_line += punct;
+ pending_line += '\n';
+ }
+ }
+ need_syncing = 1;
+ }
+ else if (len >= 4
+ && line[0] == '.' && line[1] == 'l' && line[2] == 'f'
+ && (compatible_flag || line[3] == '\n' || line[3] == ' ')) {
+ pending_lf_lines += line;
+ line += '\0';
+ if (interpret_lf_args(line.contents() + 3))
+ current_lineno--;
+ }
+ else if (recognize_R1_R2
+ && len >= 4
+ && line[0] == '.' && line[1] == 'R' && line[2] == '1'
+ && (compatible_flag || line[3] == '\n' || line[3] == ' ')) {
+ line.clear();
+ int start_of_line = 1;
+ int start_lineno = current_lineno;
+ for (;;) {
+ int c = getc(fp);
+ if (c != EOF && start_of_line)
+ current_lineno++;
+ if (start_of_line && c == '.') {
+ c = getc(fp);
+ if (c == 'R') {
+ c = getc(fp);
+ if (c == '2') {
+ c = getc(fp);
+ if (compatible_flag || c == ' ' || c == '\n' || c == EOF) {
+ while (c != EOF && c != '\n')
+ c = getc(fp);
+ break;
+ }
+ else {
+ line += '.';
+ line += 'R';
+ line += '2';
+ }
+ }
+ else {
+ line += '.';
+ line += 'R';
+ }
+ }
+ else
+ line += '.';
+ }
+ if (c == EOF) {
+ error_with_file_and_line(current_filename, start_lineno,
+ "missing `.R2' line");
+ break;
+ }
+ if (illegal_input_char(c))
+ error("illegal input character code %1", int(c));
+ else {
+ line += c;
+ start_of_line = c == '\n';
+ }
+ }
+ output_pending_line();
+ if (accumulate)
+ output_references();
+ else
+ nreferences = 0;
+ process_commands(line, current_filename, start_lineno + 1);
+ need_syncing = 1;
+ }
+ else {
+ output_pending_line();
+ pending_line = line;
+ }
+ }
+ need_syncing = 0;
+ output_pending_line();
+ if (fp != stdin)
+ fclose(fp);
+}
+
+class label_processing_state {
+ enum {
+ NORMAL,
+ PENDING_LABEL,
+ PENDING_LABEL_POST,
+ PENDING_LABEL_POST_PRE,
+ PENDING_POST
+ } state;
+ label_type type; // type of pending labels
+ int count; // number of pending labels
+ reference **rptr; // pointer to next reference
+ int rcount; // number of references left
+ FILE *fp;
+ int handle_pending(int c);
+public:
+ label_processing_state(reference **, int, FILE *);
+ ~label_processing_state();
+ void process(int c);
+};
+
+static void output_pending_line()
+{
+ if (label_in_text && !accumulate && ncitations > 0) {
+ label_processing_state state(citation, ncitations, outfp);
+ int len = pending_line.length();
+ for (int i = 0; i < len; i++)
+ state.process((unsigned char)(pending_line[i]));
+ }
+ else
+ put_string(pending_line, outfp);
+ pending_line.clear();
+ if (pending_lf_lines.length() > 0) {
+ put_string(pending_lf_lines, outfp);
+ pending_lf_lines.clear();
+ }
+ if (!accumulate)
+ immediately_output_references();
+ if (need_syncing) {
+ fprintf(outfp, ".lf %d %s\n", current_lineno, current_filename);
+ need_syncing = 0;
+ }
+}
+
+static void split_punct(string &line, string &punct)
+{
+ const char *start = line.contents();
+ const char *end = start + line.length();
+ const char *ptr = start;
+ const char *last_token_start = 0;
+ for (;;) {
+ if (ptr >= end)
+ break;
+ last_token_start = ptr;
+ if (*ptr == PRE_LABEL_MARKER || *ptr == POST_LABEL_MARKER
+ || (*ptr >= LABEL_MARKER && *ptr < LABEL_MARKER + N_LABEL_TYPES))
+ ptr++;
+ else if (!get_token(&ptr, end))
+ break;
+ }
+ if (last_token_start) {
+ const token_info *ti = lookup_token(last_token_start, end);
+ if (ti->is_punct()) {
+ punct.append(last_token_start, end - last_token_start);
+ line.set_length(last_token_start - start);
+ }
+ }
+}
+
+static void divert_to_temporary_file()
+{
+ outfp = xtmpfile();
+}
+
+static void store_citation(reference *ref)
+{
+ if (ncitations >= citation_max) {
+ if (citation == 0)
+ citation = new reference*[citation_max = 100];
+ else {
+ reference **old_citation = citation;
+ citation_max *= 2;
+ citation = new reference *[citation_max];
+ memcpy(citation, old_citation, ncitations*sizeof(reference *));
+ a_delete old_citation;
+ }
+ }
+ citation[ncitations++] = ref;
+}
+
+static unsigned store_reference(const string &str)
+{
+ if (reference_hash_table == 0) {
+ reference_hash_table = new reference *[17];
+ hash_table_size = 17;
+ for (int i = 0; i < hash_table_size; i++)
+ reference_hash_table[i] = 0;
+ }
+ unsigned flags;
+ reference *ref = make_reference(str, &flags);
+ ref->compute_hash_code();
+ unsigned h = ref->hash();
+ reference **ptr;
+ for (ptr = reference_hash_table + (h % hash_table_size);
+ *ptr != 0;
+ ((ptr == reference_hash_table)
+ ? (ptr = reference_hash_table + hash_table_size - 1)
+ : --ptr))
+ if (same_reference(**ptr, *ref))
+ break;
+ if (*ptr != 0) {
+ if (ref->is_merged())
+ warning("fields ignored because reference already used");
+ delete ref;
+ ref = *ptr;
+ }
+ else {
+ *ptr = ref;
+ ref->set_number(nreferences);
+ nreferences++;
+ ref->pre_compute_label();
+ ref->compute_sort_key();
+ if (nreferences*2 >= hash_table_size) {
+ // Rehash it.
+ reference **old_table = reference_hash_table;
+ int old_size = hash_table_size;
+ hash_table_size = next_size(hash_table_size);
+ reference_hash_table = new reference*[hash_table_size];
+ int i;
+ for (i = 0; i < hash_table_size; i++)
+ reference_hash_table[i] = 0;
+ for (i = 0; i < old_size; i++)
+ if (old_table[i]) {
+ reference **p;
+ for (p = (reference_hash_table
+ + (old_table[i]->hash() % hash_table_size));
+ *p;
+ ((p == reference_hash_table)
+ ? (p = reference_hash_table + hash_table_size - 1)
+ : --p))
+ ;
+ *p = old_table[i];
+ }
+ a_delete old_table;
+ }
+ }
+ if (label_in_text)
+ store_citation(ref);
+ return flags;
+}
+
+unsigned immediately_handle_reference(const string &str)
+{
+ unsigned flags;
+ reference *ref = make_reference(str, &flags);
+ ref->set_number(nreferences);
+ if (label_in_text || label_in_reference) {
+ ref->pre_compute_label();
+ ref->immediate_compute_label();
+ }
+ nreferences++;
+ store_citation(ref);
+ return flags;
+}
+
+static void immediately_output_references()
+{
+ for (int i = 0; i < ncitations; i++) {
+ reference *ref = citation[i];
+ if (label_in_reference) {
+ fputs(".ds [F ", outfp);
+ const string &label = ref->get_label(NORMAL_LABEL);
+ if (label.length() > 0
+ && (label[0] == ' ' || label[0] == '\\' || label[0] == '"'))
+ putc('"', outfp);
+ put_string(label, outfp);
+ putc('\n', outfp);
+ }
+ ref->output(outfp);
+ delete ref;
+ }
+ ncitations = 0;
+}
+
+static void output_citation_group(reference **v, int n, label_type type,
+ FILE *fp)
+{
+ if (sort_adjacent_labels) {
+ // Do an insertion sort. Usually n will be very small.
+ for (int i = 1; i < n; i++) {
+ int num = v[i]->get_number();
+ reference *temp = v[i];
+ int j;
+ for (j = i - 1; j >= 0 && v[j]->get_number() > num; j--)
+ v[j + 1] = v[j];
+ v[j + 1] = temp;
+ }
+ }
+ // This messes up if !accumulate.
+ if (accumulate && n > 1) {
+ // remove duplicates
+ int j = 1;
+ for (int i = 1; i < n; i++)
+ if (v[i]->get_label(type) != v[i - 1]->get_label(type))
+ v[j++] = v[i];
+ n = j;
+ }
+ string merged_label;
+ for (int i = 0; i < n; i++) {
+ int nmerged = v[i]->merge_labels(v + i + 1, n - i - 1, type, merged_label);
+ if (nmerged > 0) {
+ put_string(merged_label, fp);
+ i += nmerged;
+ }
+ else
+ put_string(v[i]->get_label(type), fp);
+ if (i < n - 1)
+ put_string(sep_label, fp);
+ }
+}
+
+
+label_processing_state::label_processing_state(reference **p, int n, FILE *f)
+: state(NORMAL), count(0), rptr(p), rcount(n), fp(f)
+{
+}
+
+label_processing_state::~label_processing_state()
+{
+ int handled = handle_pending(EOF);
+ assert(!handled);
+ assert(rcount == 0);
+}
+
+int label_processing_state::handle_pending(int c)
+{
+ switch (state) {
+ case NORMAL:
+ break;
+ case PENDING_LABEL:
+ if (c == POST_LABEL_MARKER) {
+ state = PENDING_LABEL_POST;
+ return 1;
+ }
+ else {
+ output_citation_group(rptr, count, type, fp);
+ rptr += count ;
+ rcount -= count;
+ state = NORMAL;
+ }
+ break;
+ case PENDING_LABEL_POST:
+ if (c == PRE_LABEL_MARKER) {
+ state = PENDING_LABEL_POST_PRE;
+ return 1;
+ }
+ else {
+ output_citation_group(rptr, count, type, fp);
+ rptr += count;
+ rcount -= count;
+ put_string(post_label, fp);
+ state = NORMAL;
+ }
+ break;
+ case PENDING_LABEL_POST_PRE:
+ if (c >= LABEL_MARKER
+ && c < LABEL_MARKER + N_LABEL_TYPES
+ && c - LABEL_MARKER == type) {
+ count += 1;
+ state = PENDING_LABEL;
+ return 1;
+ }
+ else {
+ output_citation_group(rptr, count, type, fp);
+ rptr += count;
+ rcount -= count;
+ put_string(sep_label, fp);
+ state = NORMAL;
+ }
+ break;
+ case PENDING_POST:
+ if (c == PRE_LABEL_MARKER) {
+ put_string(sep_label, fp);
+ state = NORMAL;
+ return 1;
+ }
+ else {
+ put_string(post_label, fp);
+ state = NORMAL;
+ }
+ break;
+ }
+ return 0;
+}
+
+void label_processing_state::process(int c)
+{
+ if (handle_pending(c))
+ return;
+ assert(state == NORMAL);
+ switch (c) {
+ case PRE_LABEL_MARKER:
+ put_string(pre_label, fp);
+ state = NORMAL;
+ break;
+ case POST_LABEL_MARKER:
+ state = PENDING_POST;
+ break;
+ case LABEL_MARKER:
+ case LABEL_MARKER + 1:
+ count = 1;
+ state = PENDING_LABEL;
+ type = label_type(c - LABEL_MARKER);
+ break;
+ default:
+ state = NORMAL;
+ putc(c, fp);
+ break;
+ }
+}
+
+extern "C" {
+
+static int rcompare(const void *p1, const void *p2)
+{
+ return compare_reference(**(reference **)p1, **(reference **)p2);
+}
+
+}
+
+void output_references()
+{
+ assert(accumulate);
+ if (nreferences > 0) {
+ int j = 0;
+ int i;
+ for (i = 0; i < hash_table_size; i++)
+ if (reference_hash_table[i] != 0)
+ reference_hash_table[j++] = reference_hash_table[i];
+ assert(j == nreferences);
+ for (; j < hash_table_size; j++)
+ reference_hash_table[j] = 0;
+ qsort(reference_hash_table, nreferences, sizeof(reference*), rcompare);
+ for (i = 0; i < nreferences; i++)
+ reference_hash_table[i]->set_number(i);
+ compute_labels(reference_hash_table, nreferences);
+ }
+ if (outfp != stdout) {
+ rewind(outfp);
+ {
+ label_processing_state state(citation, ncitations, stdout);
+ int c;
+ while ((c = getc(outfp)) != EOF)
+ state.process(c);
+ }
+ ncitations = 0;
+ fclose(outfp);
+ outfp = stdout;
+ }
+ if (nreferences > 0) {
+ fputs(".]<\n", outfp);
+ for (int i = 0; i < nreferences; i++) {
+ if (sort_fields.length() > 0)
+ reference_hash_table[i]->print_sort_key_comment(outfp);
+ if (label_in_reference) {
+ fputs(".ds [F ", outfp);
+ const string &label = reference_hash_table[i]->get_label(NORMAL_LABEL);
+ if (label.length() > 0
+ && (label[0] == ' ' || label[0] == '\\' || label[0] == '"'))
+ putc('"', outfp);
+ put_string(label, outfp);
+ putc('\n', outfp);
+ }
+ reference_hash_table[i]->output(outfp);
+ delete reference_hash_table[i];
+ reference_hash_table[i] = 0;
+ }
+ fputs(".]>\n", outfp);
+ nreferences = 0;
+ }
+ clear_labels();
+}
+
+static reference *find_reference(const char *query, int query_len)
+{
+ // This is so that error messages look better.
+ while (query_len > 0 && csspace(query[query_len - 1]))
+ query_len--;
+ string str;
+ for (int i = 0; i < query_len; i++)
+ str += query[i] == '\n' ? ' ' : query[i];
+ str += '\0';
+ possibly_load_default_database();
+ search_list_iterator iter(&database_list, str.contents());
+ reference_id rid;
+ const char *start;
+ int len;
+ if (!iter.next(&start, &len, &rid)) {
+ error("no matches for `%1'", str.contents());
+ return 0;
+ }
+ const char *end = start + len;
+ while (start < end) {
+ if (*start == '%')
+ break;
+ while (start < end && *start++ != '\n')
+ ;
+ }
+ if (start >= end) {
+ error("found a reference for `%1' but it didn't contain any fields",
+ str.contents());
+ return 0;
+ }
+ reference *result = new reference(start, end - start, &rid);
+ if (iter.next(&start, &len, &rid))
+ warning("multiple matches for `%1'", str.contents());
+ return result;
+}
+
+static reference *make_reference(const string &str, unsigned *flagsp)
+{
+ const char *start = str.contents();
+ const char *end = start + str.length();
+ const char *ptr = start;
+ while (ptr < end) {
+ if (*ptr == '%')
+ break;
+ while (ptr < end && *ptr++ != '\n')
+ ;
+ }
+ *flagsp = 0;
+ for (; start < ptr; start++) {
+ if (*start == '#')
+ *flagsp = (SHORT_LABEL | (*flagsp & (FORCE_RIGHT_BRACKET
+ | FORCE_LEFT_BRACKET)));
+ else if (*start == '[')
+ *flagsp |= FORCE_LEFT_BRACKET;
+ else if (*start == ']')
+ *flagsp |= FORCE_RIGHT_BRACKET;
+ else if (!csspace(*start))
+ break;
+ }
+ if (start >= end) {
+ error("empty reference");
+ return new reference;
+ }
+ reference *database_ref = 0;
+ if (start < ptr)
+ database_ref = find_reference(start, ptr - start);
+ reference *inline_ref = 0;
+ if (ptr < end)
+ inline_ref = new reference(ptr, end - ptr);
+ if (inline_ref) {
+ if (database_ref) {
+ database_ref->merge(*inline_ref);
+ delete inline_ref;
+ return database_ref;
+ }
+ else
+ return inline_ref;
+ }
+ else if (database_ref)
+ return database_ref;
+ else
+ return new reference;
+}
+
+static void do_ref(const string &str)
+{
+ if (accumulate)
+ (void)store_reference(str);
+ else {
+ (void)immediately_handle_reference(str);
+ immediately_output_references();
+ }
+}
+
+static void trim_blanks(string &str)
+{
+ const char *start = str.contents();
+ const char *end = start + str.length();
+ while (end > start && end[-1] != '\n' && csspace(end[-1]))
+ --end;
+ str.set_length(end - start);
+}
+
+void do_bib(const char *filename)
+{
+ FILE *fp;
+ if (strcmp(filename, "-") == 0)
+ fp = stdin;
+ else {
+ errno = 0;
+ fp = fopen(filename, "r");
+ if (fp == 0) {
+ error("can't open `%1': %2", filename, strerror(errno));
+ return;
+ }
+ current_filename = filename;
+ }
+ enum {
+ START, MIDDLE, BODY, BODY_START, BODY_BLANK, BODY_DOT
+ } state = START;
+ string body;
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ if (illegal_input_char(c)) {
+ error("illegal input character code %1", c);
+ continue;
+ }
+ switch (state) {
+ case START:
+ if (c == '%') {
+ body = c;
+ state = BODY;
+ }
+ else if (c != '\n')
+ state = MIDDLE;
+ break;
+ case MIDDLE:
+ if (c == '\n')
+ state = START;
+ break;
+ case BODY:
+ body += c;
+ if (c == '\n')
+ state = BODY_START;
+ break;
+ case BODY_START:
+ if (c == '\n') {
+ do_ref(body);
+ state = START;
+ }
+ else if (c == '.')
+ state = BODY_DOT;
+ else if (csspace(c)) {
+ state = BODY_BLANK;
+ body += c;
+ }
+ else {
+ body += c;
+ state = BODY;
+ }
+ break;
+ case BODY_BLANK:
+ if (c == '\n') {
+ trim_blanks(body);
+ do_ref(body);
+ state = START;
+ }
+ else if (csspace(c))
+ body += c;
+ else {
+ body += c;
+ state = BODY;
+ }
+ break;
+ case BODY_DOT:
+ if (c == ']') {
+ do_ref(body);
+ state = MIDDLE;
+ }
+ else {
+ body += '.';
+ body += c;
+ state = c == '\n' ? BODY_START : BODY;
+ }
+ break;
+ default:
+ assert(0);
+ }
+ if (c == '\n')
+ current_lineno++;
+ }
+ switch (state) {
+ case START:
+ case MIDDLE:
+ break;
+ case BODY:
+ body += '\n';
+ do_ref(body);
+ break;
+ case BODY_DOT:
+ case BODY_START:
+ do_ref(body);
+ break;
+ case BODY_BLANK:
+ trim_blanks(body);
+ do_ref(body);
+ break;
+ }
+ fclose(fp);
+}
+
+// from the Dragon Book
+
+unsigned hash_string(const char *s, int len)
+{
+ const char *end = s + len;
+ unsigned h = 0, g;
+ while (s < end) {
+ h <<= 4;
+ h += *s++;
+ if ((g = h & 0xf0000000) != 0) {
+ h ^= g >> 24;
+ h ^= g;
+ }
+ }
+ return h;
+}
+
+int next_size(int n)
+{
+ static const int table_sizes[] = {
+ 101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009,
+ 80021, 160001, 500009, 1000003, 2000003, 4000037, 8000009,
+ 16000057, 32000011, 64000031, 128000003, 0
+ };
+
+ const int *p;
+ for (p = table_sizes; *p <= n && *p != 0; p++)
+ ;
+ assert(*p != 0);
+ return *p;
+}
+
diff --git a/src/preproc/refer/refer.h b/src/preproc/refer/refer.h
new file mode 100644
index 00000000..f0ab3cd7
--- /dev/null
+++ b/src/preproc/refer/refer.h
@@ -0,0 +1,78 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+
+#include "errarg.h"
+#include "error.h"
+#include "lib.h"
+#include "stringclass.h"
+#include "cset.h"
+#include "cmap.h"
+
+#include "defs.h"
+
+unsigned hash_string(const char *, int);
+int next_size(int);
+
+extern string capitalize_fields;
+extern string reverse_fields;
+extern string abbreviate_fields;
+extern string period_before_last_name;
+extern string period_before_initial;
+extern string period_before_hyphen;
+extern string period_before_other;
+extern string sort_fields;
+extern int annotation_field;
+extern string annotation_macro;
+extern string discard_fields;
+extern string articles;
+extern int abbreviate_label_ranges;
+extern string label_range_indicator;
+extern int date_as_label;
+extern string join_authors_exactly_two;
+extern string join_authors_last_two;
+extern string join_authors_default;
+extern string separate_label_second_parts;
+extern string et_al;
+extern int et_al_min_elide;
+extern int et_al_min_total;
+
+extern int compatible_flag;
+
+extern int set_label_spec(const char *);
+extern int set_date_label_spec(const char *);
+extern int set_short_label_spec(const char *);
+
+extern int short_label_flag;
+
+void clear_labels();
+void command_error(const char *,
+ const errarg &arg1 = empty_errarg,
+ const errarg &arg2 = empty_errarg,
+ const errarg &arg3 = empty_errarg);
+
+struct reference;
+
+void compute_labels(reference **, int);
diff --git a/src/preproc/refer/refer.man b/src/preproc/refer/refer.man
new file mode 100644
index 00000000..6b09c973
--- /dev/null
+++ b/src/preproc/refer/refer.man
@@ -0,0 +1,1299 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.de TQ
+.br
+.ns
+.TP \\$1
+..
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.\" The BSD man macros can't handle " in arguments to font change macros,
+.\" so use \(ts instead of ".
+.tr \(ts"
+.TH @G@REFER @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+@g@refer \- preprocess bibliographic references for groff
+.SH SYNOPSIS
+.nr a \n(.j
+.ad l
+.nr i \n(.i
+.in +\w'\fB@g@refer 'u
+.ti \niu
+.B @g@refer
+.de OP
+.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
+.el .RB "[\ " "\\$1" "\ ]"
+..
+.OP \-benvCPRS
+.OP \-a n
+.OP \-c fields
+.OP \-f n
+.OP \-i fields
+.OP \-k field
+.OP \-l m,n
+.OP \-p filename
+.OP \-s fields
+.OP \-t n
+.OP \-B field.macro
+.RI [\ filename \|.\|.\|.\ ]
+.br
+.ad \na
+.SH DESCRIPTION
+This file documents the GNU version of
+.BR refer ,
+which is part of the groff document formatting system.
+.B refer
+copies the contents of
+.IR filename \|.\|.\|.
+to the standard output,
+except that lines between
+.B .[
+and
+.B .]
+are interpreted as citations,
+and lines between
+.B .R1
+and
+.B .R2
+are interpreted as commands about how citations are to be processed.
+.LP
+Each citation specifies a reference.
+The citation can specify a reference that is contained in
+a bibliographic database by giving a set of keywords
+that only that reference contains.
+Alternatively it can specify a reference by supplying a database
+record in the citation.
+A combination of these alternatives is also possible.
+.LP
+For each citation,
+.B refer
+can produce a mark in the text.
+This mark consists of some label which can be separated from
+the text and from other labels in various ways.
+For each reference it also outputs
+.B groff
+commands that can be used by a macro package to produce a formatted
+reference for each citation.
+The output of
+.B refer
+must therefore be processed using a suitable macro package.
+The
+.B \-ms
+and
+.B \-me
+macros are both suitable.
+The commands to format a citation's reference can be output immediately after
+the citation,
+or the references may be accumulated,
+and the commands output at some later point.
+If the references are accumulated, then multiple citations of the same
+reference will produce a single formatted reference.
+.LP
+The interpretation of lines between
+.B .R1
+and
+.B .R2
+as commands is a new feature of GNU refer.
+Documents making use of this feature can still be processed by
+Unix refer just by adding the lines
+.RS
+.LP
+.nf
+.ft B
+\&.de R1
+\&.ig R2
+\&..
+.ft
+.fi
+.RE
+to the beginning of the document.
+This will cause
+.B troff
+to ignore everything between
+.B .R1
+and
+.BR .R2 .
+The effect of some commands can also be achieved by options.
+These options are supported mainly for compatibility with Unix refer.
+It is usually more convenient to use commands.
+.LP
+.B refer
+generates
+.B .lf
+lines so that filenames and line numbers in messages produced
+by commands that read
+.B refer
+output will be correct;
+it also interprets lines beginning with
+.B .lf
+so that filenames and line numbers in the messages and
+.B .lf
+lines that it produces will be accurate even if the input has been
+preprocessed by a command such as
+.BR @g@soelim (@MAN1EXT@).
+.SH OPTIONS
+.LP
+Most options are equivalent to commands
+(for a description of these commands see the
+.B Commands
+subsection):
+.TP
+.B \-b
+.B
+no-label-in-text; no-label-in-reference
+.TP
+.B \-e
+.B accumulate
+.TP
+.B \-n
+.B no-default-database
+.TP
+.B \-C
+.B compatible
+.TP
+.B \-P
+.B move-punctuation
+.TP
+.B \-S
+.B
+label "(A.n|Q) ', ' (D.y|D)"; bracket-label " (" ) "; "
+.TP
+.BI \-a n
+.B reverse
+.BI A n
+.TP
+.BI \-c fields
+.B capitalize
+.I fields
+.TP
+.BI \-f n
+.B label
+.BI % n
+.TP
+.BI \-i fields
+.B search-ignore
+.I fields
+.TP
+.B \-k
+.B label
+.B L\(ti%a
+.TP
+.BI \-k field
+.B label
+.IB field \(ti%a
+.TP
+.B \-l
+.B label
+.BI A.nD.y%a
+.TP
+.BI \-l m
+.B label
+.BI A.n+ m D.y%a
+.TP
+.BI \-l, n
+.B label
+.BI A.nD.y\- n %a
+.TP
+.BI \-l m , n
+.B label
+.BI A.n+ m D.y\- n %a
+.TP
+.BI \-p filename
+.B database
+.I filename
+.TP
+.BI \-s spec
+.B sort
+.I spec
+.TP
+.BI \-t n
+.B search-truncate
+.I n
+.LP
+These options are equivalent to the following commands with the
+addition that the filenames specified on the command line are
+processed as if they were arguments to the
+.B bibliography
+command instead of in the normal way:
+.TP
+.B \-B
+.B
+annotate X AP; no-label-in-reference
+.TP
+.BI \-B field . macro
+.B annotate
+.I field
+.IB macro ;
+.B no-label-in-reference
+.LP
+The following options have no equivalent commands:
+.TP
+.B \-v
+Print the version number.
+.TP
+.B \-R
+Don't recognize lines beginning with
+.BR .R1 / .R2 .
+.SH USAGE
+.SS Bibliographic databases
+The bibliographic database is a text file consisting of records
+separated by one or more blank lines.
+Within each record fields start with a
+.B %
+at the beginning of a line.
+Each field has a one character name that immediately follows the
+.BR % .
+It is best to use only upper and lower case letters for the names
+of fields.
+The name of the field should be followed by exactly one space,
+and then by the contents of the field.
+Empty fields are ignored.
+The conventional meaning of each field is as follows:
+.TP
+.B A
+The name of an author.
+If the name contains a title such as
+.B Jr.
+at the end,
+it should be separated from the last name by a comma.
+There can be multiple occurrences of the
+.B A
+field.
+The order is significant.
+It is a good idea always to supply an
+.B A
+field or a
+.B Q
+field.
+.TP
+.B B
+For an article that is part of a book, the title of the book
+.TP
+.B C
+The place (city) of publication.
+.TP
+.B D
+The date of publication.
+The year should be specified in full.
+If the month is specified, the name rather than the number of the month
+should be used, but only the first three letters are required.
+It is a good idea always to supply a
+.B D
+field;
+if the date is unknown, a value such as
+.B in press
+or
+.B unknown
+can be used.
+.TP
+.B E
+For an article that is part of a book, the name of an editor of the book.
+Where the work has editors and no authors,
+the names of the editors should be given as
+.B A
+fields and
+.B ,\ (ed)
+or
+.B ,\ (eds)
+should be appended to the last author.
+.TP
+.B G
+US Government ordering number.
+.TP
+.B I
+The publisher (issuer).
+.TP
+.B J
+For an article in a journal, the name of the journal.
+.TP
+.B K
+Keywords to be used for searching.
+.TP
+.B L
+Label.
+.TP
+.B N
+Journal issue number.
+.TP
+.B O
+Other information.
+This is usually printed at the end of the reference.
+.TP
+.B P
+Page number.
+A range of pages can be specified as
+.IB m \- n\fR.
+.TP
+.B Q
+The name of the author, if the author is not a person.
+This will only be used if there are no
+.B A
+fields.
+There can only be one
+.B Q
+field.
+.TP
+.B R
+Technical report number.
+.TP
+.B S
+Series name.
+.TP
+.B T
+Title.
+For an article in a book or journal,
+this should be the title of the article.
+.TP
+.B V
+Volume number of the journal or book.
+.TP
+.B X
+Annotation.
+.LP
+For all fields except
+.B A
+and
+.BR E ,
+if there is more than one occurrence of a particular field in a record,
+only the last such field will be used.
+.LP
+If accent strings are used, they should follow the character to be accented.
+This means that the
+.B AM
+macro must be used with the
+.B \-ms
+macros.
+Accent strings should not be quoted:
+use one
+.B \e
+rather than two.
+.SS Citations
+The format of a citation is
+.RS
+.BI .[ opening-text
+.br
+.I
+flags keywords
+.br
+.I fields
+.br
+.BI .] closing-text
+.RE
+.LP
+The
+.IR opening-text ,
+.IR closing-text
+and
+.I flags
+components are optional.
+Only one of the
+.I keywords
+and
+.I fields
+components need be specified.
+.LP
+The
+.I keywords
+component says to search the bibliographic databases for a reference
+that contains all the words in
+.IR keywords .
+It is an error if more than one reference if found.
+.LP
+The
+.I fields
+components specifies additional fields to replace or supplement
+those specified in the reference.
+When references are being accumulated and the
+.I keywords
+component is non-empty,
+then additional fields should be specified only on the first
+occasion that a particular reference is cited,
+and will apply to all citations of that reference.
+.LP
+The
+.I opening-text
+and
+.I closing-text
+component specifies strings to be used to bracket the label instead
+of the strings specified in the
+.B bracket-label
+command.
+If either of these components is non-empty,
+the strings specified in the
+.B bracket-label
+command will not be used;
+this behaviour can be altered using the
+.B [
+and
+.B ]
+flags.
+Note that leading and trailing spaces are significant for these components.
+.LP
+The
+.I flags
+component is a list of
+non-alphanumeric characters each of which modifies the treatment
+of this particular citation.
+Unix refer will treat these flags as part of the keywords and
+so will ignore them since they are non-alphanumeric.
+The following flags are currently recognized:
+.TP
+.B #
+This says to use the label specified by the
+.B short-label
+command,
+instead of that specified by the
+.B label
+command.
+If no short label has been specified, the normal label will be used.
+Typically the short label is used with author-date labels
+and consists of only the date and possibly a disambiguating letter;
+the
+.B #
+is supposed to be suggestive of a numeric type of label.
+.TP
+.B [
+Precede
+.I opening-text
+with the first string specified in the
+.B bracket-label
+command.
+.TP
+.B ]
+Follow
+.I closing-text
+with the second string specified in the
+.B bracket-label
+command.
+.LP
+One advantages of using the
+.B [
+and
+.B ]
+flags rather than including the brackets in
+.I opening-text
+and
+.I closing-text
+is that
+you can change the style of bracket used in the document just by changing the
+.B bracket-label
+command.
+Another advantage is that sorting and merging of citations
+will not necessarily be inhibited if the flags are used.
+.LP
+If a label is to be inserted into the text,
+it will be attached to the line preceding the
+.B .[
+line.
+If there is no such line, then an extra line will be inserted before the
+.B .[
+line and a warning will be given.
+.LP
+There is no special notation for making a citation to multiple references.
+Just use a sequence of citations, one for each reference.
+Don't put anything between the citations.
+The labels for all the citations will be attached to the line preceding
+the first citation.
+The labels may also be sorted or merged.
+See the description of the
+.B <>
+label expression, and of the
+.B sort-adjacent-labels
+and
+.B abbreviate-label-ranges
+command.
+A label will not be merged if its citation has a non-empty
+.I opening-text
+or
+.IR closing-text .
+However, the labels for a citation using the
+.B ]
+flag and without any
+.I closing-text
+immediately followed by a citation using the
+.B [
+flag and without any
+.I opening-text
+may be sorted and merged
+even though the first citation's
+.I opening-text
+or the second citation's
+.I closing-text
+is non-empty.
+(If you wish to prevent this just make the first citation's
+.I closing-text
+.BR \e& .)
+.SS Commands
+Commands are contained between lines starting with
+.B .R1
+and
+.BR .R2 .
+Recognition of these lines can be prevented by the
+.B \-R
+option.
+When a
+.B .R1
+line is recognized any accumulated references are flushed out.
+Neither
+.B .R1
+nor
+.B .R2
+lines,
+nor anything between them
+is output.
+.LP
+Commands are separated by newlines or
+.BR ; s.
+.B #
+introduces a comment that extends to the end of the line
+(but does not conceal the newline).
+Each command is broken up into words.
+Words are separated by spaces or tabs.
+A word that begins with
+.B \(ts
+extends to the next
+.B \(ts
+that is not followed by another
+.BR \(ts .
+If there is no such
+.B \(ts
+the word extends to the end of the line.
+Pairs of
+.B \(ts
+in a word beginning with
+.B \(ts
+collapse to a single
+.BR \(ts .
+Neither
+.B #
+nor
+.B ;
+are recognized inside
+.BR \(ts s.
+A line can be continued by ending it with
+.BR \e ;
+this works everywhere except after a
+.BR # .
+.LP
+.ds n \fR*
+Each command
+.I name
+that is marked with \*n has an associated negative command
+.BI no- name
+that undoes the effect of
+.IR name .
+For example, the
+.B no-sort
+command specifies that references should not be sorted.
+The negative commands take no arguments.
+.LP
+In the following description each argument must be a single word;
+.I field
+is used for a single upper or lower case letter naming a field;
+.I fields
+is used for a sequence of such letters;
+.I m
+and
+.I n
+are used for a non-negative numbers;
+.I string
+is used for an arbitrary string;
+.I filename
+is used for the name of a file.
+.Tp \w'\fBabbreviate-label-ranges'u+2n
+.BI abbreviate\*n\ fields\ string1\ string2\ string3\ string4
+Abbreviate the first names of
+.IR fields .
+An initial letter will be separated from another initial letter by
+.IR string1 ,
+from the last name by
+.IR string2 ,
+and from anything else
+(such as a
+.B von
+or
+.BR de )
+by
+.IR string3 .
+These default to a period followed by a space.
+In a hyphenated first name,
+the initial of the first part of the name will be separated from the hyphen by
+.IR string4 ;
+this defaults to a period.
+No attempt is made to handle any ambiguities that might
+result from abbreviation.
+Names are abbreviated before sorting and before
+label construction.
+.TP
+.BI abbreviate-label-ranges\*n\ string
+Three or more adjacent labels that refer to consecutive references
+will be abbreviated to a label consisting
+of the first label, followed by
+.I string
+followed by the last label.
+This is mainly useful with numeric labels.
+If
+.I string
+is omitted it defaults to
+.BR \- .
+.TP
+.B accumulate\*n
+Accumulate references instead of writing out each reference
+as it is encountered.
+Accumulated references will be written out whenever a reference
+of the form
+.RS
+.IP
+.B .[
+.br
+.B $LIST$
+.br
+.B .]
+.LP
+is encountered,
+after all input files hve been processed,
+and whenever
+.B .R1
+line is recognized.
+.RE
+.TP
+.BI annotate\*n\ field\ string
+.I field
+is an annotation;
+print it at the end of the reference as a paragraph preceded by the line
+.RS
+.IP
+.BI . string
+.LP
+If
+.I macro
+is omitted it will default to
+.BR AP ;
+if
+.I field
+is also omitted it will default to
+.BR X .
+Only one field can be an annotation.
+.RE
+.TP
+.BI articles\ string \fR\|.\|.\|.
+.IR string \|.\|.\|.
+are definite or indefinite articles, and should be ignored at the beginning of
+.B T
+fields when sorting.
+Initially,
+.BR the ,
+.B a
+and
+.B an
+are recognized as articles.
+.TP
+.BI bibliography\ filename \fR\|.\|.\|.
+Write out all the references contained in the bibliographic databases
+.IR filename \|.\|.\|.
+.TP
+.BI bracket-label\ string1\ string2\ string3
+In the text, bracket each label
+with
+.I string1
+and
+.IR string2 .
+An occurrence of
+.I string2
+immediately followed by
+.I string1
+will be turned into
+.IR string3 .
+The default behaviour is
+.RS
+.IP
+.B
+bracket-label \e*([. \e*(.] ", "
+.RE
+.TP
+.BI capitalize\ fields
+Convert
+.I fields
+to caps and small caps.
+.TP
+.B compatible\*n
+Recognize
+.B .R1
+and
+.B .R2
+even when followed by a character other than space or newline.
+.TP
+.BI database\ filename \fR\|.\|.\|.
+Search the bibliographic databases
+.IR filename \|.\|.\|.
+For each
+.I filename
+if an index
+.IB filename @INDEX_SUFFIX@
+created by
+.BR @g@indxbib (@MAN1EXT@)
+exists, then it will be searched instead;
+each index can cover multiple databases.
+.TP
+.BI date-as-label\*n\ string
+.I string
+is a label expression that specifies a string with which to replace the
+.B D
+field after constructing the label.
+See the
+.B "Label expressions"
+subsection for a description of label expressions.
+This command is useful if you do not want explicit labels in the
+reference list, but instead want to handle any necessary
+disambiguation by qualifying the date in some way.
+The label used in the text would typically be some combination of the
+author and date.
+In most cases you should also use the
+.B no-label-in-reference
+command.
+For example,
+.RS
+.IP
+.B
+date-as-label D.+yD.y%a*D.-y
+.LP
+would attach a disambiguating letter to the year part of the
+.B D
+field in the reference.
+.RE
+.TP
+.B default-database\*n
+The default database should be searched.
+This is the default behaviour, so the negative version of
+this command is more useful.
+refer determines whether the default database should be searched
+on the first occasion that it needs to do a search.
+Thus a
+.B no-default-database
+command must be given before then,
+in order to be effective.
+.TP
+.BI discard\*n\ fields
+When the reference is read,
+.I fields
+should be discarded;
+no string definitions for
+.I fields
+will be output.
+Initially,
+.I fields
+are
+.BR XYZ .
+.TP
+.BI et-al\*n\ string\ m\ n
+Control use of
+.B
+et al
+in the evaluation of
+.B @
+expressions in label expressions.
+If the number of authors needed to make the author sequence
+unambiguous is
+.I u
+and the total number of authors is
+.I t
+then the last
+.IR t \|\-\| u
+authors will be replaced by
+.I string
+provided that
+.IR t \|\-\| u
+is not less than
+.I m
+and
+.I t
+is not less than
+.IR n .
+The default behaviour is
+.RS
+.IP
+.B
+et-al " et al" 2 3
+.RE
+.TP
+.BI include\ filename
+Include
+.I filename
+and interpret the contents as commands.
+.TP
+.BI join-authors\ string1\ string2\ string3
+This says how authors should be joined together.
+When there are exactly two authors, they will be joined with
+.IR string1 .
+When there are more than two authors, all but the last two will
+be joined with
+.IR string2 ,
+and the last two authors will be joined with
+.IR string3 .
+If
+.I string3
+is omitted,
+it will default to
+.IR string1 ;
+if
+.I string2
+is also omitted it will also default to
+.IR string1 .
+For example,
+.RS
+.IP
+.B
+join-authors " and " ", " ", and "
+.LP
+will restore the default method for joining authors.
+.RE
+.TP
+.B label-in-reference\*n
+When outputting the reference,
+define the string
+.B [F
+to be the reference's label.
+This is the default behaviour; so the negative version
+of this command is more useful.
+.TP
+.B label-in-text\*n
+For each reference output a label in the text.
+The label will be separated from the surrounding text as described in the
+.B bracket-label
+command.
+This is the default behaviour; so the negative version
+of this command is more useful.
+.TP
+.BI label\ string
+.I string
+is a label expression describing how to label each reference.
+.TP
+.BI separate-label-second-parts\ string
+When merging two-part labels, separate the second part of the second
+label from the first label with
+.IR string .
+See the description of the
+.B <>
+label expression.
+.TP
+.B move-punctuation\*n
+In the text, move any punctuation at the end of line past the label.
+It is usually a good idea to give this command unless you are using
+superscripted numbers as labels.
+.TP
+.BI reverse\*n\ string
+Reverse the fields whose names
+are in
+.IR string .
+Each field name can be followed by a number which says
+how many such fields should be reversed.
+If no number is given for a field, all such fields will be reversed.
+.TP
+.BI search-ignore\*n\ fields
+While searching for keys in databases for which no index exists,
+ignore the contents of
+.IR fields .
+Initially, fields
+.B XYZ
+are ignored.
+.TP
+.BI search-truncate\*n\ n
+Only require the first
+.I n
+characters of keys to be given.
+In effect when searching for a given key
+words in the database are truncated to the maximum of
+.I n
+and the length of the key.
+Initially
+.I n
+is 6.
+.TP
+.BI short-label\*n\ string
+.I string
+is a label expression that specifies an alternative (usually shorter)
+style of label.
+This is used when the
+.B #
+flag is given in the citation.
+When using author-date style labels, the identity of the author
+or authors is sometimes clear from the context, and so it
+may be desirable to omit the author or authors from the label.
+The
+.B short-label
+command will typically be used to specify a label containing just
+a date and possibly a disambiguating letter.
+.TP
+.BI sort\*n\ string
+Sort references according to
+.BR string .
+References will automatically be accumulated.
+.I string
+should be a list of field names, each followed by a number,
+indicating how many fields with the name should be used for sorting.
+.B +
+can be used to indicate that all the fields with the name should be used.
+Also
+.B .
+can be used to indicate the references should be sorted using the
+(tentative) label.
+(The
+.B
+Label expressions
+subsection describes the concept of a tentative label.)
+.TP
+.B sort-adjacent-labels\*n
+Sort labels that are adjacent in the text according to their
+position in the reference list.
+This command should usually be given if the
+.B abbreviate-label-ranges
+command has been given,
+or if the label expression contains a
+.B <>
+expression.
+This will have no effect unless references are being accumulated.
+.SS Label expressions
+.LP
+Label expressions can be evaluated both normally and tentatively.
+The result of normal evaluation is used for output.
+The result of tentative evaluation, called the
+.I
+tentative label,
+is used to gather the information
+that normal evaluation needs to disambiguate the label.
+Label expressions specified by the
+.B date-as-label
+and
+.B short-label
+commands are not evaluated tentatively.
+Normal and tentative evaluation are the same for all types
+of expression other than
+.BR @ ,
+.BR * ,
+and
+.B %
+expressions.
+The description below applies to normal evaluation,
+except where otherwise specified.
+.TP
+.I field
+.TQ
+.I field\ n
+The
+.IR n -th
+part of
+.IR field .
+If
+.I n
+is omitted, it defaults to 1.
+.TP
+.BI ' string '
+The characters in
+.I string
+literally.
+.TP
+.B @
+All the authors joined as specified by the
+.B join-authors
+command.
+The whole of each author's name will be used.
+However, if the references are sorted by author
+(that is the sort specification starts with
+.BR A+ ),
+then authors' last names will be used instead, provided that this does
+not introduce ambiguity,
+and also an initial subsequence of the authors may be used
+instead of all the authors, again provided that this does not
+introduce ambiguity.
+The use of only the last name for the
+.IR i -th
+author of some reference
+is considered to be ambiguous if
+there is some other reference,
+such that the first
+.IR i \|-\|1
+authors of the references are the same,
+the
+.IR i -th
+authors are not the same,
+but the
+.IR i -th
+authors' last names are the same.
+A proper initial subsequence of the sequence
+of authors for some reference is considered to be ambiguous if there is
+a reference with some other sequence of authors which also has
+that subsequence as a proper initial subsequence.
+When an initial subsequence of authors is used, the remaining
+authors are replaced by the string specified by the
+.B et-al
+command;
+this command may also specify additional requirements that must be
+met before an initial subsequence can be used.
+.B @
+tentatively evaluates to a canonical representation of the authors,
+such that authors that compare equally for sorting purpose
+will have the same representation.
+.TP
+.BI % n
+.TQ
+.B %a
+.TQ
+.B %A
+.TQ
+.B %i
+.TQ
+.B %I
+The serial number of the reference formatted according to the character
+following the
+.BR % .
+The serial number of a reference is 1 plus the number of earlier references
+with same tentative label as this reference.
+These expressions tentatively evaluate to an empty string.
+.TP
+.IB expr *
+If there is another reference with the same tentative label as
+this reference, then
+.IR expr ,
+otherwise an empty string.
+It tentatively evaluates to an empty string.
+.TP
+.IB expr + n
+.TQ
+.IB expr \- n
+The first
+.RB ( + )
+or last
+.RB ( \- )
+.I n
+upper or lower case letters or digits of
+.IR expr .
+Troff special characters (such as
+.BR \e('a )
+count as a single letter.
+Accent strings are retained but do not count towards the total.
+.TP
+.IB expr .l
+.I expr
+converted to lowercase.
+.TP
+.IB expr .u
+.I expr
+converted to uppercase.
+.TP
+.IB expr .c
+.I expr
+converted to caps and small caps.
+.TP
+.IB expr .r
+.I expr
+reversed so that the last name is first.
+.TP
+.IB expr .a
+.I expr
+with first names abbreviated.
+Note that fields specified in the
+.B abbreviate
+command are abbreviated before any labels are evaluated.
+Thus
+.B .a
+is useful only when you want a field to be abbreviated in a label
+but not in a reference.
+.TP
+.IB expr .y
+The year part of
+.IR expr .
+.TP
+.IB expr .+y
+The part of
+.I expr
+before the year, or the whole of
+.I expr
+if it does not contain a year.
+.TP
+.IB expr .\-y
+The part of
+.I expr
+after the year, or an empty string if
+.I expr
+does not contain a year.
+.TP
+.IB expr .n
+The last name part of
+.IR expr .
+.TP
+.IB expr1 \(ti expr2
+.I expr1
+except that if the last character of
+.I expr1
+is
+.B \-
+then it will be replaced by
+.IR expr2 .
+.TP
+.I expr1\ expr2
+The concatenation of
+.I expr1
+and
+.IR expr2 .
+.TP
+.IB expr1 | expr2
+If
+.I expr1
+is non-empty then
+.I expr1
+otherwise
+.IR expr2 .
+.TP
+.IB expr1 & expr2
+If
+.I expr1
+is non-empty
+then
+.I expr2
+otherwise an empty string.
+.TP
+.IB expr1 ? expr2 : expr3
+If
+.I expr1
+is non-empty
+then
+.I expr2
+otherwise
+.IR expr3 .
+.TP
+.BI < expr >
+The label is in two parts, which are separated by
+.IR expr .
+Two adjacent two-part labels which have the same first part will be
+merged by appending the second part of the second label onto the first
+label separated by the string specified in the
+.B separate-label-second-parts
+command (initially, a comma followed by a space); the resulting label
+will also be a two-part label with the same first part as before
+merging, and so additional labels can be merged into it.
+Note that it is permissible for the first part to be empty;
+this maybe desirable for expressions used in the
+.B short-label
+command.
+.TP
+.BI ( expr )
+The same as
+.IR expr .
+Used for grouping.
+.LP
+The above expressions are listed in order of precedence
+(highest first);
+.B &
+and
+.B |
+have the same precedence.
+.SS Macro interface
+Each reference starts with a call to the macro
+.BR ]- .
+The string
+.B [F
+will be defined to be the label for this reference,
+unless the
+.B no-label-in-reference
+command has been given.
+There then follows a series of string definitions,
+one for each field:
+string
+.BI [ X
+corresponds to field
+.IR X .
+The number register
+.B [P
+is set to 1 if the
+.B P
+field contains a range of pages.
+The
+.BR [T ,
+.B [A
+and
+.B [O
+number registers are set to 1 according as the
+.BR T ,
+.B A
+and
+.B O
+fields end with one of the characters
+.BR .?! .
+The
+.B [E
+number register will be set to 1 if the
+.B [E
+string contains more than one name.
+The reference is followed by a call to the
+.B ][
+macro.
+The first argument to this macro gives a number representing
+the type of the reference.
+If a reference contains a
+.B J
+field, it will be classified as type 1,
+otherwise if it contains a
+.B B
+field, it will type 3,
+otherwise if it contains a
+.B G
+or
+.B R
+field it will be type 4,
+otherwise if contains a
+.B I
+field it will be type 2,
+otherwise it will be type 0.
+The second argument is a symbolic name for the type:
+.BR other ,
+.BR journal-article ,
+.BR book ,
+.B article-in-book
+or
+.BR tech-report .
+Groups of references that have been accumulated
+or are produced by the
+.B bibliography
+command are preceded by a call to the
+.B ]<
+macro and followed by a call to the
+.B ]>
+macro.
+.SH FILES
+.Tp \w'\fB@DEFAULT_INDEX@'u+2n
+.B @DEFAULT_INDEX@
+Default database.
+.TP
+.IB file @INDEX_SUFFIX@
+Index files.
+.SH "SEE ALSO"
+.BR @g@indxbib (@MAN1EXT@),
+.BR @g@lookbib (@MAN1EXT@),
+.BR lkbib (@MAN1EXT@)
+.br
+.SH BUGS
+In label expressions,
+.B <>
+expressions are ignored inside
+.BI . char
+expressions.
diff --git a/src/preproc/refer/token.cc b/src/preproc/refer/token.cc
new file mode 100644
index 00000000..1cf6890f
--- /dev/null
+++ b/src/preproc/refer/token.cc
@@ -0,0 +1,378 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "refer.h"
+#include "token.h"
+
+#define TOKEN_TABLE_SIZE 1009
+// I believe in Icelandic thorn sorts after z.
+#define THORN_SORT_KEY "{"
+
+struct token_table_entry {
+ const char *tok;
+ token_info ti;
+ token_table_entry();
+};
+
+token_table_entry token_table[TOKEN_TABLE_SIZE];
+int ntokens = 0;
+
+static void skip_name(const char **ptr, const char *end)
+{
+ if (*ptr < end) {
+ switch (*(*ptr)++) {
+ case '(':
+ if (*ptr < end) {
+ *ptr += 1;
+ if (*ptr < end)
+ *ptr += 1;
+ }
+ break;
+ case '[':
+ while (*ptr < end)
+ if (*(*ptr)++ == ']')
+ break;
+ break;
+ }
+ }
+}
+
+int get_token(const char **ptr, const char *end)
+{
+ if (*ptr >= end)
+ return 0;
+ char c = *(*ptr)++;
+ if (c == '\\' && *ptr < end) {
+ switch (**ptr) {
+ default:
+ *ptr += 1;
+ break;
+ case '(':
+ case '[':
+ skip_name(ptr, end);
+ break;
+ case '*':
+ case 'f':
+ *ptr += 1;
+ skip_name(ptr, end);
+ break;
+ }
+ }
+ return 1;
+}
+
+token_info::token_info()
+: type(TOKEN_OTHER), sort_key(0), other_case(0)
+{
+}
+
+void token_info::set(token_type t, const char *sk, const char *oc)
+{
+ assert(oc == 0 || t == TOKEN_UPPER || t == TOKEN_LOWER);
+ type = t;
+ sort_key = sk;
+ other_case = oc;
+}
+
+void token_info::sortify(const char *start, const char *end, string &result)
+ const
+{
+ if (sort_key)
+ result += sort_key;
+ else if (type == TOKEN_UPPER || type == TOKEN_LOWER) {
+ for (; start < end; start++)
+ if (csalpha(*start))
+ result += cmlower(*start);
+ }
+}
+
+int token_info::sortify_non_empty(const char *start, const char *end) const
+{
+ if (sort_key)
+ return *sort_key != '\0';
+ if (type != TOKEN_UPPER && type != TOKEN_LOWER)
+ return 0;
+ for (; start < end; start++)
+ if (csalpha(*start))
+ return 1;
+ return 0;
+}
+
+
+void token_info::lower_case(const char *start, const char *end,
+ string &result) const
+{
+ if (type != TOKEN_UPPER) {
+ while (start < end)
+ result += *start++;
+ }
+ else if (other_case)
+ result += other_case;
+ else {
+ while (start < end)
+ result += cmlower(*start++);
+ }
+}
+
+void token_info::upper_case(const char *start, const char *end,
+ string &result) const
+{
+ if (type != TOKEN_LOWER) {
+ while (start < end)
+ result += *start++;
+ }
+ else if (other_case)
+ result += other_case;
+ else {
+ while (start < end)
+ result += cmupper(*start++);
+ }
+}
+
+token_table_entry::token_table_entry()
+: tok(0)
+{
+}
+
+static void store_token(const char *tok, token_type typ,
+ const char *sk = 0, const char *oc = 0)
+{
+ unsigned n = hash_string(tok, strlen(tok)) % TOKEN_TABLE_SIZE;
+ for (;;) {
+ if (token_table[n].tok == 0) {
+ if (++ntokens == TOKEN_TABLE_SIZE)
+ assert(0);
+ token_table[n].tok = tok;
+ break;
+ }
+ if (strcmp(tok, token_table[n].tok) == 0)
+ break;
+ if (n == 0)
+ n = TOKEN_TABLE_SIZE - 1;
+ else
+ --n;
+ }
+ token_table[n].ti.set(typ, sk, oc);
+}
+
+
+token_info default_token_info;
+
+const token_info *lookup_token(const char *start, const char *end)
+{
+ unsigned n = hash_string(start, end - start) % TOKEN_TABLE_SIZE;
+ for (;;) {
+ if (token_table[n].tok == 0)
+ break;
+ if (strlen(token_table[n].tok) == end - start
+ && memcmp(token_table[n].tok, start, end - start) == 0)
+ return &(token_table[n].ti);
+ if (n == 0)
+ n = TOKEN_TABLE_SIZE - 1;
+ else
+ --n;
+ }
+ return &default_token_info;
+}
+
+static void init_ascii()
+{
+ const char *p;
+ for (p = "abcdefghijklmnopqrstuvwxyz"; *p; p++) {
+ char buf[2];
+ buf[0] = *p;
+ buf[1] = '\0';
+ store_token(strsave(buf), TOKEN_LOWER);
+ buf[0] = cmupper(buf[0]);
+ store_token(strsave(buf), TOKEN_UPPER);
+ }
+ for (p = "0123456789"; *p; p++) {
+ char buf[2];
+ buf[0] = *p;
+ buf[1] = '\0';
+ const char *s = strsave(buf);
+ store_token(s, TOKEN_OTHER, s);
+ }
+ for (p = ".,:;?!"; *p; p++) {
+ char buf[2];
+ buf[0] = *p;
+ buf[1] = '\0';
+ store_token(strsave(buf), TOKEN_PUNCT);
+ }
+ store_token("-", TOKEN_HYPHEN);
+}
+
+static void store_letter(const char *lower, const char *upper,
+ const char *sort_key = 0)
+{
+ store_token(lower, TOKEN_LOWER, sort_key, upper);
+ store_token(upper, TOKEN_UPPER, sort_key, lower);
+}
+
+static void init_letter(unsigned char uc_code, unsigned char lc_code,
+ const char *sort_key)
+{
+ char lbuf[2];
+ lbuf[0] = lc_code;
+ lbuf[1] = 0;
+ char ubuf[2];
+ ubuf[0] = uc_code;
+ ubuf[1] = 0;
+ store_letter(strsave(lbuf), strsave(ubuf), sort_key);
+}
+
+static void init_latin1()
+{
+ init_letter(0xc0, 0xe0, "a");
+ init_letter(0xc1, 0xe1, "a");
+ init_letter(0xc2, 0xe2, "a");
+ init_letter(0xc3, 0xe3, "a");
+ init_letter(0xc4, 0xe4, "a");
+ init_letter(0xc5, 0xe5, "a");
+ init_letter(0xc6, 0xe6, "ae");
+ init_letter(0xc7, 0xe7, "c");
+ init_letter(0xc8, 0xe8, "e");
+ init_letter(0xc9, 0xe9, "e");
+ init_letter(0xca, 0xea, "e");
+ init_letter(0xcb, 0xeb, "e");
+ init_letter(0xcc, 0xec, "i");
+ init_letter(0xcd, 0xed, "i");
+ init_letter(0xce, 0xee, "i");
+ init_letter(0xcf, 0xef, "i");
+
+ init_letter(0xd0, 0xf0, "d");
+ init_letter(0xd1, 0xf1, "n");
+ init_letter(0xd2, 0xf2, "o");
+ init_letter(0xd3, 0xf3, "o");
+ init_letter(0xd4, 0xf4, "o");
+ init_letter(0xd5, 0xf5, "o");
+ init_letter(0xd6, 0xf6, "o");
+ init_letter(0xd8, 0xf8, "o");
+ init_letter(0xd9, 0xf9, "u");
+ init_letter(0xda, 0xfa, "u");
+ init_letter(0xdb, 0xfb, "u");
+ init_letter(0xdc, 0xfc, "u");
+ init_letter(0xdd, 0xfd, "y");
+ init_letter(0xde, 0xfe, THORN_SORT_KEY);
+
+ store_token("\337", TOKEN_LOWER, "ss", "SS");
+ store_token("\377", TOKEN_LOWER, "y", "Y");
+}
+
+static void init_two_char_letter(char l1, char l2, char u1, char u2,
+ const char *sk = 0)
+{
+ char buf[6];
+ buf[0] = '\\';
+ buf[1] = '(';
+ buf[2] = l1;
+ buf[3] = l2;
+ buf[4] = '\0';
+ const char *p = strsave(buf);
+ buf[2] = u1;
+ buf[3] = u2;
+ store_letter(p, strsave(buf), sk);
+ buf[1] = '[';
+ buf[4] = ']';
+ buf[5] = '\0';
+ p = strsave(buf);
+ buf[2] = l1;
+ buf[3] = l2;
+ store_letter(strsave(buf), p, sk);
+
+}
+
+static void init_special_chars()
+{
+ const char *p;
+ for (p = "':^`~"; *p; p++)
+ for (const char *q = "aeiouy"; *q; q++) {
+ // Use a variable to work around bug in gcc 2.0
+ char c = cmupper(*q);
+ init_two_char_letter(*p, *q, *p, c);
+ }
+ for (p = "/l/o~n,coeaeij"; *p; p += 2) {
+ // Use variables to work around bug in gcc 2.0
+ char c0 = cmupper(p[0]);
+ char c1 = cmupper(p[1]);
+ init_two_char_letter(p[0], p[1], c0, c1);
+ }
+ init_two_char_letter('v', 's', 'v', 'S', "s");
+ init_two_char_letter('v', 'z', 'v', 'Z', "z");
+ init_two_char_letter('o', 'a', 'o', 'A', "a");
+ init_two_char_letter('T', 'p', 'T', 'P', THORN_SORT_KEY);
+ init_two_char_letter('-', 'd', '-', 'D');
+
+ store_token("\\(ss", TOKEN_LOWER, 0, "SS");
+ store_token("\\[ss]", TOKEN_LOWER, 0, "SS");
+
+ store_token("\\(Sd", TOKEN_LOWER, "d", "\\(-D");
+ store_token("\\[Sd]", TOKEN_LOWER, "d", "\\[-D]");
+ store_token("\\(hy", TOKEN_HYPHEN);
+ store_token("\\[hy]", TOKEN_HYPHEN);
+ store_token("\\(en", TOKEN_RANGE_SEP);
+ store_token("\\[en]", TOKEN_RANGE_SEP);
+}
+
+static void init_strings()
+{
+ char buf[6];
+ buf[0] = '\\';
+ buf[1] = '*';
+ for (const char *p = "'`^^,:~v_o./;"; *p; p++) {
+ buf[2] = *p;
+ buf[3] = '\0';
+ store_token(strsave(buf), TOKEN_ACCENT);
+ buf[2] = '[';
+ buf[3] = *p;
+ buf[4] = ']';
+ buf[5] = '\0';
+ store_token(strsave(buf), TOKEN_ACCENT);
+ }
+
+ // -ms special letters
+ store_letter("\\*(th", "\\*(Th", THORN_SORT_KEY);
+ store_letter("\\*[th]", "\\*[Th]", THORN_SORT_KEY);
+ store_letter("\\*(d-", "\\*(D-");
+ store_letter("\\*[d-]", "\\*[D-]");
+ store_letter("\\*(ae", "\\*(Ae", "ae");
+ store_letter("\\*[ae]", "\\*[Ae]", "ae");
+ store_letter("\\*(oe", "\\*(Oe", "oe");
+ store_letter("\\*[oe]", "\\*[Oe]", "oe");
+
+ store_token("\\*3", TOKEN_LOWER, "y", "Y");
+ store_token("\\*8", TOKEN_LOWER, "ss", "SS");
+ store_token("\\*q", TOKEN_LOWER, "o", "O");
+}
+
+struct token_initer {
+ token_initer();
+};
+
+static token_initer the_token_initer;
+
+token_initer::token_initer()
+{
+ init_ascii();
+ init_latin1();
+ init_special_chars();
+ init_strings();
+ default_token_info.set(TOKEN_OTHER);
+}
diff --git a/src/preproc/refer/token.h b/src/preproc/refer/token.h
new file mode 100644
index 00000000..6da430d6
--- /dev/null
+++ b/src/preproc/refer/token.h
@@ -0,0 +1,88 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+enum token_type {
+ TOKEN_OTHER,
+ TOKEN_UPPER,
+ TOKEN_LOWER,
+ TOKEN_ACCENT,
+ TOKEN_PUNCT,
+ TOKEN_HYPHEN,
+ TOKEN_RANGE_SEP
+};
+
+class token_info {
+private:
+ token_type type;
+ const char *sort_key;
+ const char *other_case;
+public:
+ token_info();
+ void set(token_type, const char *sk = 0, const char *oc = 0);
+ void lower_case(const char *start, const char *end, string &result) const;
+ void upper_case(const char *start, const char *end, string &result) const;
+ void sortify(const char *start, const char *end, string &result) const;
+ int sortify_non_empty(const char *start, const char *end) const;
+ int is_upper() const;
+ int is_lower() const;
+ int is_accent() const;
+ int is_other() const;
+ int is_punct() const;
+ int is_hyphen() const;
+ int is_range_sep() const;
+};
+
+inline int token_info::is_upper() const
+{
+ return type == TOKEN_UPPER;
+}
+
+inline int token_info::is_lower() const
+{
+ return type == TOKEN_LOWER;
+}
+
+inline int token_info::is_accent() const
+{
+ return type == TOKEN_ACCENT;
+}
+
+inline int token_info::is_other() const
+{
+ return type == TOKEN_OTHER;
+}
+
+inline int token_info::is_punct() const
+{
+ return type == TOKEN_PUNCT;
+}
+
+inline int token_info::is_hyphen() const
+{
+ return type == TOKEN_HYPHEN;
+}
+
+inline int token_info::is_range_sep() const
+{
+ return type == TOKEN_RANGE_SEP;
+}
+
+int get_token(const char **ptr, const char *end);
+const token_info *lookup_token(const char *start, const char *end);
diff --git a/src/preproc/soelim/Makefile.sub b/src/preproc/soelim/Makefile.sub
new file mode 100644
index 00000000..77007e25
--- /dev/null
+++ b/src/preproc/soelim/Makefile.sub
@@ -0,0 +1,6 @@
+PROG=soelim
+MAN1=soelim.n
+XLIBS=$(LIBGROFF)
+OBJS=soelim.o
+CCSRCS=$(srcdir)/soelim.cc
+NAMEPREFIX=$(g)
diff --git a/src/preproc/soelim/TODO b/src/preproc/soelim/TODO
new file mode 100644
index 00000000..f2a3924e
--- /dev/null
+++ b/src/preproc/soelim/TODO
@@ -0,0 +1 @@
+Understand .pso.
diff --git a/src/preproc/soelim/soelim.cc b/src/preproc/soelim/soelim.cc
new file mode 100644
index 00000000..571f7345
--- /dev/null
+++ b/src/preproc/soelim/soelim.cc
@@ -0,0 +1,337 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+#include "stringclass.h"
+
+static int include_list_length;
+static char **include_list;
+
+int compatible_flag = 0;
+
+extern int interpret_lf_args(const char *);
+
+int do_file(const char *filename);
+
+
+static void
+include_path_append(char *path)
+{
+ ++include_list_length;
+ size_t nbytes = include_list_length * sizeof(char *);
+ if (include_list)
+ include_list = (char **)realloc((void *)include_list, nbytes);
+ else
+ include_list = (char **)malloc(nbytes);
+ if (include_list == NULL)
+ {
+ fprintf(stderr, "%s: out of memory\n", program_name);
+ exit(2);
+ }
+ include_list[include_list_length - 1] = path;
+}
+
+
+void usage()
+{
+ fprintf(stderr, "usage: %s [ -vC ] [ -I file ] [ files ]\n", program_name);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ include_path_append(".");
+ int opt;
+ while ((opt = getopt(argc, argv, "CI:v")) != EOF)
+ switch (opt) {
+ case 'v':
+ {
+ extern const char *Version_string;
+ fprintf(stderr, "GNU soelim version %s\n", Version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'C':
+ compatible_flag = 1;
+ break;
+ case 'I':
+ include_path_append(optarg);
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ }
+ int nbad = 0;
+ if (optind >= argc)
+ nbad += !do_file("-");
+ else
+ for (int i = optind; i < argc; i++)
+ nbad += !do_file(argv[i]);
+ if (ferror(stdout) || fflush(stdout) < 0)
+ fatal("output error");
+ return nbad != 0;
+}
+
+void set_location()
+{
+ printf(".lf %d %s\n", current_lineno, current_filename);
+}
+
+void do_so(const char *line)
+{
+ const char *p = line;
+ while (*p == ' ')
+ p++;
+ string filename;
+ int success = 1;
+ for (const char *q = p;
+ success && *q != '\0' && *q != '\n' && *q != ' ';
+ q++)
+ if (*q == '\\') {
+ switch (*++q) {
+ case 'e':
+ case '\\':
+ filename += '\\';
+ break;
+ case ' ':
+ filename += ' ';
+ break;
+ default:
+ success = 0;
+ break;
+ }
+ }
+ else
+ filename += char(*q);
+ if (success && filename.length() > 0) {
+ filename += '\0';
+ const char *fn = current_filename;
+ int ln = current_lineno;
+ current_lineno--;
+ if (do_file(filename.contents())) {
+ current_filename = fn;
+ current_lineno = ln;
+ set_location();
+ return;
+ }
+ current_lineno++;
+ }
+ fputs(".so", stdout);
+ fputs(line, stdout);
+}
+
+int do_file(const char *filename)
+{
+ FILE *fp;
+ string whole_filename;
+ if (strcmp(filename, "-") == 0) {
+ fp = stdin;
+ whole_filename = filename;
+ whole_filename += '\0';
+ }
+ else if (filename[0] == '/') {
+ whole_filename = filename;
+ whole_filename += '\0';
+ errno = 0;
+ fp = fopen(filename, "r");
+ if (fp == 0) {
+ error("can't open `%1': %2", filename, strerror(errno));
+ return 0;
+ }
+ }
+ else {
+ size_t j;
+ for (j = 0; j < include_list_length; ++j)
+ {
+ char *path = include_list[j];
+ if (0 == strcmp(path, "."))
+ whole_filename = filename;
+ else
+ whole_filename = string(path) + "/" + filename;
+ whole_filename += '\0';
+ errno = 0;
+ fp = fopen(whole_filename.contents(), "r");
+ if (fp != 0)
+ break;
+ if (errno != ENOENT) {
+ error("can't open `%1': %2",
+ whole_filename.contents(), strerror(errno));
+ return 0;
+ }
+ }
+ if (j >= include_list_length)
+ {
+ errno = ENOENT;
+ error("can't open `%1': %2", filename, strerror(errno));
+ return 0;
+ }
+ }
+ current_filename = whole_filename.contents();
+ current_lineno = 1;
+ set_location();
+ enum { START, MIDDLE, HAD_DOT, HAD_s, HAD_so, HAD_l, HAD_lf } state = START;
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ switch (state) {
+ case START:
+ if (c == '.')
+ state = HAD_DOT;
+ else {
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case MIDDLE:
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ break;
+ case HAD_DOT:
+ if (c == 's')
+ state = HAD_s;
+ else if (c == 'l')
+ state = HAD_l;
+ else {
+ putchar('.');
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case HAD_s:
+ if (c == 'o')
+ state = HAD_so;
+ else {
+ putchar('.');
+ putchar('s');
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case HAD_so:
+ if (c == ' ' || c == '\n' || compatible_flag) {
+ string line;
+ for (; c != EOF && c != '\n'; c = getc(fp))
+ line += c;
+ current_lineno++;
+ line += '\n';
+ line += '\0';
+ do_so(line.contents());
+ state = START;
+ }
+ else {
+ fputs(".so", stdout);
+ putchar(c);
+ state = MIDDLE;
+ }
+ break;
+ case HAD_l:
+ if (c == 'f')
+ state = HAD_lf;
+ else {
+ putchar('.');
+ putchar('l');
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case HAD_lf:
+ if (c == ' ' || c == '\n' || compatible_flag) {
+ string line;
+ for (; c != EOF && c != '\n'; c = getc(fp))
+ line += c;
+ current_lineno++;
+ line += '\n';
+ line += '\0';
+ interpret_lf_args(line.contents());
+ printf(".lf%s", line.contents());
+ state = START;
+ }
+ else {
+ fputs(".lf", stdout);
+ putchar(c);
+ state = MIDDLE;
+ }
+ break;
+ default:
+ assert(0);
+ }
+ }
+ switch (state) {
+ case HAD_DOT:
+ fputs(".\n", stdout);
+ break;
+ case HAD_l:
+ fputs(".l\n", stdout);
+ break;
+ case HAD_s:
+ fputs(".s\n", stdout);
+ break;
+ case HAD_lf:
+ fputs(".lf\n", stdout);
+ break;
+ case HAD_so:
+ fputs(".so\n", stdout);
+ break;
+ case MIDDLE:
+ putc('\n', stdout);
+ break;
+ case START:
+ break;
+ }
+ if (fp != stdin)
+ fclose(fp);
+ current_filename = 0;
+ return 1;
+}
diff --git a/src/preproc/soelim/soelim.man b/src/preproc/soelim/soelim.man
new file mode 100644
index 00000000..7026f3ee
--- /dev/null
+++ b/src/preproc/soelim/soelim.man
@@ -0,0 +1,72 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1999 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.TH @G@SOELIM @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+@g@soelim \- interpret .so requests in groff input
+.SH SYNOPSIS
+.B @g@soelim
+[
+.B \-Cv
+]
+[
+.BI \-I dir
+]
+[
+.IR files \|.\|.\|.\|
+]
+.SH DESCRIPTION
+.B @g@soelim
+reads
+.I files
+and replaces lines of the form
+.IP
+.BI .so\ file
+.LP
+by the contents of
+.IR file .
+It is useful if files included with
+.B so
+need to be preprocessed.
+Normally,
+.B @g@soelim
+should be invoked with the
+.B \-s
+option of
+.BR groff .
+.SH OPTIONS
+.TP
+.B \-C
+Recognize
+.B .so
+even when followed by a character other than space or newline.
+.TP
+.BI \-I dir
+This option may be used to specify a directory to search for
+files (both those on the command line and those named in
+.B \&.so
+lines).
+The current directory is always searched first.
+This option may be specified more than once,
+the directories will be searched in the order specified.
+No directory search is performed for files specified using an absolute path.
+.TP
+.B \-v
+Print the version number.
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@)
diff --git a/src/preproc/tbl/Makefile.sub b/src/preproc/tbl/Makefile.sub
new file mode 100644
index 00000000..224baffc
--- /dev/null
+++ b/src/preproc/tbl/Makefile.sub
@@ -0,0 +1,12 @@
+PROG=tbl
+MAN1=tbl.n
+XLIBS=$(LIBGROFF)
+OBJS=\
+ main.o \
+ table.o
+CCSRCS=\
+ $(srcdir)/main.cc \
+ $(srcdir)/table.cc
+HDRS=\
+ $(srcdir)/table.h
+NAMEPREFIX=$(g)
diff --git a/src/preproc/tbl/main.cc b/src/preproc/tbl/main.cc
new file mode 100644
index 00000000..8a559e8d
--- /dev/null
+++ b/src/preproc/tbl/main.cc
@@ -0,0 +1,1513 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "table.h"
+
+#define MAX_POINT_SIZE 99
+#define MAX_VERTICAL_SPACING 72
+
+static int compatible_flag = 0;
+
+class table_input {
+ FILE *fp;
+ enum { START, MIDDLE, REREAD_T, REREAD_TE, REREAD_E, END, ERROR } state;
+ string unget_stack;
+public:
+ table_input(FILE *);
+ int get();
+ int ended() { return unget_stack.empty() && state == END; }
+ void unget(char);
+};
+
+table_input::table_input(FILE *p)
+: fp(p), state(START)
+{
+}
+
+void table_input::unget(char c)
+{
+ assert(c != '\0');
+ unget_stack += c;
+ if (c == '\n')
+ current_lineno--;
+}
+
+int table_input::get()
+{
+ int len = unget_stack.length();
+ if (len != 0) {
+ unsigned char c = unget_stack[len - 1];
+ unget_stack.set_length(len - 1);
+ if (c == '\n')
+ current_lineno++;
+ return c;
+ }
+ int c;
+ for (;;) {
+ switch (state) {
+ case START:
+ if ((c = getc(fp)) == '.') {
+ if ((c = getc(fp)) == 'T') {
+ if ((c = getc(fp)) == 'E') {
+ if (compatible_flag) {
+ state = END;
+ return EOF;
+ }
+ else {
+ c = getc(fp);
+ if (c != EOF)
+ ungetc(c, fp);
+ if (c == EOF || c == ' ' || c == '\n') {
+ state = END;
+ return EOF;
+ }
+ state = REREAD_TE;
+ return '.';
+ }
+ }
+ else {
+ if (c != EOF)
+ ungetc(c, fp);
+ state = REREAD_T;
+ return '.';
+ }
+ }
+ else {
+ if (c != EOF)
+ ungetc(c, fp);
+ state = MIDDLE;
+ return '.';
+ }
+ }
+ else if (c == EOF) {
+ state = ERROR;
+ return EOF;
+ }
+ else {
+ if (c == '\n')
+ current_lineno++;
+ else {
+ state = MIDDLE;
+ if (c == '\0') {
+ error("illegal input character code 0");
+ break;
+ }
+ }
+ return c;
+ }
+ break;
+ case MIDDLE:
+ // handle line continuation
+ if ((c = getc(fp)) == '\\') {
+ c = getc(fp);
+ if (c == '\n')
+ c = getc(fp); // perhaps state ought to be START now
+ else {
+ if (c != EOF)
+ ungetc(c, fp);
+ c = '\\';
+ }
+ }
+ if (c == EOF) {
+ state = ERROR;
+ return EOF;
+ }
+ else {
+ if (c == '\n') {
+ state = START;
+ current_lineno++;
+ }
+ else if (c == '\0') {
+ error("illegal input character code 0");
+ break;
+ }
+ return c;
+ }
+ case REREAD_T:
+ state = MIDDLE;
+ return 'T';
+ case REREAD_TE:
+ state = REREAD_E;
+ return 'T';
+ case REREAD_E:
+ state = MIDDLE;
+ return 'E';
+ case END:
+ case ERROR:
+ return EOF;
+ }
+ }
+}
+
+void process_input_file(FILE *);
+void process_table(table_input &in);
+
+void process_input_file(FILE *fp)
+{
+ enum { START, MIDDLE, HAD_DOT, HAD_T, HAD_TS, HAD_l, HAD_lf } state;
+ state = START;
+ int c;
+ while ((c = getc(fp)) != EOF)
+ switch (state) {
+ case START:
+ if (c == '.')
+ state = HAD_DOT;
+ else {
+ if (c == '\n')
+ current_lineno++;
+ else
+ state = MIDDLE;
+ putchar(c);
+ }
+ break;
+ case MIDDLE:
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ putchar(c);
+ break;
+ case HAD_DOT:
+ if (c == 'T')
+ state = HAD_T;
+ else if (c == 'l')
+ state = HAD_l;
+ else {
+ putchar('.');
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case HAD_T:
+ if (c == 'S')
+ state = HAD_TS;
+ else {
+ putchar('.');
+ putchar('T');
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case HAD_TS:
+ if (c == ' ' || c == '\n' || compatible_flag) {
+ putchar('.');
+ putchar('T');
+ putchar('S');
+ while (c != '\n') {
+ if (c == EOF) {
+ error("end of file at beginning of table");
+ return;
+ }
+ putchar(c);
+ c = getc(fp);
+ }
+ putchar('\n');
+ printf(".if '\\*(.T'html' \\X(table-start(\n");
+ current_lineno++;
+ {
+ table_input input(fp);
+ process_table(input);
+ set_troff_location(current_filename, current_lineno);
+ if (input.ended()) {
+ printf(".if '\\*(.T'html' \\X(table-end(\n");
+ fputs(".TE", stdout);
+ while ((c = getc(fp)) != '\n') {
+ if (c == EOF) {
+ putchar('\n');
+ return;
+ }
+ putchar(c);
+ }
+ putchar('\n');
+ current_lineno++;
+ }
+ }
+ state = START;
+ }
+ else {
+ fputs(".TS", stdout);
+ putchar(c);
+ state = MIDDLE;
+ }
+ break;
+ case HAD_l:
+ if (c == 'f')
+ state = HAD_lf;
+ else {
+ putchar('.');
+ putchar('l');
+ putchar(c);
+ if (c == '\n') {
+ current_lineno++;
+ state = START;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case HAD_lf:
+ if (c == ' ' || c == '\n' || compatible_flag) {
+ string line;
+ while (c != EOF) {
+ line += c;
+ if (c == '\n') {
+ current_lineno++;
+ break;
+ }
+ c = getc(fp);
+ }
+ line += '\0';
+ interpret_lf_args(line.contents());
+ printf(".lf%s", line.contents());
+ state = START;
+ }
+ else {
+ fputs(".lf", stdout);
+ putchar(c);
+ state = MIDDLE;
+ }
+ break;
+ default:
+ assert(0);
+ }
+ switch(state) {
+ case START:
+ break;
+ case MIDDLE:
+ putchar('\n');
+ break;
+ case HAD_DOT:
+ fputs(".\n", stdout);
+ break;
+ case HAD_l:
+ fputs(".l\n", stdout);
+ break;
+ case HAD_T:
+ fputs(".T\n", stdout);
+ break;
+ case HAD_lf:
+ fputs(".lf\n", stdout);
+ break;
+ case HAD_TS:
+ fputs(".TS\n", stdout);
+ break;
+ }
+ if (fp != stdin)
+ fclose(fp);
+}
+
+struct options {
+ unsigned flags;
+ int linesize;
+ char delim[2];
+ char tab_char;
+ char decimal_point_char;
+
+ options();
+};
+
+options::options()
+: flags(0), linesize(0), tab_char('\t'), decimal_point_char('.')
+{
+ delim[0] = delim[1] = '\0';
+}
+
+// Return non-zero if p and q are the same ignoring case.
+
+int strieq(const char *p, const char *q)
+{
+ for (; cmlower(*p) == cmlower(*q); p++, q++)
+ if (*p == '\0')
+ return 1;
+ return 0;
+}
+
+// return 0 if we should give up in this table
+
+options *process_options(table_input &in)
+{
+ options *opt = new options;
+ string line;
+ int level = 0;
+ for (;;) {
+ int c = in.get();
+ if (c == EOF) {
+ int i = line.length();
+ while (--i >= 0)
+ in.unget(line[i]);
+ return opt;
+ }
+ if (c == '\n') {
+ in.unget(c);
+ int i = line.length();
+ while (--i >= 0)
+ in.unget(line[i]);
+ return opt;
+ }
+ else if (c == '(')
+ level++;
+ else if (c == ')')
+ level--;
+ else if (c == ';' && level == 0) {
+ line += '\0';
+ break;
+ }
+ line += c;
+ }
+ if (line.empty())
+ return opt;
+ char *p = &line[0];
+ for (;;) {
+ while (!csalpha(*p) && *p != '\0')
+ p++;
+ if (*p == '\0')
+ break;
+ char *q = p;
+ while (csalpha(*q))
+ q++;
+ char *arg = 0;
+ if (*q != '(' && *q != '\0')
+ *q++ = '\0';
+ while (csspace(*q))
+ q++;
+ if (*q == '(') {
+ *q++ = '\0';
+ arg = q;
+ while (*q != ')' && *q != '\0')
+ q++;
+ if (*q == '\0')
+ error("missing `)'");
+ else
+ *q++ = '\0';
+ }
+ if (*p == '\0') {
+ if (arg)
+ error("argument without option");
+ }
+ else if (strieq(p, "tab")) {
+ if (!arg)
+ error("`tab' option requires argument in parentheses");
+ else {
+ if (arg[0] == '\0' || arg[1] != '\0')
+ error("argument to `tab' option must be a single character");
+ else
+ opt->tab_char = arg[0];
+ }
+ }
+ else if (strieq(p, "linesize")) {
+ if (!arg)
+ error("`linesize' option requires argument in parentheses");
+ else {
+ if (sscanf(arg, "%d", &opt->linesize) != 1)
+ error("bad linesize `%s'", arg);
+ else if (opt->linesize <= 0) {
+ error("linesize must be positive");
+ opt->linesize = 0;
+ }
+ }
+ }
+ else if (strieq(p, "delim")) {
+ if (!arg)
+ error("`delim' option requires argument in parentheses");
+ else if (arg[0] == '\0' || arg[1] == '\0' || arg[2] != '\0')
+ error("argument to `delim' option must be two characters");
+ else {
+ opt->delim[0] = arg[0];
+ opt->delim[1] = arg[1];
+ }
+ }
+ else if (strieq(p, "center") || strieq(p, "centre")) {
+ if (arg)
+ error("`center' option does not take a argument");
+ opt->flags |= table::CENTER;
+ }
+ else if (strieq(p, "expand")) {
+ if (arg)
+ error("`expand' option does not take a argument");
+ opt->flags |= table::EXPAND;
+ }
+ else if (strieq(p, "box") || strieq(p, "frame")) {
+ if (arg)
+ error("`box' option does not take a argument");
+ opt->flags |= table::BOX;
+ }
+ else if (strieq(p, "doublebox") || strieq(p, "doubleframe")) {
+ if (arg)
+ error("`doublebox' option does not take a argument");
+ opt->flags |= table::DOUBLEBOX;
+ }
+ else if (strieq(p, "allbox")) {
+ if (arg)
+ error("`allbox' option does not take a argument");
+ opt->flags |= table::ALLBOX;
+ }
+ else if (strieq(p, "nokeep")) {
+ if (arg)
+ error("`nokeep' option does not take a argument");
+ opt->flags |= table::NOKEEP;
+ }
+ else if (strieq(p, "decimalpoint")) {
+ if (!arg)
+ error("`decimalpoint' option requires argument in parentheses");
+ else {
+ if (arg[0] == '\0' || arg[1] != '\0')
+ error("argument to `decimalpoint' option must be a single character");
+ else
+ opt->decimal_point_char = arg[0];
+ }
+ }
+ else {
+ error("unrecognised global option `%1'", p);
+ // delete opt;
+ // return 0;
+ }
+ p = q;
+ }
+ return opt;
+}
+
+entry_modifier::entry_modifier()
+: vertical_alignment(CENTER), zero_width(0), stagger(0)
+{
+ vertical_spacing.inc = vertical_spacing.val = 0;
+ point_size.inc = point_size.val = 0;
+}
+
+entry_modifier::~entry_modifier()
+{
+}
+
+entry_format::entry_format() : type(FORMAT_LEFT)
+{
+}
+
+entry_format::entry_format(format_type t) : type(t)
+{
+}
+
+void entry_format::debug_print() const
+{
+ switch (type) {
+ case FORMAT_LEFT:
+ putc('l', stderr);
+ break;
+ case FORMAT_CENTER:
+ putc('c', stderr);
+ break;
+ case FORMAT_RIGHT:
+ putc('r', stderr);
+ break;
+ case FORMAT_NUMERIC:
+ putc('n', stderr);
+ break;
+ case FORMAT_ALPHABETIC:
+ putc('a', stderr);
+ break;
+ case FORMAT_SPAN:
+ putc('s', stderr);
+ break;
+ case FORMAT_VSPAN:
+ putc('^', stderr);
+ break;
+ case FORMAT_HLINE:
+ putc('_', stderr);
+ break;
+ case FORMAT_DOUBLE_HLINE:
+ putc('=', stderr);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ if (point_size.val != 0) {
+ putc('p', stderr);
+ if (point_size.inc > 0)
+ putc('+', stderr);
+ else if (point_size.inc < 0)
+ putc('-', stderr);
+ fprintf(stderr, "%d ", point_size.val);
+ }
+ if (vertical_spacing.val != 0) {
+ putc('v', stderr);
+ if (vertical_spacing.inc > 0)
+ putc('+', stderr);
+ else if (vertical_spacing.inc < 0)
+ putc('-', stderr);
+ fprintf(stderr, "%d ", vertical_spacing.val);
+ }
+ if (!font.empty()) {
+ putc('f', stderr);
+ put_string(font, stderr);
+ putc(' ', stderr);
+ }
+ switch (vertical_alignment) {
+ case entry_modifier::CENTER:
+ break;
+ case entry_modifier::TOP:
+ putc('t', stderr);
+ break;
+ case entry_modifier::BOTTOM:
+ putc('d', stderr);
+ break;
+ }
+ if (zero_width)
+ putc('z', stderr);
+ if (stagger)
+ putc('u', stderr);
+}
+
+struct format {
+ int nrows;
+ int ncolumns;
+ int *separation;
+ string *width;
+ char *equal;
+ entry_format **entry;
+ char **vline;
+
+ format(int nr, int nc);
+ ~format();
+ void add_rows(int n);
+};
+
+format::format(int nr, int nc) : nrows(nr), ncolumns(nc)
+{
+ int i;
+ separation = ncolumns > 1 ? new int[ncolumns - 1] : 0;
+ for (i = 0; i < ncolumns-1; i++)
+ separation[i] = -1;
+ width = new string[ncolumns];
+ equal = new char[ncolumns];
+ for (i = 0; i < ncolumns; i++)
+ equal[i] = 0;
+ entry = new entry_format *[nrows];
+ for (i = 0; i < nrows; i++)
+ entry[i] = new entry_format[ncolumns];
+ vline = new char*[nrows];
+ for (i = 0; i < nrows; i++) {
+ vline[i] = new char[ncolumns+1];
+ for (int j = 0; j < ncolumns+1; j++)
+ vline[i][j] = 0;
+ }
+}
+
+void format::add_rows(int n)
+{
+ int i;
+ char **old_vline = vline;
+ vline = new char*[nrows + n];
+ for (i = 0; i < nrows; i++)
+ vline[i] = old_vline[i];
+ a_delete old_vline;
+ for (i = 0; i < n; i++) {
+ vline[nrows + i] = new char[ncolumns + 1];
+ for (int j = 0; j < ncolumns + 1; j++)
+ vline[nrows + i][j] = 0;
+ }
+ entry_format **old_entry = entry;
+ entry = new entry_format *[nrows + n];
+ for (i = 0; i < nrows; i++)
+ entry[i] = old_entry[i];
+ a_delete old_entry;
+ for (i = 0; i < n; i++)
+ entry[nrows + i] = new entry_format[ncolumns];
+ nrows += n;
+}
+
+format::~format()
+{
+ a_delete separation;
+ ad_delete(ncolumns) width;
+ a_delete equal;
+ for (int i = 0; i < nrows; i++) {
+ a_delete vline[i];
+ ad_delete(ncolumns) entry[i];
+ }
+ a_delete vline;
+ a_delete entry;
+}
+
+struct input_entry_format : public entry_format {
+ input_entry_format *next;
+ string width;
+ int separation;
+ int vline;
+ int pre_vline;
+ int last_column;
+ int equal;
+ input_entry_format(format_type, input_entry_format * = 0);
+ ~input_entry_format();
+ void debug_print();
+};
+
+input_entry_format::input_entry_format(format_type t, input_entry_format *p)
+: entry_format(t), next(p)
+{
+ separation = -1;
+ last_column = 0;
+ vline = 0;
+ pre_vline = 0;
+ equal = 0;
+}
+
+input_entry_format::~input_entry_format()
+{
+}
+
+void free_input_entry_format_list(input_entry_format *list)
+{
+ while (list) {
+ input_entry_format *tem = list;
+ list = list->next;
+ delete tem;
+ }
+}
+
+void input_entry_format::debug_print()
+{
+ int i;
+ for (i = 0; i < pre_vline; i++)
+ putc('|', stderr);
+ entry_format::debug_print();
+ if (!width.empty()) {
+ putc('w', stderr);
+ putc('(', stderr);
+ put_string(width, stderr);
+ putc(')', stderr);
+ }
+ if (equal)
+ putc('e', stderr);
+ if (separation >= 0)
+ fprintf(stderr, "%d", separation);
+ for (i = 0; i < vline; i++)
+ putc('|', stderr);
+ if (last_column)
+ putc(',', stderr);
+}
+
+// Return zero if we should give up on this table.
+// If this is a continuation format line, current_format will be the current
+// format line.
+
+format *process_format(table_input &in, options *opt,
+ format *current_format = 0)
+{
+ input_entry_format *list = 0;
+ int c = in.get();
+ for (;;) {
+ int pre_vline = 0;
+ int got_format = 0;
+ int got_period = 0;
+ format_type t;
+ for (;;) {
+ if (c == EOF) {
+ error("end of input while processing format");
+ free_input_entry_format_list(list);
+ return 0;
+ }
+ switch (c) {
+ case 'n':
+ case 'N':
+ t = FORMAT_NUMERIC;
+ got_format = 1;
+ break;
+ case 'a':
+ case 'A':
+ got_format = 1;
+ t = FORMAT_ALPHABETIC;
+ break;
+ case 'c':
+ case 'C':
+ got_format = 1;
+ t = FORMAT_CENTER;
+ break;
+ case 'l':
+ case 'L':
+ got_format = 1;
+ t = FORMAT_LEFT;
+ break;
+ case 'r':
+ case 'R':
+ got_format = 1;
+ t = FORMAT_RIGHT;
+ break;
+ case 's':
+ case 'S':
+ got_format = 1;
+ t = FORMAT_SPAN;
+ break;
+ case '^':
+ got_format = 1;
+ t = FORMAT_VSPAN;
+ break;
+ case '_':
+ case '-': // tbl also accepts this
+ got_format = 1;
+ t = FORMAT_HLINE;
+ break;
+ case '=':
+ got_format = 1;
+ t = FORMAT_DOUBLE_HLINE;
+ break;
+ case '.':
+ got_period = 1;
+ break;
+ case '|':
+ pre_vline++;
+ break;
+ case ' ':
+ case '\t':
+ case '\n':
+ break;
+ default:
+ if (c == opt->tab_char)
+ break;
+ error("unrecognised format `%1'", char(c));
+ free_input_entry_format_list(list);
+ return 0;
+ }
+ if (got_period)
+ break;
+ c = in.get();
+ if (got_format)
+ break;
+ }
+ if (got_period)
+ break;
+ list = new input_entry_format(t, list);
+ if (pre_vline)
+ list->pre_vline = pre_vline;
+ int success = 1;
+ do {
+ switch (c) {
+ case 't':
+ case 'T':
+ c = in.get();
+ list->vertical_alignment = entry_modifier::TOP;
+ break;
+ case 'd':
+ case 'D':
+ c = in.get();
+ list->vertical_alignment = entry_modifier::BOTTOM;
+ break;
+ case 'u':
+ case 'U':
+ c = in.get();
+ list->stagger = 1;
+ break;
+ case 'z':
+ case 'Z':
+ c = in.get();
+ list->zero_width = 1;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ int w = 0;
+ do {
+ w = w*10 + (c - '0');
+ c = in.get();
+ } while (c != EOF && csdigit(c));
+ list->separation = w;
+ }
+ break;
+ case 'f':
+ case 'F':
+ do {
+ c = in.get();
+ } while (c == ' ' || c == '\t');
+ if (c == EOF) {
+ error("missing font name");
+ break;
+ }
+ if (c == '(') {
+ for (;;) {
+ c = in.get();
+ if (c == EOF || c == ' ' || c == '\t') {
+ error("missing `)'");
+ break;
+ }
+ if (c == ')') {
+ c = in.get();
+ break;
+ }
+ list->font += char(c);
+ }
+ }
+ else {
+ list->font = c;
+ char cc = c;
+ c = in.get();
+ if (!csdigit(cc)
+ && c != EOF && c != ' ' && c != '\t' && c != '.' && c != '\n') {
+ list->font += char(c);
+ c = in.get();
+ }
+ }
+ break;
+ case 'v':
+ case 'V':
+ c = in.get();
+ list->vertical_spacing.val = 0;
+ list->vertical_spacing.inc = 0;
+ if (c == '+' || c == '-') {
+ list->vertical_spacing.inc = (c == '+' ? 1 : -1);
+ c = in.get();
+ }
+ if (c == EOF || !csdigit(c)) {
+ error("`v' modifier must be followed by number");
+ list->vertical_spacing.inc = 0;
+ }
+ else {
+ do {
+ list->vertical_spacing.val *= 10;
+ list->vertical_spacing.val += c - '0';
+ c = in.get();
+ } while (c != EOF && csdigit(c));
+ }
+ if (list->vertical_spacing.val > MAX_VERTICAL_SPACING
+ || list->vertical_spacing.val < -MAX_VERTICAL_SPACING) {
+ error("unreasonable point size");
+ list->vertical_spacing.val = 0;
+ list->vertical_spacing.inc = 0;
+ }
+ break;
+ case 'p':
+ case 'P':
+ c = in.get();
+ list->point_size.val = 0;
+ list->point_size.inc = 0;
+ if (c == '+' || c == '-') {
+ list->point_size.inc = (c == '+' ? 1 : -1);
+ c = in.get();
+ }
+ if (c == EOF || !csdigit(c)) {
+ error("`p' modifier must be followed by number");
+ list->point_size.inc = 0;
+ }
+ else {
+ do {
+ list->point_size.val *= 10;
+ list->point_size.val += c - '0';
+ c = in.get();
+ } while (c != EOF && csdigit(c));
+ }
+ if (list->point_size.val > MAX_POINT_SIZE
+ || list->point_size.val < -MAX_POINT_SIZE) {
+ error("unreasonable point size");
+ list->point_size.val = 0;
+ list->point_size.inc = 0;
+ }
+ break;
+ case 'w':
+ case 'W':
+ c = in.get();
+ while (c == ' ' || c == '\t')
+ c = in.get();
+ if (c == '(') {
+ list->width = "";
+ c = in.get();
+ while (c != ')') {
+ if (c == EOF || c == '\n') {
+ error("missing `)'");
+ free_input_entry_format_list(list);
+ return 0;
+ }
+ list->width += c;
+ c = in.get();
+ }
+ c = in.get();
+ }
+ else {
+ if (c == '+' || c == '-') {
+ list->width = char(c);
+ c = in.get();
+ }
+ else
+ list->width = "";
+ if (c == EOF || !csdigit(c))
+ error("bad argument for `w' modifier");
+ else {
+ do {
+ list->width += char(c);
+ c = in.get();
+ } while (c != EOF && csdigit(c));
+ }
+ }
+ break;
+ case 'e':
+ case 'E':
+ c = in.get();
+ list->equal++;
+ break;
+ case '|':
+ c = in.get();
+ list->vline++;
+ break;
+ case 'B':
+ case 'b':
+ c = in.get();
+ list->font = "B";
+ break;
+ case 'I':
+ case 'i':
+ c = in.get();
+ list->font = "I";
+ break;
+ case ' ':
+ case '\t':
+ c = in.get();
+ break;
+ default:
+ if (c == opt->tab_char)
+ c = in.get();
+ else
+ success = 0;
+ break;
+ }
+ } while (success);
+ if (list->vline > 2) {
+ list->vline = 2;
+ error("more than 2 vertical bars between key letters");
+ }
+ if (c == '\n' || c == ',') {
+ c = in.get();
+ list->last_column = 1;
+ }
+ }
+ if (c == '.') {
+ do {
+ c = in.get();
+ } while (c == ' ' || c == '\t');
+ if (c != '\n') {
+ error("`.' not last character on line");
+ free_input_entry_format_list(list);
+ return 0;
+ }
+ }
+ if (!list) {
+ error("no format");
+ free_input_entry_format_list(list);
+ return 0;
+ }
+ list->last_column = 1;
+ // now reverse the list so that the first row is at the beginning
+ input_entry_format *rev = 0;
+ while (list != 0) {
+ input_entry_format *tem = list->next;
+ list->next = rev;
+ rev = list;
+ list = tem;
+ }
+ list = rev;
+ input_entry_format *tem;
+
+#if 0
+ for (tem = list; tem; tem = tem->next)
+ tem->debug_print();
+ putc('\n', stderr);
+#endif
+ // compute number of columns and rows
+ int ncolumns = 0;
+ int nrows = 0;
+ int col = 0;
+ for (tem = list; tem; tem = tem->next) {
+ if (tem->last_column) {
+ if (col >= ncolumns)
+ ncolumns = col + 1;
+ col = 0;
+ nrows++;
+ }
+ else
+ col++;
+ }
+ int row;
+ format *f;
+ if (current_format) {
+ if (ncolumns > current_format->ncolumns) {
+ error("cannot increase the number of columns in a continued format");
+ free_input_entry_format_list(list);
+ return 0;
+ }
+ f = current_format;
+ row = f->nrows;
+ f->add_rows(nrows);
+ }
+ else {
+ f = new format(nrows, ncolumns);
+ row = 0;
+ }
+ col = 0;
+ for (tem = list; tem; tem = tem->next) {
+ f->entry[row][col] = *tem;
+ if (col < ncolumns-1) {
+ // use the greatest separation
+ if (tem->separation > f->separation[col]) {
+ if (current_format)
+ error("cannot change column separation in continued format");
+ else
+ f->separation[col] = tem->separation;
+ }
+ }
+ else if (tem->separation >= 0)
+ error("column separation specified for last column");
+ if (tem->equal && !f->equal[col]) {
+ if (current_format)
+ error("cannot change which columns are equal in continued format");
+ else
+ f->equal[col] = 1;
+ }
+ if (!tem->width.empty()) {
+ // use the last width
+ if (!f->width[col].empty() && f->width[col] != tem->width)
+ error("multiple widths for column %1", col+1);
+ f->width[col] = tem->width;
+ }
+ if (tem->pre_vline) {
+ assert(col == 0);
+ f->vline[row][col] = tem->pre_vline;
+ }
+ f->vline[row][col+1] = tem->vline;
+ if (tem->last_column) {
+ row++;
+ col = 0;
+ }
+ else
+ col++;
+ }
+ free_input_entry_format_list(list);
+ for (col = 0; col < ncolumns; col++) {
+ entry_format *e = f->entry[f->nrows-1] + col;
+ if (e->type != FORMAT_HLINE
+ && e->type != FORMAT_DOUBLE_HLINE
+ && e->type != FORMAT_SPAN)
+ break;
+ }
+ if (col >= ncolumns) {
+ error("last row of format is all lines");
+ delete f;
+ return 0;
+ }
+ return f;
+}
+
+table *process_data(table_input &in, format *f, options *opt)
+{
+ char tab_char = opt->tab_char;
+ int ncolumns = f->ncolumns;
+ int current_row = 0;
+ int format_index = 0;
+ int give_up = 0;
+ enum { DATA_INPUT_LINE, TROFF_INPUT_LINE, SINGLE_HLINE, DOUBLE_HLINE } type;
+ table *tbl = new table(ncolumns, opt->flags, opt->linesize,
+ opt->decimal_point_char);
+ if (opt->delim[0] != '\0')
+ tbl->set_delim(opt->delim[0], opt->delim[1]);
+ for (;;) {
+ // first determine what type of line this is
+ int c = in.get();
+ if (c == EOF)
+ break;
+ if (c == '.') {
+ int d = in.get();
+ if (d != EOF && csdigit(d)) {
+ in.unget(d);
+ type = DATA_INPUT_LINE;
+ }
+ else {
+ in.unget(d);
+ type = TROFF_INPUT_LINE;
+ }
+ }
+ else if (c == '_' || c == '=') {
+ int d = in.get();
+ if (d == '\n') {
+ if (c == '_')
+ type = SINGLE_HLINE;
+ else
+ type = DOUBLE_HLINE;
+ }
+ else {
+ in.unget(d);
+ type = DATA_INPUT_LINE;
+ }
+ }
+ else {
+ type = DATA_INPUT_LINE;
+ }
+ switch (type) {
+ case DATA_INPUT_LINE:
+ {
+ string input_entry;
+ if (format_index >= f->nrows)
+ format_index = f->nrows - 1;
+ // A format row that is all lines doesn't use up a data line.
+ while (format_index < f->nrows - 1) {
+ int c;
+ for (c = 0; c < ncolumns; c++) {
+ entry_format *e = f->entry[format_index] + c;
+ if (e->type != FORMAT_HLINE
+ && e->type != FORMAT_DOUBLE_HLINE
+ // Unfortunately tbl treats a span as needing data.
+ // && e->type != FORMAT_SPAN
+ )
+ break;
+ }
+ if (c < ncolumns)
+ break;
+ for (c = 0; c < ncolumns; c++)
+ tbl->add_entry(current_row, c, input_entry,
+ f->entry[format_index] + c, current_filename,
+ current_lineno);
+ tbl->add_vlines(current_row, f->vline[format_index]);
+ format_index++;
+ current_row++;
+ }
+ entry_format *line_format = f->entry[format_index];
+ int col = 0;
+ int row_comment = 0;
+ for (;;) {
+ if (c == tab_char || c == '\n') {
+ int ln = current_lineno;
+ if (c == '\n')
+ --ln;
+ while (col < ncolumns
+ && line_format[col].type == FORMAT_SPAN) {
+ tbl->add_entry(current_row, col, "", &line_format[col],
+ current_filename, ln);
+ col++;
+ }
+ if (c == '\n' && input_entry.length() == 2
+ && input_entry[0] == 'T' && input_entry[1] == '{') {
+ input_entry = "";
+ ln++;
+ enum {
+ START, MIDDLE, GOT_T, GOT_RIGHT_BRACE, GOT_DOT,
+ GOT_l, GOT_lf, END
+ } state = START;
+ while (state != END) {
+ c = in.get();
+ if (c == EOF)
+ break;
+ switch (state) {
+ case START:
+ if (c == 'T')
+ state = GOT_T;
+ else if (c == '.')
+ state = GOT_DOT;
+ else {
+ input_entry += c;
+ if (c != '\n')
+ state = MIDDLE;
+ }
+ break;
+ case GOT_T:
+ if (c == '}')
+ state = GOT_RIGHT_BRACE;
+ else {
+ input_entry += 'T';
+ input_entry += c;
+ state = c == '\n' ? START : MIDDLE;
+ }
+ break;
+ case GOT_DOT:
+ if (c == 'l')
+ state = GOT_l;
+ else {
+ input_entry += '.';
+ input_entry += c;
+ state = c == '\n' ? START : MIDDLE;
+ }
+ break;
+ case GOT_l:
+ if (c == 'f')
+ state = GOT_lf;
+ else {
+ input_entry += ".l";
+ input_entry += c;
+ state = c == '\n' ? START : MIDDLE;
+ }
+ break;
+ case GOT_lf:
+ if (c == ' ' || c == '\n' || compatible_flag) {
+ string args;
+ input_entry += ".lf";
+ while (c != EOF) {
+ args += c;
+ if (c == '\n')
+ break;
+ c = in.get();
+ }
+ args += '\0';
+ interpret_lf_args(args.contents());
+ // remove the '\0'
+ args.set_length(args.length() - 1);
+ input_entry += args;
+ state = START;
+ }
+ else {
+ input_entry += ".lf";
+ input_entry += c;
+ state = MIDDLE;
+ }
+ break;
+ case GOT_RIGHT_BRACE:
+ if (c == '\n' || c == tab_char)
+ state = END;
+ else {
+ input_entry += 'T';
+ input_entry += '}';
+ input_entry += c;
+ state = c == '\n' ? START : MIDDLE;
+ }
+ break;
+ case MIDDLE:
+ if (c == '\n')
+ state = START;
+ input_entry += c;
+ break;
+ case END:
+ default:
+ assert(0);
+ }
+ }
+ if (c == EOF) {
+ error("end of data in middle of text block");
+ give_up = 1;
+ break;
+ }
+ }
+ if (col >= ncolumns) {
+ if (!input_entry.empty()) {
+ if (input_entry.length() >= 2
+ && input_entry[0] == '\\'
+ && input_entry[1] == '"')
+ row_comment = 1;
+ else if (!row_comment) {
+ if (c == '\n')
+ in.unget(c);
+ input_entry += '\0';
+ error("excess data entry `%1' discarded",
+ input_entry.contents());
+ if (c == '\n')
+ (void)in.get();
+ }
+ }
+ }
+ else
+ tbl->add_entry(current_row, col, input_entry,
+ &line_format[col], current_filename, ln);
+ col++;
+ if (c == '\n')
+ break;
+ input_entry = "";
+ }
+ else
+ input_entry += c;
+ c = in.get();
+ if (c == EOF)
+ break;
+ }
+ if (give_up)
+ break;
+ input_entry = "";
+ for (; col < ncolumns; col++)
+ tbl->add_entry(current_row, col, input_entry, &line_format[col],
+ current_filename, current_lineno - 1);
+ tbl->add_vlines(current_row, f->vline[format_index]);
+ current_row++;
+ format_index++;
+ }
+ break;
+ case TROFF_INPUT_LINE:
+ {
+ string line;
+ int ln = current_lineno;
+ for (;;) {
+ line += c;
+ if (c == '\n')
+ break;
+ c = in.get();
+ if (c == EOF) {
+ break;
+ }
+ }
+ tbl->add_text_line(current_row, line, current_filename, ln);
+ if (line.length() >= 4
+ && line[0] == '.' && line[1] == 'T' && line[2] == '&') {
+ format *newf = process_format(in, opt, f);
+ if (newf == 0)
+ give_up = 1;
+ else
+ f = newf;
+ }
+ if (line.length() >= 3
+ && line[0] == '.' && line[1] == 'f' && line[2] == 'f') {
+ line += '\0';
+ interpret_lf_args(line.contents() + 3);
+ }
+ }
+ break;
+ case SINGLE_HLINE:
+ tbl->add_single_hline(current_row);
+ break;
+ case DOUBLE_HLINE:
+ tbl->add_double_hline(current_row);
+ break;
+ default:
+ assert(0);
+ }
+ if (give_up)
+ break;
+ }
+ if (!give_up && current_row == 0) {
+ error("no real data");
+ give_up = 1;
+ }
+ if (give_up) {
+ delete tbl;
+ return 0;
+ }
+ // Do this here rather than at the beginning in case continued formats
+ // change it.
+ int i;
+ for (i = 0; i < ncolumns - 1; i++)
+ if (f->separation[i] >= 0)
+ tbl->set_column_separation(i, f->separation[i]);
+ for (i = 0; i < ncolumns; i++)
+ if (!f->width[i].empty())
+ tbl->set_minimum_width(i, f->width[i]);
+ for (i = 0; i < ncolumns; i++)
+ if (f->equal[i])
+ tbl->set_equal_column(i);
+ return tbl;
+}
+
+void process_table(table_input &in)
+{
+ int c;
+ options *opt = 0;
+ format *form = 0;
+ table *tbl = 0;
+ if ((opt = process_options(in)) != 0
+ && (form = process_format(in, opt)) != 0
+ && (tbl = process_data(in, form, opt)) != 0) {
+ tbl->print();
+ delete tbl;
+ }
+ else {
+ error("giving up on this table");
+ while ((c = in.get()) != EOF)
+ ;
+ }
+ delete opt;
+ delete form;
+ if (!in.ended())
+ error("premature end of file");
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [ -vC ] [ files... ]\n", program_name);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int opt;
+ while ((opt = getopt(argc, argv, "vCT:")) != EOF)
+ switch (opt) {
+ case 'C':
+ compatible_flag = 1;
+ break;
+ case 'v':
+ {
+ extern const char *Version_string;
+ fprintf(stderr, "GNU tbl version %s\n", Version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'T':
+ // I'm sick of getting bug reports from IRIX users
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ }
+ printf(".if !\\n(.g .ab GNU tbl requires GNU troff.\n"
+ ".if !dTS .ds TS\n"
+ ".if !dTE .ds TE\n");
+ if (argc > optind) {
+ for (int i = optind; i < argc; i++)
+ if (argv[i][0] == '-' && argv[i][1] == '\0') {
+ current_filename = "-";
+ current_lineno = 1;
+ printf(".lf 1 -\n");
+ process_input_file(stdin);
+ }
+ else {
+ errno = 0;
+ FILE *fp = fopen(argv[i], "r");
+ if (fp == 0) {
+ current_lineno = -1;
+ error("can't open `%1': %2", argv[i], strerror(errno));
+ }
+ else {
+ current_lineno = 1;
+ current_filename = argv[i];
+ printf(".lf 1 %s\n", current_filename);
+ process_input_file(fp);
+ }
+ }
+ }
+ else {
+ current_filename = "-";
+ current_lineno = 1;
+ printf(".lf 1 -\n");
+ process_input_file(stdin);
+ }
+ if (ferror(stdout) || fflush(stdout) < 0)
+ fatal("output error");
+ return 0;
+}
+
diff --git a/src/preproc/tbl/table.cc b/src/preproc/tbl/table.cc
new file mode 100644
index 00000000..354c7d88
--- /dev/null
+++ b/src/preproc/tbl/table.cc
@@ -0,0 +1,2778 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "table.h"
+
+#define BAR_HEIGHT ".25m"
+#define DOUBLE_LINE_SEP "2p"
+#define HALF_DOUBLE_LINE_SEP "1p"
+#define LINE_SEP "2p"
+#define BODY_DEPTH ".25m"
+
+const int DEFAULT_COLUMN_SEPARATION = 3;
+
+#define DELIMITER_CHAR "\\[tbl]"
+#define PREFIX "3"
+#define SEPARATION_FACTOR_REG PREFIX "sep"
+#define BOTTOM_REG PREFIX "bot"
+#define RESET_MACRO_NAME PREFIX "init"
+#define LINESIZE_REG PREFIX "lps"
+#define TOP_REG PREFIX "top"
+#define CURRENT_ROW_REG PREFIX "crow"
+#define LAST_PASSED_ROW_REG PREFIX "passed"
+#define TRANSPARENT_STRING_NAME PREFIX "trans"
+#define QUOTE_STRING_NAME PREFIX "quote"
+#define SECTION_DIVERSION_NAME PREFIX "section"
+#define SECTION_DIVERSION_FLAG_REG PREFIX "sflag"
+#define SAVED_VERTICAL_POS_REG PREFIX "vert"
+#define NEED_BOTTOM_RULE_REG PREFIX "brule"
+#define KEEP_MACRO_NAME PREFIX "keep"
+#define RELEASE_MACRO_NAME PREFIX "release"
+#define SAVED_FONT_REG PREFIX "fnt"
+#define SAVED_SIZE_REG PREFIX "sz"
+#define SAVED_FILL_REG PREFIX "fll"
+#define SAVED_INDENT_REG PREFIX "ind"
+#define SAVED_CENTER_REG PREFIX "cent"
+#define TABLE_DIVERSION_NAME PREFIX "table"
+#define TABLE_DIVERSION_FLAG_REG PREFIX "tflag"
+#define TABLE_KEEP_MACRO_NAME PREFIX "tkeep"
+#define TABLE_RELEASE_MACRO_NAME PREFIX "trelease"
+#define NEEDED_REG PREFIX "needed"
+#define REPEATED_MARK_MACRO PREFIX "rmk"
+#define REPEATED_VPT_MACRO PREFIX "rvpt"
+#define SUPPRESS_BOTTOM_REG PREFIX "supbot"
+#define SAVED_DN_REG PREFIX "dn"
+
+// this must be one character
+#define COMPATIBLE_REG PREFIX "c"
+
+#define BLOCK_WIDTH_PREFIX PREFIX "tbw"
+#define BLOCK_DIVERSION_PREFIX PREFIX "tbd"
+#define BLOCK_HEIGHT_PREFIX PREFIX "tbh"
+#define SPAN_WIDTH_PREFIX PREFIX "w"
+#define SPAN_LEFT_NUMERIC_WIDTH_PREFIX PREFIX "lnw"
+#define SPAN_RIGHT_NUMERIC_WIDTH_PREFIX PREFIX "rnw"
+#define SPAN_ALPHABETIC_WIDTH_PREFIX PREFIX "aw"
+#define COLUMN_SEPARATION_PREFIX PREFIX "cs"
+#define ROW_START_PREFIX PREFIX "rs"
+#define COLUMN_START_PREFIX PREFIX "cl"
+#define COLUMN_END_PREFIX PREFIX "ce"
+#define COLUMN_DIVIDE_PREFIX PREFIX "cd"
+#define ROW_TOP_PREFIX PREFIX "rt"
+
+string block_width_reg(int r, int c);
+string block_diversion_name(int r, int c);
+string block_height_reg(int r, int c);
+string span_width_reg(int start_col, int end_col);
+string span_left_numeric_width_reg(int start_col, int end_col);
+string span_right_numeric_width_reg(int start_col, int end_col);
+string span_alphabetic_width_reg(int start_col, int end_col);
+string column_separation_reg(int col);
+string row_start_reg(int r);
+string column_start_reg(int c);
+string column_end_reg(int c);
+string column_divide_reg(int c);
+string row_top_reg(int r);
+
+void set_inline_modifier(const entry_modifier *);
+void restore_inline_modifier(const entry_modifier *m);
+void set_modifier(const entry_modifier *);
+int find_decimal_point(const char *s, char decimal_point_char,
+ const char *delim);
+
+string an_empty_string;
+int location_force_filename = 0;
+
+void printfs(const char *,
+ const string &arg1 = an_empty_string,
+ const string &arg2 = an_empty_string,
+ const string &arg3 = an_empty_string,
+ const string &arg4 = an_empty_string,
+ const string &arg5 = an_empty_string);
+
+void prints(const string &);
+
+inline void prints(char c)
+{
+ putchar(c);
+}
+
+inline void prints(const char *s)
+{
+ fputs(s, stdout);
+}
+
+void prints(const string &s)
+{
+ if (!s.empty())
+ fwrite(s.contents(), 1, s.length(), stdout);
+}
+
+struct horizontal_span {
+ horizontal_span *next;
+ short start_col;
+ short end_col;
+ horizontal_span(int, int, horizontal_span *);
+};
+
+struct single_line_entry;
+struct double_line_entry;
+struct simple_entry;
+
+class table_entry {
+friend class table;
+ table_entry *next;
+ int input_lineno;
+ const char *input_filename;
+protected:
+ int start_row;
+ int end_row;
+ short start_col;
+ short end_col;
+ const entry_modifier *mod;
+public:
+ void set_location();
+ table_entry(const entry_modifier *);
+ virtual ~table_entry();
+ virtual int divert(int ncols, const string *mw, int *sep);
+ virtual void do_width();
+ virtual void do_depth();
+ virtual void print() = 0;
+ virtual void position_vertically() = 0;
+ virtual single_line_entry *to_single_line_entry();
+ virtual double_line_entry *to_double_line_entry();
+ virtual simple_entry *to_simple_entry();
+ virtual int line_type();
+ virtual void note_double_vrule_on_right(int);
+ virtual void note_double_vrule_on_left(int);
+};
+
+class simple_entry : public table_entry {
+public:
+ simple_entry(const entry_modifier *);
+ void print();
+ void position_vertically();
+ simple_entry *to_simple_entry();
+ virtual void add_tab();
+ virtual void simple_print(int);
+};
+
+class empty_entry : public simple_entry {
+public:
+ empty_entry(const entry_modifier *);
+ int line_type();
+};
+
+class text_entry : public simple_entry {
+protected:
+ char *contents;
+ void print_contents();
+public:
+ text_entry(char *, const entry_modifier *);
+ ~text_entry();
+};
+
+void text_entry::print_contents()
+{
+ set_inline_modifier(mod);
+ prints(contents);
+ restore_inline_modifier(mod);
+}
+
+class repeated_char_entry : public text_entry {
+public:
+ repeated_char_entry(char *s, const entry_modifier *m);
+ void simple_print(int);
+};
+
+class simple_text_entry : public text_entry {
+public:
+ simple_text_entry(char *s, const entry_modifier *m);
+ void do_width();
+};
+
+class left_text_entry : public simple_text_entry {
+public:
+ left_text_entry(char *s, const entry_modifier *m);
+ void simple_print(int);
+ void add_tab();
+};
+
+class right_text_entry : public simple_text_entry {
+public:
+ right_text_entry(char *s, const entry_modifier *m);
+ void simple_print(int);
+ void add_tab();
+};
+
+class center_text_entry : public simple_text_entry {
+public:
+ center_text_entry(char *s, const entry_modifier *m);
+ void simple_print(int);
+ void add_tab();
+};
+
+class numeric_text_entry : public text_entry {
+ int dot_pos;
+public:
+ numeric_text_entry(char *s, const entry_modifier *m, int pos);
+ void do_width();
+ void simple_print(int);
+};
+
+class alphabetic_text_entry : public text_entry {
+public:
+ alphabetic_text_entry(char *s, const entry_modifier *m);
+ void do_width();
+ void simple_print(int);
+ void add_tab();
+};
+
+class line_entry : public simple_entry {
+protected:
+ char double_vrule_on_right;
+ char double_vrule_on_left;
+public:
+ line_entry(const entry_modifier *);
+ void note_double_vrule_on_right(int);
+ void note_double_vrule_on_left(int);
+ void simple_print(int) = 0;
+};
+
+class single_line_entry : public line_entry {
+public:
+ single_line_entry(const entry_modifier *m);
+ void simple_print(int);
+ single_line_entry *to_single_line_entry();
+ int line_type();
+};
+
+class double_line_entry : public line_entry {
+public:
+ double_line_entry(const entry_modifier *m);
+ void simple_print(int);
+ double_line_entry *to_double_line_entry();
+ int line_type();
+};
+
+class short_line_entry : public simple_entry {
+public:
+ short_line_entry(const entry_modifier *m);
+ void simple_print(int);
+ int line_type();
+};
+
+class short_double_line_entry : public simple_entry {
+public:
+ short_double_line_entry(const entry_modifier *m);
+ void simple_print(int);
+ int line_type();
+};
+
+class block_entry : public table_entry {
+ char *contents;
+protected:
+ void do_divert(int alphabetic, int ncols, const string *mw, int *sep);
+public:
+ block_entry(char *s, const entry_modifier *m);
+ ~block_entry();
+ int divert(int ncols, const string *mw, int *sep);
+ void do_width();
+ void do_depth();
+ void position_vertically();
+ void print() = 0;
+};
+
+class left_block_entry : public block_entry {
+public:
+ left_block_entry(char *s, const entry_modifier *m);
+ void print();
+};
+
+class right_block_entry : public block_entry {
+public:
+ right_block_entry(char *s, const entry_modifier *m);
+ void print();
+};
+
+class center_block_entry : public block_entry {
+public:
+ center_block_entry(char *s, const entry_modifier *m);
+ void print();
+};
+
+class alphabetic_block_entry : public block_entry {
+public:
+ alphabetic_block_entry(char *s, const entry_modifier *m);
+ void print();
+ int divert(int ncols, const string *mw, int *sep);
+};
+
+table_entry::table_entry(const entry_modifier *m)
+: next(0), input_lineno(-1), input_filename(0),
+ start_row(-1), end_row(-1), start_col(-1), end_col(-1), mod(m)
+{
+}
+
+table_entry::~table_entry()
+{
+}
+
+int table_entry::divert(int, const string *, int *)
+{
+ return 0;
+}
+
+void table_entry::do_width()
+{
+}
+
+single_line_entry *table_entry::to_single_line_entry()
+{
+ return 0;
+}
+
+double_line_entry *table_entry::to_double_line_entry()
+{
+ return 0;
+}
+
+simple_entry *table_entry::to_simple_entry()
+{
+ return 0;
+}
+
+void table_entry::do_depth()
+{
+}
+
+void table_entry::set_location()
+{
+ set_troff_location(input_filename, input_lineno);
+}
+
+int table_entry::line_type()
+{
+ return -1;
+}
+
+void table_entry::note_double_vrule_on_right(int)
+{
+}
+
+void table_entry::note_double_vrule_on_left(int)
+{
+}
+
+simple_entry::simple_entry(const entry_modifier *m) : table_entry(m)
+{
+}
+
+void simple_entry::add_tab()
+{
+ // do nothing
+}
+
+void simple_entry::simple_print(int)
+{
+ // do nothing
+}
+
+void simple_entry::position_vertically()
+{
+ if (start_row != end_row)
+ switch (mod->vertical_alignment) {
+ case entry_modifier::TOP:
+ printfs(".sp |\\n[%1]u\n", row_start_reg(start_row));
+ break;
+ case entry_modifier::CENTER:
+ // Peform the motion in two stages so that the center is rounded
+ // vertically upwards even if net vertical motion is upwards.
+ printfs(".sp |\\n[%1]u\n", row_start_reg(start_row));
+ printfs(".sp \\n[" BOTTOM_REG "]u-\\n[%1]u-1v/2u\n",
+ row_start_reg(start_row));
+ break;
+ case entry_modifier::BOTTOM:
+ printfs(".sp |\\n[%1]u+\\n[" BOTTOM_REG "]u-\\n[%1]u-1v\n",
+ row_start_reg(start_row));
+ break;
+ default:
+ assert(0);
+ }
+}
+
+void simple_entry::print()
+{
+ prints(".ta");
+ add_tab();
+ prints('\n');
+ set_location();
+ prints("\\&");
+ simple_print(0);
+ prints('\n');
+}
+
+simple_entry *simple_entry::to_simple_entry()
+{
+ return this;
+}
+
+empty_entry::empty_entry(const entry_modifier *m)
+: simple_entry(m)
+{
+}
+
+int empty_entry::line_type()
+{
+ return 0;
+}
+
+text_entry::text_entry(char *s, const entry_modifier *m)
+: simple_entry(m), contents(s)
+{
+}
+
+text_entry::~text_entry()
+{
+ a_delete contents;
+}
+
+
+repeated_char_entry::repeated_char_entry(char *s, const entry_modifier *m)
+: text_entry(s, m)
+{
+}
+
+void repeated_char_entry::simple_print(int)
+{
+ printfs("\\h'|\\n[%1]u'", column_start_reg(start_col));
+ set_inline_modifier(mod);
+ printfs("\\l" DELIMITER_CHAR "\\n[%1]u\\&",
+ span_width_reg(start_col, end_col));
+ prints(contents);
+ prints(DELIMITER_CHAR);
+ restore_inline_modifier(mod);
+}
+
+simple_text_entry::simple_text_entry(char *s, const entry_modifier *m)
+: text_entry(s, m)
+{
+}
+
+void simple_text_entry::do_width()
+{
+ set_location();
+ printfs(".nr %1 \\n[%1]>?\\w" DELIMITER_CHAR,
+ span_width_reg(start_col, end_col));
+ print_contents();
+ prints(DELIMITER_CHAR "\n");
+}
+
+left_text_entry::left_text_entry(char *s, const entry_modifier *m)
+: simple_text_entry(s, m)
+{
+}
+
+void left_text_entry::simple_print(int)
+{
+ printfs("\\h'|\\n[%1]u'", column_start_reg(start_col));
+ print_contents();
+}
+
+// The only point of this is to make `\a' ``work'' as in Unix tbl. Grrr.
+
+void left_text_entry::add_tab()
+{
+ printfs(" \\n[%1]u", column_end_reg(end_col));
+}
+
+right_text_entry::right_text_entry(char *s, const entry_modifier *m)
+: simple_text_entry(s, m)
+{
+}
+
+void right_text_entry::simple_print(int)
+{
+ printfs("\\h'|\\n[%1]u'", column_start_reg(start_col));
+ prints("\002\003");
+ print_contents();
+ prints("\002");
+}
+
+void right_text_entry::add_tab()
+{
+ printfs(" \\n[%1]u", column_end_reg(end_col));
+}
+
+center_text_entry::center_text_entry(char *s, const entry_modifier *m)
+: simple_text_entry(s, m)
+{
+}
+
+void center_text_entry::simple_print(int)
+{
+ printfs("\\h'|\\n[%1]u'", column_start_reg(start_col));
+ prints("\002\003");
+ print_contents();
+ prints("\003\002");
+}
+
+void center_text_entry::add_tab()
+{
+ printfs(" \\n[%1]u", column_end_reg(end_col));
+}
+
+numeric_text_entry::numeric_text_entry(char *s, const entry_modifier *m, int pos)
+: text_entry(s, m), dot_pos(pos)
+{
+}
+
+void numeric_text_entry::do_width()
+{
+ if (dot_pos != 0) {
+ set_location();
+ printfs(".nr %1 0\\w" DELIMITER_CHAR,
+ block_width_reg(start_row, start_col));
+ set_inline_modifier(mod);
+ for (int i = 0; i < dot_pos; i++)
+ prints(contents[i]);
+ restore_inline_modifier(mod);
+ prints(DELIMITER_CHAR "\n");
+ printfs(".nr %1 \\n[%1]>?\\n[%2]\n",
+ span_left_numeric_width_reg(start_col, end_col),
+ block_width_reg(start_row, start_col));
+ }
+ else
+ printfs(".nr %1 0\n", block_width_reg(start_row, start_col));
+ if (contents[dot_pos] != '\0') {
+ set_location();
+ printfs(".nr %1 \\n[%1]>?\\w" DELIMITER_CHAR,
+ span_right_numeric_width_reg(start_col, end_col));
+ set_inline_modifier(mod);
+ prints(contents + dot_pos);
+ restore_inline_modifier(mod);
+ prints(DELIMITER_CHAR "\n");
+ }
+}
+
+void numeric_text_entry::simple_print(int)
+{
+ printfs("\\h'|(\\n[%1]u-\\n[%2]u-\\n[%3]u/2u+\\n[%2]u+\\n[%4]u-\\n[%5]u)'",
+ span_width_reg(start_col, end_col),
+ span_left_numeric_width_reg(start_col, end_col),
+ span_right_numeric_width_reg(start_col, end_col),
+ column_start_reg(start_col),
+ block_width_reg(start_row, start_col));
+ print_contents();
+}
+
+alphabetic_text_entry::alphabetic_text_entry(char *s, const entry_modifier *m)
+: text_entry(s, m)
+{
+}
+
+void alphabetic_text_entry::do_width()
+{
+ set_location();
+ printfs(".nr %1 \\n[%1]>?\\w" DELIMITER_CHAR,
+ span_alphabetic_width_reg(start_col, end_col));
+ print_contents();
+ prints(DELIMITER_CHAR "\n");
+}
+
+void alphabetic_text_entry::simple_print(int)
+{
+ printfs("\\h'|\\n[%1]u'", column_start_reg(start_col));
+ printfs("\\h'\\n[%1]u-\\n[%2]u/2u'",
+ span_width_reg(start_col, end_col),
+ span_alphabetic_width_reg(start_col, end_col));
+ print_contents();
+}
+
+// The only point of this is to make `\a' ``work'' as in Unix tbl. Grrr.
+
+void alphabetic_text_entry::add_tab()
+{
+ printfs(" \\n[%1]u", column_end_reg(end_col));
+}
+
+block_entry::block_entry(char *s, const entry_modifier *m)
+: table_entry(m), contents(s)
+{
+}
+
+block_entry::~block_entry()
+{
+ a_delete contents;
+}
+
+void block_entry::position_vertically()
+{
+ if (start_row != end_row)
+ switch(mod->vertical_alignment) {
+ case entry_modifier::TOP:
+ printfs(".sp |\\n[%1]u\n", row_start_reg(start_row));
+ break;
+ case entry_modifier::CENTER:
+ // Peform the motion in two stages so that the center is rounded
+ // vertically upwards even if net vertical motion is upwards.
+ printfs(".sp |\\n[%1]u\n", row_start_reg(start_row));
+ printfs(".sp \\n[" BOTTOM_REG "]u-\\n[%1]u-\\n[%2]u/2u\n",
+ row_start_reg(start_row),
+ block_height_reg(start_row, start_col));
+ break;
+ case entry_modifier::BOTTOM:
+ printfs(".sp |\\n[%1]u+\\n[" BOTTOM_REG "]u-\\n[%1]u-\\n[%2]u\n",
+ row_start_reg(start_row),
+ block_height_reg(start_row, start_col));
+ break;
+ default:
+ assert(0);
+ }
+ if (mod->stagger)
+ prints(".sp -.5v\n");
+}
+
+int block_entry::divert(int ncols, const string *mw, int *sep)
+{
+ do_divert(0, ncols, mw, sep);
+ return 1;
+}
+
+void block_entry::do_divert(int alphabetic, int ncols, const string *mw,
+ int *sep)
+{
+ printfs(".di %1\n", block_diversion_name(start_row, start_col));
+ prints(".if \\n[" SAVED_FILL_REG "] .fi\n"
+ ".in 0\n");
+ prints(".ll ");
+ int i;
+ for (i = start_col; i <= end_col; i++)
+ if (mw[i].empty())
+ break;
+ if (i > end_col) {
+ // Every column spanned by this entry has a minimum width.
+ for (int j = start_col; j <= end_col; j++) {
+ if (j > start_col) {
+ if (sep)
+ printfs("+%1n", as_string(sep[j - 1]));
+ prints('+');
+ }
+ printfs("(n;%1)", mw[j]);
+ }
+ printfs(">?\\n[%1]u", span_width_reg(start_col, end_col));
+ }
+ else
+ printfs("(u;\\n[%1]>?(\\n[.l]*%2/%3))",
+ span_width_reg(start_col, end_col),
+ as_string(end_col - start_col + 1),
+ as_string(ncols + 1));
+ if (alphabetic)
+ prints("-2n");
+ prints("\n");
+ set_modifier(mod);
+ prints(".cp \\n(" COMPATIBLE_REG "\n");
+ set_location();
+ prints(contents);
+ prints(".br\n.di\n.cp 0\n");
+ if (!mod->zero_width) {
+ if (alphabetic) {
+ printfs(".nr %1 \\n[%1]>?(\\n[dl]+2n)\n",
+ span_width_reg(start_col, end_col));
+ printfs(".nr %1 \\n[%1]>?\\n[dl]\n",
+ span_alphabetic_width_reg(start_col, end_col));
+ }
+ else
+ printfs(".nr %1 \\n[%1]>?\\n[dl]\n", span_width_reg(start_col, end_col));
+ }
+ printfs(".nr %1 \\n[dn]\n", block_height_reg(start_row, start_col));
+ printfs(".nr %1 \\n[dl]\n", block_width_reg(start_row, start_col));
+ prints("." RESET_MACRO_NAME "\n"
+ ".in \\n[" SAVED_INDENT_REG "]u\n"
+ ".nf\n");
+ // the block might have contained .lf commands
+ location_force_filename = 1;
+}
+
+void block_entry::do_width()
+{
+ // do nothing; the action happens in divert
+}
+
+void block_entry::do_depth()
+{
+ printfs(".nr " BOTTOM_REG " \\n[" BOTTOM_REG "]>?(\\n[%1]+\\n[%2])\n",
+ row_start_reg(start_row),
+ block_height_reg(start_row, start_col));
+}
+
+left_block_entry::left_block_entry(char *s, const entry_modifier *m)
+: block_entry(s, m)
+{
+}
+
+void left_block_entry::print()
+{
+ printfs(".in +\\n[%1]u\n", column_start_reg(start_col));
+ printfs(".%1\n", block_diversion_name(start_row, start_col));
+ prints(".in\n");
+}
+
+
+
+right_block_entry::right_block_entry(char *s, const entry_modifier *m)
+: block_entry(s, m)
+{
+}
+
+void right_block_entry::print()
+{
+ printfs(".in +\\n[%1]u+\\n[%2]u-\\n[%3]u\n",
+ column_start_reg(start_col),
+ span_width_reg(start_col, end_col),
+ block_width_reg(start_row, start_col));
+ printfs(".%1\n", block_diversion_name(start_row, start_col));
+ prints(".in\n");
+}
+
+center_block_entry::center_block_entry(char *s, const entry_modifier *m)
+: block_entry(s, m)
+{
+}
+
+void center_block_entry::print()
+{
+ printfs(".in +\\n[%1]u+(\\n[%2]u-\\n[%3]u/2u)\n",
+ column_start_reg(start_col),
+ span_width_reg(start_col, end_col),
+ block_width_reg(start_row, start_col));
+ printfs(".%1\n", block_diversion_name(start_row, start_col));
+ prints(".in\n");
+}
+
+alphabetic_block_entry::alphabetic_block_entry(char *s,
+ const entry_modifier *m)
+: block_entry(s, m)
+{
+}
+
+int alphabetic_block_entry::divert(int ncols, const string *mw, int *sep)
+{
+ do_divert(1, ncols, mw, sep);
+ return 1;
+}
+
+void alphabetic_block_entry::print()
+{
+ printfs(".in +\\n[%1]u+(\\n[%2]u-\\n[%3]u/2u)\n",
+ column_start_reg(start_col),
+ span_width_reg(start_col, end_col),
+ span_alphabetic_width_reg(start_col, end_col));
+ printfs(".%1\n", block_diversion_name(start_row, start_col));
+ prints(".in\n");
+}
+
+line_entry::line_entry(const entry_modifier *m)
+: simple_entry(m), double_vrule_on_right(0), double_vrule_on_left(0)
+{
+}
+
+void line_entry::note_double_vrule_on_right(int is_corner)
+{
+ double_vrule_on_right = is_corner ? 1 : 2;
+}
+
+void line_entry::note_double_vrule_on_left(int is_corner)
+{
+ double_vrule_on_left = is_corner ? 1 : 2;
+}
+
+
+single_line_entry::single_line_entry(const entry_modifier *m)
+: line_entry(m)
+{
+}
+
+int single_line_entry::line_type()
+{
+ return 1;
+}
+
+void single_line_entry::simple_print(int dont_move)
+{
+ printfs("\\h'|\\n[%1]u",
+ column_divide_reg(start_col));
+ if (double_vrule_on_left) {
+ prints(double_vrule_on_left == 1 ? "-" : "+");
+ prints(HALF_DOUBLE_LINE_SEP);
+ }
+ prints("'");
+ if (!dont_move)
+ prints("\\v'-" BAR_HEIGHT "'");
+ printfs("\\s[\\n[" LINESIZE_REG "]]" "\\D'l |\\n[%1]u",
+ column_divide_reg(end_col+1));
+ if (double_vrule_on_right) {
+ prints(double_vrule_on_left == 1 ? "+" : "-");
+ prints(HALF_DOUBLE_LINE_SEP);
+ }
+ prints("0'\\s0");
+ if (!dont_move)
+ prints("\\v'" BAR_HEIGHT "'");
+}
+
+single_line_entry *single_line_entry::to_single_line_entry()
+{
+ return this;
+}
+
+double_line_entry::double_line_entry(const entry_modifier *m)
+: line_entry(m)
+{
+}
+
+int double_line_entry::line_type()
+{
+ return 2;
+}
+
+void double_line_entry::simple_print(int dont_move)
+{
+ if (!dont_move)
+ prints("\\v'-" BAR_HEIGHT "'");
+ printfs("\\h'|\\n[%1]u",
+ column_divide_reg(start_col));
+ if (double_vrule_on_left) {
+ prints(double_vrule_on_left == 1 ? "-" : "+");
+ prints(HALF_DOUBLE_LINE_SEP);
+ }
+ prints("'");
+ printfs("\\v'-" HALF_DOUBLE_LINE_SEP "'"
+ "\\s[\\n[" LINESIZE_REG "]]"
+ "\\D'l |\\n[%1]u",
+ column_divide_reg(end_col+1));
+ if (double_vrule_on_right)
+ prints("-" HALF_DOUBLE_LINE_SEP);
+ prints(" 0'");
+ printfs("\\v'" DOUBLE_LINE_SEP "'"
+ "\\D'l |\\n[%1]u",
+ column_divide_reg(start_col));
+ if (double_vrule_on_right) {
+ prints(double_vrule_on_left == 1 ? "+" : "-");
+ prints(HALF_DOUBLE_LINE_SEP);
+ }
+ prints(" 0'");
+ prints("\\s0"
+ "\\v'-" HALF_DOUBLE_LINE_SEP "'");
+ if (!dont_move)
+ prints("\\v'" BAR_HEIGHT "'");
+}
+
+double_line_entry *double_line_entry::to_double_line_entry()
+{
+ return this;
+}
+
+short_line_entry::short_line_entry(const entry_modifier *m)
+: simple_entry(m)
+{
+}
+
+int short_line_entry::line_type()
+{
+ return 1;
+}
+
+void short_line_entry::simple_print(int dont_move)
+{
+ if (mod->stagger)
+ prints("\\v'-.5v'");
+ if (!dont_move)
+ prints("\\v'-" BAR_HEIGHT "'");
+ printfs("\\h'|\\n[%1]u'", column_start_reg(start_col));
+ printfs("\\s[\\n[" LINESIZE_REG "]]"
+ "\\D'l \\n[%1]u 0'"
+ "\\s0",
+ span_width_reg(start_col, end_col));
+ if (!dont_move)
+ prints("\\v'" BAR_HEIGHT "'");
+ if (mod->stagger)
+ prints("\\v'.5v'");
+}
+
+short_double_line_entry::short_double_line_entry(const entry_modifier *m)
+: simple_entry(m)
+{
+}
+
+int short_double_line_entry::line_type()
+{
+ return 2;
+}
+
+void short_double_line_entry::simple_print(int dont_move)
+{
+ if (mod->stagger)
+ prints("\\v'-.5v'");
+ if (!dont_move)
+ prints("\\v'-" BAR_HEIGHT "'");
+ printfs("\\h'|\\n[%2]u'"
+ "\\v'-" HALF_DOUBLE_LINE_SEP "'"
+ "\\s[\\n[" LINESIZE_REG "]]"
+ "\\D'l \\n[%1]u 0'"
+ "\\v'" DOUBLE_LINE_SEP "'"
+ "\\D'l |\\n[%2]u 0'"
+ "\\s0"
+ "\\v'-" HALF_DOUBLE_LINE_SEP "'",
+ span_width_reg(start_col, end_col),
+ column_start_reg(start_col));
+ if (!dont_move)
+ prints("\\v'" BAR_HEIGHT "'");
+ if (mod->stagger)
+ prints("\\v'.5v'");
+}
+
+void set_modifier(const entry_modifier *m)
+{
+ if (!m->font.empty())
+ printfs(".ft %1\n", m->font);
+ if (m->point_size.val != 0) {
+ prints(".ps ");
+ if (m->point_size.inc > 0)
+ prints('+');
+ else if (m->point_size.inc < 0)
+ prints('-');
+ printfs("%1\n", as_string(m->point_size.val));
+ }
+ if (m->vertical_spacing.val != 0) {
+ prints(".vs ");
+ if (m->vertical_spacing.inc > 0)
+ prints('+');
+ else if (m->vertical_spacing.inc < 0)
+ prints('-');
+ printfs("%1\n", as_string(m->vertical_spacing.val));
+ }
+}
+
+void set_inline_modifier(const entry_modifier *m)
+{
+ if (!m->font.empty())
+ printfs("\\f[%1]", m->font);
+ if (m->point_size.val != 0) {
+ prints("\\s[");
+ if (m->point_size.inc > 0)
+ prints('+');
+ else if (m->point_size.inc < 0)
+ prints('-');
+ printfs("%1]", as_string(m->point_size.val));
+ }
+ if (m->stagger)
+ prints("\\v'-.5v'");
+}
+
+void restore_inline_modifier(const entry_modifier *m)
+{
+ if (!m->font.empty())
+ prints("\\f[\\n[" SAVED_FONT_REG "]]");
+ if (m->point_size.val != 0)
+ prints("\\s[\\n[" SAVED_SIZE_REG "]]");
+ if (m->stagger)
+ prints("\\v'.5v'");
+}
+
+
+struct stuff {
+ stuff *next;
+ int row; // occurs before row `row'
+ char printed; // has it been printed?
+
+ stuff(int);
+ virtual void print(table *) = 0;
+ virtual ~stuff();
+ virtual int is_single_line() { return 0; };
+ virtual int is_double_line() { return 0; };
+};
+
+stuff::stuff(int r) : next(0), row(r), printed(0)
+{
+}
+
+stuff::~stuff()
+{
+}
+
+struct text_stuff : public stuff {
+ string contents;
+ const char *filename;
+ int lineno;
+
+ text_stuff(const string &, int r, const char *fn, int ln);
+ ~text_stuff();
+ void print(table *);
+};
+
+
+text_stuff::text_stuff(const string &s, int r, const char *fn, int ln)
+: stuff(r), contents(s), filename(fn), lineno(ln)
+{
+}
+
+text_stuff::~text_stuff()
+{
+}
+
+void text_stuff::print(table *)
+{
+ printed = 1;
+ prints(".cp \\n(" COMPATIBLE_REG "\n");
+ set_troff_location(filename, lineno);
+ prints(contents);
+ prints(".cp 0\n");
+ location_force_filename = 1; // it might have been a .lf command
+}
+
+struct single_hline_stuff : public stuff {
+ single_hline_stuff(int r);
+ void print(table *);
+ int is_single_line();
+};
+
+single_hline_stuff::single_hline_stuff(int r) : stuff(r)
+{
+}
+
+void single_hline_stuff::print(table *tbl)
+{
+ printed = 1;
+ tbl->print_single_hline(row);
+}
+
+int single_hline_stuff::is_single_line()
+{
+ return 1;
+}
+
+struct double_hline_stuff : stuff {
+ double_hline_stuff(int r);
+ void print(table *);
+ int is_double_line();
+};
+
+double_hline_stuff::double_hline_stuff(int r) : stuff(r)
+{
+}
+
+void double_hline_stuff::print(table *tbl)
+{
+ printed = 1;
+ tbl->print_double_hline(row);
+}
+
+int double_hline_stuff::is_double_line()
+{
+ return 1;
+}
+
+struct vertical_rule {
+ vertical_rule *next;
+ int start_row;
+ int end_row;
+ short col;
+ char is_double;
+ string top_adjust;
+ string bot_adjust;
+
+ vertical_rule(int sr, int er, int c, int dbl, vertical_rule *);
+ ~vertical_rule();
+ void contribute_to_bottom_macro(table *);
+ void print();
+};
+
+vertical_rule::vertical_rule(int sr, int er, int c, int dbl, vertical_rule *p)
+: next(p), start_row(sr), end_row(er), col(c), is_double(dbl)
+{
+}
+
+vertical_rule::~vertical_rule()
+{
+}
+
+void vertical_rule::contribute_to_bottom_macro(table *tbl)
+{
+ printfs(".if \\n[" CURRENT_ROW_REG "]>=%1",
+ as_string(start_row));
+ if (end_row != tbl->get_nrows() - 1)
+ printfs("&(\\n[" CURRENT_ROW_REG "]<%1)",
+ as_string(end_row));
+ prints(" \\{");
+ printfs(".if %1<=\\n[" LAST_PASSED_ROW_REG "] .nr %2 \\n[#T]\n",
+ as_string(start_row),
+ row_top_reg(start_row));
+ const char *offset_table[3];
+ if (is_double) {
+ offset_table[0] = "-" HALF_DOUBLE_LINE_SEP;
+ offset_table[1] = "+" HALF_DOUBLE_LINE_SEP;
+ offset_table[2] = 0;
+ }
+ else {
+ offset_table[0] = "";
+ offset_table[1] = 0;
+ }
+ for (const char **offsetp = offset_table; *offsetp; offsetp++) {
+ prints(".sp -1\n"
+ "\\v'" BODY_DEPTH);
+ if (!bot_adjust.empty())
+ printfs("+%1", bot_adjust);
+ prints("'");
+ printfs("\\h'\\n[%1]u%3'\\s[\\n[" LINESIZE_REG "]]\\D'l 0 |\\n[%2]u-1v",
+ column_divide_reg(col),
+ row_top_reg(start_row),
+ *offsetp);
+ if (!bot_adjust.empty())
+ printfs("-(%1)", bot_adjust);
+ // don't perform the top adjustment if the top is actually #T
+ if (!top_adjust.empty())
+ printfs("+((%1)*(%2>\\n[" LAST_PASSED_ROW_REG "]))",
+ top_adjust,
+ as_string(start_row));
+ prints("'\\s0\n");
+ }
+ prints(".\\}\n");
+}
+
+void vertical_rule::print()
+{
+ printfs("\\*[" TRANSPARENT_STRING_NAME "]"
+ ".if %1<=\\*[" QUOTE_STRING_NAME "]\\n[" LAST_PASSED_ROW_REG "] "
+ ".nr %2 \\*[" QUOTE_STRING_NAME "]\\n[#T]\n",
+ as_string(start_row),
+ row_top_reg(start_row));
+ const char *offset_table[3];
+ if (is_double) {
+ offset_table[0] = "-" HALF_DOUBLE_LINE_SEP;
+ offset_table[1] = "+" HALF_DOUBLE_LINE_SEP;
+ offset_table[2] = 0;
+ }
+ else {
+ offset_table[0] = "";
+ offset_table[1] = 0;
+ }
+ for (const char **offsetp = offset_table; *offsetp; offsetp++) {
+ prints("\\*[" TRANSPARENT_STRING_NAME "].sp -1\n"
+ "\\*[" TRANSPARENT_STRING_NAME "]\\v'" BODY_DEPTH);
+ if (!bot_adjust.empty())
+ printfs("+%1", bot_adjust);
+ prints("'");
+ printfs("\\h'\\n[%1]u%3'"
+ "\\s[\\n[" LINESIZE_REG "]]"
+ "\\D'l 0 |\\*[" QUOTE_STRING_NAME "]\\n[%2]u-1v",
+ column_divide_reg(col),
+ row_top_reg(start_row),
+ *offsetp);
+ if (!bot_adjust.empty())
+ printfs("-(%1)", bot_adjust);
+ // don't perform the top adjustment if the top is actually #T
+ if (!top_adjust.empty())
+ printfs("+((%1)*(%2>\\*[" QUOTE_STRING_NAME "]\\n["
+ LAST_PASSED_ROW_REG "]))",
+ top_adjust,
+ as_string(start_row));
+ prints("'"
+ "\\s0\n");
+ }
+}
+
+table::table(int nc, unsigned f, int ls, char dpc)
+: flags(f), nrows(0), ncolumns(nc), linesize(ls), decimal_point_char(dpc),
+ vrule_list(0), stuff_list(0), span_list(0),
+ entry_list(0), entry_list_tailp(&entry_list), entry(0),
+ vline(0), row_is_all_lines(0), left_separation(0), right_separation(0),
+ allocated_rows(0)
+{
+ minimum_width = new string[ncolumns];
+ column_separation = ncolumns > 1 ? new int[ncolumns - 1] : 0;
+ equal = new char[ncolumns];
+ int i;
+ for (i = 0; i < ncolumns; i++)
+ equal[i] = 0;
+ for (i = 0; i < ncolumns-1; i++)
+ column_separation[i] = DEFAULT_COLUMN_SEPARATION;
+ delim[0] = delim[1] = '\0';
+}
+
+table::~table()
+{
+ for (int i = 0; i < nrows; i++) {
+ a_delete entry[i];
+ a_delete vline[i];
+ }
+ a_delete entry;
+ a_delete vline;
+ while (entry_list) {
+ table_entry *tem = entry_list;
+ entry_list = entry_list->next;
+ delete tem;
+ }
+ ad_delete(ncolumns) minimum_width;
+ a_delete column_separation;
+ a_delete equal;
+ while (stuff_list) {
+ stuff *tem = stuff_list;
+ stuff_list = stuff_list->next;
+ delete tem;
+ }
+ while (vrule_list) {
+ vertical_rule *tem = vrule_list;
+ vrule_list = vrule_list->next;
+ delete tem;
+ }
+ a_delete row_is_all_lines;
+ while (span_list) {
+ horizontal_span *tem = span_list;
+ span_list = span_list->next;
+ delete tem;
+ }
+}
+
+void table::set_delim(char c1, char c2)
+{
+ delim[0] = c1;
+ delim[1] = c2;
+}
+
+void table::set_minimum_width(int c, const string &w)
+{
+ assert(c >= 0 && c < ncolumns);
+ minimum_width[c] = w;
+}
+
+void table::set_column_separation(int c, int n)
+{
+ assert(c >= 0 && c < ncolumns - 1);
+ column_separation[c] = n;
+}
+
+void table::set_equal_column(int c)
+{
+ assert(c >= 0 && c < ncolumns);
+ equal[c] = 1;
+}
+
+void table::add_stuff(stuff *p)
+{
+ stuff **pp;
+ for (pp = &stuff_list; *pp; pp = &(*pp)->next)
+ ;
+ *pp = p;
+}
+
+void table::add_text_line(int r, const string &s, const char *filename, int lineno)
+{
+ add_stuff(new text_stuff(s, r, filename, lineno));
+}
+
+void table::add_single_hline(int r)
+{
+ add_stuff(new single_hline_stuff(r));
+}
+
+void table::add_double_hline(int r)
+{
+ add_stuff(new double_hline_stuff(r));
+}
+
+void table::allocate(int r)
+{
+ if (r >= nrows) {
+ typedef table_entry **PPtable_entry; // work around g++ 1.36.1 bug
+ if (r >= allocated_rows) {
+ if (allocated_rows == 0) {
+ allocated_rows = 16;
+ if (allocated_rows <= r)
+ allocated_rows = r + 1;
+ entry = new PPtable_entry[allocated_rows];
+ vline = new char*[allocated_rows];
+ }
+ else {
+ table_entry ***old_entry = entry;
+ int old_allocated_rows = allocated_rows;
+ allocated_rows *= 2;
+ if (allocated_rows <= r)
+ allocated_rows = r + 1;
+ entry = new PPtable_entry[allocated_rows];
+ memcpy(entry, old_entry, sizeof(table_entry**)*old_allocated_rows);
+ a_delete old_entry;
+ char **old_vline = vline;
+ vline = new char*[allocated_rows];
+ memcpy(vline, old_vline, sizeof(char*)*old_allocated_rows);
+ a_delete old_vline;
+ }
+ }
+ assert(allocated_rows > r);
+ while (nrows <= r) {
+ entry[nrows] = new table_entry*[ncolumns];
+ int i;
+ for (i = 0; i < ncolumns; i++)
+ entry[nrows][i] = 0;
+ vline[nrows] = new char[ncolumns+1];
+ for (i = 0; i < ncolumns+1; i++)
+ vline[nrows][i] = 0;
+ nrows++;
+ }
+ }
+}
+
+void table::do_hspan(int r, int c)
+{
+ assert(r >= 0 && c >= 0 && r < nrows && c < ncolumns);
+ if (c == 0) {
+ error("first column cannot be horizontally spanned");
+ return;
+ }
+ table_entry *e = entry[r][c];
+ if (e) {
+ assert(e->start_row <= r && r <= e->end_row
+ && e->start_col <= c && c <= e->end_col
+ && e->end_row - e->start_row > 0
+ && e->end_col - e->start_col > 0);
+ return;
+ }
+ e = entry[r][c-1];
+ // e can be 0 if we had an empty entry or an error
+ if (e == 0)
+ return;
+ if (e->start_row != r) {
+ /*
+ l l
+ ^ s */
+ error("impossible horizontal span at row %1, column %2", r + 1, c + 1);
+ }
+ else {
+ e->end_col = c;
+ entry[r][c] = e;
+ }
+}
+
+void table::do_vspan(int r, int c)
+{
+ assert(r >= 0 && c >= 0 && r < nrows && c < ncolumns);
+ if (r == 0) {
+ error("first row cannot be vertically spanned");
+ return;
+ }
+ table_entry *e = entry[r][c];
+ if (e) {
+ assert(e->start_row <= r && r <= e->end_row
+ && e->start_col <= c && c <= e->end_col
+ && e->end_row - e->start_row > 0
+ && e->end_col - e->start_col > 0);
+ return;
+ }
+ e = entry[r-1][c];
+ // e can be 0 if we had an empty entry or an error
+ if (e == 0)
+ return;
+ if (e->start_col != c) {
+ /* l s
+ l ^ */
+ error("impossible vertical span at row %1, column %2", r + 1, c + 1);
+ }
+ else {
+ for (int i = c; i <= e->end_col; i++) {
+ assert(entry[r][i] == 0);
+ entry[r][i] = e;
+ }
+ e->end_row = r;
+ }
+}
+
+int find_decimal_point(const char *s, char decimal_point_char,
+ const char *delim)
+{
+ if (s == 0 || *s == '\0')
+ return -1;
+ const char *p;
+ int in_delim = 0; // is p within eqn delimiters?
+ // tbl recognises \& even within eqn delimiters; I don't
+ for (p = s; *p; p++)
+ if (in_delim) {
+ if (*p == delim[1])
+ in_delim = 0;
+ }
+ else if (*p == delim[0])
+ in_delim = 1;
+ else if (p[0] == '\\' && p[1] == '&')
+ return p - s;
+ int possible_pos = -1;
+ in_delim = 0;
+ for (p = s; *p; p++)
+ if (in_delim) {
+ if (*p == delim[1])
+ in_delim = 0;
+ }
+ else if (*p == delim[0])
+ in_delim = 1;
+ else if (p[0] == decimal_point_char && csdigit(p[1]))
+ possible_pos = p - s;
+ if (possible_pos >= 0)
+ return possible_pos;
+ in_delim = 0;
+ for (p = s; *p; p++)
+ if (in_delim) {
+ if (*p == delim[1])
+ in_delim = 0;
+ }
+ else if (*p == delim[0])
+ in_delim = 1;
+ else if (csdigit(*p))
+ possible_pos = p + 1 - s;
+ return possible_pos;
+}
+
+void table::add_entry(int r, int c, const string &str, const entry_format *f,
+ const char *fn, int ln)
+{
+ allocate(r);
+ table_entry *e = 0;
+ if (str == "\\_") {
+ e = new short_line_entry(f);
+ }
+ else if (str == "\\=") {
+ e = new short_double_line_entry(f);
+ }
+ else if (str == "_") {
+ single_line_entry *lefte;
+ if (c > 0 && entry[r][c-1] != 0 &&
+ (lefte = entry[r][c-1]->to_single_line_entry()) != 0
+ && lefte->start_row == r
+ && lefte->mod->stagger == f->stagger) {
+ lefte->end_col = c;
+ entry[r][c] = lefte;
+ }
+ else
+ e = new single_line_entry(f);
+ }
+ else if (str == "=") {
+ double_line_entry *lefte;
+ if (c > 0 && entry[r][c-1] != 0 &&
+ (lefte = entry[r][c-1]->to_double_line_entry()) != 0
+ && lefte->start_row == r
+ && lefte->mod->stagger == f->stagger) {
+ lefte->end_col = c;
+ entry[r][c] = lefte;
+ }
+ else
+ e = new double_line_entry(f);
+ }
+ else if (str == "\\^") {
+ do_vspan(r, c);
+ }
+ else if (str.length() > 2 && str[0] == '\\' && str[1] == 'R') {
+ if (str.search('\n') >= 0)
+ error_with_file_and_line(fn, ln, "bad repeated character");
+ else {
+ char *s = str.substring(2, str.length() - 2).extract();
+ e = new repeated_char_entry(s, f);
+ }
+ }
+ else {
+ int is_block = str.search('\n') >= 0;
+ char *s;
+ switch (f->type) {
+ case FORMAT_SPAN:
+ assert(str.empty());
+ do_hspan(r, c);
+ break;
+ case FORMAT_LEFT:
+ if (!str.empty()) {
+ s = str.extract();
+ if (is_block)
+ e = new left_block_entry(s, f);
+ else
+ e = new left_text_entry(s, f);
+ }
+ else
+ e = new empty_entry(f);
+ break;
+ case FORMAT_CENTER:
+ if (!str.empty()) {
+ s = str.extract();
+ if (is_block)
+ e = new center_block_entry(s, f);
+ else
+ e = new center_text_entry(s, f);
+ }
+ else
+ e = new empty_entry(f);
+ break;
+ case FORMAT_RIGHT:
+ if (!str.empty()) {
+ s = str.extract();
+ if (is_block)
+ e = new right_block_entry(s, f);
+ else
+ e = new right_text_entry(s, f);
+ }
+ else
+ e = new empty_entry(f);
+ break;
+ case FORMAT_NUMERIC:
+ if (!str.empty()) {
+ s = str.extract();
+ if (is_block) {
+ error_with_file_and_line(fn, ln, "can't have numeric text block");
+ e = new left_block_entry(s, f);
+ }
+ else {
+ int pos = find_decimal_point(s, decimal_point_char, delim);
+ if (pos < 0)
+ e = new center_text_entry(s, f);
+ else
+ e = new numeric_text_entry(s, f, pos);
+ }
+ }
+ else
+ e = new empty_entry(f);
+ break;
+ case FORMAT_ALPHABETIC:
+ if (!str.empty()) {
+ s = str.extract();
+ if (is_block)
+ e = new alphabetic_block_entry(s, f);
+ else
+ e = new alphabetic_text_entry(s, f);
+ }
+ else
+ e = new empty_entry(f);
+ break;
+ case FORMAT_VSPAN:
+ do_vspan(r, c);
+ break;
+ case FORMAT_HLINE:
+ if (str.length() != 0)
+ error_with_file_and_line(fn, ln,
+ "non-empty data entry for `_' format ignored");
+ e = new single_line_entry(f);
+ break;
+ case FORMAT_DOUBLE_HLINE:
+ if (str.length() != 0)
+ error_with_file_and_line(fn, ln,
+ "non-empty data entry for `=' format ignored");
+ e = new double_line_entry(f);
+ break;
+ default:
+ assert(0);
+ }
+ }
+ if (e) {
+ table_entry *preve = entry[r][c];
+ if (preve) {
+ /* c s
+ ^ l */
+ error_with_file_and_line(fn, ln, "row %1, column %2 already spanned",
+ r + 1, c + 1);
+ delete e;
+ }
+ else {
+ e->input_lineno = ln;
+ e->input_filename = fn;
+ e->start_row = e->end_row = r;
+ e->start_col = e->end_col = c;
+ *entry_list_tailp = e;
+ entry_list_tailp = &e->next;
+ entry[r][c] = e;
+ }
+ }
+}
+
+// add vertical lines for row r
+
+void table::add_vlines(int r, const char *v)
+{
+ allocate(r);
+ for (int i = 0; i < ncolumns+1; i++)
+ vline[r][i] = v[i];
+}
+
+void table::check()
+{
+ table_entry *p = entry_list;
+ int i, j;
+ while (p) {
+ for (i = p->start_row; i <= p->end_row; i++)
+ for (j = p->start_col; j <= p->end_col; j++)
+ assert(entry[i][j] == p);
+ p = p->next;
+ }
+}
+
+void table::print()
+{
+ location_force_filename = 1;
+ check();
+ init_output();
+ determine_row_type();
+ compute_widths();
+ if (!(flags & CENTER))
+ prints(".if \\n[" SAVED_CENTER_REG "] \\{");
+ prints(".in +(u;\\n[.l]-\\n[.i]-\\n[TW]/2)\n"
+ ".nr " SAVED_INDENT_REG " \\n[.i]\n");
+ if (!(flags & CENTER))
+ prints(".\\}\n");
+ build_vrule_list();
+ define_bottom_macro();
+ do_top();
+ for (int i = 0; i < nrows; i++)
+ do_row(i);
+ do_bottom();
+}
+
+void table::determine_row_type()
+{
+ row_is_all_lines = new char[nrows];
+ for (int i = 0; i < nrows; i++) {
+ int had_single = 0;
+ int had_double = 0;
+ int had_non_line = 0;
+ for (int c = 0; c < ncolumns; c++) {
+ table_entry *e = entry[i][c];
+ if (e != 0) {
+ if (e->start_row == e->end_row) {
+ int t = e->line_type();
+ switch (t) {
+ case -1:
+ had_non_line = 1;
+ break;
+ case 0:
+ // empty
+ break;
+ case 1:
+ had_single = 1;
+ break;
+ case 2:
+ had_double = 1;
+ break;
+ default:
+ assert(0);
+ }
+ if (had_non_line)
+ break;
+ }
+ c = e->end_col;
+ }
+ }
+ if (had_non_line)
+ row_is_all_lines[i] = 0;
+ else if (had_double)
+ row_is_all_lines[i] = 2;
+ else if (had_single)
+ row_is_all_lines[i] = 1;
+ else
+ row_is_all_lines[i] = 0;
+ }
+}
+
+
+void table::init_output()
+{
+ prints(".nr " COMPATIBLE_REG " \\n(.C\n"
+ ".cp 0\n");
+ if (linesize > 0)
+ printfs(".nr " LINESIZE_REG " %1\n", as_string(linesize));
+ else
+ prints(".nr " LINESIZE_REG " \\n[.s]\n");
+ if (!(flags & CENTER))
+ prints(".nr " SAVED_CENTER_REG " \\n[.ce]\n");
+ prints(".de " RESET_MACRO_NAME "\n"
+ ".ft \\n[.f]\n"
+ ".ps \\n[.s]\n"
+ ".vs \\n[.v]u\n"
+ ".in \\n[.i]u\n"
+ ".ll \\n[.l]u\n"
+ ".ls \\n[.L]\n"
+ ".ad \\n[.j]\n"
+ ".ie \\n[.u] .fi\n"
+ ".el .nf\n"
+ ".ce \\n[.ce]\n"
+ "..\n"
+ ".nr " SAVED_INDENT_REG " \\n[.i]\n"
+ ".nr " SAVED_FONT_REG " \\n[.f]\n"
+ ".nr " SAVED_SIZE_REG " \\n[.s]\n"
+ ".nr " SAVED_FILL_REG " \\n[.u]\n"
+ ".nr T. 0\n"
+ ".nr " CURRENT_ROW_REG " 0-1\n"
+ ".nr " LAST_PASSED_ROW_REG " 0-1\n"
+ ".nr " SECTION_DIVERSION_FLAG_REG " 0\n"
+ ".ds " TRANSPARENT_STRING_NAME "\n"
+ ".ds " QUOTE_STRING_NAME "\n"
+ ".nr " NEED_BOTTOM_RULE_REG " 1\n"
+ ".nr " SUPPRESS_BOTTOM_REG " 0\n"
+ ".eo\n"
+ ".de " REPEATED_MARK_MACRO "\n"
+ ".mk \\$1\n"
+ ".if !'\\n(.z'' \\!." REPEATED_MARK_MACRO " \"\\$1\"\n"
+ "..\n"
+ ".de " REPEATED_VPT_MACRO "\n"
+ ".vpt \\$1\n"
+ ".if !'\\n(.z'' \\!." REPEATED_VPT_MACRO " \"\\$1\"\n"
+ "..\n");
+ if (!(flags & NOKEEP))
+ prints(".de " KEEP_MACRO_NAME "\n"
+ ".if '\\n[.z]'' \\{.ds " QUOTE_STRING_NAME " \\\\\n"
+ ".ds " TRANSPARENT_STRING_NAME " \\!\n"
+ ".di " SECTION_DIVERSION_NAME "\n"
+ ".nr " SECTION_DIVERSION_FLAG_REG " 1\n"
+ ".in 0\n"
+ ".\\}\n"
+ "..\n"
+ ".de " RELEASE_MACRO_NAME "\n"
+ ".if \\n[" SECTION_DIVERSION_FLAG_REG "] \\{"
+ ".di\n"
+ ".in \\n[" SAVED_INDENT_REG "]u\n"
+ ".nr " SAVED_DN_REG " \\n[dn]\n"
+ ".ds " QUOTE_STRING_NAME "\n"
+ ".ds " TRANSPARENT_STRING_NAME "\n"
+ ".nr " SECTION_DIVERSION_FLAG_REG " 0\n"
+ ".if \\n[.t]<=\\n[dn] \\{"
+ ".nr T. 1\n"
+ ".T#\n"
+ ".nr " SUPPRESS_BOTTOM_REG " 1\n"
+ ".sp \\n[.t]u\n"
+ ".nr " SUPPRESS_BOTTOM_REG " 0\n"
+ ".mk #T\n"
+ ".\\}\n"
+ ".if \\n[.t]<=\\n[" SAVED_DN_REG "] "
+ /* Since we turn off traps, it won't get into an infinite loop
+ when we try and print it; it will just go off the bottom of the
+ page. */
+ ".tm warning: page \\n%: table text block will not fit on one page\n"
+ ".nf\n"
+ ".ls 1\n"
+ "." SECTION_DIVERSION_NAME "\n"
+ ".ls\n"
+ ".rm " SECTION_DIVERSION_NAME "\n"
+ ".\\}\n"
+ "..\n"
+ ".nr " TABLE_DIVERSION_FLAG_REG " 0\n"
+ ".de " TABLE_KEEP_MACRO_NAME "\n"
+ ".if '\\n[.z]'' \\{"
+ ".di " TABLE_DIVERSION_NAME "\n"
+ ".nr " TABLE_DIVERSION_FLAG_REG " 1\n"
+ ".\\}\n"
+ "..\n"
+ ".de " TABLE_RELEASE_MACRO_NAME "\n"
+ ".if \\n[" TABLE_DIVERSION_FLAG_REG "] \\{.br\n"
+ ".di\n"
+ ".nr " SAVED_DN_REG " \\n[dn]\n"
+ ".ne \\n[dn]u+\\n[.V]u\n"
+ ".ie \\n[.t]<=\\n[" SAVED_DN_REG "] "
+ ".tm error: page \\n%: table will not fit on one page; use .TS H/.TH with a supporting macro package\n"
+ ".el \\{"
+ ".in 0\n"
+ ".ls 1\n"
+ ".nf\n"
+ "." TABLE_DIVERSION_NAME "\n"
+ ".\\}\n"
+ ".rm " TABLE_DIVERSION_NAME "\n"
+ ".\\}\n"
+ "..\n");
+ prints(".ec\n"
+ ".ce 0\n"
+ ".nf\n");
+}
+
+string block_width_reg(int r, int c)
+{
+ static char name[sizeof(BLOCK_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS];
+ sprintf(name, BLOCK_WIDTH_PREFIX "%d,%d", r, c);
+ return string(name);
+}
+
+string block_diversion_name(int r, int c)
+{
+ static char name[sizeof(BLOCK_DIVERSION_PREFIX)+INT_DIGITS+1+INT_DIGITS];
+ sprintf(name, BLOCK_DIVERSION_PREFIX "%d,%d", r, c);
+ return string(name);
+}
+
+string block_height_reg(int r, int c)
+{
+ static char name[sizeof(BLOCK_HEIGHT_PREFIX)+INT_DIGITS+1+INT_DIGITS];
+ sprintf(name, BLOCK_HEIGHT_PREFIX "%d,%d", r, c);
+ return string(name);
+}
+
+string span_width_reg(int start_col, int end_col)
+{
+ static char name[sizeof(SPAN_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS];
+ sprintf(name, SPAN_WIDTH_PREFIX "%d", start_col);
+ if (end_col != start_col)
+ sprintf(strchr(name, '\0'), ",%d", end_col);
+ return string(name);
+}
+
+string span_left_numeric_width_reg(int start_col, int end_col)
+{
+ static char name[sizeof(SPAN_LEFT_NUMERIC_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS];
+ sprintf(name, SPAN_LEFT_NUMERIC_WIDTH_PREFIX "%d", start_col);
+ if (end_col != start_col)
+ sprintf(strchr(name, '\0'), ",%d", end_col);
+ return string(name);
+}
+
+string span_right_numeric_width_reg(int start_col, int end_col)
+{
+ static char name[sizeof(SPAN_RIGHT_NUMERIC_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS];
+ sprintf(name, SPAN_RIGHT_NUMERIC_WIDTH_PREFIX "%d", start_col);
+ if (end_col != start_col)
+ sprintf(strchr(name, '\0'), ",%d", end_col);
+ return string(name);
+}
+
+string span_alphabetic_width_reg(int start_col, int end_col)
+{
+ static char name[sizeof(SPAN_ALPHABETIC_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS];
+ sprintf(name, SPAN_ALPHABETIC_WIDTH_PREFIX "%d", start_col);
+ if (end_col != start_col)
+ sprintf(strchr(name, '\0'), ",%d", end_col);
+ return string(name);
+}
+
+
+string column_separation_reg(int col)
+{
+ static char name[sizeof(COLUMN_SEPARATION_PREFIX)+INT_DIGITS];
+ sprintf(name, COLUMN_SEPARATION_PREFIX "%d", col);
+ return string(name);
+}
+
+string row_start_reg(int row)
+{
+ static char name[sizeof(ROW_START_PREFIX)+INT_DIGITS];
+ sprintf(name, ROW_START_PREFIX "%d", row);
+ return string(name);
+}
+
+string column_start_reg(int col)
+{
+ static char name[sizeof(COLUMN_START_PREFIX)+INT_DIGITS];
+ sprintf(name, COLUMN_START_PREFIX "%d", col);
+ return string(name);
+}
+
+string column_end_reg(int col)
+{
+ static char name[sizeof(COLUMN_END_PREFIX)+INT_DIGITS];
+ sprintf(name, COLUMN_END_PREFIX "%d", col);
+ return string(name);
+}
+
+string column_divide_reg(int col)
+{
+ static char name[sizeof(COLUMN_DIVIDE_PREFIX)+INT_DIGITS];
+ sprintf(name, COLUMN_DIVIDE_PREFIX "%d", col);
+ return string(name);
+}
+
+string row_top_reg(int row)
+{
+ static char name[sizeof(ROW_TOP_PREFIX)+INT_DIGITS];
+ sprintf(name, ROW_TOP_PREFIX "%d", row);
+ return string(name);
+}
+
+void init_span_reg(int start_col, int end_col)
+{
+ printfs(".nr %1 \\n(.H\n.nr %2 0\n.nr %3 0\n.nr %4 0\n",
+ span_width_reg(start_col, end_col),
+ span_alphabetic_width_reg(start_col, end_col),
+ span_left_numeric_width_reg(start_col, end_col),
+ span_right_numeric_width_reg(start_col, end_col));
+}
+
+void compute_span_width(int start_col, int end_col)
+{
+ printfs(".nr %1 \\n[%1]>?(\\n[%2]+\\n[%3])\n"
+ ".if \\n[%4] .nr %1 \\n[%1]>?(\\n[%4]+2n)\n",
+ span_width_reg(start_col, end_col),
+ span_left_numeric_width_reg(start_col, end_col),
+ span_right_numeric_width_reg(start_col, end_col),
+ span_alphabetic_width_reg(start_col, end_col));
+
+}
+
+// Increase the widths of columns so that the width of any spanning entry
+// is no greater than the sum of the widths of the columns that it spans.
+// Ensure that the widths of columns remain equal.
+
+void table::divide_span(int start_col, int end_col)
+{
+ assert(end_col > start_col);
+ printfs(".nr " NEEDED_REG " \\n[%1]-(\\n[%2]",
+ span_width_reg(start_col, end_col),
+ span_width_reg(start_col, start_col));
+ int i;
+ for (i = start_col + 1; i <= end_col; i++) {
+ // The column separation may shrink with the expand option.
+ if (!(flags & EXPAND))
+ printfs("+%1n", as_string(column_separation[i - 1]));
+ printfs("+\\n[%1]", span_width_reg(i, i));
+ }
+ prints(")\n");
+ printfs(".nr " NEEDED_REG " \\n[" NEEDED_REG "]/%1\n",
+ as_string(end_col - start_col + 1));
+ prints(".if \\n[" NEEDED_REG "] \\{");
+ for (i = start_col; i <= end_col; i++)
+ printfs(".nr %1 +\\n[" NEEDED_REG "]\n",
+ span_width_reg(i, i));
+ int equal_flag = 0;
+ for (i = start_col; i <= end_col && !equal_flag; i++)
+ if (equal[i])
+ equal_flag = 1;
+ if (equal_flag) {
+ for (i = 0; i < ncolumns; i++)
+ if (i < start_col || i > end_col)
+ printfs(".nr %1 +\\n[" NEEDED_REG "]\n",
+ span_width_reg(i, i));
+ }
+ prints(".\\}\n");
+}
+
+
+void table::sum_columns(int start_col, int end_col)
+{
+ assert(end_col > start_col);
+ printfs(".nr %1 \\n[%2]",
+ span_width_reg(start_col, end_col),
+ span_width_reg(start_col, start_col));
+ for (int i = start_col + 1; i <= end_col; i++)
+ printfs("+(%1*\\n[" SEPARATION_FACTOR_REG "])+\\n[%2]",
+ as_string(column_separation[i - 1]),
+ span_width_reg(i, i));
+ prints('\n');
+}
+
+horizontal_span::horizontal_span(int sc, int ec, horizontal_span *p)
+: next(p), start_col(sc), end_col(ec)
+{
+}
+
+void table::build_span_list()
+{
+ span_list = 0;
+ table_entry *p = entry_list;
+ while (p) {
+ if (p->end_col != p->start_col) {
+ horizontal_span *q;
+ for (q = span_list; q; q = q->next)
+ if (q->start_col == p->start_col
+ && q->end_col == p->end_col)
+ break;
+ if (!q)
+ span_list = new horizontal_span(p->start_col, p->end_col, span_list);
+ }
+ p = p->next;
+ }
+ // Now sort span_list primarily by order of end_row, and secondarily
+ // by reverse order of start_row. This ensures that if we divide
+ // spans using the order in span_list, we will get reasonable results.
+ horizontal_span *unsorted = span_list;
+ span_list = 0;
+ while (unsorted) {
+ horizontal_span **pp;
+ for (pp = &span_list; *pp; pp = &(*pp)->next)
+ if (unsorted->end_col < (*pp)->end_col
+ || (unsorted->end_col == (*pp)->end_col
+ && (unsorted->start_col > (*pp)->start_col)))
+ break;
+ horizontal_span *tem = unsorted->next;
+ unsorted->next = *pp;
+ *pp = unsorted;
+ unsorted = tem;
+ }
+}
+
+
+void table::compute_separation_factor()
+{
+ if (flags & (ALLBOX|BOX|DOUBLEBOX))
+ left_separation = right_separation = 1;
+ else {
+ for (int i = 0; i < nrows; i++) {
+ if (vline[i][0] > 0)
+ left_separation = 1;
+ if (vline[i][ncolumns] > 0)
+ right_separation = 1;
+ }
+ }
+ if (flags & EXPAND) {
+ int total_sep = left_separation + right_separation;
+ int i;
+ for (i = 0; i < ncolumns - 1; i++)
+ total_sep += column_separation[i];
+ if (total_sep != 0) {
+ // Don't let the separation factor be negative.
+ prints(".nr " SEPARATION_FACTOR_REG " \\n[.l]-\\n[.i]");
+ for (i = 0; i < ncolumns; i++)
+ printfs("-\\n[%1]", span_width_reg(i, i));
+ printfs("/%1>?0\n", as_string(total_sep));
+ }
+ }
+}
+
+void table::compute_column_positions()
+{
+ printfs(".nr %1 0\n", column_divide_reg(0));
+ printfs(".nr %1 %2*\\n[" SEPARATION_FACTOR_REG "]\n",
+ column_start_reg(0),
+ as_string(left_separation));
+ int i;
+ for (i = 1;; i++) {
+ printfs(".nr %1 \\n[%2]+\\n[%3]\n",
+ column_end_reg(i-1),
+ column_start_reg(i-1),
+ span_width_reg(i-1, i-1));
+ if (i >= ncolumns)
+ break;
+ printfs(".nr %1 \\n[%2]+(%3*\\n[" SEPARATION_FACTOR_REG "])\n",
+ column_start_reg(i),
+ column_end_reg(i-1),
+ as_string(column_separation[i-1]));
+ printfs(".nr %1 \\n[%2]+\\n[%3]/2\n",
+ column_divide_reg(i),
+ column_end_reg(i-1),
+ column_start_reg(i));
+ }
+ printfs(".nr %1 \\n[%2]+(%3*\\n[" SEPARATION_FACTOR_REG "])\n",
+ column_divide_reg(ncolumns),
+ column_end_reg(i-1),
+ as_string(right_separation));
+ printfs(".nr TW \\n[%1]\n",
+ column_divide_reg(ncolumns));
+ if (flags & DOUBLEBOX) {
+ printfs(".nr %1 +" DOUBLE_LINE_SEP "\n", column_divide_reg(0));
+ printfs(".nr %1 -" DOUBLE_LINE_SEP "\n", column_divide_reg(ncolumns));
+ }
+}
+
+void table::make_columns_equal()
+{
+ int first = -1; // index of first equal column
+ int i;
+ for (i = 0; i < ncolumns; i++)
+ if (equal[i]) {
+ if (first < 0) {
+ printfs(".nr %1 \\n[%1]", span_width_reg(i, i));
+ first = i;
+ }
+ else
+ printfs(">?\\n[%1]", span_width_reg(i, i));
+ }
+ if (first >= 0) {
+ prints('\n');
+ for (i = first + 1; i < ncolumns; i++)
+ if (equal[i])
+ printfs(".nr %1 \\n[%2]\n",
+ span_width_reg(i, i),
+ span_width_reg(first, first));
+ }
+}
+
+void table::compute_widths()
+{
+ build_span_list();
+ int i;
+ horizontal_span *p;
+ prints(".nr " SEPARATION_FACTOR_REG " 1n\n");
+ for (i = 0; i < ncolumns; i++) {
+ init_span_reg(i, i);
+ if (!minimum_width[i].empty())
+ printfs(".nr %1 %2\n", span_width_reg(i, i), minimum_width[i]);
+ }
+ for (p = span_list; p; p = p->next)
+ init_span_reg(p->start_col, p->end_col);
+ table_entry *q;
+ for (q = entry_list; q; q = q->next)
+ if (!q->mod->zero_width)
+ q->do_width();
+ for (i = 0; i < ncolumns; i++)
+ compute_span_width(i, i);
+ for (p = span_list; p; p = p->next)
+ compute_span_width(p->start_col, p->end_col);
+ make_columns_equal();
+ // Note that divide_span keeps equal width columns equal.
+ for (p = span_list; p; p = p->next)
+ divide_span(p->start_col, p->end_col);
+ for (p = span_list; p; p = p->next)
+ sum_columns(p->start_col, p->end_col);
+ int had_spanning_block = 0;
+ int had_equal_block = 0;
+ for (q = entry_list; q; q = q->next)
+ if (q->divert(ncolumns, minimum_width,
+ (flags & EXPAND) ? column_separation : 0)) {
+ if (q->end_col > q->start_col)
+ had_spanning_block = 1;
+ for (i = q->start_col; i <= q->end_col && !had_equal_block; i++)
+ if (equal[i])
+ had_equal_block = 1;
+ }
+ if (had_equal_block)
+ make_columns_equal();
+ if (had_spanning_block)
+ for (p = span_list; p; p = p->next)
+ divide_span(p->start_col, p->end_col);
+ compute_separation_factor();
+ for (p = span_list; p; p = p->next)
+ sum_columns(p->start_col, p->end_col);
+ compute_column_positions();
+}
+
+void table::print_single_hline(int r)
+{
+ prints(".vs " LINE_SEP ">?\\n[.V]u\n"
+ ".ls 1\n"
+ "\\v'" BODY_DEPTH "'"
+ "\\s[\\n[" LINESIZE_REG "]]");
+ if (r > nrows - 1)
+ prints("\\D'l |\\n[TW]u 0'");
+ else {
+ int start_col = 0;
+ for (;;) {
+ while (start_col < ncolumns
+ && entry[r][start_col] != 0
+ && entry[r][start_col]->start_row != r)
+ start_col++;
+ int end_col;
+ for (end_col = start_col;
+ end_col < ncolumns
+ && (entry[r][end_col] == 0
+ || entry[r][end_col]->start_row == r);
+ end_col++)
+ ;
+ if (end_col <= start_col)
+ break;
+ printfs("\\h'|\\n[%1]u",
+ column_divide_reg(start_col));
+ if ((r > 0 && vline[r-1][start_col] == 2)
+ || (r < nrows && vline[r][start_col] == 2))
+ prints("-" HALF_DOUBLE_LINE_SEP);
+ prints("'");
+ printfs("\\D'l |\\n[%1]u",
+ column_divide_reg(end_col));
+ if ((r > 0 && vline[r-1][end_col] == 2)
+ || (r < nrows && vline[r][end_col] == 2))
+ prints("+" HALF_DOUBLE_LINE_SEP);
+ prints(" 0'");
+ start_col = end_col;
+ }
+ }
+ prints("\\s0\n");
+ prints(".ls\n"
+ ".vs\n");
+}
+
+void table::print_double_hline(int r)
+{
+ prints(".vs " LINE_SEP "+" DOUBLE_LINE_SEP
+ ">?\\n[.V]u\n"
+ ".ls 1\n"
+ "\\v'" BODY_DEPTH "'"
+ "\\s[\\n[" LINESIZE_REG "]]");
+ if (r > nrows - 1)
+ prints("\\v'-" DOUBLE_LINE_SEP "'"
+ "\\D'l |\\n[TW]u 0'"
+ "\\v'" DOUBLE_LINE_SEP "'"
+ "\\h'|0'"
+ "\\D'l |\\n[TW]u 0'");
+ else {
+ int start_col = 0;
+ for (;;) {
+ while (start_col < ncolumns
+ && entry[r][start_col] != 0
+ && entry[r][start_col]->start_row != r)
+ start_col++;
+ int end_col;
+ for (end_col = start_col;
+ end_col < ncolumns
+ && (entry[r][end_col] == 0
+ || entry[r][end_col]->start_row == r);
+ end_col++)
+ ;
+ if (end_col <= start_col)
+ break;
+ const char *left_adjust = 0;
+ if ((r > 0 && vline[r-1][start_col] == 2)
+ || (r < nrows && vline[r][start_col] == 2))
+ left_adjust = "-" HALF_DOUBLE_LINE_SEP;
+ const char *right_adjust = 0;
+ if ((r > 0 && vline[r-1][end_col] == 2)
+ || (r < nrows && vline[r][end_col] == 2))
+ right_adjust = "+" HALF_DOUBLE_LINE_SEP;
+ printfs("\\v'-" DOUBLE_LINE_SEP "'"
+ "\\h'|\\n[%1]u",
+ column_divide_reg(start_col));
+ if (left_adjust)
+ prints(left_adjust);
+ prints("'");
+ printfs("\\D'l |\\n[%1]u",
+ column_divide_reg(end_col));
+ if (right_adjust)
+ prints(right_adjust);
+ prints(" 0'");
+ printfs("\\v'" DOUBLE_LINE_SEP "'"
+ "\\h'|\\n[%1]u",
+ column_divide_reg(start_col));
+ if (left_adjust)
+ prints(left_adjust);
+ prints("'");
+ printfs("\\D'l |\\n[%1]u",
+ column_divide_reg(end_col));
+ if (right_adjust)
+ prints(right_adjust);
+ prints(" 0'");
+ start_col = end_col;
+ }
+ }
+ prints("\\s0\n"
+ ".ls\n"
+ ".vs\n");
+}
+
+void table::compute_vrule_top_adjust(int start_row, int col, string &result)
+{
+ if (row_is_all_lines[start_row] && start_row < nrows - 1) {
+ if (row_is_all_lines[start_row] == 2)
+ result = LINE_SEP ">?\\n[.V]u" "+" DOUBLE_LINE_SEP;
+ else
+ result = LINE_SEP ">?\\n[.V]u";
+ start_row++;
+ }
+ else {
+ result = "";
+ if (start_row == 0)
+ return;
+ for (stuff *p = stuff_list; p && p->row <= start_row; p = p->next)
+ if (p->row == start_row
+ && (p->is_single_line() || p->is_double_line()))
+ return;
+ }
+ int left = 0;
+ if (col > 0) {
+ table_entry *e = entry[start_row-1][col-1];
+ if (e && e->start_row == e->end_row) {
+ if (e->to_double_line_entry() != 0)
+ left = 2;
+ else if (e->to_single_line_entry() != 0)
+ left = 1;
+ }
+ }
+ int right = 0;
+ if (col < ncolumns) {
+ table_entry *e = entry[start_row-1][col];
+ if (e && e->start_row == e->end_row) {
+ if (e->to_double_line_entry() != 0)
+ right = 2;
+ else if (e->to_single_line_entry() != 0)
+ right = 1;
+ }
+ }
+ if (row_is_all_lines[start_row-1] == 0) {
+ if (left > 0 || right > 0) {
+ result += "-" BODY_DEPTH "-" BAR_HEIGHT;
+ if ((left == 2 && right != 2) || (right == 2 && left != 2))
+ result += "-" HALF_DOUBLE_LINE_SEP;
+ else if (left == 2 && right == 2)
+ result += "+" HALF_DOUBLE_LINE_SEP;
+ }
+ }
+ else if (row_is_all_lines[start_row-1] == 2) {
+ if ((left == 2 && right != 2) || (right == 2 && left != 2))
+ result += "-" DOUBLE_LINE_SEP;
+ else if (left == 1 || right == 1)
+ result += "-" HALF_DOUBLE_LINE_SEP;
+ }
+}
+
+void table::compute_vrule_bot_adjust(int end_row, int col, string &result)
+{
+ if (row_is_all_lines[end_row] && end_row > 0) {
+ end_row--;
+ result = "";
+ }
+ else {
+ stuff *p;
+ for (p = stuff_list; p && p->row < end_row + 1; p = p->next)
+ ;
+ if (p && p->row == end_row + 1 && p->is_double_line()) {
+ result = "-" DOUBLE_LINE_SEP;
+ return;
+ }
+ if ((p != 0 && p->row == end_row + 1)
+ || end_row == nrows - 1) {
+ result = "";
+ return;
+ }
+ if (row_is_all_lines[end_row+1] == 1)
+ result = LINE_SEP;
+ else if (row_is_all_lines[end_row+1] == 2)
+ result = LINE_SEP "+" DOUBLE_LINE_SEP;
+ else
+ result = "";
+ }
+ int left = 0;
+ if (col > 0) {
+ table_entry *e = entry[end_row+1][col-1];
+ if (e && e->start_row == e->end_row) {
+ if (e->to_double_line_entry() != 0)
+ left = 2;
+ else if (e->to_single_line_entry() != 0)
+ left = 1;
+ }
+ }
+ int right = 0;
+ if (col < ncolumns) {
+ table_entry *e = entry[end_row+1][col];
+ if (e && e->start_row == e->end_row) {
+ if (e->to_double_line_entry() != 0)
+ right = 2;
+ else if (e->to_single_line_entry() != 0)
+ right = 1;
+ }
+ }
+ if (row_is_all_lines[end_row+1] == 0) {
+ if (left > 0 || right > 0) {
+ result = "1v-" BODY_DEPTH "-" BAR_HEIGHT;
+ if ((left == 2 && right != 2) || (right == 2 && left != 2))
+ result += "+" HALF_DOUBLE_LINE_SEP;
+ else if (left == 2 && right == 2)
+ result += "-" HALF_DOUBLE_LINE_SEP;
+ }
+ }
+ else if (row_is_all_lines[end_row+1] == 2) {
+ if (left == 2 && right == 2)
+ result += "-" DOUBLE_LINE_SEP;
+ else if (left != 2 && right != 2 && (left == 1 || right == 1))
+ result += "-" HALF_DOUBLE_LINE_SEP;
+ }
+}
+
+void table::add_vertical_rule(int start_row, int end_row, int col, int is_double)
+{
+ vrule_list = new vertical_rule(start_row, end_row, col, is_double,
+ vrule_list);
+ compute_vrule_top_adjust(start_row, col, vrule_list->top_adjust);
+ compute_vrule_bot_adjust(end_row, col, vrule_list->bot_adjust);
+}
+
+void table::build_vrule_list()
+{
+ int col;
+ if (flags & ALLBOX) {
+ for (col = 1; col < ncolumns; col++) {
+ int start_row = 0;
+ for (;;) {
+ while (start_row < nrows && vline_spanned(start_row, col))
+ start_row++;
+ if (start_row >= nrows)
+ break;
+ int end_row = start_row;
+ while (end_row < nrows && !vline_spanned(end_row, col))
+ end_row++;
+ end_row--;
+ add_vertical_rule(start_row, end_row, col, 0);
+ start_row = end_row + 1;
+ }
+ }
+ }
+ if (flags & (BOX|ALLBOX|DOUBLEBOX)) {
+ add_vertical_rule(0, nrows - 1, 0, 0);
+ add_vertical_rule(0, nrows - 1, ncolumns, 0);
+ }
+ for (int end_row = 0; end_row < nrows; end_row++)
+ for (col = 0; col < ncolumns+1; col++)
+ if (vline[end_row][col] > 0
+ && !vline_spanned(end_row, col)
+ && (end_row == nrows - 1
+ || vline[end_row+1][col] != vline[end_row][col]
+ || vline_spanned(end_row+1, col))) {
+ int start_row;
+ for (start_row = end_row - 1;
+ start_row >= 0
+ && vline[start_row][col] == vline[end_row][col]
+ && !vline_spanned(start_row, col);
+ start_row--)
+ ;
+ start_row++;
+ add_vertical_rule(start_row, end_row, col, vline[end_row][col] > 1);
+ }
+ for (vertical_rule *p = vrule_list; p; p = p->next)
+ if (p->is_double)
+ for (int r = p->start_row; r <= p->end_row; r++) {
+ if (p->col > 0 && entry[r][p->col-1] != 0
+ && entry[r][p->col-1]->end_col == p->col-1) {
+ int is_corner = r == p->start_row || r == p->end_row;
+ entry[r][p->col-1]->note_double_vrule_on_right(is_corner);
+ }
+ if (p->col < ncolumns && entry[r][p->col] != 0
+ && entry[r][p->col]->start_col == p->col) {
+ int is_corner = r == p->start_row || r == p->end_row;
+ entry[r][p->col]->note_double_vrule_on_left(is_corner);
+ }
+ }
+}
+
+void table::define_bottom_macro()
+{
+ prints(".eo\n"
+ ".de T#\n"
+ ".if !\\n[" SUPPRESS_BOTTOM_REG "] \\{"
+ "." REPEATED_VPT_MACRO " 0\n"
+ ".mk " SAVED_VERTICAL_POS_REG "\n");
+ if (flags & (BOX|ALLBOX|DOUBLEBOX)) {
+ prints(".if \\n[T.]&\\n[" NEED_BOTTOM_RULE_REG "] \\{");
+ print_single_hline(0);
+ prints(".\\}\n");
+ }
+ prints(".ls 1\n");
+ for (vertical_rule *p = vrule_list; p; p = p->next)
+ p->contribute_to_bottom_macro(this);
+ if (flags & DOUBLEBOX)
+ prints(".if \\n[T.] \\{.vs " DOUBLE_LINE_SEP ">?\\n[.V]u\n"
+ "\\v'" BODY_DEPTH "'\\s[\\n[" LINESIZE_REG "]]"
+ "\\D'l \\n[TW]u 0'\\s0\n"
+ ".vs\n"
+ ".\\}\n"
+ ".if \\n[" LAST_PASSED_ROW_REG "]>=0 "
+ ".nr " TOP_REG " \\n[#T]-" DOUBLE_LINE_SEP "\n"
+ ".sp -1\n"
+ "\\v'" BODY_DEPTH "'\\s[\\n[" LINESIZE_REG "]]"
+ "\\D'l 0 |\\n[" TOP_REG "]u-1v'\\s0\n"
+ ".sp -1\n"
+ "\\v'" BODY_DEPTH "'\\h'|\\n[TW]u'\\s[\\n[" LINESIZE_REG "]]"
+ "\\D'l 0 |\\n[" TOP_REG "]u-1v'\\s0\n");
+ prints(".ls\n");
+ prints(".nr " LAST_PASSED_ROW_REG " \\n[" CURRENT_ROW_REG "]\n"
+ ".sp |\\n[" SAVED_VERTICAL_POS_REG "]u\n"
+ "." REPEATED_VPT_MACRO " 1\n"
+ ".\\}\n"
+ "..\n"
+ ".ec\n");
+}
+
+
+// is the vertical line before column c in row r horizontally spanned?
+
+int table::vline_spanned(int r, int c)
+{
+ assert(r >= 0 && r < nrows && c >= 0 && c < ncolumns + 1);
+ return (c != 0 && c != ncolumns && entry[r][c] != 0
+ && entry[r][c]->start_col != c
+ // horizontally spanning lines don't count
+ && entry[r][c]->to_double_line_entry() == 0
+ && entry[r][c]->to_single_line_entry() == 0);
+}
+
+int table::row_begins_section(int r)
+{
+ assert(r >= 0 && r < nrows);
+ for (int i = 0; i < ncolumns; i++)
+ if (entry[r][i] && entry[r][i]->start_row != r)
+ return 0;
+ return 1;
+}
+
+int table::row_ends_section(int r)
+{
+ assert(r >= 0 && r < nrows);
+ for (int i = 0; i < ncolumns; i++)
+ if (entry[r][i] && entry[r][i]->end_row != r)
+ return 0;
+ return 1;
+}
+
+void table::do_row(int r)
+{
+ if (!(flags & NOKEEP) && row_begins_section(r))
+ prints("." KEEP_MACRO_NAME "\n");
+ int had_line = 0;
+ stuff *p;
+ for (p = stuff_list; p && p->row < r; p = p->next)
+ ;
+ for (stuff *p1 = p; p1 && p1->row == r; p1 = p1->next)
+ if (!p1->printed && (p1->is_single_line() || p1->is_double_line())) {
+ had_line = 1;
+ break;
+ }
+ if (!had_line && !row_is_all_lines[r])
+ printfs("." REPEATED_MARK_MACRO " %1\n", row_top_reg(r));
+ had_line = 0;
+ for (; p && p->row == r; p = p->next)
+ if (!p->printed) {
+ p->print(this);
+ if (!had_line && (p->is_single_line() || p->is_double_line())) {
+ printfs("." REPEATED_MARK_MACRO " %1\n", row_top_reg(r));
+ had_line = 1;
+ }
+ }
+ // Change the row *after* printing the stuff list (which might contain .TH).
+ printfs("\\*[" TRANSPARENT_STRING_NAME "].nr " CURRENT_ROW_REG " %1\n",
+ as_string(r));
+ if (!had_line && row_is_all_lines[r])
+ printfs("." REPEATED_MARK_MACRO " %1\n", row_top_reg(r));
+ // we might have had a .TH, for example, since we last tried
+ if (!(flags & NOKEEP) && row_begins_section(r))
+ prints("." KEEP_MACRO_NAME "\n");
+ printfs(".mk %1\n", row_start_reg(r));
+ prints(".mk " BOTTOM_REG "\n"
+ "." REPEATED_VPT_MACRO " 0\n");
+ int c;
+ int row_is_blank = 1;
+ int first_start_row = r;
+ for (c = 0; c < ncolumns; c++) {
+ table_entry *e = entry[r][c];
+ if (e) {
+ if (e->end_row == r) {
+ e->do_depth();
+ if (e->start_row < first_start_row)
+ first_start_row = e->start_row;
+ row_is_blank = 0;
+ }
+ c = e->end_col;
+ }
+ }
+ if (row_is_blank)
+ prints(".nr " BOTTOM_REG " +1v\n");
+ if (row_is_all_lines[r]) {
+ prints(".vs " LINE_SEP);
+ if (row_is_all_lines[r] == 2)
+ prints("+" DOUBLE_LINE_SEP);
+ prints(">?\\n[.V]u\n.ls 1\n");
+ prints("\\&");
+ prints("\\v'" BODY_DEPTH);
+ if (row_is_all_lines[r] == 2)
+ prints("-" HALF_DOUBLE_LINE_SEP);
+ prints("'");
+ for (c = 0; c < ncolumns; c++) {
+ table_entry *e = entry[r][c];
+ if (e) {
+ if (e->end_row == e->start_row)
+ e->to_simple_entry()->simple_print(1);
+ c = e->end_col;
+ }
+ }
+ prints("\n");
+ prints(".ls\n"
+ ".vs\n");
+ prints(".nr " BOTTOM_REG " \\n[" BOTTOM_REG "]>?\\n[.d]\n");
+ printfs(".sp |\\n[%1]u\n", row_start_reg(r));
+ }
+ for (int i = row_is_all_lines[r] ? r - 1 : r;
+ i >= first_start_row;
+ i--) {
+ simple_entry *first = 0;
+ for (c = 0; c < ncolumns; c++) {
+ table_entry *e = entry[r][c];
+ if (e) {
+ if (e->end_row == r && e->start_row == i) {
+ simple_entry *simple = e->to_simple_entry();
+ if (simple) {
+ if (!first) {
+ prints(".ta");
+ first = simple;
+ }
+ simple->add_tab();
+ }
+ }
+ c = e->end_col;
+ }
+ }
+ if (first) {
+ prints('\n');
+ first->position_vertically();
+ first->set_location();
+ prints("\\&");
+ first->simple_print(0);
+ for (c = first->end_col + 1; c < ncolumns; c++) {
+ table_entry *e = entry[r][c];
+ if (e) {
+ if (e->end_row == r && e->start_row == i) {
+ simple_entry *simple = e->to_simple_entry();
+ if (simple)
+ simple->simple_print(0);
+ }
+ c = e->end_col;
+ }
+ }
+ prints('\n');
+ prints(".nr " BOTTOM_REG " \\n[" BOTTOM_REG "]>?\\n[.d]\n");
+ printfs(".sp |\\n[%1]u\n", row_start_reg(r));
+ }
+ }
+ for (c = 0; c < ncolumns; c++) {
+ table_entry *e = entry[r][c];
+ if (e) {
+ if (e->end_row == r && e->to_simple_entry() == 0) {
+ e->position_vertically();
+ e->print();
+ prints(".nr " BOTTOM_REG " \\n[" BOTTOM_REG "]>?\\n[.d]\n");
+ printfs(".sp |\\n[%1]u\n", row_start_reg(r));
+ }
+ c = e->end_col;
+ }
+ }
+ prints("." REPEATED_VPT_MACRO " 1\n"
+ ".sp |\\n[" BOTTOM_REG "]u\n"
+ "\\*[" TRANSPARENT_STRING_NAME "].nr " NEED_BOTTOM_RULE_REG " 1\n");
+ if (r != nrows - 1 && (flags & ALLBOX)) {
+ print_single_hline(r + 1);
+ prints("\\*[" TRANSPARENT_STRING_NAME "].nr " NEED_BOTTOM_RULE_REG " 0\n");
+ }
+ if (r != nrows - 1) {
+ if (p && p->row == r + 1
+ && (p->is_single_line() || p->is_double_line())) {
+ p->print(this);
+ prints("\\*[" TRANSPARENT_STRING_NAME "].nr " NEED_BOTTOM_RULE_REG
+ " 0\n");
+ }
+ int printed_one = 0;
+ for (vertical_rule *vr = vrule_list; vr; vr = vr->next)
+ if (vr->end_row == r) {
+ if (!printed_one) {
+ prints("." REPEATED_VPT_MACRO " 0\n");
+ printed_one = 1;
+ }
+ vr->print();
+ }
+ if (printed_one)
+ prints("." REPEATED_VPT_MACRO " 1\n");
+ if (!(flags & NOKEEP) && row_ends_section(r))
+ prints("." RELEASE_MACRO_NAME "\n");
+ }
+}
+
+void table::do_top()
+{
+ prints(".fc \002\003\n");
+ if (!(flags & NOKEEP) && (flags & (BOX|DOUBLEBOX|ALLBOX)))
+ prints("." TABLE_KEEP_MACRO_NAME "\n");
+ if (flags & DOUBLEBOX) {
+ prints(".ls 1\n"
+ ".vs " LINE_SEP ">?\\n[.V]u\n"
+ "\\v'" BODY_DEPTH "'\\s[\\n[" LINESIZE_REG "]]\\D'l \\n[TW]u 0'\\s0\n"
+ ".vs\n"
+ "." REPEATED_MARK_MACRO " " TOP_REG "\n"
+ ".vs " DOUBLE_LINE_SEP ">?\\n[.V]u\n");
+ printfs("\\v'" BODY_DEPTH "'"
+ "\\s[\\n[" LINESIZE_REG "]]"
+ "\\h'\\n[%1]u'"
+ "\\D'l |\\n[%2]u 0'"
+ "\\s0"
+ "\n",
+ column_divide_reg(0),
+ column_divide_reg(ncolumns));
+ prints(".ls\n"
+ ".vs\n");
+ }
+ else if (flags & (ALLBOX|BOX)) {
+ print_single_hline(0);
+ }
+ //printfs(".mk %1\n", row_top_reg(0));
+}
+
+void table::do_bottom()
+{
+ // print stuff after last row
+ for (stuff *p = stuff_list; p; p = p->next)
+ if (p->row > nrows - 1)
+ p->print(this);
+ if (!(flags & NOKEEP))
+ prints("." RELEASE_MACRO_NAME "\n");
+ printfs(".mk %1\n", row_top_reg(nrows));
+ prints(".nr " NEED_BOTTOM_RULE_REG " 1\n"
+ ".nr T. 1\n"
+ ".T#\n");
+ if (!(flags & NOKEEP) && (flags & (BOX|DOUBLEBOX|ALLBOX)))
+ prints("." TABLE_RELEASE_MACRO_NAME "\n");
+ if (flags & DOUBLEBOX)
+ prints(".sp " DOUBLE_LINE_SEP "\n");
+ prints("." RESET_MACRO_NAME "\n"
+ ".fc\n"
+ ".cp \\n(" COMPATIBLE_REG "\n");
+}
+
+int table::get_nrows()
+{
+ return nrows;
+}
+
+const char *last_filename = 0;
+
+void set_troff_location(const char *fn, int ln)
+{
+ if (!location_force_filename && last_filename != 0
+ && strcmp(fn, last_filename) == 0)
+ printfs(".lf %1\n", as_string(ln));
+ else {
+ printfs(".lf %1 %2\n", as_string(ln), fn);
+ last_filename = fn;
+ location_force_filename = 0;
+ }
+}
+
+void printfs(const char *s, const string &arg1, const string &arg2,
+ const string &arg3, const string &arg4, const string &arg5)
+{
+ if (s) {
+ char c;
+ while ((c = *s++) != '\0') {
+ if (c == '%') {
+ switch (*s++) {
+ case '1':
+ prints(arg1);
+ break;
+ case '2':
+ prints(arg2);
+ break;
+ case '3':
+ prints(arg3);
+ break;
+ case '4':
+ prints(arg4);
+ break;
+ case '5':
+ prints(arg5);
+ break;
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ break;
+ case '%':
+ prints('%');
+ break;
+ default:
+ assert(0);
+ }
+ }
+ else
+ prints(c);
+ }
+ }
+}
+
diff --git a/src/preproc/tbl/table.h b/src/preproc/tbl/table.h
new file mode 100644
index 00000000..ca55b802
--- /dev/null
+++ b/src/preproc/tbl/table.h
@@ -0,0 +1,152 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "cset.h"
+#include "cmap.h"
+#include "stringclass.h"
+#include "errarg.h"
+#include "error.h"
+#include "lib.h"
+
+struct inc_number {
+ short inc;
+ short val;
+};
+
+struct entry_modifier {
+ inc_number point_size;
+ inc_number vertical_spacing;
+ string font;
+ enum { CENTER, TOP, BOTTOM } vertical_alignment;
+ char zero_width;
+ char stagger;
+
+ entry_modifier();
+ ~entry_modifier();
+};
+
+enum format_type {
+ FORMAT_LEFT,
+ FORMAT_CENTER,
+ FORMAT_RIGHT,
+ FORMAT_NUMERIC,
+ FORMAT_ALPHABETIC,
+ FORMAT_SPAN,
+ FORMAT_VSPAN,
+ FORMAT_HLINE,
+ FORMAT_DOUBLE_HLINE
+};
+
+struct entry_format : public entry_modifier {
+ format_type type;
+
+ entry_format(format_type);
+ entry_format();
+ void debug_print() const;
+};
+
+struct table_entry;
+struct horizontal_span;
+struct stuff;
+struct vertical_rule;
+
+class table {
+ unsigned flags;
+ int nrows;
+ int ncolumns;
+ int linesize;
+ char delim[2];
+ char decimal_point_char;
+ vertical_rule *vrule_list;
+ stuff *stuff_list;
+ horizontal_span *span_list;
+ table_entry *entry_list;
+ table_entry **entry_list_tailp;
+ table_entry ***entry;
+ char **vline;
+ char *row_is_all_lines;
+ string *minimum_width;
+ int *column_separation;
+ char *equal;
+ int left_separation;
+ int right_separation;
+ int allocated_rows;
+ void build_span_list();
+ void do_hspan(int r, int c);
+ void do_vspan(int r, int c);
+ void allocate(int r);
+ void compute_widths();
+ void divide_span(int, int);
+ void sum_columns(int, int);
+ void compute_separation_factor();
+ void compute_column_positions();
+ void do_row(int);
+ void init_output();
+ void add_stuff(stuff *);
+ void do_top();
+ void do_bottom();
+ void do_vertical_rules();
+ void build_vrule_list();
+ void add_vertical_rule(int, int, int, int);
+ void define_bottom_macro();
+ int vline_spanned(int r, int c);
+ int row_begins_section(int);
+ int row_ends_section(int);
+ void make_columns_equal();
+ void compute_vrule_top_adjust(int, int, string &);
+ void compute_vrule_bot_adjust(int, int, string &);
+ void determine_row_type();
+public:
+ /* used by flags */
+ enum {
+ CENTER = 01,
+ EXPAND = 02,
+ BOX = 04,
+ ALLBOX = 010,
+ DOUBLEBOX = 020,
+ NOKEEP = 040
+ };
+ table(int nc, unsigned flags, int linesize, char decimal_point_char);
+ ~table();
+
+ void add_text_line(int r, const string &, const char *, int);
+ void add_single_hline(int r);
+ void add_double_hline(int r);
+ void add_entry(int r, int c, const string &, const entry_format *,
+ const char *, int lineno);
+ void add_vlines(int r, const char *);
+ void check();
+ void print();
+ void set_minimum_width(int c, const string &w);
+ void set_column_separation(int c, int n);
+ void set_equal_column(int c);
+ void set_delim(char c1, char c2);
+ void print_single_hline(int r);
+ void print_double_hline(int r);
+ int get_nrows();
+};
+
+void set_troff_location(const char *, int);
diff --git a/src/preproc/tbl/tbl.man b/src/preproc/tbl/tbl.man
new file mode 100644
index 00000000..6016ddf3
--- /dev/null
+++ b/src/preproc/tbl/tbl.man
@@ -0,0 +1,178 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.TH @G@TBL @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+@g@tbl \- format tables for troff
+.SH SYNOPSIS
+.B @g@tbl
+[
+.B \-Cv
+]
+[
+.IR files \|.\|.\|.
+]
+.SH DESCRIPTION
+This manual page describes the GNU version of
+.BR tbl ,
+which is part of the groff document formatting system.
+.B tbl
+compiles descriptions of tables embedded within
+.B troff
+input files into commands that are understood by
+.BR troff .
+Normally, it should be invoked using the
+.B \-t
+option of
+.B groff.
+It is highly compatible with Unix
+.BR tbl .
+The output generated by GNU
+.B tbl
+cannot be processed with Unix
+.BR troff ;
+it must be processed with GNU
+.BR troff .
+If no files are given on the command line, the standard input
+will be read.
+A filename of
+.B \-
+will cause the standard input to be read.
+.SH OPTIONS
+.TP
+.B \-C
+Recognize
+.B .TS
+and
+.B .TE
+even when followed by a character other than space or newline.
+.TP
+.B \-v
+Print the version number.
+.SH USAGE
+Only the differences between GNU
+.B tbl
+and Unix
+.B tbl
+are described here.
+.LP
+Normally
+.B tbl
+attempts to prevent undesirable breaks in the table by using diversions.
+This can sometimes interact badly with macro packages' own use of diversions,
+when footnotes, for example, are used.
+The
+.B nokeep
+option tells
+.B tbl
+not to try and prevent breaks in this way.
+.LP
+The
+.B decimalpoint
+option specifies the character to be recognized as the decimal
+point character in place of the default period.
+It takes an argument in parentheses, which must be a single
+character, as for the
+.B tab
+option.
+.LP
+The
+.B f
+format modifier can be followed by an arbitrary length
+font name in parentheses.
+.LP
+There is a
+.B d
+format modifier which means that a vertically spanning entry
+should be aligned at the bottom of its range.
+.LP
+There is no limit on the number of columns in a table, nor any limit
+on the number of text blocks.
+All the lines of a table are considered in deciding column
+widths, not just the first 200.
+Table continuation
+.RB ( .T& )
+lines are not restricted to the first 200 lines.
+.LP
+Numeric and alphabetic items may appear in the same column.
+.LP
+Numeric and alphabetic items may span horizontally.
+.LP
+.B tbl
+uses register, string, macro and diversion names beginning with
+.BR 3 .
+When using
+.B tbl
+you should avoid using any names beginning with a
+.BR 3 .
+.SH BUGS
+You should use
+.BR .TS\ H / .TH
+in conjunction with a supporting macro package for
+.I all
+multi-page boxed tables.
+If there is no header that you wish to appear at the top of each page
+of the table, place the
+.B .TH
+line immediately after the format section.
+Do not enclose a multi-page table within keep/release macros,
+or divert it in any other way.
+.LP
+A text block within a table must be able to fit on one page.
+.LP
+The
+.B bp
+request cannot be used to force a page-break in a multi-page table.
+Instead, define
+.B BP
+as follows
+.IP
+.B .de BP
+.br
+.B .ie '\e\en(.z'' .bp \e\e$1
+.br
+.B .el \e!.BP \e\e$1
+.br
+.B ..
+.br
+.LP
+and use
+.B BP
+instead of
+.BR bp .
+.LP
+Using \ea directly in a table to get leaders will not work.
+This is correct behaviour: \ea is a
+.B uninterpreted
+leader.
+To get leaders use a real leader, either by using a control A or like
+this:
+.IP
+.nf
+.ft B
+\&.ds a \ea
+\&.TS
+tab(;);
+lw(1i) l.
+A\e*a;B
+\&.TE
+.ft
+.fi
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@)
diff --git a/src/roff/groff/Makefile.sub b/src/roff/groff/Makefile.sub
new file mode 100644
index 00000000..42ae221c
--- /dev/null
+++ b/src/roff/groff/Makefile.sub
@@ -0,0 +1,8 @@
+PROG=groff
+MAN1=groff.n
+XLIBS=$(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=groff.o pipeline.o
+CCSRCS=$(srcdir)/groff.cc
+CSRCS=$(srcdir)/pipeline.c
+HDRS=$(srcdir)/pipeline.h
diff --git a/src/roff/groff/groff.cc b/src/roff/groff/groff.cc
new file mode 100644
index 00000000..c5f55e02
--- /dev/null
+++ b/src/roff/groff/groff.cc
@@ -0,0 +1,619 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+// A front end for groff.
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+
+#include "lib.h"
+#include "assert.h"
+#include "errarg.h"
+#include "error.h"
+#include "stringclass.h"
+#include "cset.h"
+#include "font.h"
+#include "device.h"
+#include "pipeline.h"
+#include "defs.h"
+
+#define BSHELL "/bin/sh"
+#define GXDITVIEW "gxditview"
+
+// troff will be passed an argument of -rXREG=1 if the -X option is
+// specified
+#define XREG ".X"
+
+#ifndef STDLIB_H_DECLARES_PUTENV
+extern "C" {
+ int putenv(const char *);
+}
+#endif /* not STDLIB_H_DECLARES_PUTENV */
+
+const int SOELIM_INDEX = 0;
+const int REFER_INDEX = SOELIM_INDEX + 1;
+const int PIC_INDEX = REFER_INDEX + 1;
+const int TBL_INDEX = PIC_INDEX + 1;
+const int EQN_INDEX = TBL_INDEX + 1;
+const int TROFF_INDEX = EQN_INDEX + 1;
+const int POST_INDEX = TROFF_INDEX + 1;
+const int SPOOL_INDEX = POST_INDEX + 1;
+
+const int NCOMMANDS = SPOOL_INDEX + 1;
+
+class possible_command {
+ char *name;
+ string args;
+ char **argv;
+
+ void build_argv();
+public:
+ possible_command();
+ ~possible_command();
+ void set_name(const char *);
+ void set_name(const char *, const char *);
+ const char *get_name();
+ void append_arg(const char *, const char * = 0);
+ void insert_arg(const char *);
+ void clear_args();
+ char **get_argv();
+ void print(int is_last, FILE *fp);
+};
+
+int lflag = 0;
+char *spooler = 0;
+char *driver = 0;
+
+possible_command commands[NCOMMANDS];
+
+int run_commands();
+void print_commands();
+void append_arg_to_string(const char *arg, string &str);
+void handle_unknown_desc_command(const char *command, const char *arg,
+ const char *filename, int lineno);
+const char *xbasename(const char *);
+
+void usage();
+void help();
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ assert(NCOMMANDS <= MAX_COMMANDS);
+ string Pargs, Largs, Fargs;
+ int Vflag = 0;
+ int zflag = 0;
+ int iflag = 0;
+ int Xflag = 0;
+ int safer_flag = 1;
+ int opt;
+ const char *command_prefix = getenv("GROFF_COMMAND_PREFIX");
+ if (!command_prefix)
+ command_prefix = PROG_PREFIX;
+ commands[TROFF_INDEX].set_name(command_prefix, "troff");
+ while ((opt = getopt(argc, argv,
+ "abCd:eEf:F:hiI:lL:m:M:n:No:pP:r:RsStT:UvVw:W:XzZ"))
+ != EOF) {
+ char buf[3];
+ buf[0] = '-';
+ buf[1] = opt;
+ buf[2] = '\0';
+ switch (opt) {
+ case 'i':
+ iflag = 1;
+ break;
+ case 'I':
+ commands[SOELIM_INDEX].set_name(command_prefix, "soelim");
+ commands[SOELIM_INDEX].append_arg(buf, optarg);
+ break;
+ case 't':
+ commands[TBL_INDEX].set_name(command_prefix, "tbl");
+ break;
+ case 'p':
+ commands[PIC_INDEX].set_name(command_prefix, "pic");
+ break;
+ case 'e':
+ commands[EQN_INDEX].set_name(command_prefix, "eqn");
+ break;
+ case 's':
+ commands[SOELIM_INDEX].set_name(command_prefix, "soelim");
+ break;
+ case 'R':
+ commands[REFER_INDEX].set_name(command_prefix, "refer");
+ break;
+ case 'z':
+ case 'a':
+ commands[TROFF_INDEX].append_arg(buf);
+ // fall through
+ case 'Z':
+ zflag++;
+ break;
+ case 'l':
+ lflag++;
+ break;
+ case 'V':
+ Vflag++;
+ break;
+ case 'v':
+ case 'C':
+ commands[SOELIM_INDEX].append_arg(buf);
+ commands[PIC_INDEX].append_arg(buf);
+ commands[TBL_INDEX].append_arg(buf);
+ commands[EQN_INDEX].append_arg(buf);
+ commands[TROFF_INDEX].append_arg(buf);
+ break;
+ case 'N':
+ commands[EQN_INDEX].append_arg(buf);
+ break;
+ case 'h':
+ help();
+ break;
+ case 'E':
+ case 'b':
+ commands[TROFF_INDEX].append_arg(buf);
+ break;
+ case 'S':
+ safer_flag = 1;
+ break;
+ case 'U':
+ safer_flag = 0;
+ break;
+ case 'T':
+ if (strcmp(optarg, "Xps") == 0) {
+ warning("-TXps option is obsolete: use -X -Tps instead");
+ device = "ps";
+ Xflag++;
+ }
+ else
+ device = optarg;
+ break;
+ case 'F':
+ font::command_line_font_dir(optarg);
+ if (Fargs.length() > 0) {
+ Fargs += ':';
+ Fargs += optarg;
+ }
+ else
+ Fargs = optarg;
+ break;
+ case 'f':
+ case 'o':
+ case 'm':
+ case 'r':
+ case 'd':
+ case 'n':
+ case 'w':
+ case 'W':
+ commands[TROFF_INDEX].append_arg(buf, optarg);
+ break;
+ case 'M':
+ commands[EQN_INDEX].append_arg(buf, optarg);
+ commands[TROFF_INDEX].append_arg(buf, optarg);
+ break;
+ case 'P':
+ Pargs += optarg;
+ Pargs += '\0';
+ break;
+ case 'L':
+ append_arg_to_string(optarg, Largs);
+ break;
+ case 'X':
+ Xflag++;
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ if (safer_flag) {
+ commands[PIC_INDEX].append_arg("-S");
+ commands[TROFF_INDEX].insert_arg("-msafer");
+ } else {
+ commands[TROFF_INDEX].insert_arg("-U");
+ }
+ font::set_unknown_desc_command_handler(handle_unknown_desc_command);
+ if (!font::load_desc())
+ fatal("invalid device `%1'", device);
+ if (!driver)
+ fatal("no `postpro' command in DESC file for device `%1'", device);
+ const char *real_driver = 0;
+ if (Xflag) {
+ real_driver = driver;
+ driver = GXDITVIEW;
+ commands[TROFF_INDEX].append_arg("-r" XREG "=", "1");
+ }
+ if (driver)
+ commands[POST_INDEX].set_name(driver);
+ int gxditview_flag = driver && strcmp(xbasename(driver), GXDITVIEW) == 0;
+ if (gxditview_flag && argc - optind == 1) {
+ commands[POST_INDEX].append_arg("-title");
+ commands[POST_INDEX].append_arg(argv[optind]);
+ commands[POST_INDEX].append_arg("-xrm");
+ commands[POST_INDEX].append_arg("*iconName:", argv[optind]);
+ string filename_string("|");
+ append_arg_to_string(argv[0], filename_string);
+ append_arg_to_string("-Z", filename_string);
+ for (int i = 1; i < argc; i++)
+ append_arg_to_string(argv[i], filename_string);
+ filename_string += '\0';
+ commands[POST_INDEX].append_arg("-filename");
+ commands[POST_INDEX].append_arg(filename_string.contents());
+ }
+ if (gxditview_flag && Xflag) {
+ string print_string(real_driver);
+ if (spooler) {
+ print_string += " | ";
+ print_string += spooler;
+ print_string += Largs;
+ }
+ print_string += '\0';
+ commands[POST_INDEX].append_arg("-printCommand");
+ commands[POST_INDEX].append_arg(print_string.contents());
+ }
+ const char *p = Pargs.contents();
+ const char *end = p + Pargs.length();
+ while (p < end) {
+ commands[POST_INDEX].append_arg(p);
+ p = strchr(p, '\0') + 1;
+ }
+ if (gxditview_flag)
+ commands[POST_INDEX].append_arg("-");
+ if (lflag && !Xflag && spooler) {
+ commands[SPOOL_INDEX].set_name(BSHELL);
+ commands[SPOOL_INDEX].append_arg("-c");
+ Largs += '\0';
+ Largs = spooler + Largs;
+ commands[SPOOL_INDEX].append_arg(Largs.contents());
+ }
+ if (zflag) {
+ commands[POST_INDEX].set_name(0);
+ commands[SPOOL_INDEX].set_name(0);
+ }
+ commands[TROFF_INDEX].append_arg("-T", device);
+ commands[EQN_INDEX].append_arg("-T", device);
+
+ int first_index;
+ for (first_index = 0; first_index < TROFF_INDEX; first_index++)
+ if (commands[first_index].get_name() != 0)
+ break;
+ if (optind < argc) {
+ if (argv[optind][0] == '-' && argv[optind][1] != '\0')
+ commands[first_index].append_arg("--");
+ for (int i = optind; i < argc; i++)
+ commands[first_index].append_arg(argv[i]);
+ if (iflag)
+ commands[first_index].append_arg("-");
+ }
+ if (Fargs.length() > 0) {
+ string e = "GROFF_FONT_PATH";
+ e += '=';
+ e += Fargs;
+ char *fontpath = getenv("GROFF_FONT_PATH");
+ if (fontpath && *fontpath) {
+ e += ':';
+ e += fontpath;
+ }
+ e += '\0';
+ if (putenv(strsave(e.contents())))
+ fatal("putenv failed");
+ }
+ if (Vflag) {
+ print_commands();
+ exit(0);
+ }
+ return run_commands();
+}
+
+const char *xbasename(const char *s)
+{
+ if (!s)
+ return 0;
+ const char *p = strrchr(s, '/');
+ return p ? p + 1 : s;
+}
+
+void handle_unknown_desc_command(const char *command, const char *arg,
+ const char *filename, int lineno)
+{
+ if (strcmp(command, "print") == 0) {
+ if (arg == 0)
+ error_with_file_and_line(filename, lineno,
+ "`print' command requires an argument");
+ else
+ spooler = strsave(arg);
+ }
+ if (strcmp(command, "postpro") == 0) {
+ if (arg == 0)
+ error_with_file_and_line(filename, lineno,
+ "`postpro' command requires an argument");
+ else {
+ for (const char *p = arg; *p; p++)
+ if (csspace(*p)) {
+ error_with_file_and_line(filename, lineno,
+ "invalid `postpro' argument `%1'"
+ ": program name required", arg);
+ return;
+ }
+ driver = strsave(arg);
+ }
+ }
+}
+
+void print_commands()
+{
+ int last;
+ for (last = SPOOL_INDEX; last >= 0; last--)
+ if (commands[last].get_name() != 0)
+ break;
+ for (int i = 0; i <= last; i++)
+ if (commands[i].get_name() != 0)
+ commands[i].print(i == last, stdout);
+}
+
+// Run the commands. Return the code with which to exit.
+
+int run_commands()
+{
+ char **v[NCOMMANDS];
+ int j = 0;
+ for (int i = 0; i < NCOMMANDS; i++)
+ if (commands[i].get_name() != 0)
+ v[j++] = commands[i].get_argv();
+ return run_pipeline(j, v);
+}
+
+possible_command::possible_command()
+: name(0), argv(0)
+{
+}
+
+possible_command::~possible_command()
+{
+ a_delete name;
+ a_delete argv;
+}
+
+void possible_command::set_name(const char *s)
+{
+ a_delete name;
+ name = strsave(s);
+}
+
+void possible_command::set_name(const char *s1, const char *s2)
+{
+ a_delete name;
+ name = new char[strlen(s1) + strlen(s2) + 1];
+ strcpy(name, s1);
+ strcat(name, s2);
+}
+
+const char *possible_command::get_name()
+{
+ return name;
+}
+
+void possible_command::clear_args()
+{
+ args.clear();
+}
+
+void possible_command::append_arg(const char *s, const char *t)
+{
+ args += s;
+ if (t)
+ args += t;
+ args += '\0';
+}
+
+void possible_command::insert_arg(const char *s)
+{
+ string str(s);
+ str += '\0';
+ str += args;
+ args = str;
+}
+
+void possible_command::build_argv()
+{
+ if (argv)
+ return;
+ // Count the number of arguments.
+ int len = args.length();
+ int argc = 1;
+ char *p = 0;
+ if (len > 0) {
+ p = &args[0];
+ for (int i = 0; i < len; i++)
+ if (p[i] == '\0')
+ argc++;
+ }
+ // Build an argument vector.
+ argv = new char *[argc + 1];
+ argv[0] = name;
+ for (int i = 1; i < argc; i++) {
+ argv[i] = p;
+ p = strchr(p, '\0') + 1;
+ }
+ argv[argc] = 0;
+}
+
+void possible_command::print(int is_last, FILE *fp)
+{
+ build_argv();
+ if (argv[0] != 0 && strcmp(argv[0], BSHELL) == 0
+ && argv[1] != 0 && strcmp(argv[1], "-c") == 0
+ && argv[2] != 0 && argv[3] == 0)
+ fputs(argv[2], fp);
+ else {
+ fputs(argv[0], fp);
+ string str;
+ for (int i = 1; argv[i] != 0; i++) {
+ str.clear();
+ append_arg_to_string(argv[i], str);
+ put_string(str, fp);
+ }
+ }
+ if (is_last)
+ putc('\n', fp);
+ else
+ fputs(" | ", fp);
+}
+
+void append_arg_to_string(const char *arg, string &str)
+{
+ str += ' ';
+ int needs_quoting = 0;
+ int contains_single_quote = 0;
+ const char*p;
+ for (p = arg; *p != '\0'; p++)
+ switch (*p) {
+ case ';':
+ case '&':
+ case '(':
+ case ')':
+ case '|':
+ case '^':
+ case '<':
+ case '>':
+ case '\n':
+ case ' ':
+ case '\t':
+ case '\\':
+ case '"':
+ case '$':
+ case '?':
+ case '*':
+ needs_quoting = 1;
+ break;
+ case '\'':
+ contains_single_quote = 1;
+ break;
+ }
+ if (contains_single_quote || arg[0] == '\0') {
+ str += '"';
+ for (p = arg; *p != '\0'; p++)
+ switch (*p) {
+ case '"':
+ case '\\':
+ case '$':
+ str += '\\';
+ // fall through
+ default:
+ str += *p;
+ break;
+ }
+ str += '"';
+ }
+ else if (needs_quoting) {
+ str += '\'';
+ str += arg;
+ str += '\'';
+ }
+ else
+ str += arg;
+}
+
+char **possible_command::get_argv()
+{
+ build_argv();
+ return argv;
+}
+
+void synopsis()
+{
+ fprintf(stderr,
+"usage: %s [-abehilpstvzCENRSUVXZ] [-Fdir] [-mname] [-Tdev] [-ffam] [-wname]\n"
+" [-Wname] [-Mdir] [-dcs] [-rcn] [-nnum] [-olist] [-Parg] [-Larg]\n"
+" [files...]\n",
+ program_name);
+}
+
+void help()
+{
+ synopsis();
+ fputs("\n"
+"-h\tprint this message\n"
+"-t\tpreprocess with tbl\n"
+"-p\tpreprocess with pic\n"
+"-e\tpreprocess with eqn\n"
+"-s\tpreprocess with soelim\n"
+"-R\tpreprocess with refer\n"
+"-Tdev\tuse device dev\n"
+"-X\tuse X11 previewer rather than usual postprocessor\n"
+"-mname\tread macros tmac.name\n"
+"-dcs\tdefine a string c as s\n"
+"-rcn\tdefine a number register c as n\n"
+"-nnum\tnumber first page n\n"
+"-olist\toutput only pages in list\n"
+"-ffam\tuse fam as the default font family\n"
+"-Fdir\tsearch directory dir for device directories\n"
+"-Mdir\tsearch dir for macro files\n"
+"-v\tprint version number\n"
+"-z\tsuppress formatted output\n"
+"-Z\tdon't postprocess\n"
+"-a\tproduce ASCII description of output\n"
+"-i\tread standard input after named input files\n"
+"-wname\tenable warning name\n"
+"-Wname\tinhibit warning name\n"
+"-E\tinhibit all errors\n"
+"-b\tprint backtraces with errors or warnings\n"
+"-l\tspool the output\n"
+"-C\tenable compatibility mode\n"
+"-V\tprint commands on stdout instead of running them\n"
+"-Parg\tpass arg to the postprocessor\n"
+"-Larg\tpass arg to the spooler\n"
+"-N\tdon't allow newlines within eqn delimiters\n"
+"-S\tenable safer mode (the default)\n"
+"-U\tenable unsafe mode\n"
+"\n",
+ stderr);
+ exit(0);
+}
+
+void usage()
+{
+ synopsis();
+ fprintf(stderr, "%s -h gives more help\n", program_name);
+ exit(1);
+}
+
+extern "C" {
+
+void c_error(const char *format, const char *arg1, const char *arg2,
+ const char *arg3)
+{
+ error(format, arg1, arg2, arg3);
+}
+
+void c_fatal(const char *format, const char *arg1, const char *arg2,
+ const char *arg3)
+{
+ fatal(format, arg1, arg2, arg3);
+}
+
+}
diff --git a/src/roff/groff/groff.man b/src/roff/groff/groff.man
new file mode 100644
index 00000000..0d36ba8e
--- /dev/null
+++ b/src/roff/groff/groff.man
@@ -0,0 +1,432 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1999-2000 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.de TQ
+.br
+.ns
+.TP \\$1
+..
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.TH GROFF @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+groff \- front end for the groff document formatting system
+.SH SYNOPSIS
+.B groff
+[
+.B \-abehilpstvzCENRSUVXZ
+]
+[
+.BI \-w name
+]
+[
+.BI \-W name
+]
+[
+.BI \-m name
+]
+[
+.BI \-F dir
+]
+[
+.BI \-I dir
+]
+[
+.BI \-T dev
+]
+[
+.BI \-f fam
+]
+[
+.BI \-M dir
+]
+[
+.BI \-d cs
+]
+[
+.BI \-r cn
+]
+[
+.BI \-n num
+]
+[
+.BI \-o list
+]
+[
+.BI \-P arg
+]
+[
+.BI \-L arg
+]
+[
+.IR files \|.\|.\|.\|
+]
+.SH DESCRIPTION
+.B groff
+is a front-end to the groff document formatting system.
+Normally it runs the
+.B @g@troff
+program and a postprocessor appropriate for the selected
+device.
+Available devices are:
+.TP
+.B ps
+For PostScript printers and previewers
+.TP
+.B dvi
+For TeX dvi format.
+.TP
+.B X75
+For a 75 dpi X11 previewer.
+.TP
+.B X100
+For a 100dpi X11 previewer.
+.TP
+.B ascii
+For typewriter-like devices.
+.TP
+.B latin1
+For typewriter-like devices using the ISO Latin-1 (ISO 8859-1) character set.
+.TP
+.B utf8
+For typewriter-like devices using the Unicode (ISO 10646) character set with
+UTF-8 encoding.
+.TP
+.B lj4
+For an HP LaserJet4-compatible (or other PCL5-compatible) printer.
+.TP
+.B html
+To produce HTML output.
+.LP
+The postprocessor to be used for a device is specified by the
+.B postpro
+command in the device description file.
+This can be overridden with the
+.B \-X
+option.
+.LP
+The default device is
+.BR @DEVICE@ .
+It can optionally preprocess with any of
+.BR @g@pic ,
+.BR @g@eqn ,
+.BR @g@tbl ,
+.BR @g@refer ,
+or
+.B @g@soelim.
+.LP
+Options without an argument can be grouped behind a single
+.BR \- .
+A filename of
+.B \-
+denotes the standard input.
+.LP
+The
+.B grog
+command can be used to guess the correct groff command to use to
+format a file.
+.SH OPTIONS
+.TP
+.B \-h
+Print a help message.
+.TP
+.B \-e
+Preprocess with @g@eqn.
+.TP
+.B \-t
+Preprocess with @g@tbl.
+.TP
+.B \-p
+Preprocess with @g@pic.
+.TP
+.B \-s
+Preprocess with @g@soelim.
+.TP
+.BI \-I dir
+This option is as described in
+.BR @g@soelim (@MAN1EXT@) .
+This option implies the
+.B \-s
+option.
+.TP
+.B \-R
+Preprocess with @g@refer.
+No mechanism is provided for passing arguments to
+.B @g@refer
+because most @g@refer options have equivalent commands
+which can be included in the file.
+See
+.BR @g@refer (@MAN1EXT@)
+for more details.
+.TP
+.B \-v
+Make programs run by
+.B groff
+print out their version number.
+.TP
+.B \-V
+Print the pipeline on stdout instead of executing it.
+.TP
+.B \-z
+Suppress output from
+.BR @g@troff .
+Only error messages will be printed.
+.TP
+.B \-Z
+Do not postprocess the output of
+.BR @g@troff .
+Normally
+.B groff
+will automatically run the appropriate postprocessor.
+.TP
+.BI \-P arg
+Pass
+.I arg
+to the postprocessor.
+Each argument should be passed with a separate
+.B \-P
+option.
+Note that
+.B groff
+does not prepend
+.B \-
+to
+.I arg
+before passing it to the postprocessor.
+.TP
+.B \-l
+Send the output to a printer.
+The command used for this is specified by the
+.B print
+command in the device description file.
+.TP
+.BI \-L arg
+Pass
+.I arg
+to the spooler.
+Each argument should be passed with a separate
+.B \-L
+option.
+Note that
+.B groff
+does not prepend
+.B \-
+to
+.I arg
+before passing it to the postprocessor.
+.TP
+.BI \-T dev
+Prepare output for device
+.IR dev .
+The default device is
+.BR @DEVICE@ .
+.TP
+.B \-X
+Preview with
+.B gxditview
+instead of using the usual postprocessor.
+.B Groff
+passes
+.B gxditview
+a
+.B -printCommand
+option which will make the
+.B Print
+action do what
+.B groff
+would have done if the
+.B -l
+option had been given.
+This is unlikely to produce good results except with
+.BR \-Tps .
+.TP
+.B \-N
+Don't allow newlines with eqn delimiters.
+This is the same as the
+.B \-N
+option in
+.BR @g@eqn .
+.TP
+.B \-S
+Safer mode. Pass the
+.B \-S
+option to
+.B @g@pic
+and use the
+.B \%\-msafer
+macros with
+.BR @g@troff .
+(enabled by default)
+.TP
+.B \-U
+Unsafe mode. Reverts to the old unsafe behaviour.
+.TP
+.B \-a
+.TQ
+.B \-b
+.TQ
+.B \-i
+.TQ
+.B \-C
+.TQ
+.B \-E
+.TQ
+.BI \-w name
+.TQ
+.BI \-W name
+.TQ
+.BI \-m name
+.TQ
+.BI \-o list
+.TQ
+.BI \-d cs
+.TQ
+.BI \-r cn
+.TQ
+.BI \-F dir
+.TQ
+.BI \-M dir
+.TQ
+.BI \-f fam
+.TQ
+.BI \-n num
+These are as described in
+.BR @g@troff (@MAN1EXT@) .
+.SH ENVIRONMENT
+.TP
+.SM
+.B GROFF_COMMAND_PREFIX
+If this is set
+.IR X ,
+then
+.B groff
+will run
+.IB X troff
+instead of
+.BR @g@troff .
+This also applies to
+.BR tbl ,
+.BR pic ,
+.BR eqn ,
+.BR refer ,
+and
+.BR soelim .
+It does not apply to
+.BR grops ,
+.BR grodvi ,
+.BR grotty ,
+.BR grolj4 ,
+.BR grohtml ,
+and
+.BR gxditview .
+.TP
+.SM
+.B GROFF_TMAC_PATH
+A colon separated list of directories in which to search for
+macro files.
+.TP
+.SM
+.B GROFF_TYPESETTER
+Default device.
+.TP
+.SM
+.B GROFF_FONT_PATH
+A colon separated list of directories in which to search for the
+.BI dev name
+directory.
+.TP
+.SM
+.B PATH
+The search path for commands executed by
+.BR groff .
+.TP
+.SM
+.B GROFF_TMPDIR
+The directory in which temporary files will be created.
+If this is not set and
+.B
+.SM TMPDIR
+is set, temporary files will be created in that directory.
+Otherwise temporary files will be created in
+.BR /tmp .
+The
+.BR grops (@MAN1EXT@)
+and
+.BR @g@refer (@MAN1EXT@)
+commands can create temporary files.
+.SH FILES
+.Tp \w'\fB@FONTDIR@/dev\fIname\fB/DESC'u+3n
+.BI @FONTDIR@/dev name /DESC
+Device description file for device
+.IR name .
+.TP
+.BI @FONTDIR@/dev name / F
+Font file for font
+.I F
+of device
+.IR name .
+.SH AUTHOR
+James Clark <jjc@jclark.com>
+.SH BUGS
+Report bugs to bug-groff@gnu.org.
+Include a complete, self-contained example
+that will allow the bug to be reproduced,
+and say which version of groff you are using.
+.SH COPYRIGHT
+Copyright \(co 1989, 1990, 1991, 1992, 1999 Free Software Foundation, Inc.
+.LP
+groff 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.
+.LP
+groff 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.
+.LP
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+.SH AVAILABILITY
+The most recent released version of groff is always available for
+anonymous ftp from ftp.gnu.org in the directory gnu/groff.
+.SH "SEE ALSO"
+.BR grog (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@),
+.BR @g@tbl (@MAN1EXT@),
+.BR @g@pic (@MAN1EXT@),
+.BR @g@eqn (@MAN1EXT@),
+.BR @g@soelim (@MAN1EXT@) ,
+.BR @g@refer (@MAN1EXT@),
+.BR grops (@MAN1EXT@),
+.BR grodvi (@MAN1EXT@),
+.BR grotty (@MAN1EXT@),
+.BR grohtml (@MAN1EXT@),
+.BR gxditview (@MAN1EXT@),
+.BR groff_font (@MAN5EXT@),
+.BR groff_out (@MAN5EXT@),
+.BR groff_man (@MAN7EXT@),
+.BR groff_ms (@MAN7EXT@),
+.BR groff_me (@MAN7EXT@),
+.BR groff_char (@MAN7EXT@),
+.BR groff_msafer (@MAN7EXT@)
diff --git a/src/roff/groff/pipeline.c b/src/roff/groff/pipeline.c
new file mode 100644
index 00000000..9f444d01
--- /dev/null
+++ b/src/roff/groff/pipeline.c
@@ -0,0 +1,239 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+Compile options are:
+
+-DWCOREFLAG=0200 (or whatever)
+-DHAVE_SYS_SIGLIST
+-DSYS_SIGLIST_DECLARED
+-DHAVE_UNISTD_H
+*/
+
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifndef errno
+extern int errno;
+#endif
+
+extern char *strerror();
+
+#ifdef _POSIX_VERSION
+
+#include <sys/wait.h>
+
+#define PID_T pid_t
+
+#else /* not _POSIX_VERSION */
+
+/* traditional Unix */
+
+#define WIFEXITED(s) (((s) & 0377) == 0)
+#define WIFSTOPPED(s) (((s) & 0377) == 0177)
+#define WIFSIGNALED(s) (((s) & 0377) != 0 && (((s) & 0377) != 0177))
+#define WEXITSTATUS(s) (((s) >> 8) & 0377)
+#define WTERMSIG(s) ((s) & 0177)
+#define WSTOPSIG(s) (((s) >> 8) & 0377)
+
+#ifndef WCOREFLAG
+#define WCOREFLAG 0200
+#endif
+
+#define PID_T int
+
+#endif /* not _POSIX_VERSION */
+
+/* SVR4 uses WCOREFLG; Net 2 uses WCOREFLAG. */
+#ifndef WCOREFLAG
+#ifdef WCOREFLG
+#define WCOREFLAG WCOREFLG
+#endif /* WCOREFLG */
+#endif /* not WCOREFLAG */
+
+#ifndef WCOREDUMP
+#ifdef WCOREFLAG
+#define WCOREDUMP(s) ((s) & WCOREFLAG)
+#else /* not WCOREFLAG */
+#define WCOREDUMP(s) (0)
+#endif /* WCOREFLAG */
+#endif /* not WCOREDUMP */
+
+#include "pipeline.h"
+
+#ifdef __STDC__
+#define P(parms) parms
+#else
+#define P(parms) ()
+#define const /* as nothing */
+#endif
+
+#define error c_error
+extern void error P((const char *, const char *, const char *, const char *));
+extern void c_fatal P((const char *, const char *, const char *, const char *));
+
+static void sys_fatal P((const char *));
+static const char *xstrsignal P((int));
+static char *itoa P((int));
+
+int run_pipeline(ncommands, commands)
+ int ncommands;
+ char ***commands;
+{
+ int i;
+ int last_input = 0;
+ PID_T pids[MAX_COMMANDS];
+ int ret = 0;
+ int proc_count = ncommands;
+
+ for (i = 0; i < ncommands; i++) {
+ int pdes[2];
+ PID_T pid;
+ if (i != ncommands - 1) {
+ if (pipe(pdes) < 0)
+ sys_fatal("pipe");
+ }
+ pid = fork();
+ if (pid < 0)
+ sys_fatal("fork");
+ if (pid == 0) {
+ /* child */
+ if (last_input != 0) {
+ if (close(0) < 0)
+ sys_fatal("close");
+ if (dup(last_input) < 0)
+ sys_fatal("dup");
+ if (close(last_input) < 0)
+ sys_fatal("close");
+ }
+ if (i != ncommands - 1) {
+ if (close(1) < 0)
+ sys_fatal("close");
+ if (dup(pdes[1]) < 0)
+ sys_fatal("dup");
+ if (close(pdes[1]) < 0)
+ sys_fatal("close");
+ if (close(pdes[0]))
+ sys_fatal("close");
+ }
+ execvp(commands[i][0], commands[i]);
+ error("couldn't exec %1: %2", commands[i][0],
+ strerror(errno), (char *)0);
+ fflush(stderr); /* just in case error() doesn't */
+ _exit(EXEC_FAILED_EXIT_STATUS);
+ }
+ /* in the parent */
+ if (last_input != 0) {
+ if (close(last_input) < 0)
+ sys_fatal("close");
+ }
+ if (i != ncommands - 1) {
+ if (close(pdes[1]) < 0)
+ sys_fatal("close");
+ last_input = pdes[0];
+ }
+ pids[i] = pid;
+ }
+ while (proc_count > 0) {
+ int status;
+ PID_T pid = wait(&status);
+ if (pid < 0)
+ sys_fatal("wait");
+ for (i = 0; i < ncommands; i++)
+ if (pids[i] == pid) {
+ pids[i] = -1;
+ --proc_count;
+ if (WIFSIGNALED(status)) {
+ int sig = WTERMSIG(status);
+#ifdef SIGPIPE
+ if (sig == SIGPIPE) {
+ if (i == ncommands - 1) {
+
+ /* This works around a problem that occurred when using the
+ rerasterize action in gxditview. What seemed to be
+ happening (on SunOS 4.1.1) was that pclose() closed the
+ pipe and waited for groff, gtroff got a SIGPIPE, but
+ gpic blocked writing to gtroff, and so groff blocked
+ waiting for gpic and gxditview blocked waiting for
+ groff. I don't understand why gpic wasn't getting a
+ SIGPIPE. */
+ int j;
+ for (j = 0; j < ncommands; j++)
+ if (pids[j] > 0)
+ (void)kill(pids[j], SIGPIPE);
+ }
+ }
+ else
+#endif /* SIGPIPE */
+ {
+ error("%1: %2%3",
+ commands[i][0],
+ xstrsignal(sig),
+ WCOREDUMP(status) ? " (core dumped)" : "");
+ ret |= 2;
+ }
+ }
+ else if (WIFEXITED(status)) {
+ int exit_status = WEXITSTATUS(status);
+ if (exit_status == EXEC_FAILED_EXIT_STATUS)
+ ret |= 4;
+ else if (exit_status != 0)
+ ret |= 1;
+ }
+ else
+ error("unexpected status %1",
+ itoa(status), (char *)0, (char *)0);
+ break;
+ }
+ }
+ return ret;
+}
+
+static void sys_fatal(s)
+ const char *s;
+{
+ c_fatal("%1: %2", s, strerror(errno), (char *)0);
+}
+
+static char *itoa(n)
+ int n;
+{
+ static char buf[12];
+ sprintf(buf, "%d", n);
+ return buf;
+}
+
+static const char *xstrsignal(n)
+ int n;
+{
+ static char buf[sizeof("Signal ") + 1 + sizeof(int)*3];
+#ifdef NSIG
+#ifdef SYS_SIGLIST_DECLARED
+ if (n >= 0 && n < NSIG && sys_siglist[n] != 0)
+ return sys_siglist[n];
+#endif /* SYS_SIGLIST_DECLARED */
+#endif /* NSIG */
+ sprintf(buf, "Signal %d", n);
+ return buf;
+}
diff --git a/src/roff/groff/pipeline.h b/src/roff/groff/pipeline.h
new file mode 100644
index 00000000..72c4dace
--- /dev/null
+++ b/src/roff/groff/pipeline.h
@@ -0,0 +1,30 @@
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef __cplusplus
+extern "C" {
+ int run_pipeline(int, char ***);
+}
+#endif
+
+/* run_pipeline can handle at most this many commands */
+#define MAX_COMMANDS 10
+
+/* Children exit with this status if execvp fails. */
+#define EXEC_FAILED_EXIT_STATUS 0xff
diff --git a/src/roff/grog/Makefile.sub b/src/roff/grog/Makefile.sub
new file mode 100644
index 00000000..e1c53e17
--- /dev/null
+++ b/src/roff/grog/Makefile.sub
@@ -0,0 +1,22 @@
+MAN1=grog.n
+CLEANADD=grog
+
+all: grog
+
+grog: grog.pl grog.sh
+ if test -n "$(PERLPATH)" && test -f "$(PERLPATH)"; then \
+ rm -f $@; \
+ sed -e 's;/usr/bin/perl;$(PERLPATH);' $(srcdir)/grog.pl >$@; \
+ else \
+ rm -f $@; \
+ sed "$(SH_SCRIPT_SED_CMD)" $(srcdir)/grog.sh >$@; \
+ fi
+ chmod +x $@
+
+install_data: grog
+ -test -d $(bindir) || $(mkinstalldirs) $(bindir)
+ -rm -f $(bindir)/grog
+ $(INSTALL_PROGRAM) grog $(bindir)/grog
+
+uninstall_sub:
+ -rm -f $(bindir)/grog
diff --git a/src/roff/grog/grog.man b/src/roff/grog/grog.man
new file mode 100644
index 00000000..8e926573
--- /dev/null
+++ b/src/roff/grog/grog.man
@@ -0,0 +1,72 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.TH GROG @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+grog \- guess options for groff command
+.SH SYNOPSIS
+.B grog
+[
+.BI \- option
+\|.\|.\|.
+]
+[
+.IR files \|.\|.\|.
+]
+.SH DESCRIPTION
+.B grog
+reads
+.I files
+and guesses which of the
+.BR groff (@MAN1EXT@)
+options
+.BR \-e ,
+.BR \-man ,
+.BR \-me ,
+.BR \-mm ,
+.BR \-ms ,
+.BR \-p ,
+.BR \-s ,
+and
+.BR \-t
+are required for printing
+.IR files ,
+and prints the groff command including those options on the standard output.
+A filename of
+.B \-
+is taken to refer to the standard input.
+If no files are specified the standard input will be read.
+Any specified options will be included in the printed command.
+No space is allowed between options and their arguments.
+For example,
+.IP
+.B `grog \-Tdvi paper.ms`
+.LP
+will guess the appropriate command to print
+.B paper.ms
+and then run it after adding the
+.B \-Tdvi
+option.
+.SH "SEE ALSO"
+.BR doctype (1),
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@),
+.BR @g@tbl (@MAN1EXT@),
+.BR @g@pic (@MAN1EXT@),
+.BR @g@eqn (@MAN1EXT@),
+.BR @g@soelim (@MAN1EXT@)
diff --git a/src/roff/grog/grog.pl b/src/roff/grog/grog.pl
new file mode 100644
index 00000000..b131da64
--- /dev/null
+++ b/src/roff/grog/grog.pl
@@ -0,0 +1,149 @@
+#!/usr/bin/perl
+# grog -- guess options for groff command
+# Inspired by doctype script in Kernighan & Pike, Unix Programming
+# Environment, pp 306-8.
+
+$prog = $0;
+$prog =~ s@.*/@@;
+
+push(@command, "groff");
+
+while ($ARGV[0] =~ /^-./) {
+ $arg = shift(@ARGV);
+ last if $arg eq "--";
+ push(@command, $arg);
+}
+
+if (@ARGV) {
+ foreach $arg (@ARGV) {
+ &process($arg, 0);
+ }
+}
+else {
+ &process("-", 0);
+}
+
+sub process {
+ local($filename, $level) = @_;
+ local(*FILE);
+
+ if (!open(FILE, $filename eq "-" ? $filename : "< $filename")) {
+ print STDERR "$prog: can't open \`$filename': $!\n";
+ exit 1 unless $level;
+ return;
+ }
+ while (<FILE>) {
+ if (/^\.TS/) {
+ $_ = <FILE>;
+ if (!/^\./) {
+ $tbl++;
+ $soelim++ if $level;
+ }
+ }
+ elsif (/^\.EQ/) {
+ $_ = <FILE>;
+ if (!/^\./ || /^\.[0-9]/) {
+ $eqn++;
+ $soelim++ if $level;
+ }
+ }
+ elsif (/^\.PS([ 0-9.<].*)?$/) {
+ if (/^\.PS\s*<\s*(\S+)/) {
+ $pic++;
+ $soelim++ if $level;
+ &process($1, $level);
+ }
+ else {
+ $_ = <FILE>;
+ if (!/^\./ || /^\.ps/) {
+ $pic++;
+ $soelim++ if $level;
+ }
+ }
+ }
+ elsif (/^\.R1/ || /^\.\[/) {
+ $refer++;
+ $soelim++ if $level;
+ }
+ elsif (/^\.[PLI]P/) {
+ $PP++;
+ }
+ elsif (/^\.P$/) {
+ $P++;
+ }
+ elsif (/^\.(PH|SA)/) {
+ $mm++;
+ }
+ elsif (/^\.TH/) {
+ $TH++;
+ }
+ elsif (/^\.SH/) {
+ $SH++;
+ }
+ elsif (/^\.([pnil]p|sh)/) {
+ $me++;
+ }
+ elsif (/^\.Dd/) {
+ $mdoc++;
+ }
+ elsif (/^\.(Tp|Dp|De|Cx|Cl)/) {
+ $mdoc_old = 1;
+ }
+ # In the old version of -mdoc `Oo' is a toggle, in the new it's
+ # closed by `Oc'.
+ elsif (/^\.Oo/) {
+ $Oo++;
+ }
+ elsif (/^\.Oc/) {
+ $Oo--;
+ }
+ if (/^\.so/) {
+ chop;
+ s/^.so *//;
+ s/\\\".*//;
+ s/ .*$//;
+ &process($_, $level + 1) unless /\\/ || $_ eq "";
+ }
+ }
+ close(FILE);
+}
+
+if ($pic || $tbl || $eqn || $refer) {
+ $s = "-";
+ $s .= "s" if $soelim;
+ $s .= "R" if $refer;
+ $s .= "p" if $pic;
+ $s .= "t" if $tbl;
+ $s .= "e" if $eqn;
+ push(@command, $s);
+}
+
+if ($me > 0) {
+ push(@command, "-me");
+}
+elsif ($SH > 0 && $TH > 0) {
+ push(@command, "-man");
+}
+elsif ($PP > 0) {
+ push(@command, "-ms");
+}
+elsif ($P > 0 || $mm > 0) {
+ push(@command, "-mm");
+}
+elsif ($mdoc > 0) {
+ push(@command, ($mdoc_old || $Oo > 0) ? "-mdoc.old" : "-mdoc");
+}
+
+push(@command, "--") if @ARGV && $ARGV[0] =~ /^-./;
+
+push(@command, @ARGV);
+
+# We could implement an option to execute the command here.
+
+foreach (@command) {
+ next unless /[\$\\\"\';&()|<> \t\n]/;
+ s/\'/\'\\\'\'/;
+ $_ = "'" . $_ . "'";
+}
+
+print join(' ', @command), "\n";
diff --git a/src/roff/grog/grog.sh b/src/roff/grog/grog.sh
new file mode 100644
index 00000000..631b356a
--- /dev/null
+++ b/src/roff/grog/grog.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+# grog -- guess options for groff command
+# Like doctype in Kernighan & Pike, Unix Programming Environment, pp 306-8.
+
+soelim=gsoelim
+
+opts=
+
+for arg
+do
+ case "$arg" in
+ --)
+ shift; break;;
+ -)
+ break;;
+ -*)
+ opts="$opts $arg"; shift;;
+ *)
+ break;;
+ esac
+done
+
+egrep -h '^\.(P|[LI]P|[pnil]p|sh|Dd|Tp|Dp|De|Cx|Cl|Oo|Oc|TS|EQ|TH|SH|so|\[|R1|PH|SA)' $* \
+| sed -e '/^\.so/s/^.*$/.SO_START\
+&\
+.SO_END/' \
+| $soelim \
+| egrep '^\.(P|[LI]P|[pnil]p|sh|Dd|Tp|Dp|De|Cx|Cl|Oo|Oc|TS|EQ|TH|SH|\[|R1|PH|SA|SO_START|SO_END)' \
+| awk '
+/^\.SO_START$/ { so = 1 }
+/^\.SO_END$/ { so = 0 }
+/^\.TS/ { tbl++; if (so > 0) soelim++ }
+/^\.PS([ 0-9.<].*)?$/ { pic++; if (so > 0) soelim++ }
+/^\.EQ/ { eqn++; if (so > 0) soelim++ }
+/^\.(R1|\[)/ { refer++; if (so > 0) soelim++ }
+/^\.TH/ { TH++ }
+/^\.[PLI]P/ { PP++ }
+/^\.P$/ { P++ }
+/^\.SH/ { SH++ }
+/^\.(PH|SA)/ { mm++ }
+/^\.([pnil]p|sh)/ { me++ }
+/^\.Dd/ { mdoc++ }
+/^\.(Tp|Dp|De|Cx|Cl)/ { mdoc_old++ }
+/^\.Oo/ { Oo++ }
+/^\.Oc/ { Oo-- }
+
+END {
+ if (files ~ /^-/)
+ files = "-- " files
+ printf "groff"
+ if (pic > 0 || tbl > 0 || eqn > 0 || refer > 0) {
+ printf " -"
+ if (soelim > 0) printf "s"
+ if (refer > 0) printf "R"
+ if (pic > 0) printf "p"
+ if (tbl > 0) printf "t"
+ if (eqn > 0) printf "e"
+ }
+ if (me > 0)
+ printf " -me"
+ else if (SH > 0 && TH > 0)
+ printf " -man"
+ else if (PP > 0)
+ printf " -ms"
+ else if (P > 0 || mm > 0)
+ printf " -mm"
+ else if (mdoc > 0) {
+ if (mdoc_old > 0 || Oo > 0)
+ printf " -mdoc.old"
+ else
+ printf " -mdoc"
+ }
+ if (opts != "")
+ printf "%s", opts
+ if (files != "")
+ printf " %s", files
+ print ""
+}' "opts=$opts" "files=$*" -
diff --git a/src/roff/nroff/Makefile.sub b/src/roff/nroff/Makefile.sub
new file mode 100644
index 00000000..275db4d1
--- /dev/null
+++ b/src/roff/nroff/Makefile.sub
@@ -0,0 +1,18 @@
+MAN1=nroff.n
+NAMEPREFIX=$(g)
+CLEANADD=nroff
+
+all: nroff
+
+nroff: nroff.sh
+ rm -f $@
+ sed "$(SH_SCRIPT_SED_CMD)" $(srcdir)/nroff.sh >$@
+ chmod +x $@
+
+install_data: nroff
+ -test -d $(bindir) || $(mkinstalldirs) $(bindir)
+ -rm -f $(bindir)/$(NAMEPREFIX)nroff
+ $(INSTALL_PROGRAM) nroff $(bindir)/$(NAMEPREFIX)nroff
+
+uninstall_sub:
+ -rm -f $(bindir)/$(NAMEPREFIX)nroff
diff --git a/src/roff/nroff/nroff.man b/src/roff/nroff/nroff.man
new file mode 100644
index 00000000..8f31d6bf
--- /dev/null
+++ b/src/roff/nroff/nroff.man
@@ -0,0 +1,95 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-2000 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.TH @G@NROFF @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+@g@nroff \- emulate nroff command with groff
+.SH SYNOPSIS
+.B @g@nroff
+[
+.B \-h
+]
+[
+.B \-i
+]
+[
+.BI \-m name
+]
+[
+.BI \-n num
+]
+[
+.BI \-o list
+]
+[
+.BI \-r cn
+]
+[
+.BI \-T name
+]
+[
+.I file\|.\|.\|.
+]
+.SH DESCRIPTION
+The
+.B @g@nroff
+script emulates the
+.B nroff
+command using groff.
+The
+.B \-T
+option with an argument other than
+.BR ascii ,
+.B latin1
+or
+.B utf8
+will be ignored.
+The
+.B \-h
+option
+is equivalent to the
+.B grotty
+.B \-h
+option.
+The
+.BR \-i ,
+.BR \-n ,
+.BR \-m ,
+.B \-o
+and
+.B \-r
+options have the effect described in
+.BR @g@troff (@MAN1EXT@).
+In addition
+.B @g@nroff
+silently ignores options of
+.BR \-e ,
+.B \-q
+or
+.BR \-s .
+Options
+.B \-S
+(safer) and
+.B \-U
+(unsafe) are passed to groff.
+.B \-S
+is passed by default.
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@),
+.BR grotty (@MAN1EXT@)
diff --git a/src/roff/nroff/nroff.sh b/src/roff/nroff/nroff.sh
new file mode 100644
index 00000000..a199541d
--- /dev/null
+++ b/src/roff/nroff/nroff.sh
@@ -0,0 +1,83 @@
+#!/bin/sh
+# Emulate nroff with groff.
+
+prog="$0"
+# Default device.
+# First try the "locale charmap" command, because it's most reliable.
+# On systems where it doesn't exist, look at the environment variables.
+case "`locale charmap 2>/dev/null`" in
+ UTF-8 ) T=-Tutf8 ;;
+ ISO-8859-1 ) T=-Tlatin1 ;;
+ *)
+ case "${LC_ALL-${LC_CTYPE-${LANG}}}" in
+ *.UTF-8 ) T=-Tutf8 ;;
+ iso_8859_1 | *.ISO-8859-1 ) T=-Tlatin1 ;;
+ *)
+ case "$LESSCHARSET" in
+ utf-8 ) T=-Tutf8 ;;
+ latin1 ) T=-Tlatin1 ;;
+ *) T=-Tascii ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+opts=
+safer=-S
+
+for i
+do
+ case $1 in
+ -h)
+ opts="$opts -P-h"
+ ;;
+ -[eq]|-s*)
+ # ignore these options
+ ;;
+ -[mrnoT])
+ echo "$prog: option $1 requires an argument" >&2
+ exit 1
+ ;;
+ -i|-[mrno]*)
+ opts="$opts $1";
+ ;;
+
+ -Tascii|-Tlatin1|-Tutf8)
+ T=$1
+ ;;
+ -T*)
+ # ignore other devices
+ ;;
+ -S)
+ # safer behaviour
+ safer=-S
+ ;;
+ -U)
+ # unsafe behaviour
+ safer=-U
+ ;;
+ -u*)
+ # Solaris 2.2 `man' uses -u0; ignore it,
+ # since `less' and `more' can use the emboldening info.
+ ;;
+ --)
+ shift
+ break
+ ;;
+ -)
+ break
+ ;;
+ -*)
+ echo "$prog: invalid option $1" >&2
+ exit 1
+ ;;
+ *)
+ break
+ ;;
+ esac
+ shift
+done
+
+# This shell script is intended for use with man, so warnings are
+# probably not wanted. Also load nroff-style character definitions.
+exec groff $safer -Wall -mtty-char $T $opts ${1+"$@"}
diff --git a/src/roff/troff/Makefile.sub b/src/roff/troff/Makefile.sub
new file mode 100644
index 00000000..342ad595
--- /dev/null
+++ b/src/roff/troff/Makefile.sub
@@ -0,0 +1,57 @@
+PROG=troff
+MAN1=troff.n
+XLIBS=$(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=\
+ env.o \
+ node.o \
+ input.o \
+ div.o \
+ symbol.o \
+ dictionary.o \
+ reg.o \
+ number.o \
+ majorminor.o
+CCSRCS=\
+ $(srcdir)/env.cc \
+ $(srcdir)/node.cc \
+ $(srcdir)/input.cc \
+ $(srcdir)/div.cc \
+ $(srcdir)/symbol.cc \
+ $(srcdir)/dictionary.cc \
+ $(srcdir)/reg.cc \
+ $(srcdir)/number.cc \
+ majorminor.cc
+HDRS=\
+ $(srcdir)/charinfo.h \
+ $(srcdir)/dictionary.h \
+ $(srcdir)/div.h \
+ $(srcdir)/env.h \
+ $(srcdir)/hvunits.h \
+ $(srcdir)/node.h \
+ $(srcdir)/reg.h \
+ $(srcdir)/request.h \
+ $(srcdir)/symbol.h \
+ $(srcdir)/token.h \
+ $(srcdir)/troff.h
+GENSRCS=majorminor.cc
+NAMEPREFIX=$(g)
+
+majorminor.cc: $(top_srcdir)/VERSION $(top_srcdir)/REVISION
+ @echo Making $@
+ @-rm -f $@
+ @echo const char \*major_version = \
+ \"`sed -e 's/^\([^.]*\)\..*$$/\1/' $(top_srcdir)/VERSION`\"\; >$@
+ @echo const char \*minor_version = \
+ \"`sed -e 's/^[^.]*\.\([0-9]*\).*$$/\1/' $(top_srcdir)/VERSION`\"\; >>$@
+ @echo const char \*revision = \"`cat $(top_srcdir)/REVISION`\"\; >>$@
+
+install_data: hyphen.us
+ -test -d $(datadir) || $(mkinstalldirs) $(datadir)
+ -test -d $(datasubdir) || $(mkinstalldirs) $(datasubdir)
+ -test -d $(tmacdir) || $(mkinstalldirs) $(tmacdir)
+ -rm -f $(tmacdir)/hyphen.us
+ $(INSTALL_DATA) $(srcdir)/hyphen.us $(tmacdir)/hyphen.us
+
+uninstall_sub:
+ -rm -f $(tmacdir)/hyphen.us
diff --git a/src/roff/troff/TODO b/src/roff/troff/TODO
new file mode 100644
index 00000000..7e511235
--- /dev/null
+++ b/src/roff/troff/TODO
@@ -0,0 +1,139 @@
+Give a more helpful error message when the indent is set to a value
+greater than the line-length.
+
+Tracing. This is a pain to implement because requests are responsible
+for reading their own arguments.
+
+Possibly implement -s option (stop every N pages). This functionality
+would be more appropriate in a postprocessor.
+
+Line breaking should be smarter. In particular, it should be possible
+to shrink spaces. Also avoid having a line that's been shrunk a lot
+next to a line that's been stretched a lot. The difficulty is to
+design a mechanism that allows the user complete control over the
+decision of where to break the line.
+
+Provide a mechanism to control the shape of the rag in non-justified
+text.
+
+Add a discretionary break escape sequence. \B'...'...'...' like TeX.
+
+Think about kerning between characters and spaces. (Need to implement
+get_breakpoints and split methods for kern_pair_node class.)
+
+In troff, if .L > 1 when a diversion is reread in no-fill mode, then
+extra line-spacing is added on. Groff at the moment treats line-spacing
+like vertical spacing and doesn't do this.
+
+Suppose \(ch comes from a special font S, and that the current font is
+R. Suppose that R contains a hyphen character and that S does not.
+Suppose that the current font is R. Suppose that \(ch is in a word
+and has a non-zero hyphen-type. Then we ought to be able to hyphenate,
+but we won't be able to because we will look for the hyphen only in
+font S and not in font R.
+
+Variant of tm which doesn't write a newline.
+
+Perhaps the current input level should be accessible in a number register.
+
+Should \w deal with a newline like \X?
+
+Have another look at uses of token::delimiter. Perhaps we need to
+distinguish the case where we want to see if a token could start a
+number, from the case where we want to see if it could occur somewhere
+in a number expression.
+
+Provide a facility like copy thru in pic.
+
+Fancier implementation of font families which doesn't group fonts into
+families purely on the basis of their names.
+
+In the DESC file make the number of fonts optional if they are all on
+one line.
+
+Number register to give the diversion level.
+
+Time various alternative implementations of scale (both in font.c and
+number.c). On a sparc it's faster to always do it in floating point.
+
+Devise a more compact representation for the hyphenation patterns trie.
+
+Have a per-environment parameter to increase letter-spacing.
+
+Number register to return character height.
+
+Number register to return character slant.
+
+Request to set character height.
+
+Request to set character slant.
+
+Provide some way to upcase or downcase strings.
+
+Support non-uniformly scalable fonts. Perhaps associate a suffix with
+a particular range of sizes. eg
+ sizesuffix .display 14-512
+Then is you ask for R at pointsize 16, groff will first look for
+R.display and then R. Probably necessary to be able to specify a
+separate unitwidth for each sizesuffix (eg. for X).
+
+Request to copy an environment into the current environment.
+
+Variant of `.it' for which a line interrupted with \c counts as one
+input line.
+
+Make it possible to suppress hyphenation on a word-by-word basis.
+(Perhaps store hyphenation flags in tfont.)
+
+Possibly allow multiple simultaneous input line traps.
+
+Unpaddable, breakable space escape sequence.
+
+Support hanging punctuation.
+
+In justified text, if the last line of a paragraph is only a little
+bit short it might be desirable to justify the line. Allow the user
+control over this.
+
+Have a blank line macro like the end macro. When a blank line macro
+has been set, then a blank line causes the blank line macro to be
+called rather than doing the equivalent of .sp.
+
+The pm request could print where the macro was defined. Also could
+optionally print the contents of a macro.
+
+Provide some way to round numbers to multiples of the current
+horizontal or vertical resolution.
+
+Better string-processing support (substring, length, search).
+
+Generalized ligatures.
+
+Provide some way for a macro to tell whether it was called with `'' or
+`.'. This would be useful for implementing a tracing macro package.
+
+Request to remove an environment. (Maintain a count of the references
+to the environment from the environment table, environment dictionary
+or environment stack.)
+
+Perhaps in the nr request a leading `-' should only be recognized as a
+decrement when it's at the same input level as the request.
+
+Don't ever change a charinfo. Create new variants instead and chain
+them together.
+
+Make it possible to tr characters onto \~.
+
+Unix troff appears to read the first character of a request name in
+copy mode. Should we do the same?
+
+Number register giving name of end macro.
+
+More thorough range checking.
+
+Provide syntax for octal and hexadecimal numeric constants. Perhaps
+o#100 and x#7f as per Scheme. Or perhaps PostScript 16#7f. Ambiguity
+between whether `c' is treated as digit or scaling indicator.
+
+Request to return from a macro (ie ignore the rest of the current
+input level).
diff --git a/src/roff/troff/charinfo.h b/src/roff/troff/charinfo.h
new file mode 100644
index 00000000..a4ecd574
--- /dev/null
+++ b/src/roff/troff/charinfo.h
@@ -0,0 +1,171 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+class macro;
+
+class charinfo {
+ static int next_index;
+ charinfo *translation;
+ int index;
+ int number;
+ macro *mac;
+ unsigned char special_translation;
+ unsigned char hyphenation_code;
+ unsigned char flags;
+ unsigned char ascii_code;
+ char not_found;
+ char transparent_translate; // non-zero means translation applies to
+ // to transparent throughput
+public:
+ enum {
+ ENDS_SENTENCE = 1,
+ BREAK_BEFORE = 2,
+ BREAK_AFTER = 4,
+ OVERLAPS_HORIZONTALLY = 8,
+ OVERLAPS_VERTICALLY = 16,
+ TRANSPARENT = 32,
+ NUMBERED = 64
+ };
+ enum {
+ TRANSLATE_NONE,
+ TRANSLATE_SPACE,
+ TRANSLATE_DUMMY,
+ TRANSLATE_STRETCHABLE_SPACE,
+ TRANSLATE_HYPHEN_INDICATOR
+ };
+ symbol nm;
+ charinfo(symbol s);
+ int get_index();
+ int ends_sentence();
+ int overlaps_vertically();
+ int overlaps_horizontally();
+ int can_break_before();
+ int can_break_after();
+ int transparent();
+ unsigned char get_hyphenation_code();
+ unsigned char get_ascii_code();
+ void set_hyphenation_code(unsigned char);
+ void set_ascii_code(unsigned char);
+ charinfo *get_translation(int = 0);
+ void set_translation(charinfo *, int);
+ void set_flags(unsigned char);
+ void set_special_translation(int, int);
+ int get_special_translation(int = 0);
+ macro *set_macro(macro *);
+ macro *get_macro();
+ int first_time_not_found();
+ void set_number(int);
+ int get_number();
+ int numbered();
+ symbol *get_symbol();
+};
+
+charinfo *get_charinfo(symbol);
+extern charinfo *charset_table[];
+charinfo *get_charinfo_by_number(int);
+
+inline int charinfo::overlaps_horizontally()
+{
+ return flags & OVERLAPS_HORIZONTALLY;
+}
+
+inline int charinfo::overlaps_vertically()
+{
+ return flags & OVERLAPS_VERTICALLY;
+}
+
+inline int charinfo::can_break_before()
+{
+ return flags & BREAK_BEFORE;
+}
+
+inline int charinfo::can_break_after()
+{
+ return flags & BREAK_AFTER;
+}
+
+inline int charinfo::ends_sentence()
+{
+ return flags & ENDS_SENTENCE;
+}
+
+inline int charinfo::transparent()
+{
+ return flags & TRANSPARENT;
+}
+
+inline int charinfo::numbered()
+{
+ return flags & NUMBERED;
+}
+
+inline charinfo *charinfo::get_translation(int transparent_throughput)
+{
+ return (transparent_throughput && !transparent_translate
+ ? 0
+ : translation);
+}
+
+inline unsigned char charinfo::get_hyphenation_code()
+{
+ return hyphenation_code;
+}
+
+inline unsigned char charinfo::get_ascii_code()
+{
+ return ascii_code;
+}
+
+inline void charinfo::set_flags(unsigned char c)
+{
+ flags = c;
+}
+
+inline int charinfo::get_index()
+{
+ return index;
+}
+
+inline int charinfo::get_special_translation(int transparent_throughput)
+{
+ return (transparent_throughput && !transparent_translate
+ ? int(TRANSLATE_NONE)
+ : special_translation);
+}
+
+inline macro *charinfo::get_macro()
+{
+ return mac;
+}
+
+inline int charinfo::first_time_not_found()
+{
+ if (not_found)
+ return 0;
+ else {
+ not_found = 1;
+ return 1;
+ }
+}
+
+inline symbol *charinfo::get_symbol()
+{
+ return( &nm );
+}
diff --git a/src/roff/troff/column.cc b/src/roff/troff/column.cc
new file mode 100644
index 00000000..fce389db
--- /dev/null
+++ b/src/roff/troff/column.cc
@@ -0,0 +1,732 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef COLUMN
+
+#include "troff.h"
+#include "symbol.h"
+#include "dictionary.h"
+#include "hvunits.h"
+#include "env.h"
+#include "request.h"
+#include "node.h"
+#include "token.h"
+#include "div.h"
+#include "reg.h"
+#include "stringclass.h"
+
+void output_file::vjustify(vunits, symbol)
+{
+ // do nothing
+}
+
+struct justification_spec;
+struct output_line;
+
+class column : public output_file {
+private:
+ output_file *out;
+ vunits bottom;
+ output_line *col;
+ output_line **tail;
+ void add_output_line(output_line *);
+ void begin_page(int pageno, vunits page_length);
+ void flush();
+ void print_line(hunits, vunits, node *, vunits, vunits);
+ void vjustify(vunits, symbol);
+ void transparent_char(unsigned char c);
+ void copy_file(hunits, vunits, const char *);
+ int is_printing();
+ void check_bottom();
+public:
+ column();
+ ~column();
+ void start();
+ void output();
+ void justify(const justification_spec &);
+ void trim();
+ void reset();
+ vunits get_bottom();
+ vunits get_last_extra_space();
+ int is_active() { return out != 0; }
+};
+
+column *the_column = 0;
+
+struct transparent_output_line;
+struct vjustify_output_line;
+
+class output_line {
+ output_line *next;
+public:
+ output_line();
+ virtual ~output_line();
+ virtual void output(output_file *, vunits);
+ virtual transparent_output_line *as_transparent_output_line();
+ virtual vjustify_output_line *as_vjustify_output_line();
+ virtual vunits distance();
+ virtual vunits height();
+ virtual void reset();
+ virtual vunits extra_space(); // post line
+ friend class column;
+ friend class justification_spec;
+};
+
+class position_output_line : public output_line {
+ vunits dist;
+public:
+ position_output_line(vunits);
+ vunits distance();
+};
+
+class node_output_line : public position_output_line {
+ node *nd;
+ hunits page_offset;
+ vunits before;
+ vunits after;
+public:
+ node_output_line(vunits, node *, hunits, vunits, vunits);
+ ~node_output_line();
+ void output(output_file *, vunits);
+ vunits height();
+ vunits extra_space();
+};
+
+class vjustify_output_line : public position_output_line {
+ vunits current;
+ symbol typ;
+public:
+ vjustify_output_line(vunits dist, symbol);
+ vunits height();
+ vjustify_output_line *as_vjustify_output_line();
+ void vary(vunits amount);
+ void reset();
+ symbol type();
+};
+
+inline symbol vjustify_output_line::type()
+{
+ return typ;
+}
+
+class copy_file_output_line : public position_output_line {
+ symbol filename;
+ hunits hpos;
+public:
+ copy_file_output_line(vunits, const char *, hunits);
+ void output(output_file *, vunits);
+};
+
+class transparent_output_line : public output_line {
+ string buf;
+public:
+ transparent_output_line();
+ void output(output_file *, vunits);
+ void append_char(unsigned char c);
+ transparent_output_line *as_transparent_output_line();
+};
+
+output_line::output_line() : next(0)
+{
+}
+
+output_line::~output_line()
+{
+}
+
+void output_line::reset()
+{
+}
+
+transparent_output_line *output_line::as_transparent_output_line()
+{
+ return 0;
+}
+
+vjustify_output_line *output_line::as_vjustify_output_line()
+{
+ return 0;
+}
+
+void output_line::output(output_file *, vunits)
+{
+}
+
+vunits output_line::distance()
+{
+ return V0;
+}
+
+vunits output_line::height()
+{
+ return V0;
+}
+
+vunits output_line::extra_space()
+{
+ return V0;
+}
+
+position_output_line::position_output_line(vunits d)
+: dist(d)
+{
+}
+
+vunits position_output_line::distance()
+{
+ return dist;
+}
+
+node_output_line::node_output_line(vunits d, node *n, hunits po, vunits b, vunits a)
+: position_output_line(d), nd(n), page_offset(po), before(b), after(a)
+{
+}
+
+node_output_line::~node_output_line()
+{
+ delete_node_list(nd);
+}
+
+void node_output_line::output(output_file *out, vunits pos)
+{
+ out->print_line(page_offset, pos, nd, before, after);
+ nd = 0;
+}
+
+vunits node_output_line::height()
+{
+ return after;
+}
+
+vunits node_output_line::extra_space()
+{
+ return after;
+}
+
+vjustify_output_line::vjustify_output_line(vunits d, symbol t)
+: position_output_line(d), typ(t)
+{
+}
+
+void vjustify_output_line::reset()
+{
+ current = V0;
+}
+
+vunits vjustify_output_line::height()
+{
+ return current;
+}
+
+vjustify_output_line *vjustify_output_line::as_vjustify_output_line()
+{
+ return this;
+}
+
+inline void vjustify_output_line::vary(vunits amount)
+{
+ current += amount;
+}
+
+transparent_output_line::transparent_output_line()
+{
+}
+
+transparent_output_line *transparent_output_line::as_transparent_output_line()
+{
+ return this;
+}
+
+void transparent_output_line::append_char(unsigned char c)
+{
+ assert(c != 0);
+ buf += c;
+}
+
+void transparent_output_line::output(output_file *out, vunits)
+{
+ int len = buf.length();
+ for (int i = 0; i < len; i++)
+ out->transparent_char(buf[i]);
+}
+
+copy_file_output_line::copy_file_output_line(vunits d, const char *f, hunits h)
+: position_output_line(d), hpos(h), filename(f)
+{
+}
+
+void copy_file_output_line::output(output_file *out, vunits pos)
+{
+ out->copy_file(hpos, pos, filename.contents());
+}
+
+column::column()
+: bottom(V0), col(0), tail(&col), out(0)
+{
+}
+
+column::~column()
+{
+ assert(out != 0);
+ error("automatically outputting column before exiting");
+ output();
+ delete the_output;
+}
+
+void column::start()
+{
+ assert(out == 0);
+ if (!the_output)
+ init_output();
+ assert(the_output != 0);
+ out = the_output;
+ the_output = this;
+}
+
+void column::begin_page(int pageno, vunits page_length)
+{
+ assert(out != 0);
+ if (col) {
+ error("automatically outputting column before beginning next page");
+ output();
+ the_output->begin_page(pageno, page_length);
+ }
+ else
+ out->begin_page(pageno, page_length);
+
+}
+
+void column::flush()
+{
+ assert(out != 0);
+ out->flush();
+}
+
+int column::is_printing()
+{
+ assert(out != 0);
+ return out->is_printing();
+}
+
+vunits column::get_bottom()
+{
+ return bottom;
+}
+
+void column::add_output_line(output_line *ln)
+{
+ *tail = ln;
+ bottom += ln->distance();
+ bottom += ln->height();
+ ln->next = 0;
+ tail = &(*tail)->next;
+}
+
+void column::print_line(hunits page_offset, vunits pos, node *nd,
+ vunits before, vunits after)
+{
+ assert(out != 0);
+ add_output_line(new node_output_line(pos - bottom, nd, page_offset, before, after));
+}
+
+void column::vjustify(vunits pos, symbol typ)
+{
+ assert(out != 0);
+ add_output_line(new vjustify_output_line(pos - bottom, typ));
+}
+
+void column::transparent_char(unsigned char c)
+{
+ assert(out != 0);
+ transparent_output_line *tl = 0;
+ if (*tail)
+ tl = (*tail)->as_transparent_output_line();
+ if (!tl) {
+ tl = new transparent_output_line;
+ add_output_line(tl);
+ }
+ tl->append_char(c);
+}
+
+void column::copy_file(hunits page_offset, vunits pos, const char *filename)
+{
+ assert(out != 0);
+ add_output_line(new copy_file_output_line(pos - bottom, filename, page_offset));
+}
+
+void column::trim()
+{
+ output_line **spp = 0;
+ for (output_line **pp = &col; *pp; pp = &(*pp)->next)
+ if ((*pp)->as_vjustify_output_line() == 0)
+ spp = 0;
+ else if (!spp)
+ spp = pp;
+ if (spp) {
+ output_line *ln = *spp;
+ *spp = 0;
+ tail = spp;
+ while (ln) {
+ output_line *tem = ln->next;
+ bottom -= ln->distance();
+ bottom -= ln->height();
+ delete ln;
+ ln = tem;
+ }
+ }
+}
+
+void column::reset()
+{
+ bottom = V0;
+ for (output_line *ln = col; ln; ln = ln->next) {
+ bottom += ln->distance();
+ ln->reset();
+ bottom += ln->height();
+ }
+}
+
+void column::check_bottom()
+{
+ vunits b;
+ for (output_line *ln = col; ln; ln = ln->next) {
+ b += ln->distance();
+ b += ln->height();
+ }
+ assert(b == bottom);
+}
+
+void column::output()
+{
+ assert(out != 0);
+ vunits vpos(V0);
+ output_line *ln = col;
+ while (ln) {
+ vpos += ln->distance();
+ ln->output(out, vpos);
+ vpos += ln->height();
+ output_line *tem = ln->next;
+ delete ln;
+ ln = tem;
+ }
+ tail = &col;
+ bottom = V0;
+ col = 0;
+ the_output = out;
+ out = 0;
+}
+
+vunits column::get_last_extra_space()
+{
+ if (!col)
+ return V0;
+ for (output_line *p = col; p->next; p = p->next)
+ ;
+ return p->extra_space();
+}
+
+class justification_spec {
+ vunits height;
+ symbol *type;
+ vunits *amount;
+ int n;
+ int maxn;
+public:
+ justification_spec(vunits);
+ ~justification_spec();
+ void append(symbol t, vunits v);
+ void justify(output_line *, vunits *bottomp) const;
+};
+
+justification_spec::justification_spec(vunits h)
+: height(h), n(0), maxn(10)
+{
+ type = new symbol[maxn];
+ amount = new vunits[maxn];
+}
+
+justification_spec::~justification_spec()
+{
+ a_delete type;
+ a_delete amount;
+}
+
+void justification_spec::append(symbol t, vunits v)
+{
+ if (v <= V0) {
+ if (v < V0)
+ warning(WARN_RANGE,
+ "maximum space for vertical justification must not be negative");
+ else
+ warning(WARN_RANGE,
+ "maximum space for vertical justification must not be zero");
+ return;
+ }
+ if (n >= maxn) {
+ maxn *= 2;
+ symbol *old_type = type;
+ type = new symbol[maxn];
+ int i;
+ for (i = 0; i < n; i++)
+ type[i] = old_type[i];
+ a_delete old_type;
+ vunits *old_amount = amount;
+ amount = new vunits[maxn];
+ for (i = 0; i < n; i++)
+ amount[i] = old_amount[i];
+ a_delete old_amount;
+ }
+ assert(n < maxn);
+ type[n] = t;
+ amount[n] = v;
+ n++;
+}
+
+void justification_spec::justify(output_line *col, vunits *bottomp) const
+{
+ if (*bottomp >= height)
+ return;
+ vunits total;
+ output_line *p;
+ for (p = col; p; p = p->next) {
+ vjustify_output_line *sp = p->as_vjustify_output_line();
+ if (sp) {
+ symbol t = sp->type();
+ for (int i = 0; i < n; i++) {
+ if (t == type[i])
+ total += amount[i];
+ }
+ }
+ }
+ vunits gap = height - *bottomp;
+ for (p = col; p; p = p->next) {
+ vjustify_output_line *sp = p->as_vjustify_output_line();
+ if (sp) {
+ symbol t = sp->type();
+ for (int i = 0; i < n; i++) {
+ if (t == type[i]) {
+ if (total <= gap) {
+ sp->vary(amount[i]);
+ gap -= amount[i];
+ }
+ else {
+ // gap < total
+ vunits v = scale(amount[i], gap, total);
+ sp->vary(v);
+ gap -= v;
+ }
+ total -= amount[i];
+ }
+ }
+ }
+ }
+ assert(total == V0);
+ *bottomp = height - gap;
+}
+
+void column::justify(const justification_spec &js)
+{
+ check_bottom();
+ js.justify(col, &bottom);
+ check_bottom();
+}
+
+void column_justify()
+{
+ vunits height;
+ if (!the_column->is_active())
+ error("can't justify column - column not active");
+ else if (get_vunits(&height, 'v')) {
+ justification_spec js(height);
+ symbol nm = get_long_name(1);
+ if (!nm.is_null()) {
+ vunits v;
+ if (get_vunits(&v, 'v')) {
+ js.append(nm, v);
+ int err = 0;
+ while (has_arg()) {
+ nm = get_long_name(1);
+ if (nm.is_null()) {
+ err = 1;
+ break;
+ }
+ if (!get_vunits(&v, 'v')) {
+ err = 1;
+ break;
+ }
+ js.append(nm, v);
+ }
+ if (!err)
+ the_column->justify(js);
+ }
+ }
+ }
+ skip_line();
+}
+
+void column_start()
+{
+ if (the_column->is_active())
+ error("can't start column - column already active");
+ else
+ the_column->start();
+ skip_line();
+}
+
+void column_output()
+{
+ if (!the_column->is_active())
+ error("can't output column - column not active");
+ else
+ the_column->output();
+ skip_line();
+}
+
+void column_trim()
+{
+ if (!the_column->is_active())
+ error("can't trim column - column not active");
+ else
+ the_column->trim();
+ skip_line();
+}
+
+void column_reset()
+{
+ if (!the_column->is_active())
+ error("can't reset column - column not active");
+ else
+ the_column->reset();
+ skip_line();
+}
+
+class column_bottom_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *column_bottom_reg::get_string()
+{
+ return itoa(the_column->get_bottom().to_units());
+}
+
+class column_extra_space_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *column_extra_space_reg::get_string()
+{
+ return itoa(the_column->get_last_extra_space().to_units());
+}
+
+class column_active_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *column_active_reg::get_string()
+{
+ return the_column->is_active() ? "1" : "0";
+}
+
+static int no_vjustify_mode = 0;
+
+class vjustify_node : public node {
+ symbol typ;
+public:
+ vjustify_node(symbol);
+ int reread(int *);
+ const char *type();
+ int same(node *);
+ node *copy();
+};
+
+vjustify_node::vjustify_node(symbol t)
+: typ(t)
+{
+}
+
+node *vjustify_node::copy()
+{
+ return new vjustify_node(typ);
+}
+
+const char *vjustify_node::type()
+{
+ return "vjustify_node";
+}
+
+int vjustify_node::same(node *nd)
+{
+ return typ == ((vjustify_node *)nd)->typ;
+}
+
+int vjustify_node::reread(int *bolp)
+{
+ curdiv->vjustify(typ);
+ *bolp = 1;
+ return 1;
+}
+
+void macro_diversion::vjustify(symbol type)
+{
+ if (!no_vjustify_mode)
+ mac->append(new vjustify_node(type));
+}
+
+void top_level_diversion::vjustify(symbol type)
+{
+ if (no_space_mode || no_vjustify_mode)
+ return;
+ assert(first_page_begun); // I'm not sure about this.
+ the_output->vjustify(vertical_position, type);
+}
+
+void no_vjustify()
+{
+ skip_line();
+ no_vjustify_mode = 1;
+}
+
+void restore_vjustify()
+{
+ skip_line();
+ no_vjustify_mode = 0;
+}
+
+void init_column_requests()
+{
+ the_column = new column;
+ init_request("cols", column_start);
+ init_request("colo", column_output);
+ init_request("colj", column_justify);
+ init_request("colr", column_reset);
+ init_request("colt", column_trim);
+ init_request("nvj", no_vjustify);
+ init_request("rvj", restore_vjustify);
+ number_reg_dictionary.define(".colb", new column_bottom_reg);
+ number_reg_dictionary.define(".colx", new column_extra_space_reg);
+ number_reg_dictionary.define(".cola", new column_active_reg);
+ number_reg_dictionary.define(".nvj",
+ new constant_int_reg(&no_vjustify_mode));
+}
+
+#endif /* COLUMN */
diff --git a/src/roff/troff/dictionary.cc b/src/roff/troff/dictionary.cc
new file mode 100644
index 00000000..169536c6
--- /dev/null
+++ b/src/roff/troff/dictionary.cc
@@ -0,0 +1,212 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "troff.h"
+#include "symbol.h"
+#include "dictionary.h"
+
+// is `p' a good size for a hash table
+
+static int is_good_size(int p)
+{
+ const int SMALL = 10;
+ unsigned i;
+ for (i = 2; i <= p/2; i++)
+ if (p % i == 0)
+ return 0;
+ for (i = 0x100; i != 0; i <<= 8)
+ if (i % p <= SMALL || i % p > p - SMALL)
+ return 0;
+ return 1;
+}
+
+dictionary::dictionary(int n) : size(n), used(0), threshold(0.5), factor(1.5)
+{
+ table = new association[n];
+}
+
+// see Knuth, Sorting and Searching, p518, Algorithm L
+// we can't use double-hashing because we want a remove function
+
+void *dictionary::lookup(symbol s, void *v)
+{
+ int i;
+ for (i = int(s.hash() % size);
+ table[i].v != 0;
+ i == 0 ? i = size - 1: --i)
+ if (s == table[i].s) {
+ if (v != 0) {
+ void *temp = table[i].v;
+ table[i].v = v;
+ return temp;
+ }
+ else
+ return table[i].v;
+ }
+ if (v == 0)
+ return 0;
+ ++used;
+ table[i].v = v;
+ table[i].s = s;
+ if ((double)used/(double)size >= threshold || used + 1 >= size) {
+ int old_size = size;
+ size = int(size*factor);
+ while (!is_good_size(size))
+ ++size;
+ association *old_table = table;
+ table = new association[size];
+ used = 0;
+ for (i = 0; i < old_size; i++)
+ if (old_table[i].v != 0)
+ (void)lookup(old_table[i].s, old_table[i].v);
+ a_delete old_table;
+ }
+ return 0;
+}
+
+void *dictionary::lookup(const char *p)
+{
+ symbol s(p, MUST_ALREADY_EXIST);
+ if (s.is_null())
+ return 0;
+ else
+ return lookup(s);
+}
+
+// see Knuth, Sorting and Searching, p527, Algorithm R
+
+void *dictionary::remove(symbol s)
+{
+ // this relies on the fact that we are using linear probing
+ int i;
+ for (i = int(s.hash() % size);
+ table[i].v != 0 && s != table[i].s;
+ i == 0 ? i = size - 1: --i)
+ ;
+ void *p = table[i].v;
+ while (table[i].v != 0) {
+ table[i].v = 0;
+ int j = i;
+ int r;
+ do {
+ --i;
+ if (i < 0)
+ i = size - 1;
+ if (table[i].v == 0)
+ break;
+ r = int(table[i].s.hash() % size);
+ } while ((i <= r && r < j) || (r < j && j < i) || (j < i && i <= r));
+ table[j] = table[i];
+ }
+ if (p != 0)
+ --used;
+ return p;
+}
+
+dictionary_iterator::dictionary_iterator(dictionary &d) : dict(&d), i(0)
+{
+}
+
+int dictionary_iterator::get(symbol *sp, void **vp)
+{
+ for (; i < dict->size; i++)
+ if (dict->table[i].v) {
+ *sp = dict->table[i].s;
+ *vp = dict->table[i].v;
+ i++;
+ return 1;
+ }
+ return 0;
+}
+
+object_dictionary_iterator::object_dictionary_iterator(object_dictionary &od)
+ : di(od.d)
+{
+}
+
+object::object() : rcount(0)
+{
+}
+
+object::~object()
+{
+}
+
+void object::add_reference()
+{
+ rcount += 1;
+}
+
+void object::remove_reference()
+{
+ if (--rcount == 0)
+ delete this;
+}
+
+object_dictionary::object_dictionary(int n) : d(n)
+{
+}
+
+object *object_dictionary::lookup(symbol nm)
+{
+ return (object *)d.lookup(nm);
+}
+
+void object_dictionary::define(symbol nm, object *obj)
+{
+ obj->add_reference();
+ obj = (object *)d.lookup(nm, obj);
+ if (obj)
+ obj->remove_reference();
+}
+
+void object_dictionary::rename(symbol oldnm, symbol newnm)
+{
+ object *obj = (object *)d.remove(oldnm);
+ if (obj) {
+ obj = (object *)d.lookup(newnm, obj);
+ if (obj)
+ obj->remove_reference();
+ }
+}
+
+void object_dictionary::remove(symbol nm)
+{
+ object *obj = (object *)d.remove(nm);
+ if (obj)
+ obj->remove_reference();
+}
+
+// Return non-zero if oldnm was defined.
+
+int object_dictionary::alias(symbol newnm, symbol oldnm)
+{
+ object *obj = (object *)d.lookup(oldnm);
+ if (obj) {
+ obj->add_reference();
+ obj = (object *)d.lookup(newnm, obj);
+ if (obj)
+ obj->remove_reference();
+ return 1;
+ }
+ return 0;
+}
+
diff --git a/src/roff/troff/dictionary.h b/src/roff/troff/dictionary.h
new file mode 100644
index 00000000..4f319be4
--- /dev/null
+++ b/src/roff/troff/dictionary.h
@@ -0,0 +1,92 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+
+// there is no distinction between name with no value and name with NULL value
+// null names are not permitted (they will be ignored).
+
+struct association {
+ symbol s;
+ void *v;
+ association() : v(0) {}
+};
+
+class dictionary;
+
+class dictionary_iterator {
+ dictionary *dict;
+ int i;
+public:
+ dictionary_iterator(dictionary &);
+ int get(symbol *, void **);
+};
+
+class dictionary {
+ int size;
+ int used;
+ double threshold;
+ double factor;
+ association *table;
+ void rehash(int);
+public:
+ dictionary(int);
+ void *lookup(symbol s, void *v=0); // returns value associated with key
+ void *lookup(const char *);
+ // if second parameter not NULL, value will be replaced
+ void *remove(symbol);
+ friend class dictionary_iterator;
+};
+
+class object {
+ int rcount;
+ public:
+ object();
+ virtual ~object();
+ void add_reference();
+ void remove_reference();
+};
+
+class object_dictionary;
+
+class object_dictionary_iterator {
+ dictionary_iterator di;
+public:
+ object_dictionary_iterator(object_dictionary &);
+ int get(symbol *, object **);
+};
+
+class object_dictionary {
+ dictionary d;
+public:
+ object_dictionary(int);
+ object *lookup(symbol nm);
+ void define(symbol nm, object *obj);
+ void rename(symbol oldnm, symbol newnm);
+ void remove(symbol nm);
+ int alias(symbol newnm, symbol oldnm);
+ friend class object_dictionary_iterator;
+};
+
+
+inline int object_dictionary_iterator::get(symbol *sp, object **op)
+{
+ return di.get(sp, (void **)op);
+}
diff --git a/src/roff/troff/div.cc b/src/roff/troff/div.cc
new file mode 100644
index 00000000..995c54cd
--- /dev/null
+++ b/src/roff/troff/div.cc
@@ -0,0 +1,1129 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+// diversions
+
+#include "troff.h"
+#include "symbol.h"
+#include "dictionary.h"
+#include "hvunits.h"
+#include "env.h"
+#include "request.h"
+#include "node.h"
+#include "token.h"
+#include "div.h"
+#include "reg.h"
+
+int exit_started = 0; // the exit process has started
+int done_end_macro = 0; // the end macro (if any) has finished
+int seen_last_page_ejector = 0; // seen the LAST_PAGE_EJECTOR cookie
+int last_page_number = 0; // if > 0, the number of the last page
+ // specified with -o
+static int began_page_in_end_macro = 0; // a new page was begun during the end macro
+
+static int last_post_line_extra_space = 0; // needed for \n(.a
+static int nl_reg_contents = -1;
+static int dl_reg_contents = 0;
+static int dn_reg_contents = 0;
+static int vertical_position_traps_flag = 1;
+static vunits truncated_space;
+static vunits needed_space;
+
+diversion::diversion(symbol s)
+: prev(0), nm(s), vertical_position(V0), high_water_mark(V0), marked_place(V0)
+{
+}
+
+struct vertical_size {
+ vunits pre_extra, post_extra, pre, post;
+ vertical_size(vunits vs, vunits post_vs);
+};
+
+vertical_size::vertical_size(vunits vs, vunits post_vs)
+: pre_extra(V0), post_extra(V0), pre(vs), post(post_vs)
+{
+}
+
+void node::set_vertical_size(vertical_size *)
+{
+}
+
+void extra_size_node::set_vertical_size(vertical_size *v)
+{
+ if (n < V0) {
+ if (-n > v->pre_extra)
+ v->pre_extra = -n;
+ }
+ else if (n > v->post_extra)
+ v->post_extra = n;
+}
+
+void vertical_size_node::set_vertical_size(vertical_size *v)
+{
+ if (n < V0)
+ v->pre = -n;
+ else
+ v->post = n;
+}
+
+top_level_diversion *topdiv;
+
+diversion *curdiv;
+
+void do_divert(int append)
+{
+ tok.skip();
+ symbol nm = get_name();
+ if (nm.is_null()) {
+ if (curdiv->prev) {
+ diversion *temp = curdiv;
+ curdiv = curdiv->prev;
+ delete temp;
+ }
+ else
+ warning(WARN_DI, "diversion stack underflow");
+ }
+ else {
+ macro_diversion *md = new macro_diversion(nm, append);
+ md->prev = curdiv;
+ curdiv = md;
+ }
+ skip_line();
+}
+
+void divert()
+{
+ do_divert(0);
+}
+
+void divert_append()
+{
+ do_divert(1);
+}
+
+void diversion::need(vunits n)
+{
+ vunits d = distance_to_next_trap();
+ if (d < n) {
+ space(d, 1);
+ truncated_space = -d;
+ needed_space = n;
+ }
+}
+
+macro_diversion::macro_diversion(symbol s, int append)
+: diversion(s), max_width(H0)
+{
+#if 0
+ if (append) {
+ /* We don't allow recursive appends eg:
+
+ .da a
+ .a
+ .di
+
+ This causes an infinite loop in troff anyway.
+ This is because the user could do
+
+ .as a foo
+
+ in the diversion, and this would mess things up royally,
+ since there would be two things appending to the same
+ macro_header.
+ To make it work, we would have to copy the _contents_
+ of the macro into which we were diverting; this doesn't
+ strike me as worthwhile.
+ However,
+
+ .di a
+ .a
+ .a
+ .di
+
+ will work and will make `a' contain two copies of what it contained
+ before; in troff, `a' would contain nothing. */
+ request_or_macro *rm
+ = (request_or_macro *)request_dictionary.remove(s);
+ if (!rm || (mac = rm->to_macro()) == 0)
+ mac = new macro;
+ }
+ else
+ mac = new macro;
+#endif
+ // We can now catch the situation described above by comparing
+ // the length of the charlist in the macro_header with the length
+ // stored in the macro. When we detect this, we copy the contents.
+ mac = new macro;
+ if (append) {
+ request_or_macro *rm
+ = (request_or_macro *)request_dictionary.lookup(s);
+ if (rm) {
+ macro *m = rm->to_macro();
+ if (m)
+ *mac = *m;
+ }
+ }
+}
+
+macro_diversion::~macro_diversion()
+{
+ request_or_macro *rm = (request_or_macro *)request_dictionary.lookup(nm);
+ macro *m = rm ? rm->to_macro() : 0;
+ if (m) {
+ *m = *mac;
+ delete mac;
+ }
+ else
+ request_dictionary.define(nm, mac);
+ mac = 0;
+ dl_reg_contents = max_width.to_units();
+ dn_reg_contents = vertical_position.to_units();
+}
+
+vunits macro_diversion::distance_to_next_trap()
+{
+ if (!diversion_trap.is_null() && diversion_trap_pos > vertical_position)
+ return diversion_trap_pos - vertical_position;
+ else
+ // Substract vresolution so that vunits::vunits does not overflow.
+ return vunits(INT_MAX - vresolution);
+}
+
+void macro_diversion::transparent_output(unsigned char c)
+{
+ mac->append(c);
+}
+
+void macro_diversion::transparent_output(node *n)
+{
+ mac->append(n);
+}
+
+void macro_diversion::output(node *nd, int retain_size,
+ vunits vs, vunits post_vs, hunits width)
+{
+ vertical_size v(vs, post_vs);
+ while (nd != 0) {
+ nd->set_vertical_size(&v);
+ node *temp = nd;
+ nd = nd->next;
+ if (temp->interpret(mac)) {
+ delete temp;
+ }
+ else {
+#if 1
+ temp->freeze_space();
+#endif
+ mac->append(temp);
+ }
+ }
+ if (!v.post_extra.is_zero())
+ last_post_line_extra_space = v.post_extra.to_units();
+ if (!retain_size) {
+ v.pre = vs;
+ v.post = post_vs;
+ }
+ if (width > max_width)
+ max_width = width;
+ vunits x = v.pre + v.pre_extra + v.post + v.post_extra;
+ if (vertical_position_traps_flag
+ && !diversion_trap.is_null() && diversion_trap_pos > vertical_position
+ && diversion_trap_pos <= vertical_position + x) {
+ vunits trunc = vertical_position + x - diversion_trap_pos;
+ if (trunc > v.post)
+ trunc = v.post;
+ v.post -= trunc;
+ x -= trunc;
+ truncated_space = trunc;
+ spring_trap(diversion_trap);
+ }
+ mac->append(new vertical_size_node(-v.pre));
+ mac->append(new vertical_size_node(v.post));
+ mac->append('\n');
+ vertical_position += x;
+ if (vertical_position - v.post > high_water_mark)
+ high_water_mark = vertical_position - v.post;
+}
+
+void macro_diversion::space(vunits n, int)
+{
+ if (vertical_position_traps_flag
+ && !diversion_trap.is_null() && diversion_trap_pos > vertical_position
+ && diversion_trap_pos <= vertical_position + n) {
+ truncated_space = vertical_position + n - diversion_trap_pos;
+ n = diversion_trap_pos - vertical_position;
+ spring_trap(diversion_trap);
+ }
+ else if (n + vertical_position < V0)
+ n = -vertical_position;
+ mac->append(new diverted_space_node(n));
+ vertical_position += n;
+}
+
+void macro_diversion::copy_file(const char *filename)
+{
+ mac->append(new diverted_copy_file_node(filename));
+}
+
+top_level_diversion::top_level_diversion()
+: page_number(0), page_count(0), last_page_count(-1),
+ page_length(units_per_inch*11),
+ prev_page_offset(units_per_inch), page_offset(units_per_inch),
+ page_trap_list(0), have_next_page_number(0),
+ ejecting_page(0), before_first_page(1), no_space_mode(0)
+{
+}
+
+// find the next trap after pos
+
+trap *top_level_diversion::find_next_trap(vunits *next_trap_pos)
+{
+ trap *next_trap = 0;
+ for (trap *pt = page_trap_list; pt != 0; pt = pt->next)
+ if (!pt->nm.is_null()) {
+ if (pt->position >= V0) {
+ if (pt->position > vertical_position
+ && pt->position < page_length
+ && (next_trap == 0 || pt->position < *next_trap_pos)) {
+ next_trap = pt;
+ *next_trap_pos = pt->position;
+ }
+ }
+ else {
+ vunits pos = pt->position;
+ pos += page_length;
+ if (pos > 0 && pos > vertical_position && (next_trap == 0 || pos < *next_trap_pos)) {
+ next_trap = pt;
+ *next_trap_pos = pos;
+ }
+ }
+ }
+ return next_trap;
+}
+
+vunits top_level_diversion::distance_to_next_trap()
+{
+ vunits d;
+ if (!find_next_trap(&d))
+ return page_length - vertical_position;
+ else
+ return d - vertical_position;
+}
+
+void top_level_diversion::output(node *nd, int retain_size,
+ vunits vs, vunits post_vs, hunits /*width*/)
+{
+ no_space_mode = 0;
+ vunits next_trap_pos;
+ trap *next_trap = find_next_trap(&next_trap_pos);
+ if (before_first_page && begin_page())
+ fatal("sorry, I didn't manage to begin the first page in time: use an explicit .br request");
+ vertical_size v(vs, post_vs);
+ for (node *tem = nd; tem != 0; tem = tem->next)
+ tem->set_vertical_size(&v);
+ if (!v.post_extra.is_zero())
+ last_post_line_extra_space = v.post_extra.to_units();
+ if (!retain_size) {
+ v.pre = vs;
+ v.post = post_vs;
+ }
+ vertical_position += v.pre;
+ vertical_position += v.pre_extra;
+ the_output->print_line(page_offset, vertical_position, nd,
+ v.pre + v.pre_extra, v.post_extra);
+ vertical_position += v.post_extra;
+ if (vertical_position > high_water_mark)
+ high_water_mark = vertical_position;
+ if (vertical_position_traps_flag && vertical_position >= page_length)
+ begin_page();
+ else if (vertical_position_traps_flag
+ && next_trap != 0 && vertical_position >= next_trap_pos) {
+ nl_reg_contents = vertical_position.to_units();
+ truncated_space = v.post;
+ spring_trap(next_trap->nm);
+ }
+ else if (v.post > V0) {
+ vertical_position += v.post;
+ if (vertical_position_traps_flag
+ && next_trap != 0 && vertical_position >= next_trap_pos) {
+ truncated_space = vertical_position - next_trap_pos;
+ vertical_position = next_trap_pos;
+ nl_reg_contents = vertical_position.to_units();
+ spring_trap(next_trap->nm);
+ }
+ else if (vertical_position_traps_flag && vertical_position >= page_length)
+ begin_page();
+ else
+ nl_reg_contents = vertical_position.to_units();
+ }
+ else
+ nl_reg_contents = vertical_position.to_units();
+}
+
+void top_level_diversion::transparent_output(unsigned char c)
+{
+ if (before_first_page && begin_page())
+ // This can only happen with the transparent() request.
+ fatal("sorry, I didn't manage to begin the first page in time: use an explicit .br request");
+ const char *s = asciify(c);
+ while (*s)
+ the_output->transparent_char(*s++);
+}
+
+void top_level_diversion::transparent_output(node * /*n*/)
+{
+ error("can't transparently output node at top level");
+}
+
+void top_level_diversion::copy_file(const char *filename)
+{
+ if (before_first_page && begin_page())
+ fatal("sorry, I didn't manage to begin the first page in time: use an explicit .br request");
+ the_output->copy_file(page_offset, vertical_position, filename);
+}
+
+void top_level_diversion::space(vunits n, int forced)
+{
+ if (no_space_mode) {
+ if (!forced)
+ return;
+ else
+ no_space_mode = 0;
+ }
+ if (before_first_page) {
+ if (begin_page()) {
+ // This happens if there's a top of page trap, and the first-page
+ // transition is caused by `'sp'.
+ truncated_space = n > V0 ? n : V0;
+ return;
+ }
+ }
+ vunits next_trap_pos;
+ trap *next_trap = find_next_trap(&next_trap_pos);
+ vunits y = vertical_position + n;
+ if (vertical_position_traps_flag && next_trap != 0 && y >= next_trap_pos) {
+ vertical_position = next_trap_pos;
+ nl_reg_contents = vertical_position.to_units();
+ truncated_space = y - vertical_position;
+ spring_trap(next_trap->nm);
+ }
+ else if (y < V0) {
+ vertical_position = V0;
+ nl_reg_contents = vertical_position.to_units();
+ }
+ else if (vertical_position_traps_flag && y >= page_length && n >= V0)
+ begin_page();
+ else {
+ vertical_position = y;
+ nl_reg_contents = vertical_position.to_units();
+ }
+}
+
+trap::trap(symbol s, vunits n, trap *p)
+ : next(p), position(n), nm(s)
+{
+}
+
+void top_level_diversion::add_trap(symbol nm, vunits pos)
+{
+ trap *first_free_slot = 0;
+ trap **p;
+ for (p = &page_trap_list; *p; p = &(*p)->next) {
+ if ((*p)->nm.is_null()) {
+ if (first_free_slot == 0)
+ first_free_slot = *p;
+ }
+ else if ((*p)->position == pos) {
+ (*p)->nm = nm;
+ return;
+ }
+ }
+ if (first_free_slot) {
+ first_free_slot->nm = nm;
+ first_free_slot->position = pos;
+ }
+ else
+ *p = new trap(nm, pos, 0);
+}
+
+void top_level_diversion::remove_trap(symbol nm)
+{
+ for (trap *p = page_trap_list; p; p = p->next)
+ if (p->nm == nm) {
+ p->nm = NULL_SYMBOL;
+ return;
+ }
+}
+
+void top_level_diversion::remove_trap_at(vunits pos)
+{
+ for (trap *p = page_trap_list; p; p = p->next)
+ if (p->position == pos) {
+ p->nm = NULL_SYMBOL;
+ return;
+ }
+}
+
+void top_level_diversion::change_trap(symbol nm, vunits pos)
+{
+ for (trap *p = page_trap_list; p; p = p->next)
+ if (p->nm == nm) {
+ p->position = pos;
+ return;
+ }
+}
+
+void top_level_diversion::print_traps()
+{
+ for (trap *p = page_trap_list; p; p = p->next)
+ if (p->nm.is_null())
+ fprintf(stderr, " empty\n");
+ else
+ fprintf(stderr, "%s\t%d\n", p->nm.contents(), p->position.to_units());
+ fflush(stderr);
+}
+
+void end_diversions()
+{
+ while (curdiv != topdiv) {
+ error("automatically ending diversion `%1' on exit",
+ curdiv->nm.contents());
+ diversion *tem = curdiv;
+ curdiv = curdiv->prev;
+ delete tem;
+ }
+}
+
+void cleanup_and_exit(int exit_code)
+{
+ if (the_output) {
+ the_output->trailer(topdiv->get_page_length());
+ delete the_output;
+ }
+ exit(exit_code);
+}
+
+// returns non-zero if it sprung a top of page trap
+
+int top_level_diversion::begin_page()
+{
+ if (exit_started) {
+ if (page_count == last_page_count
+ ? curenv->is_empty()
+ : (done_end_macro && (seen_last_page_ejector || began_page_in_end_macro)))
+ cleanup_and_exit(0);
+ if (!done_end_macro)
+ began_page_in_end_macro = 1;
+ }
+ if (last_page_number > 0 && page_number == last_page_number)
+ cleanup_and_exit(0);
+ if (!the_output)
+ init_output();
+ ++page_count;
+ if (have_next_page_number) {
+ page_number = next_page_number;
+ have_next_page_number = 0;
+ }
+ else if (before_first_page == 1)
+ page_number = 1;
+ else
+ page_number++;
+ // spring the top of page trap if there is one
+ vunits next_trap_pos;
+ vertical_position = -vresolution;
+ trap *next_trap = find_next_trap(&next_trap_pos);
+ vertical_position = V0;
+ high_water_mark = V0;
+ ejecting_page = 0;
+ // If before_first_page was 2, then the top of page transition was undone
+ // using eg .nr nl 0-1. See nl_reg::set_value.
+ if (before_first_page != 2)
+ the_output->begin_page(page_number, page_length);
+ before_first_page = 0;
+ nl_reg_contents = vertical_position.to_units();
+ if (vertical_position_traps_flag && next_trap != 0 && next_trap_pos == V0) {
+ truncated_space = V0;
+ spring_trap(next_trap->nm);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+void continue_page_eject()
+{
+ if (topdiv->get_ejecting()) {
+ if (curdiv != topdiv)
+ error("can't continue page ejection because of current diversion");
+ else if (!vertical_position_traps_flag)
+ error("can't continue page ejection because vertical position traps disabled");
+ else {
+ push_page_ejector();
+ topdiv->space(topdiv->get_page_length(), 1);
+ }
+ }
+}
+
+void top_level_diversion::set_next_page_number(int n)
+{
+ next_page_number= n;
+ have_next_page_number = 1;
+}
+
+int top_level_diversion::get_next_page_number()
+{
+ return have_next_page_number ? next_page_number : page_number + 1;
+}
+
+void top_level_diversion::set_page_length(vunits n)
+{
+ page_length = n;
+}
+
+diversion::~diversion()
+{
+}
+
+void page_offset()
+{
+ hunits n;
+ // The troff manual says that the default scaling indicator is v,
+ // but it is in fact m: v wouldn't make sense for a horizontally
+ // oriented request.
+ if (!has_arg() || !get_hunits(&n, 'm', topdiv->page_offset))
+ n = topdiv->prev_page_offset;
+ topdiv->prev_page_offset = topdiv->page_offset;
+ topdiv->page_offset = n;
+ skip_line();
+}
+
+void page_length()
+{
+ vunits n;
+ if (has_arg() && get_vunits(&n, 'v', topdiv->get_page_length()))
+ topdiv->set_page_length(n);
+ else
+ topdiv->set_page_length(11*units_per_inch);
+ skip_line();
+}
+
+void when_request()
+{
+ vunits n;
+ if (get_vunits(&n, 'v')) {
+ symbol s = get_name();
+ if (s.is_null())
+ topdiv->remove_trap_at(n);
+ else
+ topdiv->add_trap(s, n);
+ }
+ skip_line();
+}
+
+void begin_page()
+{
+ int got_arg = 0;
+ int n;
+ if (has_arg() && get_integer(&n, topdiv->get_page_number()))
+ got_arg = 1;
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (curdiv == topdiv) {
+ if (topdiv->before_first_page) {
+ if (!break_flag) {
+ if (got_arg)
+ topdiv->set_next_page_number(n);
+ if (got_arg || !topdiv->no_space_mode)
+ topdiv->begin_page();
+ }
+ else if (topdiv->no_space_mode && !got_arg)
+ topdiv->begin_page();
+ else {
+ /* Given this
+
+ .wh 0 x
+ .de x
+ .tm \\n%
+ ..
+ .bp 3
+
+ troff prints
+
+ 1
+ 3
+
+ This code makes groff do the same. */
+
+ push_page_ejector();
+ topdiv->begin_page();
+ if (got_arg)
+ topdiv->set_next_page_number(n);
+ topdiv->set_ejecting();
+ }
+ }
+ else {
+ push_page_ejector();
+ if (break_flag)
+ curenv->do_break();
+ if (got_arg)
+ topdiv->set_next_page_number(n);
+ if (!(topdiv->no_space_mode && !got_arg))
+ topdiv->set_ejecting();
+ }
+ }
+ tok.next();
+}
+
+void no_space()
+{
+ if (curdiv == topdiv)
+ topdiv->no_space_mode = 1;
+ skip_line();
+}
+
+void restore_spacing()
+{
+ if (curdiv == topdiv)
+ topdiv->no_space_mode = 0;
+ skip_line();
+}
+
+/* It is necessary to generate a break before before reading the argument,
+because otherwise arguments using | will be wrong. But if we just
+generate a break as usual, then the line forced out may spring a trap
+and thus push a macro onto the input stack before we have had a chance
+to read the argument to the sp request. We resolve this dilemma by
+setting, before generating the break, a flag which will postpone the
+actual pushing of the macro associated with the trap sprung by the
+outputting of the line forced out by the break till after we have read
+the argument to the request. If the break did cause a trap to be
+sprung, then we don't actually do the space. */
+
+void space_request()
+{
+ postpone_traps();
+ if (break_flag)
+ curenv->do_break();
+ vunits n;
+ if (!has_arg() || !get_vunits(&n, 'v'))
+ n = curenv->get_vertical_spacing();
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (!unpostpone_traps())
+ curdiv->space(n);
+ else
+ // The line might have had line spacing that was truncated.
+ truncated_space += n;
+ tok.next();
+}
+
+void blank_line()
+{
+ curenv->do_break();
+ if (!trap_sprung_flag)
+ curdiv->space(curenv->get_vertical_spacing());
+ else
+ truncated_space += curenv->get_vertical_spacing();
+}
+
+/* need_space might spring a trap and so we must be careful that the
+BEGIN_TRAP token is not skipped over. */
+
+void need_space()
+{
+ vunits n;
+ if (!has_arg() || !get_vunits(&n, 'v'))
+ n = curenv->get_vertical_spacing();
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ curdiv->need(n);
+ tok.next();
+}
+
+void page_number()
+{
+ int n;
+ if (has_arg() && get_integer(&n, topdiv->get_page_number()))
+ topdiv->set_next_page_number(n);
+ skip_line();
+}
+
+vunits saved_space;
+
+void save_vertical_space()
+{
+ vunits x;
+ if (get_vunits(&x, 'v')) {
+ if (curdiv->distance_to_next_trap() > x)
+ curdiv->space(x, 1);
+ else
+ saved_space = x;
+ }
+ skip_line();
+}
+
+void output_saved_vertical_space()
+{
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (saved_space > V0)
+ curdiv->space(saved_space, 1);
+ saved_space = V0;
+ tok.next();
+}
+
+void flush_output()
+{
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ if (the_output)
+ the_output->flush();
+ tok.next();
+}
+
+void macro_diversion::set_diversion_trap(symbol s, vunits n)
+{
+ diversion_trap = s;
+ diversion_trap_pos = n;
+}
+
+void macro_diversion::clear_diversion_trap()
+{
+ diversion_trap = NULL_SYMBOL;
+}
+
+void top_level_diversion::set_diversion_trap(symbol, vunits)
+{
+ error("can't set diversion trap when no current diversion");
+}
+
+void top_level_diversion::clear_diversion_trap()
+{
+ error("can't set diversion trap when no current diversion");
+}
+
+void diversion_trap()
+{
+ vunits n;
+ if (has_arg() && get_vunits(&n, 'v')) {
+ symbol s = get_name();
+ if (!s.is_null())
+ curdiv->set_diversion_trap(s, n);
+ else
+ curdiv->clear_diversion_trap();
+ }
+ else
+ curdiv->clear_diversion_trap();
+ skip_line();
+}
+
+void change_trap()
+{
+ symbol s = get_name(1);
+ if (!s.is_null()) {
+ vunits x;
+ if (has_arg() && get_vunits(&x, 'v'))
+ topdiv->change_trap(s, x);
+ else
+ topdiv->remove_trap(s);
+ }
+ skip_line();
+}
+
+void print_traps()
+{
+ topdiv->print_traps();
+ skip_line();
+}
+
+void mark()
+{
+ symbol s = get_name();
+ if (s.is_null())
+ curdiv->marked_place = curdiv->get_vertical_position();
+ else if (curdiv == topdiv)
+ set_number_reg(s, nl_reg_contents);
+ else
+ set_number_reg(s, curdiv->get_vertical_position().to_units());
+ skip_line();
+}
+
+// This is truly bizarre. It is documented in the SQ manual.
+
+void return_request()
+{
+ vunits dist = curdiv->marked_place - curdiv->get_vertical_position();
+ if (has_arg()) {
+ if (tok.ch() == '-') {
+ tok.next();
+ vunits x;
+ if (get_vunits(&x, 'v'))
+ dist = -x;
+ }
+ else {
+ vunits x;
+ if (get_vunits(&x, 'v'))
+ dist = x >= V0 ? x - curdiv->get_vertical_position() : V0;
+ }
+ }
+ if (dist < V0)
+ curdiv->space(dist);
+ skip_line();
+}
+
+void vertical_position_traps()
+{
+ int n;
+ if (has_arg() && get_integer(&n))
+ vertical_position_traps_flag = (n != 0);
+ else
+ vertical_position_traps_flag = 1;
+ skip_line();
+}
+
+class page_offset_reg : public reg {
+public:
+ int get_value(units *);
+ const char *get_string();
+};
+
+int page_offset_reg::get_value(units *res)
+{
+ *res = topdiv->get_page_offset().to_units();
+ return 1;
+}
+
+const char *page_offset_reg::get_string()
+{
+ return itoa(topdiv->get_page_offset().to_units());
+}
+
+class page_length_reg : public reg {
+public:
+ int get_value(units *);
+ const char *get_string();
+};
+
+int page_length_reg::get_value(units *res)
+{
+ *res = topdiv->get_page_length().to_units();
+ return 1;
+}
+
+const char *page_length_reg::get_string()
+{
+ return itoa(topdiv->get_page_length().to_units());
+}
+
+class vertical_position_reg : public reg {
+public:
+ int get_value(units *);
+ const char *get_string();
+};
+
+int vertical_position_reg::get_value(units *res)
+{
+ if (curdiv == topdiv && topdiv->before_first_page)
+ *res = -1;
+ else
+ *res = curdiv->get_vertical_position().to_units();
+ return 1;
+}
+
+const char *vertical_position_reg::get_string()
+{
+ if (curdiv == topdiv && topdiv->before_first_page)
+ return "-1";
+ else
+ return itoa(curdiv->get_vertical_position().to_units());
+}
+
+class high_water_mark_reg : public reg {
+public:
+ int get_value(units *);
+ const char *get_string();
+};
+
+int high_water_mark_reg::get_value(units *res)
+{
+ *res = curdiv->get_high_water_mark().to_units();
+ return 1;
+}
+
+const char *high_water_mark_reg::get_string()
+{
+ return itoa(curdiv->get_high_water_mark().to_units());
+}
+
+class distance_to_next_trap_reg : public reg {
+public:
+ int get_value(units *);
+ const char *get_string();
+};
+
+int distance_to_next_trap_reg::get_value(units *res)
+{
+ *res = curdiv->distance_to_next_trap().to_units();
+ return 1;
+}
+
+const char *distance_to_next_trap_reg::get_string()
+{
+ return itoa(curdiv->distance_to_next_trap().to_units());
+}
+
+class diversion_name_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *diversion_name_reg::get_string()
+{
+ return curdiv->get_diversion_name();
+}
+
+class page_number_reg : public general_reg {
+public:
+ page_number_reg();
+ int get_value(units *);
+ void set_value(units);
+};
+
+page_number_reg::page_number_reg()
+{
+}
+
+void page_number_reg::set_value(units n)
+{
+ topdiv->set_page_number(n);
+}
+
+int page_number_reg::get_value(units *res)
+{
+ *res = topdiv->get_page_number();
+ return 1;
+}
+
+class next_page_number_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *next_page_number_reg::get_string()
+{
+ return itoa(topdiv->get_next_page_number());
+}
+
+class page_ejecting_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *page_ejecting_reg::get_string()
+{
+ return itoa(topdiv->get_ejecting());
+}
+
+class constant_vunits_reg : public reg {
+ vunits *p;
+public:
+ constant_vunits_reg(vunits *);
+ const char *get_string();
+};
+
+constant_vunits_reg::constant_vunits_reg(vunits *q) : p(q)
+{
+}
+
+const char *constant_vunits_reg::get_string()
+{
+ return itoa(p->to_units());
+}
+
+class nl_reg : public variable_reg {
+public:
+ nl_reg();
+ void set_value(units);
+};
+
+nl_reg::nl_reg() : variable_reg(&nl_reg_contents)
+{
+}
+
+void nl_reg::set_value(units n)
+{
+ variable_reg::set_value(n);
+ // Setting nl to a negative value when the vertical position in
+ // the top-level diversion is 0 undoes the top of page transition,
+ // so that the header macro will be called as if the top of page
+ // transition hasn't happened. This is used by Larry Wall's
+ // wrapman program. Setting before_first_page to 2 rather than 1,
+ // tells top_level_diversion::begin_page not to call
+ // output_file::begin_page again.
+ if (n < 0 && topdiv->get_vertical_position() == V0)
+ topdiv->before_first_page = 2;
+}
+
+void init_div_requests()
+{
+ init_request("wh", when_request);
+ init_request("ch", change_trap);
+ init_request("pl", page_length);
+ init_request("po", page_offset);
+ init_request("rs", restore_spacing);
+ init_request("ns", no_space);
+ init_request("sp", space_request);
+ init_request("di", divert);
+ init_request("da", divert_append);
+ init_request("bp", begin_page);
+ init_request("ne", need_space);
+ init_request("pn", page_number);
+ init_request("dt", diversion_trap);
+ init_request("rt", return_request);
+ init_request("mk", mark);
+ init_request("sv", save_vertical_space);
+ init_request("os", output_saved_vertical_space);
+ init_request("fl", flush_output);
+ init_request("vpt", vertical_position_traps);
+ init_request("ptr", print_traps);
+ number_reg_dictionary.define(".a",
+ new constant_int_reg(&last_post_line_extra_space));
+ number_reg_dictionary.define(".z", new diversion_name_reg);
+ number_reg_dictionary.define(".o", new page_offset_reg);
+ number_reg_dictionary.define(".p", new page_length_reg);
+ number_reg_dictionary.define(".d", new vertical_position_reg);
+ number_reg_dictionary.define(".h", new high_water_mark_reg);
+ number_reg_dictionary.define(".t", new distance_to_next_trap_reg);
+ number_reg_dictionary.define("dl", new variable_reg(&dl_reg_contents));
+ number_reg_dictionary.define("dn", new variable_reg(&dn_reg_contents));
+ number_reg_dictionary.define("nl", new nl_reg);
+ number_reg_dictionary.define(".vpt",
+ new constant_int_reg(&vertical_position_traps_flag));
+ number_reg_dictionary.define("%", new page_number_reg);
+ number_reg_dictionary.define(".pn", new next_page_number_reg);
+ number_reg_dictionary.define(".trunc",
+ new constant_vunits_reg(&truncated_space));
+ number_reg_dictionary.define(".ne",
+ new constant_vunits_reg(&needed_space));
+ number_reg_dictionary.define(".pe", new page_ejecting_reg);
+}
diff --git a/src/roff/troff/div.h b/src/roff/troff/div.h
new file mode 100644
index 00000000..e97e0a77
--- /dev/null
+++ b/src/roff/troff/div.h
@@ -0,0 +1,150 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+class diversion {
+ friend void do_divert(int append);
+ friend void end_diversions();
+ diversion *prev;
+protected:
+ symbol nm;
+ vunits vertical_position;
+ vunits high_water_mark;
+public:
+ vunits marked_place;
+ diversion(symbol s = NULL_SYMBOL);
+ virtual ~diversion();
+ virtual void output(node *nd, int retain_size, vunits vs, vunits post_vs,
+ hunits width) = 0;
+ virtual void transparent_output(unsigned char) = 0;
+ virtual void transparent_output(node *) = 0;
+ virtual void space(vunits distance, int forced = 0) = 0;
+#ifdef COLUMN
+ virtual void vjustify(symbol) = 0;
+#endif /* COLUMN */
+ vunits get_vertical_position() { return vertical_position; }
+ vunits get_high_water_mark() { return high_water_mark; }
+ virtual vunits distance_to_next_trap() = 0;
+ void need(vunits);
+ const char *get_diversion_name() { return nm.contents(); }
+ virtual void set_diversion_trap(symbol, vunits) = 0;
+ virtual void clear_diversion_trap() = 0;
+ virtual void copy_file(const char *filename) = 0;
+};
+
+class macro;
+
+class macro_diversion : public diversion {
+ macro *mac;
+ hunits max_width;
+ symbol diversion_trap;
+ vunits diversion_trap_pos;
+public:
+ macro_diversion(symbol, int);
+ ~macro_diversion();
+ void output(node *nd, int retain_size, vunits vs, vunits post_vs,
+ hunits width);
+ void transparent_output(unsigned char);
+ void transparent_output(node *);
+ void space(vunits distance, int forced = 0);
+#ifdef COLUMN
+ void vjustify(symbol);
+#endif /* COLUMN */
+ vunits distance_to_next_trap();
+ void set_diversion_trap(symbol, vunits);
+ void clear_diversion_trap();
+ void copy_file(const char *filename);
+};
+
+struct trap {
+ trap *next;
+ vunits position;
+ symbol nm;
+ trap(symbol, vunits, trap *);
+};
+
+struct output_file;
+
+class top_level_diversion : public diversion {
+ int page_number;
+ int page_count;
+ int last_page_count;
+ vunits page_length;
+ hunits prev_page_offset;
+ hunits page_offset;
+ trap *page_trap_list;
+ trap *find_next_trap(vunits *);
+ int have_next_page_number;
+ int next_page_number;
+ int ejecting_page; // Is the current page being ejected?
+public:
+ int before_first_page;
+ int no_space_mode;
+ top_level_diversion();
+ void output(node *nd, int retain_size, vunits vs, vunits post_vs,
+ hunits width);
+ void transparent_output(unsigned char);
+ void transparent_output(node *);
+ void space(vunits distance, int forced = 0);
+#ifdef COLUMN
+ void vjustify(symbol);
+#endif /* COLUMN */
+ hunits get_page_offset() { return page_offset; }
+ vunits get_page_length() { return page_length; }
+ vunits distance_to_next_trap();
+ void add_trap(symbol nm, vunits pos);
+ void change_trap(symbol nm, vunits pos);
+ void remove_trap(symbol);
+ void remove_trap_at(vunits pos);
+ void print_traps();
+ int get_page_count() { return page_count; }
+ int get_page_number() { return page_number; }
+ int get_next_page_number();
+ void set_page_number(int n) { page_number = n; }
+ int begin_page();
+ void set_next_page_number(int);
+ void set_page_length(vunits);
+ void copy_file(const char *filename);
+ int get_ejecting() { return ejecting_page; }
+ void set_ejecting() { ejecting_page = 1; }
+ friend void page_offset();
+ void set_diversion_trap(symbol, vunits);
+ void clear_diversion_trap();
+ void set_last_page() { last_page_count = page_count; }
+};
+
+extern top_level_diversion *topdiv;
+extern diversion *curdiv;
+
+extern int exit_started;
+extern int done_end_macro;
+extern int last_page_number;
+extern int seen_last_page_ejector;
+
+void spring_trap(symbol); // implemented by input.c
+extern int trap_sprung_flag;
+void postpone_traps();
+int unpostpone_traps();
+
+void push_page_ejector();
+void continue_page_eject();
+void handle_first_page_transition();
+void blank_line();
+
+extern void cleanup_and_exit(int);
diff --git a/src/roff/troff/env.cc b/src/roff/troff/env.cc
new file mode 100644
index 00000000..973c15ea
--- /dev/null
+++ b/src/roff/troff/env.cc
@@ -0,0 +1,3114 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "troff.h"
+#include "symbol.h"
+#include "dictionary.h"
+#include "hvunits.h"
+#include "env.h"
+#include "request.h"
+#include "node.h"
+#include "token.h"
+#include "div.h"
+#include "reg.h"
+#include "charinfo.h"
+#include "searchpath.h"
+#include "macropath.h"
+#include <math.h>
+
+symbol default_family("T");
+
+enum { ADJUST_LEFT = 0, ADJUST_BOTH = 1, ADJUST_CENTER = 3, ADJUST_RIGHT = 5 };
+
+enum { HYPHEN_LAST_LINE = 2, HYPHEN_LAST_CHARS = 4, HYPHEN_FIRST_CHARS = 8 };
+
+struct env_list {
+ environment *env;
+ env_list *next;
+ env_list(environment *e, env_list *p) : env(e), next(p) {}
+};
+
+env_list *env_stack;
+const int NENVIRONMENTS = 10;
+environment *env_table[NENVIRONMENTS];
+dictionary env_dictionary(10);
+environment *curenv;
+static int next_line_number = 0;
+
+charinfo *field_delimiter_char;
+charinfo *padding_indicator_char;
+
+int translate_space_to_dummy = 0;
+
+class pending_output_line {
+ node *nd;
+ int no_fill;
+ vunits vs;
+ vunits post_vs;
+ hunits width;
+#ifdef WIDOW_CONTROL
+ int last_line; // Is it the last line of the paragraph?
+#endif /* WIDOW_CONTROL */
+public:
+ pending_output_line *next;
+
+ pending_output_line(node *, int, vunits, vunits, hunits,
+ pending_output_line * = 0);
+ ~pending_output_line();
+ int output();
+
+#ifdef WIDOW_CONTROL
+ friend void environment::mark_last_line();
+ friend void environment::output(node *, int, vunits, vunits, hunits);
+#endif /* WIDOW_CONTROL */
+};
+
+pending_output_line::pending_output_line(node *n, int nf, vunits v, vunits pv,
+ hunits w, pending_output_line *p)
+: nd(n), no_fill(nf), vs(v), post_vs(pv), width(w),
+#ifdef WIDOW_CONTROL
+ last_line(0),
+#endif /* WIDOW_CONTROL */
+ next(p)
+{
+}
+
+pending_output_line::~pending_output_line()
+{
+ delete_node_list(nd);
+}
+
+int pending_output_line::output()
+{
+ if (trap_sprung_flag)
+ return 0;
+#ifdef WIDOW_CONTROL
+ if (next && next->last_line && !no_fill) {
+ curdiv->need(vs + post_vs + vunits(vresolution));
+ if (trap_sprung_flag) {
+ next->last_line = 0; // Try to avoid infinite loops.
+ return 0;
+ }
+ }
+#endif
+ curdiv->output(nd, no_fill, vs, post_vs, width);
+ nd = 0;
+ return 1;
+}
+
+void environment::output(node *nd, int no_fill, vunits vs, vunits post_vs,
+ hunits width)
+{
+#ifdef WIDOW_CONTROL
+ while (pending_lines) {
+ if (widow_control && !pending_lines->no_fill && !pending_lines->next)
+ break;
+ if (!pending_lines->output())
+ break;
+ pending_output_line *tem = pending_lines;
+ pending_lines = pending_lines->next;
+ delete tem;
+ }
+#else /* WIDOW_CONTROL */
+ output_pending_lines();
+#endif /* WIDOW_CONTROL */
+ if (!trap_sprung_flag && !pending_lines
+#ifdef WIDOW_CONTROL
+ && (!widow_control || no_fill)
+#endif /* WIDOW_CONTROL */
+ )
+ curdiv->output(nd, no_fill, vs, post_vs, width);
+ else {
+ pending_output_line **p;
+ for (p = &pending_lines; *p; p = &(*p)->next)
+ ;
+ *p = new pending_output_line(nd, no_fill, vs, post_vs, width);
+ }
+}
+
+// a line from .tl goes at the head of the queue
+
+void environment::output_title(node *nd, int no_fill, vunits vs,
+ vunits post_vs, hunits width)
+{
+ if (!trap_sprung_flag)
+ curdiv->output(nd, no_fill, vs, post_vs, width);
+ else
+ pending_lines = new pending_output_line(nd, no_fill, vs, post_vs, width,
+ pending_lines);
+}
+
+void environment::output_pending_lines()
+{
+ while (pending_lines && pending_lines->output()) {
+ pending_output_line *tem = pending_lines;
+ pending_lines = pending_lines->next;
+ delete tem;
+ }
+}
+
+#ifdef WIDOW_CONTROL
+
+void environment::mark_last_line()
+{
+ if (!widow_control || !pending_lines)
+ return;
+ for (pending_output_line *p = pending_lines; p->next; p = p->next)
+ ;
+ if (!p->no_fill)
+ p->last_line = 1;
+}
+
+void widow_control_request()
+{
+ int n;
+ if (has_arg() && get_integer(&n))
+ curenv->widow_control = n != 0;
+ else
+ curenv->widow_control = 1;
+ skip_line();
+}
+
+#endif /* WIDOW_CONTROL */
+
+/* font_size functions */
+
+size_range *font_size::size_table = 0;
+int font_size::nranges = 0;
+
+extern "C" {
+
+static int compare_ranges(const void *p1, const void *p2)
+{
+ return ((size_range *)p1)->min - ((size_range *)p2)->min;
+}
+
+}
+
+void font_size::init_size_table(int *sizes)
+{
+ nranges = 0;
+ while (sizes[nranges*2] != 0)
+ nranges++;
+ assert(nranges > 0);
+ size_table = new size_range[nranges];
+ for (int i = 0; i < nranges; i++) {
+ size_table[i].min = sizes[i*2];
+ size_table[i].max = sizes[i*2 + 1];
+ }
+ qsort(size_table, nranges, sizeof(size_range), compare_ranges);
+}
+
+font_size::font_size(int sp)
+{
+ for (int i = 0; i < nranges; i++) {
+ if (sp < size_table[i].min) {
+ if (i > 0 && size_table[i].min - sp >= sp - size_table[i - 1].max)
+ p = size_table[i - 1].max;
+ else
+ p = size_table[i].min;
+ return;
+ }
+ if (sp <= size_table[i].max) {
+ p = sp;
+ return;
+ }
+ }
+ p = size_table[nranges - 1].max;
+}
+
+int font_size::to_units()
+{
+ return scale(p, units_per_inch, sizescale*72);
+}
+
+// we can't do this in a static constructor because various dictionaries
+// have to get initialized first
+
+void init_environments()
+{
+ curenv = env_table[0] = new environment("0");
+}
+
+void tab_character()
+{
+ curenv->tab_char = get_optional_char();
+ skip_line();
+}
+
+void leader_character()
+{
+ curenv->leader_char = get_optional_char();
+ skip_line();
+}
+
+void environment::add_char(charinfo *ci)
+{
+ if (interrupted)
+ ;
+ // don't allow fields in dummy environments
+ else if (ci == field_delimiter_char && !dummy) {
+ if (current_field)
+ wrap_up_field();
+ else
+ start_field();
+ }
+ else if (current_field && ci == padding_indicator_char)
+ add_padding();
+ else if (current_tab) {
+ if (tab_contents == 0)
+ tab_contents = new line_start_node;
+ if (ci != hyphen_indicator_char)
+ tab_contents = tab_contents->add_char(ci, this, &tab_width);
+ else
+ tab_contents = tab_contents->add_discretionary_hyphen();
+ }
+ else {
+ if (line == 0)
+ start_line();
+ if (ci != hyphen_indicator_char)
+ line = line->add_char(ci, this, &width_total);
+ else
+ line = line->add_discretionary_hyphen();
+ }
+}
+
+node *environment::make_char_node(charinfo *ci)
+{
+ return make_node(ci, this);
+}
+
+void environment::add_node(node *n)
+{
+ assert(n != 0);
+ if (current_tab || current_field)
+ n->freeze_space();
+ if (interrupted) {
+ delete n;
+ }
+ else if (current_tab) {
+ n->next = tab_contents;
+ tab_contents = n;
+ tab_width += n->width();
+ }
+ else {
+ if (line == 0) {
+ if (discarding && n->discardable()) {
+ // XXX possibly: input_line_start -= n->width();
+ delete n;
+ return;
+ }
+ start_line();
+ }
+ width_total += n->width();
+ space_total += n->nspaces();
+ n->next = line;
+ line = n;
+ }
+}
+
+
+void environment::add_hyphen_indicator()
+{
+ if (current_tab || interrupted || current_field
+ || hyphen_indicator_char != 0)
+ return;
+ if (line == 0)
+ start_line();
+ line = line->add_discretionary_hyphen();
+}
+
+int environment::get_hyphenation_flags()
+{
+ return hyphenation_flags;
+}
+
+int environment::get_hyphen_line_max()
+{
+ return hyphen_line_max;
+}
+
+int environment::get_hyphen_line_count()
+{
+ return hyphen_line_count;
+}
+
+int environment::get_center_lines()
+{
+ return center_lines;
+}
+
+int environment::get_right_justify_lines()
+{
+ return right_justify_lines;
+}
+
+void environment::add_italic_correction()
+{
+ if (current_tab) {
+ if (tab_contents)
+ tab_contents = tab_contents->add_italic_correction(&tab_width);
+ }
+ else if (line)
+ line = line->add_italic_correction(&width_total);
+}
+
+void environment::space_newline()
+{
+ assert(!current_tab && !current_field);
+ if (interrupted)
+ return;
+ hunits x = H0;
+ if (!translate_space_to_dummy) {
+ x = env_space_width(this);
+ if (node_list_ends_sentence(line) == 1)
+ x += env_sentence_space_width(this);
+ }
+ if (line != 0 && line->merge_space(x)) {
+ width_total += x;
+ return;
+ }
+ add_node(new word_space_node(x));
+ possibly_break_line(spread_flag);
+ spread_flag = 0;
+}
+
+void environment::space()
+{
+ if (interrupted)
+ return;
+ if (current_field && padding_indicator_char == 0) {
+ add_padding();
+ return;
+ }
+ hunits x = translate_space_to_dummy ? H0 : env_space_width(this);
+ node *p = current_tab ? tab_contents : line;
+ hunits *tp = current_tab ? &tab_width : &width_total;
+ if (p && p->nspaces() == 1 && p->width() == x
+ && node_list_ends_sentence(p->next) == 1) {
+ hunits xx = translate_space_to_dummy ? H0 : env_sentence_space_width(this);
+ if (p->merge_space(xx)) {
+ *tp += xx;
+ return;
+ }
+ }
+ if (p && p->merge_space(x)) {
+ *tp += x;
+ return;
+ }
+ add_node(new word_space_node(x));
+ possibly_break_line(spread_flag);
+ spread_flag = 0;
+}
+
+void environment::set_font(symbol nm)
+{
+ if (interrupted)
+ return;
+ if (nm == symbol("P")) {
+ if (family->make_definite(prev_fontno) < 0)
+ return;
+ int tem = fontno;
+ fontno = prev_fontno;
+ prev_fontno = tem;
+ }
+ else {
+ prev_fontno = fontno;
+ int n = symbol_fontno(nm);
+ if (n < 0) {
+ n = next_available_font_position();
+ if (!mount_font(n, nm))
+ return;
+ }
+ if (family->make_definite(n) < 0)
+ return;
+ fontno = n;
+ }
+}
+
+void environment::set_font(int n)
+{
+ if (interrupted)
+ return;
+ if (is_good_fontno(n)) {
+ prev_fontno = fontno;
+ fontno = n;
+ }
+ else
+ warning(WARN_FONT, "bad font number");
+}
+
+void environment::set_family(symbol fam)
+{
+ if (fam.is_null()) {
+ if (prev_family->make_definite(fontno) < 0)
+ return;
+ font_family *tem = family;
+ family = prev_family;
+ prev_family = tem;
+ }
+ else {
+ font_family *f = lookup_family(fam);
+ if (f->make_definite(fontno) < 0)
+ return;
+ prev_family = family;
+ family = f;
+ }
+}
+
+void environment::set_size(int n)
+{
+ if (interrupted)
+ return;
+ if (n == 0) {
+ font_size temp = prev_size;
+ prev_size = size;
+ size = temp;
+ int temp2 = prev_requested_size;
+ prev_requested_size = requested_size;
+ requested_size = temp2;
+ }
+ else {
+ prev_size = size;
+ size = font_size(n);
+ prev_requested_size = requested_size;
+ requested_size = n;
+ }
+}
+
+void environment::set_char_height(int n)
+{
+ if (interrupted)
+ return;
+ if (n == requested_size || n <= 0)
+ char_height = 0;
+ else
+ char_height = n;
+}
+
+void environment::set_char_slant(int n)
+{
+ if (interrupted)
+ return;
+ char_slant = n;
+}
+
+environment::environment(symbol nm)
+: dummy(0),
+ prev_line_length((units_per_inch*13)/2),
+ line_length((units_per_inch*13)/2),
+ prev_title_length((units_per_inch*13)/2),
+ title_length((units_per_inch*13)/2),
+ prev_size(sizescale*10),
+ size(sizescale*10),
+ requested_size(sizescale*10),
+ prev_requested_size(sizescale*10),
+ char_height(0),
+ char_slant(0),
+ space_size(12),
+ sentence_space_size(12),
+ adjust_mode(ADJUST_BOTH),
+ fill(1),
+ interrupted(0),
+ prev_line_interrupted(0),
+ center_lines(0),
+ right_justify_lines(0),
+ prev_vertical_spacing(points_to_units(12)),
+ vertical_spacing(points_to_units(12)),
+ prev_post_vertical_spacing(0),
+ post_vertical_spacing(0),
+ prev_line_spacing(1),
+ line_spacing(1),
+ prev_indent(0),
+ indent(0),
+ temporary_indent(0),
+ have_temporary_indent(0),
+ underline_lines(0),
+ input_trap_count(0),
+ line(0),
+ prev_text_length(0),
+ width_total(0),
+ space_total(0),
+ input_line_start(0),
+ tabs(units_per_inch/2, TAB_LEFT),
+ current_tab(TAB_NONE),
+ leader_node(0),
+ tab_char(0),
+ leader_char(charset_table['.']),
+ current_field(0),
+ discarding(0),
+ spread_flag(0),
+ margin_character_flags(0),
+ margin_character_node(0),
+ margin_character_distance(points_to_units(10)),
+ numbering_nodes(0),
+ number_text_separation(1),
+ line_number_indent(0),
+ line_number_multiple(1),
+ no_number_count(0),
+ hyphenation_flags(1),
+ hyphen_line_count(0),
+ hyphen_line_max(-1),
+ hyphenation_space(H0),
+ hyphenation_margin(H0),
+ composite(0),
+ pending_lines(0),
+#ifdef WIDOW_CONTROL
+ widow_control(0),
+#endif /* WIDOW_CONTROL */
+ name(nm),
+ control_char('.'),
+ no_break_control_char('\''),
+ hyphen_indicator_char(0)
+{
+ prev_family = family = lookup_family(default_family);
+ prev_fontno = fontno = 1;
+ if (!is_good_fontno(1))
+ fatal("font number 1 not a valid font");
+ if (family->make_definite(1) < 0)
+ fatal("invalid default family `%1'", default_family.contents());
+ prev_fontno = fontno;
+}
+
+environment::environment(const environment *e)
+: dummy(1),
+ prev_line_length(e->prev_line_length),
+ line_length(e->line_length),
+ prev_title_length(e->prev_title_length),
+ title_length(e->title_length),
+ prev_size(e->prev_size),
+ size(e->size),
+ requested_size(e->requested_size),
+ prev_requested_size(e->prev_requested_size),
+ char_height(e->char_height),
+ char_slant(e->char_slant),
+ prev_fontno(e->prev_fontno),
+ fontno(e->fontno),
+ prev_family(e->prev_family),
+ family(e->family),
+ space_size(e->space_size),
+ sentence_space_size(e->sentence_space_size),
+ adjust_mode(e->adjust_mode),
+ fill(e->fill),
+ interrupted(0),
+ prev_line_interrupted(0),
+ center_lines(0),
+ right_justify_lines(0),
+ prev_vertical_spacing(e->prev_vertical_spacing),
+ vertical_spacing(e->vertical_spacing),
+ prev_post_vertical_spacing(e->prev_post_vertical_spacing),
+ post_vertical_spacing(e->post_vertical_spacing),
+ prev_line_spacing(e->prev_line_spacing),
+ line_spacing(e->line_spacing),
+ prev_indent(e->prev_indent),
+ indent(e->indent),
+ temporary_indent(0),
+ have_temporary_indent(0),
+ underline_lines(0),
+ input_trap_count(0),
+ line(0),
+ prev_text_length(e->prev_text_length),
+ width_total(0),
+ space_total(0),
+ input_line_start(0),
+ tabs(e->tabs),
+ current_tab(TAB_NONE),
+ leader_node(0),
+ tab_char(e->tab_char),
+ leader_char(e->leader_char),
+ current_field(0),
+ discarding(0),
+ spread_flag(0),
+ margin_character_flags(e->margin_character_flags),
+ margin_character_node(e->margin_character_node),
+ margin_character_distance(e->margin_character_distance),
+ numbering_nodes(0),
+ number_text_separation(e->number_text_separation),
+ line_number_indent(e->line_number_indent),
+ line_number_multiple(e->line_number_multiple),
+ no_number_count(e->no_number_count),
+ hyphenation_flags(e->hyphenation_flags),
+ hyphen_line_count(0),
+ hyphen_line_max(e->hyphen_line_max),
+ hyphenation_space(e->hyphenation_space),
+ hyphenation_margin(e->hyphenation_margin),
+ composite(0),
+ pending_lines(0),
+#ifdef WIDOW_CONTROL
+ widow_control(e->widow_control),
+#endif /* WIDOW_CONTROL */
+ name(e->name), // so that eg `.if "\n[.ev]"0"' works
+ control_char(e->control_char),
+ no_break_control_char(e->no_break_control_char),
+ hyphen_indicator_char(e->hyphen_indicator_char)
+{
+}
+
+environment::~environment()
+{
+ delete leader_node;
+ delete_node_list(line);
+ delete_node_list(numbering_nodes);
+}
+
+hunits environment::get_input_line_position()
+{
+ hunits n;
+ if (line == 0)
+ n = -input_line_start;
+ else
+ n = width_total - input_line_start;
+ if (current_tab)
+ n += tab_width;
+ return n;
+}
+
+void environment::set_input_line_position(hunits n)
+{
+ input_line_start = line == 0 ? -n : width_total - n;
+ if (current_tab)
+ input_line_start += tab_width;
+}
+
+hunits environment::get_line_length()
+{
+ return line_length;
+}
+
+hunits environment::get_saved_line_length()
+{
+ if (line)
+ return target_text_length + saved_indent;
+ else
+ return line_length;
+}
+
+vunits environment::get_vertical_spacing()
+{
+ return vertical_spacing;
+}
+
+vunits environment::get_post_vertical_spacing()
+{
+ return post_vertical_spacing;
+}
+
+int environment::get_line_spacing()
+{
+ return line_spacing;
+}
+
+vunits environment::total_post_vertical_spacing()
+{
+ vunits tem(post_vertical_spacing);
+ if (line_spacing > 1)
+ tem += (line_spacing - 1)*vertical_spacing;
+ return tem;
+}
+
+int environment::get_bold()
+{
+ return get_bold_fontno(fontno);
+}
+
+hunits environment::get_digit_width()
+{
+ return env_digit_width(this);
+}
+
+int environment::get_adjust_mode()
+{
+ return adjust_mode;
+}
+
+int environment::get_fill()
+{
+ return fill;
+}
+
+hunits environment::get_indent()
+{
+ return indent;
+}
+
+hunits environment::get_saved_indent()
+{
+ if (line)
+ return saved_indent;
+ else if (have_temporary_indent)
+ return temporary_indent;
+ else
+ return indent;
+}
+
+hunits environment::get_temporary_indent()
+{
+ return temporary_indent;
+}
+
+hunits environment::get_title_length()
+{
+ return title_length;
+}
+
+node *environment::get_prev_char()
+{
+ for (node *n = current_tab ? tab_contents : line; n; n = n->next) {
+ node *last = n->last_char_node();
+ if (last)
+ return last;
+ }
+ return 0;
+}
+
+hunits environment::get_prev_char_width()
+{
+ node *last = get_prev_char();
+ if (!last)
+ return H0;
+ return last->width();
+}
+
+hunits environment::get_prev_char_skew()
+{
+ node *last = get_prev_char();
+ if (!last)
+ return H0;
+ return last->skew();
+}
+
+vunits environment::get_prev_char_height()
+{
+ node *last = get_prev_char();
+ if (!last)
+ return V0;
+ vunits min, max;
+ last->vertical_extent(&min, &max);
+ return -min;
+}
+
+vunits environment::get_prev_char_depth()
+{
+ node *last = get_prev_char();
+ if (!last)
+ return V0;
+ vunits min, max;
+ last->vertical_extent(&min, &max);
+ return max;
+}
+
+hunits environment::get_text_length()
+{
+ hunits n = line == 0 ? H0 : width_total;
+ if (current_tab)
+ n += tab_width;
+ return n;
+}
+
+hunits environment::get_prev_text_length()
+{
+ return prev_text_length;
+}
+
+
+static int sb_reg_contents = 0;
+static int st_reg_contents = 0;
+static int ct_reg_contents = 0;
+static int rsb_reg_contents = 0;
+static int rst_reg_contents = 0;
+static int skw_reg_contents = 0;
+static int ssc_reg_contents = 0;
+
+void environment::width_registers()
+{
+ // this is used to implement \w; it sets the st, sb, ct registers
+ vunits min = 0, max = 0, cur = 0;
+ int character_type = 0;
+ ssc_reg_contents = line ? line->subscript_correction().to_units() : 0;
+ skw_reg_contents = line ? line->skew().to_units() : 0;
+ line = reverse_node_list(line);
+ vunits real_min = V0;
+ vunits real_max = V0;
+ vunits v1, v2;
+ for (node *tem = line; tem; tem = tem->next) {
+ tem->vertical_extent(&v1, &v2);
+ v1 += cur;
+ if (v1 < real_min)
+ real_min = v1;
+ v2 += cur;
+ if (v2 > real_max)
+ real_max = v2;
+ if ((cur += tem->vertical_width()) < min)
+ min = cur;
+ else if (cur > max)
+ max = cur;
+ character_type |= tem->character_type();
+ }
+ line = reverse_node_list(line);
+ st_reg_contents = -min.to_units();
+ sb_reg_contents = -max.to_units();
+ rst_reg_contents = -real_min.to_units();
+ rsb_reg_contents = -real_max.to_units();
+ ct_reg_contents = character_type;
+}
+
+node *environment::extract_output_line()
+{
+ if (current_tab)
+ wrap_up_tab();
+ node *n = line;
+ line = 0;
+ return n;
+}
+
+/* environment related requests */
+
+void environment_switch()
+{
+ int pop = 0; // 1 means pop, 2 means pop but no error message on underflow
+ if (curenv->is_dummy())
+ error("can't switch environments when current environment is dummy");
+ else if (!has_arg())
+ pop = 1;
+ else {
+ symbol nm;
+ if (!tok.delimiter()) {
+ // It looks like a number.
+ int n;
+ if (get_integer(&n)) {
+ if (n >= 0 && n < NENVIRONMENTS) {
+ env_stack = new env_list(curenv, env_stack);
+ if (env_table[n] == 0)
+ env_table[n] = new environment(itoa(n));
+ curenv = env_table[n];
+ }
+ else
+ nm = itoa(n);
+ }
+ else
+ pop = 2;
+ }
+ else {
+ nm = get_long_name(1);
+ if (nm.is_null())
+ pop = 2;
+ }
+ if (!nm.is_null()) {
+ environment *e = (environment *)env_dictionary.lookup(nm);
+ if (!e) {
+ e = new environment(nm);
+ (void)env_dictionary.lookup(nm, e);
+ }
+ env_stack = new env_list(curenv, env_stack);
+ curenv = e;
+ }
+ }
+ if (pop) {
+ if (env_stack == 0) {
+ if (pop == 1)
+ error("environment stack underflow");
+ }
+ else {
+ curenv = env_stack->env;
+ env_list *tem = env_stack;
+ env_stack = env_stack->next;
+ delete tem;
+ }
+ }
+ skip_line();
+}
+
+
+static symbol P_symbol("P");
+
+void font_change()
+{
+ symbol s = get_name();
+ int is_number = 1;
+ if (s.is_null() || s == P_symbol) {
+ s = P_symbol;
+ is_number = 0;
+ }
+ else {
+ for (const char *p = s.contents(); p != 0 && *p != 0; p++)
+ if (!csdigit(*p)) {
+ is_number = 0;
+ break;
+ }
+ }
+ if (is_number)
+ curenv->set_font(atoi(s.contents()));
+ else
+ curenv->set_font(s);
+ skip_line();
+}
+
+void family_change()
+{
+ symbol s = get_name(1);
+ if (!s.is_null())
+ curenv->set_family(s);
+ skip_line();
+}
+
+void point_size()
+{
+ int n;
+ if (has_arg() && get_number(&n, 'z', curenv->get_requested_point_size())) {
+ if (n <= 0)
+ n = 1;
+ curenv->set_size(n);
+ }
+ else
+ curenv->set_size(0);
+ skip_line();
+}
+
+void space_size()
+{
+ int n;
+ if (get_integer(&n)) {
+ curenv->space_size = n;
+ if (has_arg() && get_integer(&n))
+ curenv->sentence_space_size = n;
+ else
+ curenv->sentence_space_size = curenv->space_size;
+ }
+ skip_line();
+}
+
+void fill()
+{
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ curenv->fill = 1;
+ tok.next();
+}
+
+void no_fill()
+{
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ curenv->fill = 0;
+ tok.next();
+}
+
+void center()
+{
+ int n;
+ if (!has_arg() || !get_integer(&n))
+ n = 1;
+ else if (n < 0)
+ n = 0;
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ curenv->right_justify_lines = 0;
+ curenv->center_lines = n;
+ tok.next();
+}
+
+void right_justify()
+{
+ int n;
+ if (!has_arg() || !get_integer(&n))
+ n = 1;
+ else if (n < 0)
+ n = 0;
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ curenv->center_lines = 0;
+ curenv->right_justify_lines = n;
+ tok.next();
+}
+
+void line_length()
+{
+ hunits temp;
+ if (has_arg() && get_hunits(&temp, 'm', curenv->line_length)) {
+ if (temp < H0) {
+ warning(WARN_RANGE, "bad line length %1u", temp.to_units());
+ temp = H0;
+ }
+ }
+ else
+ temp = curenv->prev_line_length;
+ curenv->prev_line_length = curenv->line_length;
+ curenv->line_length = temp;
+ skip_line();
+}
+
+void title_length()
+{
+ hunits temp;
+ if (has_arg() && get_hunits(&temp, 'm', curenv->title_length)) {
+ if (temp < H0) {
+ warning(WARN_RANGE, "bad title length %1u", temp.to_units());
+ temp = H0;
+ }
+ }
+ else
+ temp = curenv->prev_title_length;
+ curenv->prev_title_length = curenv->title_length;
+ curenv->title_length = temp;
+ skip_line();
+}
+
+void vertical_spacing()
+{
+ vunits temp;
+ if (has_arg() && get_vunits(&temp, 'p', curenv->vertical_spacing)) {
+ if (temp <= V0) {
+ warning(WARN_RANGE, "vertical spacing must be greater than 0");
+ temp = vresolution;
+ }
+ }
+ else
+ temp = curenv->prev_vertical_spacing;
+ curenv->prev_vertical_spacing = curenv->vertical_spacing;
+ curenv->vertical_spacing = temp;
+ skip_line();
+}
+
+void post_vertical_spacing()
+{
+ vunits temp;
+ if (has_arg() && get_vunits(&temp, 'p', curenv->post_vertical_spacing)) {
+ if (temp < V0) {
+ warning(WARN_RANGE,
+ "post vertical spacing must be greater than or equal to 0");
+ temp = V0;
+ }
+ }
+ else
+ temp = curenv->prev_post_vertical_spacing;
+ curenv->prev_post_vertical_spacing = curenv->post_vertical_spacing;
+ curenv->post_vertical_spacing = temp;
+ skip_line();
+}
+
+void line_spacing()
+{
+ int temp;
+ if (has_arg() && get_integer(&temp)) {
+ if (temp < 1) {
+ warning(WARN_RANGE, "value %1 out of range: interpreted as 1", temp);
+ temp = 1;
+ }
+ }
+ else
+ temp = curenv->prev_line_spacing;
+ curenv->prev_line_spacing = curenv->line_spacing;
+ curenv->line_spacing = temp;
+ skip_line();
+}
+
+void indent()
+{
+ hunits temp;
+ if (has_arg() && get_hunits(&temp, 'm', curenv->indent)) {
+ if (temp < H0) {
+ warning(WARN_RANGE, "indent cannot be negative");
+ temp = H0;
+ }
+ }
+ else
+ temp = curenv->prev_indent;
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ curenv->have_temporary_indent = 0;
+ curenv->prev_indent = curenv->indent;
+ curenv->indent = temp;
+ tok.next();
+}
+
+void temporary_indent()
+{
+ int err = 0;
+ hunits temp;
+ if (!get_hunits(&temp, 'm', curenv->get_indent()))
+ err = 1;
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ if (temp < H0) {
+ warning(WARN_RANGE, "total indent cannot be negative");
+ temp = H0;
+ }
+ if (!err) {
+ curenv->temporary_indent = temp;
+ curenv->have_temporary_indent = 1;
+ }
+ tok.next();
+}
+
+void underline()
+{
+ int n;
+ if (!has_arg() || !get_integer(&n))
+ n = 1;
+ if (n <= 0) {
+ if (curenv->underline_lines > 0) {
+ curenv->prev_fontno = curenv->fontno;
+ curenv->fontno = curenv->pre_underline_fontno;
+ }
+ curenv->underline_lines = 0;
+ }
+ else {
+ curenv->underline_lines = n;
+ curenv->pre_underline_fontno = curenv->fontno;
+ curenv->fontno = get_underline_fontno();
+ }
+ skip_line();
+}
+
+void control_char()
+{
+ curenv->control_char = '.';
+ if (has_arg()) {
+ if (tok.ch() == 0)
+ error("bad control character");
+ else
+ curenv->control_char = tok.ch();
+ }
+ skip_line();
+}
+
+void no_break_control_char()
+{
+ curenv->no_break_control_char = '\'';
+ if (has_arg()) {
+ if (tok.ch() == 0)
+ error("bad control character");
+ else
+ curenv->no_break_control_char = tok.ch();
+ }
+ skip_line();
+}
+
+void margin_character()
+{
+ while (tok.space())
+ tok.next();
+ charinfo *ci = tok.get_char();
+ if (ci) {
+ // Call tok.next() only after making the node so that
+ // .mc \s+9\(br\s0 works.
+ node *nd = curenv->make_char_node(ci);
+ tok.next();
+ if (nd) {
+ delete curenv->margin_character_node;
+ curenv->margin_character_node = nd;
+ curenv->margin_character_flags = (MARGIN_CHARACTER_ON
+ |MARGIN_CHARACTER_NEXT);
+ hunits d;
+ if (has_arg() && get_hunits(&d, 'm'))
+ curenv->margin_character_distance = d;
+ }
+ }
+ else {
+ check_missing_character();
+ curenv->margin_character_flags &= ~MARGIN_CHARACTER_ON;
+ if (curenv->margin_character_flags == 0) {
+ delete curenv->margin_character_node;
+ curenv->margin_character_node = 0;
+ }
+ }
+ skip_line();
+}
+
+void number_lines()
+{
+ delete_node_list(curenv->numbering_nodes);
+ curenv->numbering_nodes = 0;
+ if (has_arg()) {
+ node *nd = 0;
+ for (int i = '9'; i >= '0'; i--) {
+ node *tem = make_node(charset_table[i], curenv);
+ if (!tem) {
+ skip_line();
+ return;
+ }
+ tem->next = nd;
+ nd = tem;
+ }
+ curenv->numbering_nodes = nd;
+ curenv->line_number_digit_width = env_digit_width(curenv);
+ int n;
+ if (!tok.delimiter()) {
+ if (get_integer(&n, next_line_number)) {
+ next_line_number = n;
+ if (next_line_number < 0) {
+ warning(WARN_RANGE, "negative line number");
+ next_line_number = 0;
+ }
+ }
+ }
+ else
+ while (!tok.space() && !tok.newline() && !tok.eof())
+ tok.next();
+ if (has_arg()) {
+ if (!tok.delimiter()) {
+ if (get_integer(&n)) {
+ if (n <= 0) {
+ warning(WARN_RANGE, "negative or zero line number multiple");
+ }
+ else
+ curenv->line_number_multiple = n;
+ }
+ }
+ else
+ while (!tok.space() && !tok.newline() && !tok.eof())
+ tok.next();
+ if (has_arg()) {
+ if (!tok.delimiter()) {
+ if (get_integer(&n))
+ curenv->number_text_separation = n;
+ }
+ else
+ while (!tok.space() && !tok.newline() && !tok.eof())
+ tok.next();
+ if (has_arg() && !tok.delimiter() && get_integer(&n))
+ curenv->line_number_indent = n;
+ }
+ }
+ }
+ skip_line();
+}
+
+void no_number()
+{
+ int n;
+ if (has_arg() && get_integer(&n))
+ curenv->no_number_count = n > 0 ? n : 0;
+ else
+ curenv->no_number_count = 1;
+ skip_line();
+}
+
+void no_hyphenate()
+{
+ curenv->hyphenation_flags = 0;
+ skip_line();
+}
+
+void hyphenate_request()
+{
+ int n;
+ if (has_arg() && get_integer(&n))
+ curenv->hyphenation_flags = n;
+ else
+ curenv->hyphenation_flags = 1;
+ skip_line();
+}
+
+void hyphen_char()
+{
+ curenv->hyphen_indicator_char = get_optional_char();
+ skip_line();
+}
+
+void hyphen_line_max_request()
+{
+ int n;
+ if (has_arg() && get_integer(&n))
+ curenv->hyphen_line_max = n;
+ else
+ curenv->hyphen_line_max = -1;
+ skip_line();
+}
+
+void environment::interrupt()
+{
+ if (!dummy) {
+ add_node(new transparent_dummy_node);
+ interrupted = 1;
+ }
+}
+
+void environment::newline()
+{
+ if (underline_lines > 0) {
+ if (--underline_lines == 0) {
+ prev_fontno = fontno;
+ fontno = pre_underline_fontno;
+ }
+ }
+ if (current_field)
+ wrap_up_field();
+ if (current_tab)
+ wrap_up_tab();
+ // strip trailing spaces
+ while (line != 0 && line->discardable()) {
+ width_total -= line->width();
+ space_total -= line->nspaces();
+ node *tem = line;
+ line = line->next;
+ delete tem;
+ }
+ node *to_be_output = 0;
+ hunits to_be_output_width;
+ prev_line_interrupted = 0;
+ if (dummy)
+ space_newline();
+ else if (interrupted) {
+ interrupted = 0;
+ // see environment::final_break
+ prev_line_interrupted = exit_started ? 2 : 1;
+ }
+ else if (center_lines > 0) {
+ --center_lines;
+ hunits x = target_text_length - width_total;
+ if (x > H0)
+ saved_indent += x/2;
+ to_be_output = line;
+ to_be_output_width = width_total;
+ line = 0;
+ }
+ else if (right_justify_lines > 0) {
+ --right_justify_lines;
+ hunits x = target_text_length - width_total;
+ if (x > H0)
+ saved_indent += x;
+ to_be_output = line;
+ to_be_output_width = width_total;
+ line = 0;
+ }
+ else if (fill)
+ space_newline();
+ else {
+ to_be_output = line;
+ to_be_output_width = width_total;
+ line = 0;
+ }
+ input_line_start = line == 0 ? H0 : width_total;
+ if (to_be_output) {
+ output_line(to_be_output, to_be_output_width);
+ hyphen_line_count = 0;
+ }
+ if (input_trap_count > 0) {
+ if (--input_trap_count == 0)
+ spring_trap(input_trap);
+ }
+}
+
+void environment::output_line(node *n, hunits width)
+{
+ prev_text_length = width;
+ if (margin_character_flags) {
+ hunits d = line_length + margin_character_distance - saved_indent - width;
+ if (d > 0) {
+ n = new hmotion_node(d, n);
+ width += d;
+ }
+ margin_character_flags &= ~MARGIN_CHARACTER_NEXT;
+ node *tem;
+ if (!margin_character_flags) {
+ tem = margin_character_node;
+ margin_character_node = 0;
+ }
+ else
+ tem = margin_character_node->copy();
+ tem->next = n;
+ n = tem;
+ width += tem->width();
+ }
+ node *nn = 0;
+ while (n != 0) {
+ node *tem = n->next;
+ n->next = nn;
+ nn = n;
+ n = tem;
+ }
+ if (!saved_indent.is_zero())
+ nn = new hmotion_node(saved_indent, nn);
+ width += saved_indent;
+ if (no_number_count > 0)
+ --no_number_count;
+ else if (numbering_nodes) {
+ hunits w = (line_number_digit_width
+ *(3+line_number_indent+number_text_separation));
+ if (next_line_number % line_number_multiple != 0)
+ nn = new hmotion_node(w, nn);
+ else {
+ hunits x = w;
+ nn = new hmotion_node(number_text_separation*line_number_digit_width,
+ nn);
+ x -= number_text_separation*line_number_digit_width;
+ char buf[30];
+ sprintf(buf, "%3d", next_line_number);
+ for (char *p = strchr(buf, '\0') - 1; p >= buf && *p != ' '; --p) {
+ node *gn = numbering_nodes;
+ for (int count = *p - '0'; count > 0; count--)
+ gn = gn->next;
+ gn = gn->copy();
+ x -= gn->width();
+ gn->next = nn;
+ nn = gn;
+ }
+ nn = new hmotion_node(x, nn);
+ }
+ width += w;
+ ++next_line_number;
+ }
+ output(nn, !fill, vertical_spacing, total_post_vertical_spacing(), width);
+}
+
+void environment::start_line()
+{
+ assert(line == 0);
+ discarding = 0;
+ line = new line_start_node;
+ if (have_temporary_indent) {
+ saved_indent = temporary_indent;
+ have_temporary_indent = 0;
+ }
+ else
+ saved_indent = indent;
+ target_text_length = line_length - saved_indent;
+ width_total = H0;
+ space_total = 0;
+}
+
+hunits environment::get_hyphenation_space()
+{
+ return hyphenation_space;
+}
+
+void hyphenation_space_request()
+{
+ hunits n;
+ if (get_hunits(&n, 'm')) {
+ if (n < H0) {
+ warning(WARN_RANGE, "hyphenation space cannot be negative");
+ n = H0;
+ }
+ curenv->hyphenation_space = n;
+ }
+ skip_line();
+}
+
+hunits environment::get_hyphenation_margin()
+{
+ return hyphenation_margin;
+}
+
+void hyphenation_margin_request()
+{
+ hunits n;
+ if (get_hunits(&n, 'm')) {
+ if (n < H0) {
+ warning(WARN_RANGE, "hyphenation margin cannot be negative");
+ n = H0;
+ }
+ curenv->hyphenation_margin = n;
+ }
+ skip_line();
+}
+
+breakpoint *environment::choose_breakpoint()
+{
+ hunits x = width_total;
+ int s = space_total;
+ node *n = line;
+ breakpoint *best_bp = 0; // the best breakpoint so far
+ int best_bp_fits = 0;
+ while (n != 0) {
+ x -= n->width();
+ s -= n->nspaces();
+ breakpoint *bp = n->get_breakpoints(x, s);
+ while (bp != 0) {
+ if (bp->width <= target_text_length) {
+ if (!bp->hyphenated) {
+ breakpoint *tem = bp->next;
+ bp->next = 0;
+ while (tem != 0) {
+ breakpoint *tem1 = tem;
+ tem = tem->next;
+ delete tem1;
+ }
+ if (best_bp_fits
+ // Decide whether to use the hyphenated breakpoint.
+ && (hyphen_line_max < 0
+ // Only choose the hyphenated breakpoint if it would not
+ // exceed the maximum number of consecutive hyphenated
+ // lines.
+ || hyphen_line_count + 1 <= hyphen_line_max)
+ && !(adjust_mode == ADJUST_BOTH
+ // Don't choose the hyphenated breakpoint if the line
+ // can be justified by adding no more than
+ // hyphenation_space to any word space.
+ ? (bp->nspaces > 0
+ && (((target_text_length - bp->width
+ + (bp->nspaces - 1)*hresolution)/bp->nspaces)
+ <= hyphenation_space))
+ // Don't choose the hyphenated breakpoint if the line
+ // is no more than hyphenation_margin short.
+ : target_text_length - bp->width <= hyphenation_margin)) {
+ delete bp;
+ return best_bp;
+ }
+ if (best_bp)
+ delete best_bp;
+ return bp;
+ }
+ else {
+ if ((adjust_mode == ADJUST_BOTH
+ ? hyphenation_space == H0
+ : hyphenation_margin == H0)
+ && (hyphen_line_max < 0
+ || hyphen_line_count + 1 <= hyphen_line_max)) {
+ // No need to consider a non-hyphenated breakpoint.
+ if (best_bp)
+ delete best_bp;
+ return bp;
+ }
+ // It fits but it's hyphenated.
+ if (!best_bp_fits) {
+ if (best_bp)
+ delete best_bp;
+ best_bp = bp;
+ bp = bp->next;
+ best_bp_fits = 1;
+ }
+ else {
+ breakpoint *tem = bp;
+ bp = bp->next;
+ delete tem;
+ }
+ }
+ }
+ else {
+ if (best_bp)
+ delete best_bp;
+ best_bp = bp;
+ bp = bp->next;
+ }
+ }
+ n = n->next;
+ }
+ if (best_bp) {
+ if (!best_bp_fits)
+ warning(WARN_BREAK, "can't break line");
+ return best_bp;
+ }
+ return 0;
+}
+
+void environment::hyphenate_line()
+{
+ if (line == 0)
+ return;
+ hyphenation_type prev_type = line->get_hyphenation_type();
+ node **startp;
+ for (startp = &line->next; *startp != 0; startp = &(*startp)->next) {
+ hyphenation_type this_type = (*startp)->get_hyphenation_type();
+ if (prev_type == HYPHEN_BOUNDARY && this_type == HYPHEN_MIDDLE)
+ break;
+ prev_type = this_type;
+ }
+ if (*startp == 0)
+ return;
+ node *tem = *startp;
+ int i = 0;
+ do {
+ ++i;
+ tem = tem->next;
+ } while (tem != 0 && tem->get_hyphenation_type() == HYPHEN_MIDDLE);
+ int inhibit = (tem != 0 && tem->get_hyphenation_type() == HYPHEN_INHIBIT);
+ node *end = tem;
+ hyphen_list *sl = 0;
+ tem = *startp;
+ node *forward = 0;
+ while (tem != end) {
+ sl = tem->get_hyphen_list(sl);
+ node *tem1 = tem;
+ tem = tem->next;
+ tem1->next = forward;
+ forward = tem1;
+ }
+ if (!inhibit) {
+ // this is for characters like hyphen and emdash
+ int prev_code = 0;
+ for (hyphen_list *h = sl; h; h = h->next) {
+ h->breakable = (prev_code != 0
+ && h->next != 0
+ && h->next->hyphenation_code != 0);
+ prev_code = h->hyphenation_code;
+ }
+ }
+ if (hyphenation_flags != 0
+ && !inhibit
+ // this may not be right if we have extra space on this line
+ && !((hyphenation_flags & HYPHEN_LAST_LINE)
+ && (curdiv->distance_to_next_trap()
+ <= vertical_spacing + total_post_vertical_spacing()))
+ && i >= 4)
+ hyphenate(sl, hyphenation_flags);
+ while (forward != 0) {
+ node *tem1 = forward;
+ forward = forward->next;
+ tem1->next = 0;
+ tem = tem1->add_self(tem, &sl);
+ }
+ *startp = tem;
+}
+
+static node *node_list_reverse(node *n)
+{
+ node *res = 0;
+ while (n) {
+ node *tem = n;
+ n = n->next;
+ tem->next = res;
+ res = tem;
+ }
+ return res;
+}
+
+static void distribute_space(node *n, int nspaces, hunits desired_space,
+ int force_reverse = 0)
+{
+ static int reverse = 0;
+ if (force_reverse || reverse)
+ n = node_list_reverse(n);
+ for (node *tem = n; tem; tem = tem->next)
+ tem->spread_space(&nspaces, &desired_space);
+ if (force_reverse || reverse)
+ (void)node_list_reverse(n);
+ if (!force_reverse)
+ reverse = !reverse;
+ assert(desired_space.is_zero() && nspaces == 0);
+}
+
+void environment::possibly_break_line(int forced)
+{
+ if (!fill || current_tab || current_field || dummy)
+ return;
+ while (line != 0
+ && (forced
+ // When a macro follows a paragraph in fill mode, the
+ // current line should not be empty.
+ || (width_total - line->width()) > target_text_length)) {
+ hyphenate_line();
+ breakpoint *bp = choose_breakpoint();
+ if (bp == 0)
+ // we'll find one eventually
+ return;
+ node *pre, *post;
+ node **ndp = &line;
+ while (*ndp != bp->nd)
+ ndp = &(*ndp)->next;
+ bp->nd->split(bp->index, &pre, &post);
+ *ndp = post;
+ hunits extra_space_width = H0;
+ switch(adjust_mode) {
+ case ADJUST_BOTH:
+ if (bp->nspaces != 0)
+ extra_space_width = target_text_length - bp->width;
+ break;
+ case ADJUST_CENTER:
+ saved_indent += (target_text_length - bp->width)/2;
+ break;
+ case ADJUST_RIGHT:
+ saved_indent += target_text_length - bp->width;
+ break;
+ }
+ distribute_space(pre, bp->nspaces, extra_space_width);
+ hunits output_width = bp->width + extra_space_width;
+ input_line_start -= output_width;
+ if (bp->hyphenated)
+ hyphen_line_count++;
+ else
+ hyphen_line_count = 0;
+ delete bp;
+ space_total = 0;
+ width_total = 0;
+ node *first_non_discardable = 0;
+ node *tem;
+ for (tem = line; tem != 0; tem = tem->next)
+ if (!tem->discardable())
+ first_non_discardable = tem;
+ node *to_be_discarded;
+ if (first_non_discardable) {
+ to_be_discarded = first_non_discardable->next;
+ first_non_discardable->next = 0;
+ for (tem = line; tem != 0; tem = tem->next) {
+ width_total += tem->width();
+ space_total += tem->nspaces();
+ }
+ discarding = 0;
+ }
+ else {
+ discarding = 1;
+ to_be_discarded = line;
+ line = 0;
+ }
+ // Do output_line() here so that line will be 0 iff the
+ // the environment will be empty.
+ output_line(pre, output_width);
+ while (to_be_discarded != 0) {
+ tem = to_be_discarded;
+ to_be_discarded = to_be_discarded->next;
+ input_line_start -= tem->width();
+ delete tem;
+ }
+ if (line != 0) {
+ if (have_temporary_indent) {
+ saved_indent = temporary_indent;
+ have_temporary_indent = 0;
+ }
+ else
+ saved_indent = indent;
+ target_text_length = line_length - saved_indent;
+ }
+ }
+}
+
+/*
+Do the break at the end of input after the end macro (if any).
+
+Unix troff behaves as follows: if the last line is
+
+foo bar\c
+
+it will output foo on the current page, and bar on the next page;
+if the last line is
+
+foo\c
+
+or
+
+foo bar
+
+everything will be output on the current page. This behaviour must be
+considered a bug.
+
+The problem is that some macro packages rely on this. For example,
+the ATK macros have an end macro that emits \c if it needs to print a
+table of contents but doesn't do a 'bp in the end macro; instead the
+'bp is done in the bottom of page trap. This works with Unix troff,
+provided that the current environment is not empty at the end of the
+input file.
+
+The following will make macro packages that do that sort of thing work
+even if the current environment is empty at the end of the input file.
+If the last input line used \c and this line occurred in the end macro,
+then we'll force everything out on the current page, but we'll make
+sure that the environment isn't empty so that we won't exit at the
+bottom of this page.
+*/
+
+void environment::final_break()
+{
+ if (prev_line_interrupted == 2) {
+ do_break();
+ add_node(new transparent_dummy_node);
+ }
+ else
+ do_break();
+}
+
+void environment::do_break()
+{
+ if (curdiv == topdiv && topdiv->before_first_page) {
+ topdiv->begin_page();
+ return;
+ }
+ if (current_tab)
+ wrap_up_tab();
+ if (line) {
+ line = new space_node(H0, line); // this is so that hyphenation works
+ space_total++;
+ possibly_break_line();
+ }
+ while (line != 0 && line->discardable()) {
+ width_total -= line->width();
+ space_total -= line->nspaces();
+ node *tem = line;
+ line = line->next;
+ delete tem;
+ }
+ discarding = 0;
+ input_line_start = H0;
+ if (line != 0) {
+ if (fill) {
+ switch (adjust_mode) {
+ case ADJUST_CENTER:
+ saved_indent += (target_text_length - width_total)/2;
+ break;
+ case ADJUST_RIGHT:
+ saved_indent += target_text_length - width_total;
+ break;
+ }
+ }
+ node *tem = line;
+ line = 0;
+ output_line(tem, width_total);
+ hyphen_line_count = 0;
+ }
+ prev_line_interrupted = 0;
+#ifdef WIDOW_CONTROL
+ mark_last_line();
+ output_pending_lines();
+#endif /* WIDOW_CONTROL */
+}
+
+int environment::is_empty()
+{
+ return !current_tab && line == 0 && pending_lines == 0;
+}
+
+void break_request()
+{
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ tok.next();
+}
+
+void title()
+{
+ if (curdiv == topdiv && topdiv->before_first_page) {
+ handle_initial_title();
+ return;
+ }
+ node *part[3];
+ hunits part_width[3];
+ part[0] = part[1] = part[2] = 0;
+ environment env(curenv);
+ environment *oldenv = curenv;
+ curenv = &env;
+ read_title_parts(part, part_width);
+ curenv = oldenv;
+ curenv->size = env.size;
+ curenv->prev_size = env.prev_size;
+ curenv->requested_size = env.requested_size;
+ curenv->prev_requested_size = env.prev_requested_size;
+ curenv->char_height = env.char_height;
+ curenv->char_slant = env.char_slant;
+ curenv->fontno = env.fontno;
+ curenv->prev_fontno = env.prev_fontno;
+ node *n = 0;
+ node *p = part[2];
+ while (p != 0) {
+ node *tem = p;
+ p = p->next;
+ tem->next = n;
+ n = tem;
+ }
+ hunits title_length(curenv->title_length);
+ hunits f = title_length - part_width[1];
+ hunits f2 = f/2;
+ n = new hmotion_node(f2 - part_width[2], n);
+ p = part[1];
+ while (p != 0) {
+ node *tem = p;
+ p = p->next;
+ tem->next = n;
+ n = tem;
+ }
+ n = new hmotion_node(f - f2 - part_width[0], n);
+ p = part[0];
+ while (p != 0) {
+ node *tem = p;
+ p = p->next;
+ tem->next = n;
+ n = tem;
+ }
+ curenv->output_title(n, !curenv->fill, curenv->vertical_spacing,
+ curenv->total_post_vertical_spacing(), title_length);
+ curenv->hyphen_line_count = 0;
+ tok.next();
+}
+
+void adjust()
+{
+ curenv->adjust_mode |= 1;
+ if (has_arg()) {
+ switch (tok.ch()) {
+ case 'l':
+ curenv->adjust_mode = ADJUST_LEFT;
+ break;
+ case 'r':
+ curenv->adjust_mode = ADJUST_RIGHT;
+ break;
+ case 'c':
+ curenv->adjust_mode = ADJUST_CENTER;
+ break;
+ case 'b':
+ case 'n':
+ curenv->adjust_mode = ADJUST_BOTH;
+ break;
+ default:
+ int n;
+ if (get_integer(&n)) {
+ if (n < 0)
+ warning(WARN_RANGE, "negative adjustment mode");
+ else if (n > 5) {
+ curenv->adjust_mode = 5;
+ warning(WARN_RANGE, "adjustment mode `%1' out of range", n);
+ }
+ else
+ curenv->adjust_mode = n;
+ }
+ }
+ }
+ skip_line();
+}
+
+void no_adjust()
+{
+ curenv->adjust_mode &= ~1;
+ skip_line();
+}
+
+void input_trap()
+{
+ curenv->input_trap_count = 0;
+ int n;
+ if (has_arg() && get_integer(&n)) {
+ if (n <= 0)
+ warning(WARN_RANGE,
+ "number of lines for input trap must be greater than zero");
+ else {
+ symbol s = get_name(1);
+ if (!s.is_null()) {
+ curenv->input_trap_count = n;
+ curenv->input_trap = s;
+ }
+ }
+ }
+ skip_line();
+}
+
+/* tabs */
+
+// must not be R or C or L or a legitimate part of a number expression
+const char TAB_REPEAT_CHAR = 'T';
+
+struct tab {
+ tab *next;
+ hunits pos;
+ tab_type type;
+ tab(hunits, tab_type);
+ enum { BLOCK = 1024 };
+ static tab *free_list;
+ void *operator new(size_t);
+ void operator delete(void *);
+};
+
+tab *tab::free_list = 0;
+
+void *tab::operator new(size_t n)
+{
+ assert(n == sizeof(tab));
+ if (!free_list) {
+ free_list = (tab *)new char[sizeof(tab)*BLOCK];
+ for (int i = 0; i < BLOCK - 1; i++)
+ free_list[i].next = free_list + i + 1;
+ free_list[BLOCK-1].next = 0;
+ }
+ tab *p = free_list;
+ free_list = (tab *)(free_list->next);
+ p->next = 0;
+ return p;
+}
+
+#ifdef __GNUG__
+/* cfront can't cope with this. */
+inline
+#endif
+void tab::operator delete(void *p)
+{
+ if (p) {
+ ((tab *)p)->next = free_list;
+ free_list = (tab *)p;
+ }
+}
+
+tab::tab(hunits x, tab_type t) : next(0), pos(x), type(t)
+{
+}
+
+tab_stops::tab_stops(hunits distance, tab_type type)
+ : initial_list(0)
+{
+ repeated_list = new tab(distance, type);
+}
+
+tab_stops::~tab_stops()
+{
+ clear();
+}
+
+tab_type tab_stops::distance_to_next_tab(hunits curpos, hunits *distance)
+{
+ hunits lastpos = 0;
+ tab *tem;
+ for (tem = initial_list; tem && tem->pos <= curpos; tem = tem->next)
+ lastpos = tem->pos;
+ if (tem) {
+ *distance = tem->pos - curpos;
+ return tem->type;
+ }
+ if (repeated_list == 0)
+ return TAB_NONE;
+ hunits base = lastpos;
+ for (;;) {
+ for (tem = repeated_list; tem && tem->pos + base <= curpos; tem = tem->next)
+ lastpos = tem->pos;
+ if (tem) {
+ *distance = tem->pos + base - curpos;
+ return tem->type;
+ }
+ assert(lastpos > 0);
+ base += lastpos;
+ }
+ return TAB_NONE;
+}
+
+const char *tab_stops::to_string()
+{
+ static char *buf = 0;
+ static int buf_size = 0;
+ // figure out a maximum on the amount of space we can need
+ int count = 0;
+ tab *p;
+ for (p = initial_list; p; p = p->next)
+ ++count;
+ for (p = repeated_list; p; p = p->next)
+ ++count;
+ // (10 for digits + 1 for u + 1 for 'C' or 'R') + 2 for ' &' + 1 for '\0'
+ int need = count*12 + 3;
+ if (buf == 0 || need > buf_size) {
+ if (buf)
+ a_delete buf;
+ buf_size = need;
+ buf = new char[buf_size];
+ }
+ char *ptr = buf;
+ for (p = initial_list; p; p = p->next) {
+ strcpy(ptr, itoa(p->pos.to_units()));
+ ptr = strchr(ptr, '\0');
+ *ptr++ = 'u';
+ *ptr = '\0';
+ switch (p->type) {
+ case TAB_LEFT:
+ break;
+ case TAB_RIGHT:
+ *ptr++ = 'R';
+ break;
+ case TAB_CENTER:
+ *ptr++ = 'C';
+ break;
+ case TAB_NONE:
+ default:
+ assert(0);
+ }
+ }
+ if (repeated_list)
+ *ptr++ = TAB_REPEAT_CHAR;
+ for (p = repeated_list; p; p = p->next) {
+ strcpy(ptr, itoa(p->pos.to_units()));
+ ptr = strchr(ptr, '\0');
+ *ptr++ = 'u';
+ *ptr = '\0';
+ switch (p->type) {
+ case TAB_LEFT:
+ break;
+ case TAB_RIGHT:
+ *ptr++ = 'R';
+ break;
+ case TAB_CENTER:
+ *ptr++ = 'C';
+ break;
+ case TAB_NONE:
+ default:
+ assert(0);
+ }
+ }
+ *ptr++ = '\0';
+ return buf;
+}
+
+tab_stops::tab_stops() : initial_list(0), repeated_list(0)
+{
+}
+
+tab_stops::tab_stops(const tab_stops &ts)
+ : initial_list(0), repeated_list(0)
+{
+ tab **p = &initial_list;
+ tab *t = ts.initial_list;
+ while (t) {
+ *p = new tab(t->pos, t->type);
+ t = t->next;
+ p = &(*p)->next;
+ }
+ p = &repeated_list;
+ t = ts.repeated_list;
+ while (t) {
+ *p = new tab(t->pos, t->type);
+ t = t->next;
+ p = &(*p)->next;
+ }
+}
+
+void tab_stops::clear()
+{
+ while (initial_list) {
+ tab *tem = initial_list;
+ initial_list = initial_list->next;
+ delete tem;
+ }
+ while (repeated_list) {
+ tab *tem = repeated_list;
+ repeated_list = repeated_list->next;
+ delete tem;
+ }
+}
+
+void tab_stops::add_tab(hunits pos, tab_type type, int repeated)
+{
+ tab **p;
+ for (p = repeated ? &repeated_list : &initial_list; *p; p = &(*p)->next)
+ ;
+ *p = new tab(pos, type);
+}
+
+
+void tab_stops::operator=(const tab_stops &ts)
+{
+ clear();
+ tab **p = &initial_list;
+ tab *t = ts.initial_list;
+ while (t) {
+ *p = new tab(t->pos, t->type);
+ t = t->next;
+ p = &(*p)->next;
+ }
+ p = &repeated_list;
+ t = ts.repeated_list;
+ while (t) {
+ *p = new tab(t->pos, t->type);
+ t = t->next;
+ p = &(*p)->next;
+ }
+}
+
+void set_tabs()
+{
+ hunits pos;
+ hunits prev_pos = 0;
+ int first = 1;
+ int repeated = 0;
+ tab_stops tabs;
+ while (has_arg()) {
+ if (tok.ch() == TAB_REPEAT_CHAR) {
+ tok.next();
+ repeated = 1;
+ prev_pos = 0;
+ }
+ if (!get_hunits(&pos, 'm', prev_pos))
+ break;
+ tab_type type = TAB_LEFT;
+ if (tok.ch() == 'C') {
+ tok.next();
+ type = TAB_CENTER;
+ }
+ else if (tok.ch() == 'R') {
+ tok.next();
+ type = TAB_RIGHT;
+ }
+ else if (tok.ch() == 'L') {
+ tok.next();
+ }
+ if (pos <= prev_pos && !first)
+ warning(WARN_RANGE,
+ "positions of tab stops must be strictly increasing");
+ else {
+ tabs.add_tab(pos, type, repeated);
+ prev_pos = pos;
+ first = 0;
+ }
+ }
+ curenv->tabs = tabs;
+ skip_line();
+}
+
+const char *environment::get_tabs()
+{
+ return tabs.to_string();
+}
+
+#if 0
+tab_stops saved_tabs;
+
+void tabs_save()
+{
+ saved_tabs = curenv->tabs;
+ skip_line();
+}
+
+void tabs_restore()
+{
+ curenv->tabs = saved_tabs;
+ skip_line();
+}
+#endif
+
+tab_type environment::distance_to_next_tab(hunits *distance)
+{
+ return curenv->tabs.distance_to_next_tab(get_input_line_position(), distance);
+}
+
+void field_characters()
+{
+ field_delimiter_char = get_optional_char();
+ if (field_delimiter_char)
+ padding_indicator_char = get_optional_char();
+ else
+ padding_indicator_char = 0;
+ skip_line();
+}
+
+void environment::wrap_up_tab()
+{
+ if (!current_tab)
+ return;
+ if (line == 0)
+ start_line();
+ hunits tab_amount;
+ switch (current_tab) {
+ case TAB_RIGHT:
+ tab_amount = tab_distance - tab_width;
+ line = make_tab_node(tab_amount, line);
+ break;
+ case TAB_CENTER:
+ tab_amount = tab_distance - tab_width/2;
+ line = make_tab_node(tab_amount, line);
+ break;
+ case TAB_NONE:
+ case TAB_LEFT:
+ default:
+ assert(0);
+ }
+ width_total += tab_amount;
+ width_total += tab_width;
+ if (current_field) {
+ if (tab_precedes_field) {
+ pre_field_width += tab_amount;
+ tab_precedes_field = 0;
+ }
+ field_distance -= tab_amount;
+ field_spaces += tab_field_spaces;
+ }
+ if (tab_contents != 0) {
+ node *tem;
+ for (tem = tab_contents; tem->next != 0; tem = tem->next)
+ ;
+ tem->next = line;
+ line = tab_contents;
+ }
+ tab_field_spaces = 0;
+ tab_contents = 0;
+ tab_width = H0;
+ tab_distance = H0;
+ current_tab = TAB_NONE;
+}
+
+node *environment::make_tab_node(hunits d, node *next)
+{
+ if (leader_node != 0 && d < 0) {
+ error("motion generated by leader cannot be negative");
+ delete leader_node;
+ leader_node = 0;
+ }
+ if (!leader_node)
+ return new hmotion_node(d, next);
+ node *n = new hline_node(d, leader_node, next);
+ leader_node = 0;
+ return n;
+}
+
+void environment::handle_tab(int is_leader)
+{
+ hunits d;
+ if (current_tab)
+ wrap_up_tab();
+ charinfo *ci = is_leader ? leader_char : tab_char;
+ delete leader_node;
+ leader_node = ci ? make_char_node(ci) : 0;
+ tab_type t = distance_to_next_tab(&d);
+ switch (t) {
+ case TAB_NONE:
+ return;
+ case TAB_LEFT:
+ add_node(make_tab_node(d));
+ return;
+ case TAB_RIGHT:
+ case TAB_CENTER:
+ tab_width = 0;
+ tab_distance = d;
+ tab_contents = 0;
+ current_tab = t;
+ tab_field_spaces = 0;
+ return;
+ default:
+ assert(0);
+ }
+}
+
+void environment::start_field()
+{
+ assert(!current_field);
+ hunits d;
+ if (distance_to_next_tab(&d) != TAB_NONE) {
+ pre_field_width = get_text_length();
+ field_distance = d;
+ current_field = 1;
+ field_spaces = 0;
+ tab_field_spaces = 0;
+ for (node *p = line; p; p = p->next)
+ if (p->nspaces()) {
+ p->freeze_space();
+ space_total--;
+ }
+ tab_precedes_field = current_tab != TAB_NONE;
+ }
+ else
+ error("zero field width");
+}
+
+void environment::wrap_up_field()
+{
+ if (!current_tab && field_spaces == 0)
+ add_padding();
+ hunits padding = field_distance - (get_text_length() - pre_field_width);
+ if (current_tab && tab_field_spaces != 0) {
+ hunits tab_padding = scale(padding,
+ tab_field_spaces,
+ field_spaces + tab_field_spaces);
+ padding -= tab_padding;
+ distribute_space(tab_contents, tab_field_spaces, tab_padding, 1);
+ tab_field_spaces = 0;
+ tab_width += tab_padding;
+ }
+ if (field_spaces != 0) {
+ distribute_space(line, field_spaces, padding, 1);
+ width_total += padding;
+ if (current_tab) {
+ // the start of the tab has been moved to the right by padding, so
+ tab_distance -= padding;
+ if (tab_distance <= H0) {
+ // use the next tab stop instead
+ current_tab = tabs.distance_to_next_tab(get_input_line_position()
+ - tab_width,
+ &tab_distance);
+ if (current_tab == TAB_NONE || current_tab == TAB_LEFT) {
+ width_total += tab_width;
+ if (current_tab == TAB_LEFT) {
+ line = make_tab_node(tab_distance, line);
+ width_total += tab_distance;
+ current_tab = TAB_NONE;
+ }
+ if (tab_contents != 0) {
+ node *tem;
+ for (tem = tab_contents; tem->next != 0; tem = tem->next)
+ ;
+ tem->next = line;
+ line = tab_contents;
+ tab_contents = 0;
+ }
+ tab_width = H0;
+ tab_distance = H0;
+ }
+ }
+ }
+ }
+ current_field = 0;
+}
+
+void environment::add_padding()
+{
+ if (current_tab) {
+ tab_contents = new space_node(H0, tab_contents);
+ tab_field_spaces++;
+ }
+ else {
+ if (line == 0)
+ start_line();
+ line = new space_node(H0, line);
+ field_spaces++;
+ }
+}
+
+typedef int (environment::*INT_FUNCP)();
+typedef vunits (environment::*VUNITS_FUNCP)();
+typedef hunits (environment::*HUNITS_FUNCP)();
+typedef const char *(environment::*STRING_FUNCP)();
+
+class int_env_reg : public reg {
+ INT_FUNCP func;
+ public:
+ int_env_reg(INT_FUNCP);
+ const char *get_string();
+ int get_value(units *val);
+};
+
+class vunits_env_reg : public reg {
+ VUNITS_FUNCP func;
+ public:
+ vunits_env_reg(VUNITS_FUNCP f);
+ const char *get_string();
+ int get_value(units *val);
+};
+
+
+class hunits_env_reg : public reg {
+ HUNITS_FUNCP func;
+ public:
+ hunits_env_reg(HUNITS_FUNCP f);
+ const char *get_string();
+ int get_value(units *val);
+};
+
+class string_env_reg : public reg {
+ STRING_FUNCP func;
+public:
+ string_env_reg(STRING_FUNCP);
+ const char *get_string();
+};
+
+int_env_reg::int_env_reg(INT_FUNCP f) : func(f)
+{
+}
+
+int int_env_reg::get_value(units *val)
+{
+ *val = (curenv->*func)();
+ return 1;
+}
+
+const char *int_env_reg::get_string()
+{
+ return itoa((curenv->*func)());
+}
+
+vunits_env_reg::vunits_env_reg(VUNITS_FUNCP f) : func(f)
+{
+}
+
+int vunits_env_reg::get_value(units *val)
+{
+ *val = (curenv->*func)().to_units();
+ return 1;
+}
+
+const char *vunits_env_reg::get_string()
+{
+ return itoa((curenv->*func)().to_units());
+}
+
+hunits_env_reg::hunits_env_reg(HUNITS_FUNCP f) : func(f)
+{
+}
+
+int hunits_env_reg::get_value(units *val)
+{
+ *val = (curenv->*func)().to_units();
+ return 1;
+}
+
+const char *hunits_env_reg::get_string()
+{
+ return itoa((curenv->*func)().to_units());
+}
+
+string_env_reg::string_env_reg(STRING_FUNCP f) : func(f)
+{
+}
+
+const char *string_env_reg::get_string()
+{
+ return (curenv->*func)();
+}
+
+class horizontal_place_reg : public general_reg {
+public:
+ horizontal_place_reg();
+ int get_value(units *);
+ void set_value(units);
+};
+
+horizontal_place_reg::horizontal_place_reg()
+{
+}
+
+int horizontal_place_reg::get_value(units *res)
+{
+ *res = curenv->get_input_line_position().to_units();
+ return 1;
+}
+
+void horizontal_place_reg::set_value(units n)
+{
+ curenv->set_input_line_position(hunits(n));
+}
+
+const char *environment::get_font_family_string()
+{
+ return family->nm.contents();
+}
+
+const char *environment::get_name_string()
+{
+ return name.contents();
+}
+
+// Convert a quantity in scaled points to ascii decimal fraction.
+
+const char *sptoa(int sp)
+{
+ assert(sp > 0);
+ assert(sizescale > 0);
+ if (sizescale == 1)
+ return itoa(sp);
+ if (sp % sizescale == 0)
+ return itoa(sp/sizescale);
+ // See if 1/sizescale is exactly representable as a decimal fraction,
+ // ie its only prime factors are 2 and 5.
+ int n = sizescale;
+ int power2 = 0;
+ while ((n & 1) == 0) {
+ n >>= 1;
+ power2++;
+ }
+ int power5 = 0;
+ while ((n % 5) == 0) {
+ n /= 5;
+ power5++;
+ }
+ if (n == 1) {
+ int decimal_point = power5 > power2 ? power5 : power2;
+ if (decimal_point <= 10) {
+ int factor = 1;
+ int t;
+ for (t = decimal_point - power2; --t >= 0;)
+ factor *= 2;
+ for (t = decimal_point - power5; --t >= 0;)
+ factor *= 5;
+ if (factor == 1 || sp <= INT_MAX/factor)
+ return iftoa(sp*factor, decimal_point);
+ }
+ }
+ double s = double(sp)/double(sizescale);
+ double factor = 10.0;
+ double val = s;
+ int decimal_point = 0;
+ do {
+ double v = ceil(s*factor);
+ if (v > INT_MAX)
+ break;
+ val = v;
+ factor *= 10.0;
+ } while (++decimal_point < 10);
+ return iftoa(int(val), decimal_point);
+}
+
+const char *environment::get_point_size_string()
+{
+ return sptoa(curenv->get_point_size());
+}
+
+const char *environment::get_requested_point_size_string()
+{
+ return sptoa(curenv->get_requested_point_size());
+}
+
+#define init_int_env_reg(name, func) \
+ number_reg_dictionary.define(name, new int_env_reg(&environment::func))
+
+#define init_vunits_env_reg(name, func) \
+ number_reg_dictionary.define(name, new vunits_env_reg(&environment::func))
+
+#define init_hunits_env_reg(name, func) \
+ number_reg_dictionary.define(name, new hunits_env_reg(&environment::func))
+
+#define init_string_env_reg(name, func) \
+ number_reg_dictionary.define(name, new string_env_reg(&environment::func))
+
+void init_env_requests()
+{
+ init_request("it", input_trap);
+ init_request("ad", adjust);
+ init_request("na", no_adjust);
+ init_request("ev", environment_switch);
+ init_request("lt", title_length);
+ init_request("ps", point_size);
+ init_request("ft", font_change);
+ init_request("fam", family_change);
+ init_request("ss", space_size);
+ init_request("fi", fill);
+ init_request("nf", no_fill);
+ init_request("ce", center);
+ init_request("rj", right_justify);
+ init_request("vs", vertical_spacing);
+ init_request("ls", line_spacing);
+ init_request("ll", line_length);
+ init_request("in", indent);
+ init_request("ti", temporary_indent);
+ init_request("ul", underline);
+ init_request("cu", underline);
+ init_request("cc", control_char);
+ init_request("c2", no_break_control_char);
+ init_request("br", break_request);
+ init_request("tl", title);
+ init_request("ta", set_tabs);
+ init_request("fc", field_characters);
+ init_request("mc", margin_character);
+ init_request("nn", no_number);
+ init_request("nm", number_lines);
+ init_request("tc", tab_character);
+ init_request("lc", leader_character);
+ init_request("hy", hyphenate_request);
+ init_request("hc", hyphen_char);
+ init_request("nh", no_hyphenate);
+ init_request("hlm", hyphen_line_max_request);
+#ifdef WIDOW_CONTROL
+ init_request("wdc", widow_control_request);
+#endif /* WIDOW_CONTROL */
+#if 0
+ init_request("tas", tabs_save);
+ init_request("tar", tabs_restore);
+#endif
+ init_request("hys", hyphenation_space_request);
+ init_request("hym", hyphenation_margin_request);
+ init_request("pvs", post_vertical_spacing);
+ init_int_env_reg(".f", get_font);
+ init_int_env_reg(".b", get_bold);
+ init_hunits_env_reg(".i", get_indent);
+ init_hunits_env_reg(".in", get_saved_indent);
+ init_int_env_reg(".j", get_adjust_mode);
+ init_hunits_env_reg(".k", get_text_length);
+ init_hunits_env_reg(".l", get_line_length);
+ init_hunits_env_reg(".ll", get_saved_line_length);
+ init_int_env_reg(".L", get_line_spacing);
+ init_hunits_env_reg(".n", get_prev_text_length);
+ init_string_env_reg(".s", get_point_size_string);
+ init_string_env_reg(".sr", get_requested_point_size_string);
+ init_int_env_reg(".ps", get_point_size);
+ init_int_env_reg(".psr", get_requested_point_size);
+ init_int_env_reg(".u", get_fill);
+ init_vunits_env_reg(".v", get_vertical_spacing);
+ init_vunits_env_reg(".pvs", get_post_vertical_spacing);
+ init_hunits_env_reg(".w", get_prev_char_width);
+ init_int_env_reg(".ss", get_space_size);
+ init_int_env_reg(".sss", get_sentence_space_size);
+ init_string_env_reg(".fam", get_font_family_string);
+ init_string_env_reg(".ev", get_name_string);
+ init_int_env_reg(".hy", get_hyphenation_flags);
+ init_int_env_reg(".hlm", get_hyphen_line_max);
+ init_int_env_reg(".hlc", get_hyphen_line_count);
+ init_hunits_env_reg(".lt", get_title_length);
+ init_string_env_reg(".tabs", get_tabs);
+ init_hunits_env_reg(".csk", get_prev_char_skew);
+ init_vunits_env_reg(".cht", get_prev_char_height);
+ init_vunits_env_reg(".cdp", get_prev_char_depth);
+ init_int_env_reg(".ce", get_center_lines);
+ init_int_env_reg(".rj", get_right_justify_lines);
+ init_hunits_env_reg(".hys", get_hyphenation_space);
+ init_hunits_env_reg(".hym", get_hyphenation_margin);
+ number_reg_dictionary.define("ln", new variable_reg(&next_line_number));
+ number_reg_dictionary.define("ct", new variable_reg(&ct_reg_contents));
+ number_reg_dictionary.define("sb", new variable_reg(&sb_reg_contents));
+ number_reg_dictionary.define("st", new variable_reg(&st_reg_contents));
+ number_reg_dictionary.define("rsb", new variable_reg(&rsb_reg_contents));
+ number_reg_dictionary.define("rst", new variable_reg(&rst_reg_contents));
+ number_reg_dictionary.define("ssc", new variable_reg(&ssc_reg_contents));
+ number_reg_dictionary.define("skw", new variable_reg(&skw_reg_contents));
+ number_reg_dictionary.define("hp", new horizontal_place_reg);
+}
+
+// Hyphenation - TeX's hyphenation algorithm with a less fancy implementation.
+
+struct trie_node;
+
+class trie {
+ trie_node *tp;
+ virtual void do_match(int len, void *val) = 0;
+ virtual void do_delete(void *) = 0;
+ void delete_trie_node(trie_node *);
+public:
+ trie() : tp(0) {}
+ virtual ~trie(); // virtual to shut up g++
+ void insert(const char *, int, void *);
+ // find calls do_match for each match it finds
+ void find(const char *pat, int patlen);
+ void clear();
+};
+
+class hyphen_trie : private trie {
+ int *h;
+ void do_match(int i, void *v);
+ void do_delete(void *v);
+ void insert_pattern(const char *pat, int patlen, int *num);
+public:
+ hyphen_trie() {}
+ ~hyphen_trie() {}
+ void hyphenate(const char *word, int len, int *hyphens);
+ void read_patterns_file(const char *name);
+};
+
+
+struct hyphenation_language {
+ symbol name;
+ dictionary exceptions;
+ hyphen_trie patterns;
+ hyphenation_language(symbol nm) : name(nm), exceptions(501) {}
+ ~hyphenation_language() { }
+};
+
+dictionary language_dictionary(5);
+hyphenation_language *current_language = 0;
+
+static void set_hyphenation_language()
+{
+ symbol nm = get_name(1);
+ if (!nm.is_null()) {
+ current_language = (hyphenation_language *)language_dictionary.lookup(nm);
+ if (!current_language) {
+ current_language = new hyphenation_language(nm);
+ (void)language_dictionary.lookup(nm, (void *)current_language);
+ }
+ }
+ skip_line();
+}
+
+const int WORD_MAX = 1024;
+
+static void hyphen_word()
+{
+ if (!current_language) {
+ error("no current hyphenation language");
+ skip_line();
+ return;
+ }
+ char buf[WORD_MAX + 1];
+ unsigned char pos[WORD_MAX + 2];
+ for (;;) {
+ tok.skip();
+ if (tok.newline() || tok.eof())
+ break;
+ int i = 0;
+ int npos = 0;
+ while (i < WORD_MAX && !tok.space() && !tok.newline() && !tok.eof()) {
+ charinfo *ci = tok.get_char(1);
+ if (ci == 0) {
+ skip_line();
+ return;
+ }
+ tok.next();
+ if (ci->get_ascii_code() == '-') {
+ if (i > 0 && (npos == 0 || pos[npos - 1] != i))
+ pos[npos++] = i;
+ }
+ else {
+ int c = ci->get_hyphenation_code();
+ if (c == 0)
+ break;
+ buf[i++] = c;
+ }
+ }
+ if (i > 0) {
+ pos[npos] = 0;
+ buf[i] = 0;
+ unsigned char *tem = new unsigned char[npos + 1];
+ memcpy(tem, pos, npos+1);
+ tem = (unsigned char *)current_language->exceptions.lookup(symbol(buf),
+ tem);
+ if (tem)
+ a_delete tem;
+ }
+ }
+ skip_line();
+}
+
+struct trie_node {
+ char c;
+ trie_node *down;
+ trie_node *right;
+ void *val;
+ trie_node(char, trie_node *);
+};
+
+trie_node::trie_node(char ch, trie_node *p)
+: c(ch), down(0), right(p), val(0)
+{
+}
+
+trie::~trie()
+{
+ clear();
+}
+
+void trie::clear()
+{
+ delete_trie_node(tp);
+ tp = 0;
+}
+
+
+void trie::delete_trie_node(trie_node *p)
+{
+ if (p) {
+ delete_trie_node(p->down);
+ delete_trie_node(p->right);
+ if (p->val)
+ do_delete(p->val);
+ delete p;
+ }
+}
+
+void trie::insert(const char *pat, int patlen, void *val)
+{
+ trie_node **p = &tp;
+ assert(patlen > 0 && pat != 0);
+ for (;;) {
+ while (*p != 0 && (*p)->c < pat[0])
+ p = &((*p)->right);
+ if (*p == 0 || (*p)->c != pat[0])
+ *p = new trie_node(pat[0], *p);
+ if (--patlen == 0) {
+ (*p)->val = val;
+ break;
+ }
+ ++pat;
+ p = &((*p)->down);
+ }
+}
+
+void trie::find(const char *pat, int patlen)
+{
+ trie_node *p = tp;
+ for (int i = 0; p != 0 && i < patlen; i++) {
+ while (p != 0 && p->c < pat[i])
+ p = p->right;
+ if (p != 0 && p->c == pat[i]) {
+ if (p->val != 0)
+ do_match(i+1, p->val);
+ p = p->down;
+ }
+ else
+ break;
+ }
+}
+
+struct operation {
+ operation *next;
+ short distance;
+ short num;
+ operation(int, int, operation *);
+};
+
+operation::operation(int i, int j, operation *op)
+: next(op), distance(j), num(i)
+{
+}
+
+void hyphen_trie::insert_pattern(const char *pat, int patlen, int *num)
+{
+ operation *op = 0;
+ for (int i = 0; i < patlen+1; i++)
+ if (num[i] != 0)
+ op = new operation(num[i], patlen - i, op);
+ insert(pat, patlen, op);
+}
+
+void hyphen_trie::hyphenate(const char *word, int len, int *hyphens)
+{
+ int j;
+ for (j = 0; j < len+1; j++)
+ hyphens[j] = 0;
+ for (j = 0; j < len - 1; j++) {
+ h = hyphens + j;
+ find(word + j, len - j);
+ }
+}
+
+inline int max(int m, int n)
+{
+ return m > n ? m : n;
+}
+
+void hyphen_trie::do_match(int i, void *v)
+{
+ operation *op = (operation *)v;
+ while (op != 0) {
+ h[i - op->distance] = max(h[i - op->distance], op->num);
+ op = op->next;
+ }
+}
+
+void hyphen_trie::do_delete(void *v)
+{
+ operation *op = (operation *)v;
+ while (op) {
+ operation *tem = op;
+ op = tem->next;
+ delete tem;
+ }
+}
+
+void hyphen_trie::read_patterns_file(const char *name)
+{
+ clear();
+ char buf[WORD_MAX];
+ int num[WORD_MAX+1];
+ errno = 0;
+ char *path = 0;
+ FILE *fp = macro_path.open_file(name, &path);
+ if (fp == 0) {
+ error("can't find hyphenation patterns file `%1'", name);
+ return;
+ }
+ int c = getc(fp);
+ for (;;) {
+ for (;;) {
+ if (c == '%') {
+ do {
+ c = getc(fp);
+ } while (c != EOF && c != '\n');
+ }
+ if (c == EOF || !csspace(c))
+ break;
+ c = getc(fp);
+ }
+ if (c == EOF)
+ break;
+ int i = 0;
+ num[0] = 0;
+ do {
+ if (csdigit(c))
+ num[i] = c - '0';
+ else {
+ buf[i++] = c;
+ num[i] = 0;
+ }
+ c = getc(fp);
+ } while (i < WORD_MAX && c != EOF && !csspace(c) && c != '%');
+ insert_pattern(buf, i, num);
+ }
+ fclose(fp);
+ a_delete path;
+ return;
+}
+
+void hyphenate(hyphen_list *h, unsigned flags)
+{
+ if (!current_language)
+ return;
+ while (h) {
+ while (h && h->hyphenation_code == 0)
+ h = h->next;
+ int len = 0;
+ char hbuf[WORD_MAX+2];
+ char *buf = hbuf + 1;
+ hyphen_list *tem;
+ for (tem = h; tem && len < WORD_MAX; tem = tem->next) {
+ if (tem->hyphenation_code != 0)
+ buf[len++] = tem->hyphenation_code;
+ else
+ break;
+ }
+ hyphen_list *nexth = tem;
+ if (len > 2) {
+ buf[len] = 0;
+ unsigned char *pos
+ = (unsigned char *)current_language->exceptions.lookup(buf);
+ if (pos != 0) {
+ int j = 0;
+ int i = 1;
+ for (tem = h; tem != 0; tem = tem->next, i++)
+ if (pos[j] == i) {
+ tem->hyphen = 1;
+ j++;
+ }
+ }
+ else {
+ hbuf[0] = hbuf[len+1] = '.';
+ int num[WORD_MAX+3];
+ current_language->patterns.hyphenate(hbuf, len+2, num);
+ int i;
+ num[2] = 0;
+ if (flags & 8)
+ num[3] = 0;
+ if (flags & 4)
+ --len;
+ for (i = 2, tem = h; i < len && tem; tem = tem->next, i++)
+ if (num[i] & 1)
+ tem->hyphen = 1;
+ }
+ }
+ h = nexth;
+ }
+}
+
+static void hyphenation_patterns_file()
+{
+ symbol name = get_long_name(1);
+ if (!name.is_null()) {
+ if (!current_language)
+ error("no current hyphenation language");
+ else
+ current_language->patterns.read_patterns_file(name.contents());
+ }
+ skip_line();
+}
+
+class hyphenation_language_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *hyphenation_language_reg::get_string()
+{
+ return current_language ? current_language->name.contents() : "";
+}
+
+void init_hyphen_requests()
+{
+ init_request("hw", hyphen_word);
+ init_request("hla", set_hyphenation_language);
+ init_request("hpf", hyphenation_patterns_file);
+ number_reg_dictionary.define(".hla", new hyphenation_language_reg);
+}
diff --git a/src/roff/troff/env.h b/src/roff/troff/env.h
new file mode 100644
index 00000000..c0cc90da
--- /dev/null
+++ b/src/roff/troff/env.h
@@ -0,0 +1,333 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+struct size_range {
+ int min;
+ int max;
+};
+
+class font_size {
+ static size_range *size_table;
+ static int nranges;
+ int p;
+public:
+ font_size();
+ font_size(int points);
+ int to_points();
+ int to_scaled_points();
+ int to_units();
+ int operator==(font_size);
+ int operator!=(font_size);
+ static void init_size_table(int *sizes);
+};
+
+inline font_size::font_size() : p(0)
+{
+}
+
+inline int font_size::operator==(font_size fs)
+{
+ return p == fs.p;
+}
+
+inline int font_size::operator!=(font_size fs)
+{
+ return p != fs.p;
+}
+
+inline int font_size::to_scaled_points()
+{
+ return p;
+}
+
+inline int font_size::to_points()
+{
+ return p/sizescale;
+}
+
+struct environment;
+
+hunits env_digit_width(environment *);
+hunits env_space_width(environment *);
+hunits env_sentence_space_width(environment *);
+hunits env_narrow_space_width(environment *);
+hunits env_half_narrow_space_width(environment *);
+
+struct tab;
+
+enum tab_type { TAB_NONE, TAB_LEFT, TAB_CENTER, TAB_RIGHT };
+
+class tab_stops {
+ tab *initial_list;
+ tab *repeated_list;
+public:
+ tab_stops();
+ tab_stops(hunits distance, tab_type type);
+ tab_stops(const tab_stops &);
+ ~tab_stops();
+ void operator=(const tab_stops &);
+ tab_type distance_to_next_tab(hunits pos, hunits *distance);
+ void clear();
+ void add_tab(hunits pos, tab_type type, int repeated);
+ const char *to_string();
+};
+
+const unsigned MARGIN_CHARACTER_ON = 1;
+const unsigned MARGIN_CHARACTER_NEXT = 2;
+
+struct charinfo;
+struct node;
+struct breakpoint;
+struct font_family;
+struct pending_output_line;
+
+class environment {
+ int dummy; // dummy environment used for \w
+ hunits prev_line_length;
+ hunits line_length;
+ hunits prev_title_length;
+ hunits title_length;
+ font_size prev_size;
+ font_size size;
+ int requested_size;
+ int prev_requested_size;
+ int char_height;
+ int char_slant;
+ int prev_fontno;
+ int fontno;
+ font_family *prev_family;
+ font_family *family;
+ int space_size; // in 36ths of an em
+ int sentence_space_size; // same but for spaces at the end of sentences
+ int adjust_mode;
+ int fill;
+ int interrupted;
+ int prev_line_interrupted;
+ int center_lines;
+ int right_justify_lines;
+ vunits prev_vertical_spacing;
+ vunits vertical_spacing;
+ vunits prev_post_vertical_spacing;
+ vunits post_vertical_spacing;
+ int prev_line_spacing;
+ int line_spacing;
+ hunits prev_indent;
+ hunits indent;
+ hunits temporary_indent;
+ int have_temporary_indent;
+ hunits saved_indent;
+ hunits target_text_length;
+ int pre_underline_fontno;
+ int underline_lines;
+ symbol input_trap;
+ int input_trap_count;
+ node *line; // in reverse order
+ hunits prev_text_length;
+ hunits width_total;
+ int space_total;
+ hunits input_line_start;
+ tab_stops tabs;
+ node *tab_contents;
+ hunits tab_width;
+ hunits tab_distance;
+ tab_type current_tab;
+ node *leader_node;
+ charinfo *tab_char;
+ charinfo *leader_char;
+ int current_field; // is there a current field?
+ hunits field_distance;
+ hunits pre_field_width;
+ int field_spaces;
+ int tab_field_spaces;
+ int tab_precedes_field;
+ int discarding;
+ int spread_flag; // set by \p
+ unsigned margin_character_flags;
+ node *margin_character_node;
+ hunits margin_character_distance;
+ node *numbering_nodes;
+ hunits line_number_digit_width;
+ int number_text_separation; // in digit spaces
+ int line_number_indent; // in digit spaces
+ int line_number_multiple;
+ int no_number_count;
+ unsigned hyphenation_flags;
+ int hyphen_line_count;
+ int hyphen_line_max;
+ hunits hyphenation_space;
+ hunits hyphenation_margin;
+ int composite; // used for construction of composite char?
+ pending_output_line *pending_lines;
+#ifdef WIDOW_CONTROL
+ int widow_control;
+#endif /* WIDOW_CONTROL */
+
+ tab_type distance_to_next_tab(hunits *);
+ void start_line();
+ void output_line(node *, hunits);
+ void output(node *nd, int retain_size, vunits vs, vunits post_vs,
+ hunits width);
+ void output_title(node *nd, int retain_size, vunits vs, vunits post_vs,
+ hunits width);
+#ifdef WIDOW_CONTROL
+ void mark_last_line();
+#endif /* WIDOW_CONTROL */
+ void possibly_break_line(int forced = 0);
+ breakpoint *choose_breakpoint();
+ void hyphenate_line();
+ void start_field();
+ void wrap_up_field();
+ void add_padding();
+ node *make_tab_node(hunits d, node *next = 0);
+ node *get_prev_char();
+public:
+ const symbol name;
+ unsigned char control_char;
+ unsigned char no_break_control_char;
+ charinfo *hyphen_indicator_char;
+
+ environment(symbol);
+ environment(const environment *); // for temporary environment
+ ~environment();
+ int is_dummy() { return dummy; }
+ int is_empty();
+ int is_composite() { return composite; }
+ void set_composite() { composite = 1; }
+ vunits get_vertical_spacing(); // .v
+ vunits get_post_vertical_spacing(); // .pvs
+ int get_line_spacing(); // .L
+ vunits total_post_vertical_spacing();
+ int get_point_size() { return size.to_scaled_points(); }
+ font_size get_font_size() { return size; }
+ int get_size() { return size.to_units(); }
+ int get_requested_point_size() { return requested_size; }
+ int get_char_height() { return char_height; }
+ int get_char_slant() { return char_slant; }
+ hunits get_digit_width();
+ int get_font() { return fontno; }; // .f
+ font_family *get_family() { return family; }
+ int get_bold(); // .b
+ int get_adjust_mode(); // .j
+ int get_fill(); // .u
+ hunits get_indent(); // .i
+ hunits get_temporary_indent();
+ hunits get_line_length(); // .l
+ hunits get_saved_line_length(); // .ll
+ hunits get_saved_indent(); // .in
+ hunits get_title_length();
+ hunits get_prev_char_width(); // .w
+ hunits get_prev_char_skew();
+ vunits get_prev_char_height();
+ vunits get_prev_char_depth();
+ hunits get_text_length(); // .k
+ hunits get_prev_text_length(); // .n
+ hunits get_space_width() { return env_space_width(this); }
+ int get_space_size() { return space_size; } // in ems/36
+ int get_sentence_space_size() { return sentence_space_size; }
+ hunits get_narrow_space_width() { return env_narrow_space_width(this); }
+ hunits get_half_narrow_space_width()
+ { return env_half_narrow_space_width(this); }
+ hunits get_input_line_position();
+ const char *get_tabs();
+ int get_hyphenation_flags();
+ int get_hyphen_line_max();
+ int get_hyphen_line_count();
+ hunits get_hyphenation_space();
+ hunits get_hyphenation_margin();
+ int get_center_lines();
+ int get_right_justify_lines();
+ int get_prev_line_interrupted() { return prev_line_interrupted; }
+ node *make_char_node(charinfo *);
+ node *extract_output_line();
+ void width_registers();
+ void wrap_up_tab();
+ void set_font(int);
+ void set_font(symbol);
+ void set_family(symbol);
+ void set_size(int);
+ void set_char_height(int);
+ void set_char_slant(int);
+ void set_input_line_position(hunits); // used by \n(hp
+ void interrupt();
+ void spread() { spread_flag = 1; }
+ void do_break(); // .br
+ void final_break();
+ void newline();
+ void handle_tab(int is_leader = 0); // do a tab or leader
+ void add_node(node *);
+ void add_char(charinfo *);
+ void add_hyphen_indicator();
+ void add_italic_correction();
+ void space();
+ void space_newline();
+ const char *get_font_family_string();
+ const char *get_name_string();
+ const char *get_point_size_string();
+ const char *get_requested_point_size_string();
+ void output_pending_lines();
+
+ friend void title_length();
+ friend void space_size();
+ friend void fill();
+ friend void no_fill();
+ friend void adjust();
+ friend void no_adjust();
+ friend void center();
+ friend void right_justify();
+ friend void vertical_spacing();
+ friend void post_vertical_spacing();
+ friend void line_spacing();
+ friend void line_length();
+ friend void indent();
+ friend void temporary_indent();
+ friend void underline();
+ friend void input_trap();
+ friend void set_tabs();
+ friend void margin_character();
+ friend void no_number();
+ friend void number_lines();
+ friend void leader_character();
+ friend void tab_character();
+ friend void hyphenate_request();
+ friend void no_hyphenate();
+ friend void hyphen_line_max_request();
+ friend void hyphenation_space_request();
+ friend void hyphenation_margin_request();
+ friend void line_width();
+#if 0
+ friend void tabs_save();
+ friend void tabs_restore();
+#endif
+ friend void title();
+#ifdef WIDOW_CONTROL
+ friend void widow_control_request();
+#endif /* WIDOW_CONTROL */
+};
+
+extern environment *curenv;
+extern void pop_env();
+extern void push_env(int);
+
+void init_environments();
+void read_hyphen_file(const char *name);
+
+extern int break_flag;
+extern symbol default_family;
+extern int translate_space_to_dummy;
diff --git a/src/roff/troff/hvunits.h b/src/roff/troff/hvunits.h
new file mode 100644
index 00000000..8efb5ab3
--- /dev/null
+++ b/src/roff/troff/hvunits.h
@@ -0,0 +1,340 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+class vunits {
+ int n;
+public:
+ vunits();
+ vunits(units);
+ units to_units();
+ int is_zero();
+ vunits& operator+=(const vunits&);
+ vunits& operator-=(const vunits&);
+ friend inline vunits scale(vunits n, units x, units y); // scale n by x/y
+ friend inline vunits scale(vunits n, vunits x, vunits y);
+ friend inline vunits operator +(const vunits&, const vunits&);
+ friend inline vunits operator -(const vunits&, const vunits&);
+ friend inline vunits operator -(const vunits&);
+ friend inline int operator /(const vunits&, const vunits&);
+ friend inline vunits operator /(const vunits&, int);
+ friend inline vunits operator *(const vunits&, int);
+ friend inline vunits operator *(int, const vunits&);
+ friend inline int operator <(const vunits&, const vunits&);
+ friend inline int operator >(const vunits&, const vunits&);
+ friend inline int operator <=(const vunits&, const vunits&);
+ friend inline int operator >=(const vunits&, const vunits&);
+ friend inline int operator ==(const vunits&, const vunits&);
+ friend inline int operator !=(const vunits&, const vunits&);
+};
+
+extern vunits V0;
+
+
+class hunits {
+ int n;
+public:
+ hunits();
+ hunits(units);
+ units to_units();
+ int is_zero();
+ hunits& operator+=(const hunits&);
+ hunits& operator-=(const hunits&);
+ friend inline hunits scale(hunits n, units x, units y); // scale n by x/y
+ friend inline hunits scale(hunits n, double x);
+ friend inline hunits operator +(const hunits&, const hunits&);
+ friend inline hunits operator -(const hunits&, const hunits&);
+ friend inline hunits operator -(const hunits&);
+ friend inline int operator /(const hunits&, const hunits&);
+ friend inline hunits operator /(const hunits&, int);
+ friend inline hunits operator *(const hunits&, int);
+ friend inline hunits operator *(int, const hunits&);
+ friend inline int operator <(const hunits&, const hunits&);
+ friend inline int operator >(const hunits&, const hunits&);
+ friend inline int operator <=(const hunits&, const hunits&);
+ friend inline int operator >=(const hunits&, const hunits&);
+ friend inline int operator ==(const hunits&, const hunits&);
+ friend inline int operator !=(const hunits&, const hunits&);
+};
+
+extern hunits H0;
+
+extern int get_vunits(vunits *, unsigned char si);
+extern int get_hunits(hunits *, unsigned char si);
+extern int get_vunits(vunits *, unsigned char si, vunits prev_value);
+extern int get_hunits(hunits *, unsigned char si, hunits prev_value);
+
+inline vunits:: vunits() : n(0)
+{
+}
+
+inline units vunits::to_units()
+{
+ return n*vresolution;
+}
+
+inline int vunits::is_zero()
+{
+ return n == 0;
+}
+
+inline vunits operator +(const vunits & x, const vunits & y)
+{
+ vunits r;
+ r = x;
+ r.n += y.n;
+ return r;
+}
+
+inline vunits operator -(const vunits & x, const vunits & y)
+{
+ vunits r;
+ r = x;
+ r.n -= y.n;
+ return r;
+}
+
+inline vunits operator -(const vunits & x)
+{
+ vunits r;
+ r.n = -x.n;
+ return r;
+}
+
+inline int operator /(const vunits & x, const vunits & y)
+{
+ return x.n/y.n;
+}
+
+inline vunits operator /(const vunits & x, int n)
+{
+ vunits r;
+ r = x;
+ r.n /= n;
+ return r;
+}
+
+inline vunits operator *(const vunits & x, int n)
+{
+ vunits r;
+ r = x;
+ r.n *= n;
+ return r;
+}
+
+inline vunits operator *(int n, const vunits & x)
+{
+ vunits r;
+ r = x;
+ r.n *= n;
+ return r;
+}
+
+inline int operator <(const vunits & x, const vunits & y)
+{
+ return x.n < y.n;
+}
+
+inline int operator >(const vunits & x, const vunits & y)
+{
+ return x.n > y.n;
+}
+
+inline int operator <=(const vunits & x, const vunits & y)
+{
+ return x.n <= y.n;
+}
+
+inline int operator >=(const vunits & x, const vunits & y)
+{
+ return x.n >= y.n;
+}
+
+inline int operator ==(const vunits & x, const vunits & y)
+{
+ return x.n == y.n;
+}
+
+inline int operator !=(const vunits & x, const vunits & y)
+{
+ return x.n != y.n;
+}
+
+
+inline vunits& vunits::operator+=(const vunits & x)
+{
+ n += x.n;
+ return *this;
+}
+
+inline vunits& vunits::operator-=(const vunits & x)
+{
+ n -= x.n;
+ return *this;
+}
+
+inline hunits:: hunits() : n(0)
+{
+}
+
+inline units hunits::to_units()
+{
+ return n*hresolution;
+}
+
+inline int hunits::is_zero()
+{
+ return n == 0;
+}
+
+inline hunits operator +(const hunits & x, const hunits & y)
+{
+ hunits r;
+ r = x;
+ r.n += y.n;
+ return r;
+}
+
+inline hunits operator -(const hunits & x, const hunits & y)
+{
+ hunits r;
+ r = x;
+ r.n -= y.n;
+ return r;
+}
+
+inline hunits operator -(const hunits & x)
+{
+ hunits r;
+ r = x;
+ r.n = -x.n;
+ return r;
+}
+
+inline int operator /(const hunits & x, const hunits & y)
+{
+ return x.n/y.n;
+}
+
+inline hunits operator /(const hunits & x, int n)
+{
+ hunits r;
+ r = x;
+ r.n /= n;
+ return r;
+}
+
+inline hunits operator *(const hunits & x, int n)
+{
+ hunits r;
+ r = x;
+ r.n *= n;
+ return r;
+}
+
+inline hunits operator *(int n, const hunits & x)
+{
+ hunits r;
+ r = x;
+ r.n *= n;
+ return r;
+}
+
+inline int operator <(const hunits & x, const hunits & y)
+{
+ return x.n < y.n;
+}
+
+inline int operator >(const hunits & x, const hunits & y)
+{
+ return x.n > y.n;
+}
+
+inline int operator <=(const hunits & x, const hunits & y)
+{
+ return x.n <= y.n;
+}
+
+inline int operator >=(const hunits & x, const hunits & y)
+{
+ return x.n >= y.n;
+}
+
+inline int operator ==(const hunits & x, const hunits & y)
+{
+ return x.n == y.n;
+}
+
+inline int operator !=(const hunits & x, const hunits & y)
+{
+ return x.n != y.n;
+}
+
+
+inline hunits& hunits::operator+=(const hunits & x)
+{
+ n += x.n;
+ return *this;
+}
+
+inline hunits& hunits::operator-=(const hunits & x)
+{
+ n -= x.n;
+ return *this;
+}
+
+inline hunits scale(hunits n, units x, units y)
+{
+ hunits r;
+ r.n = scale(n.n, x, y);
+ return r;
+}
+
+inline vunits scale(vunits n, units x, units y)
+{
+ vunits r;
+ r.n = scale(n.n, x, y);
+ return r;
+}
+
+inline vunits scale(vunits n, vunits x, vunits y)
+{
+ vunits r;
+ r.n = scale(n.n, x.n, y.n);
+ return r;
+}
+
+inline hunits scale(hunits n, double x)
+{
+ hunits r;
+ r.n = int(n.n*x);
+ return r;
+}
+
+inline units scale(units n, double x)
+{
+ return int(n*x);
+}
+
+inline units points_to_units(units n)
+{
+ return scale(n, units_per_inch, 72);
+}
+
diff --git a/src/roff/troff/hyphen.us b/src/roff/troff/hyphen.us
new file mode 100755
index 00000000..d86c3d58
--- /dev/null
+++ b/src/roff/troff/hyphen.us
@@ -0,0 +1,4449 @@
+% Hyphenation patterns for US English.
+% These are the standard Plain TeX hyphenation patterns (in hyphen.tex).
+.ach4
+.ad4der
+.af1t
+.al3t
+.am5at
+.an5c
+.ang4
+.ani5m
+.ant4
+.an3te
+.anti5s
+.ar5s
+.ar4tie
+.ar4ty
+.as3c
+.as1p
+.as1s
+.aster5
+.atom5
+.au1d
+.av4i
+.awn4
+.ba4g
+.ba5na
+.bas4e
+.ber4
+.be5ra
+.be3sm
+.be5sto
+.bri2
+.but4ti
+.cam4pe
+.can5c
+.capa5b
+.car5ol
+.ca4t
+.ce4la
+.ch4
+.chill5i
+.ci2
+.cit5r
+.co3e
+.co4r
+.cor5ner
+.de4moi
+.de3o
+.de3ra
+.de3ri
+.des4c
+.dictio5
+.do4t
+.du4c
+.dumb5
+.earth5
+.eas3i
+.eb4
+.eer4
+.eg2
+.el5d
+.el3em
+.enam3
+.en3g
+.en3s
+.eq5ui5t
+.er4ri
+.es3
+.eu3
+.eye5
+.fes3
+.for5mer
+.ga2
+.ge2
+.gen3t4
+.ge5og
+.gi5a
+.gi4b
+.go4r
+.hand5i
+.han5k
+.he2
+.hero5i
+.hes3
+.het3
+.hi3b
+.hi3er
+.hon5ey
+.hon3o
+.hov5
+.id4l
+.idol3
+.im3m
+.im5pin
+.in1
+.in3ci
+.ine2
+.in2k
+.in3s
+.ir5r
+.is4i
+.ju3r
+.la4cy
+.la4m
+.lat5er
+.lath5
+.le2
+.leg5e
+.len4
+.lep5
+.lev1
+.li4g
+.lig5a
+.li2n
+.li3o
+.li4t
+.mag5a5
+.mal5o
+.man5a
+.mar5ti
+.me2
+.mer3c
+.me5ter
+.mis1
+.mist5i
+.mon3e
+.mo3ro
+.mu5ta
+.muta5b
+.ni4c
+.od2
+.odd5
+.of5te
+.or5ato
+.or3c
+.or1d
+.or3t
+.os3
+.os4tl
+.oth3
+.out3
+.ped5al
+.pe5te
+.pe5tit
+.pi4e
+.pio5n
+.pi2t
+.pre3m
+.ra4c
+.ran4t
+.ratio5na
+.ree2
+.re5mit
+.res2
+.re5stat
+.ri4g
+.rit5u
+.ro4q
+.ros5t
+.row5d
+.ru4d
+.sci3e
+.self5
+.sell5
+.se2n
+.se5rie
+.sh2
+.si2
+.sing4
+.st4
+.sta5bl
+.sy2
+.ta4
+.te4
+.ten5an
+.th2
+.ti2
+.til4
+.tim5o5
+.ting4
+.tin5k
+.ton4a
+.to4p
+.top5i
+.tou5s
+.trib5ut
+.un1a
+.un3ce
+.under5
+.un1e
+.un5k
+.un5o
+.un3u
+.up3
+.ure3
+.us5a
+.ven4de
+.ve5ra
+.wil5i
+.ye4
+4ab.
+a5bal
+a5ban
+abe2
+ab5erd
+abi5a
+ab5it5ab
+ab5lat
+ab5o5liz
+4abr
+ab5rog
+ab3ul
+a4car
+ac5ard
+ac5aro
+a5ceou
+ac1er
+a5chet
+4a2ci
+a3cie
+ac1in
+a3cio
+ac5rob
+act5if
+ac3ul
+ac4um
+a2d
+ad4din
+ad5er.
+2adi
+a3dia
+ad3ica
+adi4er
+a3dio
+a3dit
+a5diu
+ad4le
+ad3ow
+ad5ran
+ad4su
+4adu
+a3duc
+ad5um
+ae4r
+aeri4e
+a2f
+aff4
+a4gab
+aga4n
+ag5ell
+age4o
+4ageu
+ag1i
+4ag4l
+ag1n
+a2go
+3agog
+ag3oni
+a5guer
+ag5ul
+a4gy
+a3ha
+a3he
+ah4l
+a3ho
+ai2
+a5ia
+a3ic.
+ai5ly
+a4i4n
+ain5in
+ain5o
+ait5en
+a1j
+ak1en
+al5ab
+al3ad
+a4lar
+4aldi
+2ale
+al3end
+a4lenti
+a5le5o
+al1i
+al4ia.
+ali4e
+al5lev
+4allic
+4alm
+a5log.
+a4ly.
+4alys
+5a5lyst
+5alyt
+3alyz
+4ama
+am5ab
+am3ag
+ama5ra
+am5asc
+a4matis
+a4m5ato
+am5era
+am3ic
+am5if
+am5ily
+am1in
+ami4no
+a2mo
+a5mon
+amor5i
+amp5en
+a2n
+an3age
+3analy
+a3nar
+an3arc
+anar4i
+a3nati
+4and
+ande4s
+an3dis
+an1dl
+an4dow
+a5nee
+a3nen
+an5est.
+a3neu
+2ang
+ang5ie
+an1gl
+a4n1ic
+a3nies
+an3i3f
+an4ime
+a5nimi
+a5nine
+an3io
+a3nip
+an3ish
+an3it
+a3niu
+an4kli
+5anniz
+ano4
+an5ot
+anoth5
+an2sa
+an4sco
+an4sn
+an2sp
+ans3po
+an4st
+an4sur
+antal4
+an4tie
+4anto
+an2tr
+an4tw
+an3ua
+an3ul
+a5nur
+4ao
+apar4
+ap5at
+ap5ero
+a3pher
+4aphi
+a4pilla
+ap5illar
+ap3in
+ap3ita
+a3pitu
+a2pl
+apoc5
+ap5ola
+apor5i
+apos3t
+aps5es
+a3pu
+aque5
+2a2r
+ar3act
+a5rade
+ar5adis
+ar3al
+a5ramete
+aran4g
+ara3p
+ar4at
+a5ratio
+ar5ativ
+a5rau
+ar5av4
+araw4
+arbal4
+ar4chan
+ar5dine
+ar4dr
+ar5eas
+a3ree
+ar3ent
+a5ress
+ar4fi
+ar4fl
+ar1i
+ar5ial
+ar3ian
+a3riet
+ar4im
+ar5inat
+ar3io
+ar2iz
+ar2mi
+ar5o5d
+a5roni
+a3roo
+ar2p
+ar3q
+arre4
+ar4sa
+ar2sh
+4as.
+as4ab
+as3ant
+ashi4
+a5sia.
+a3sib
+a3sic
+5a5si4t
+ask3i
+as4l
+a4soc
+as5ph
+as4sh
+as3ten
+as1tr
+asur5a
+a2ta
+at3abl
+at5ac
+at3alo
+at5ap
+ate5c
+at5ech
+at3ego
+at3en.
+at3era
+ater5n
+a5terna
+at3est
+at5ev
+4ath
+ath5em
+a5then
+at4ho
+ath5om
+4ati.
+a5tia
+at5i5b
+at1ic
+at3if
+ation5ar
+at3itu
+a4tog
+a2tom
+at5omiz
+a4top
+a4tos
+a1tr
+at5rop
+at4sk
+at4tag
+at5te
+at4th
+a2tu
+at5ua
+at5ue
+at3ul
+at3ura
+a2ty
+au4b
+augh3
+au3gu
+au4l2
+aun5d
+au3r
+au5sib
+aut5en
+au1th
+a2va
+av3ag
+a5van
+ave4no
+av3era
+av5ern
+av5ery
+av1i
+avi4er
+av3ig
+av5oc
+a1vor
+3away
+aw3i
+aw4ly
+aws4
+ax4ic
+ax4id
+ay5al
+aye4
+ays4
+azi4er
+azz5i
+5ba.
+bad5ger
+ba4ge
+bal1a
+ban5dag
+ban4e
+ban3i
+barbi5
+bari4a
+bas4si
+1bat
+ba4z
+2b1b
+b2be
+b3ber
+bbi4na
+4b1d
+4be.
+beak4
+beat3
+4be2d
+be3da
+be3de
+be3di
+be3gi
+be5gu
+1bel
+be1li
+be3lo
+4be5m
+be5nig
+be5nu
+4bes4
+be3sp
+be5str
+3bet
+bet5iz
+be5tr
+be3tw
+be3w
+be5yo
+2bf
+4b3h
+bi2b
+bi4d
+3bie
+bi5en
+bi4er
+2b3if
+1bil
+bi3liz
+bina5r4
+bin4d
+bi5net
+bi3ogr
+bi5ou
+bi2t
+3bi3tio
+bi3tr
+3bit5ua
+b5itz
+b1j
+bk4
+b2l2
+blath5
+b4le.
+blen4
+5blesp
+b3lis
+b4lo
+blun4t
+4b1m
+4b3n
+bne5g
+3bod
+bod3i
+bo4e
+bol3ic
+bom4bi
+bon4a
+bon5at
+3boo
+5bor.
+4b1ora
+bor5d
+5bore
+5bori
+5bos4
+b5ota
+both5
+bo4to
+bound3
+4bp
+4brit
+broth3
+2b5s2
+bsor4
+2bt
+bt4l
+b4to
+b3tr
+buf4fer
+bu4ga
+bu3li
+bumi4
+bu4n
+bunt4i
+bu3re
+bus5ie
+buss4e
+5bust
+4buta
+3butio
+b5uto
+b1v
+4b5w
+5by.
+bys4
+1ca
+cab3in
+ca1bl
+cach4
+ca5den
+4cag4
+2c5ah
+ca3lat
+cal4la
+call5in
+4calo
+can5d
+can4e
+can4ic
+can5is
+can3iz
+can4ty
+cany4
+ca5per
+car5om
+cast5er
+cas5tig
+4casy
+ca4th
+4cativ
+cav5al
+c3c
+ccha5
+cci4a
+ccompa5
+ccon4
+ccou3t
+2ce.
+4ced.
+4ceden
+3cei
+5cel.
+3cell
+1cen
+3cenc
+2cen4e
+4ceni
+3cent
+3cep
+ce5ram
+4cesa
+3cessi
+ces5si5b
+ces5t
+cet4
+c5e4ta
+cew4
+2ch
+4ch.
+4ch3ab
+5chanic
+ch5a5nis
+che2
+cheap3
+4ched
+che5lo
+3chemi
+ch5ene
+ch3er.
+ch3ers
+4ch1in
+5chine.
+ch5iness
+5chini
+5chio
+3chit
+chi2z
+3cho2
+ch4ti
+1ci
+3cia
+ci2a5b
+cia5r
+ci5c
+4cier
+5cific.
+4cii
+ci4la
+3cili
+2cim
+2cin
+c4ina
+3cinat
+cin3em
+c1ing
+c5ing.
+5cino
+cion4
+4cipe
+ci3ph
+4cipic
+4cista
+4cisti
+2c1it
+cit3iz
+5ciz
+ck1
+ck3i
+1c4l4
+4clar
+c5laratio
+5clare
+cle4m
+4clic
+clim4
+cly4
+c5n
+1co
+co5ag
+coe2
+2cog
+co4gr
+coi4
+co3inc
+col5i
+5colo
+col3or
+com5er
+con4a
+c4one
+con3g
+con5t
+co3pa
+cop3ic
+co4pl
+4corb
+coro3n
+cos4e
+cov1
+cove4
+cow5a
+coz5e
+co5zi
+c1q
+cras5t
+5crat.
+5cratic
+cre3at
+5cred
+4c3reta
+cre4v
+cri2
+cri5f
+c4rin
+cris4
+5criti
+cro4pl
+crop5o
+cros4e
+cru4d
+4c3s2
+2c1t
+cta4b
+ct5ang
+c5tant
+c2te
+c3ter
+c4ticu
+ctim3i
+ctu4r
+c4tw
+cud5
+c4uf
+c4ui
+cu5ity
+5culi
+cul4tis
+3cultu
+cu2ma
+c3ume
+cu4mi
+3cun
+cu3pi
+cu5py
+cur5a4b
+cu5ria
+1cus
+cuss4i
+3c4ut
+cu4tie
+4c5utiv
+4cutr
+1cy
+cze4
+1d2a
+5da.
+2d3a4b
+dach4
+4daf
+2dag
+da2m2
+dan3g
+dard5
+dark5
+4dary
+3dat
+4dativ
+4dato
+5dav4
+dav5e
+5day
+d1b
+d5c
+d1d4
+2de.
+deaf5
+deb5it
+de4bon
+decan4
+de4cil
+de5com
+2d1ed
+4dee.
+de5if
+deli4e
+del5i5q
+de5lo
+d4em
+5dem.
+3demic
+dem5ic.
+de5mil
+de4mons
+demor5
+1den
+de4nar
+de3no
+denti5f
+de3nu
+de1p
+de3pa
+depi4
+de2pu
+d3eq
+d4erh
+5derm
+dern5iz
+der5s
+des2
+d2es.
+de1sc
+de2s5o
+des3ti
+de3str
+de4su
+de1t
+de2to
+de1v
+dev3il
+4dey
+4d1f
+d4ga
+d3ge4t
+dg1i
+d2gy
+d1h2
+5di.
+1d4i3a
+dia5b
+di4cam
+d4ice
+3dict
+3did
+5di3en
+d1if
+di3ge
+di4lato
+d1in
+1dina
+3dine.
+5dini
+di5niz
+1dio
+dio5g
+di4pl
+dir2
+di1re
+dirt5i
+dis1
+5disi
+d4is3t
+d2iti
+1di1v
+d1j
+d5k2
+4d5la
+3dle.
+3dled
+3dles.
+4dless
+2d3lo
+4d5lu
+2dly
+d1m
+4d1n4
+1do
+3do.
+do5de
+5doe
+2d5of
+d4og
+do4la
+doli4
+do5lor
+dom5iz
+do3nat
+doni4
+doo3d
+dop4p
+d4or
+3dos
+4d5out
+do4v
+3dox
+d1p
+1dr
+drag5on
+4drai
+dre4
+drea5r
+5dren
+dri4b
+dril4
+dro4p
+4drow
+5drupli
+4dry
+2d1s2
+ds4p
+d4sw
+d4sy
+d2th
+1du
+d1u1a
+du2c
+d1uca
+duc5er
+4duct.
+4ducts
+du5el
+du4g
+d3ule
+dum4be
+du4n
+4dup
+du4pe
+d1v
+d1w
+d2y
+5dyn
+dy4se
+dys5p
+e1a4b
+e3act
+ead1
+ead5ie
+ea4ge
+ea5ger
+ea4l
+eal5er
+eal3ou
+eam3er
+e5and
+ear3a
+ear4c
+ear5es
+ear4ic
+ear4il
+ear5k
+ear2t
+eart3e
+ea5sp
+e3ass
+east3
+ea2t
+eat5en
+eath3i
+e5atif
+e4a3tu
+ea2v
+eav3en
+eav5i
+eav5o
+2e1b
+e4bel.
+e4bels
+e4ben
+e4bit
+e3br
+e4cad
+ecan5c
+ecca5
+e1ce
+ec5essa
+ec2i
+e4cib
+ec5ificat
+ec5ifie
+ec5ify
+ec3im
+eci4t
+e5cite
+e4clam
+e4clus
+e2col
+e4comm
+e4compe
+e4conc
+e2cor
+ec3ora
+eco5ro
+e1cr
+e4crem
+ec4tan
+ec4te
+e1cu
+e4cul
+ec3ula
+2e2da
+4ed3d
+e4d1er
+ede4s
+4edi
+e3dia
+ed3ib
+ed3ica
+ed3im
+ed1it
+edi5z
+4edo
+e4dol
+edon2
+e4dri
+e4dul
+ed5ulo
+ee2c
+eed3i
+ee2f
+eel3i
+ee4ly
+ee2m
+ee4na
+ee4p1
+ee2s4
+eest4
+ee4ty
+e5ex
+e1f
+e4f3ere
+1eff
+e4fic
+5efici
+efil4
+e3fine
+ef5i5nite
+3efit
+efor5es
+e4fuse.
+4egal
+eger4
+eg5ib
+eg4ic
+eg5ing
+e5git5
+eg5n
+e4go.
+e4gos
+eg1ul
+e5gur
+5egy
+e1h4
+eher4
+ei2
+e5ic
+ei5d
+eig2
+ei5gl
+e3imb
+e3inf
+e1ing
+e5inst
+eir4d
+eit3e
+ei3th
+e5ity
+e1j
+e4jud
+ej5udi
+eki4n
+ek4la
+e1la
+e4la.
+e4lac
+elan4d
+el5ativ
+e4law
+elaxa4
+e3lea
+el5ebra
+5elec
+e4led
+el3ega
+e5len
+e4l1er
+e1les
+el2f
+el2i
+e3libe
+e4l5ic.
+el3ica
+e3lier
+el5igib
+e5lim
+e4l3ing
+e3lio
+e2lis
+el5ish
+e3liv3
+4ella
+el4lab
+ello4
+e5loc
+el5og
+el3op.
+el2sh
+el4ta
+e5lud
+el5ug
+e4mac
+e4mag
+e5man
+em5ana
+em5b
+e1me
+e2mel
+e4met
+em3ica
+emi4e
+em5igra
+em1in2
+em5ine
+em3i3ni
+e4mis
+em5ish
+e5miss
+em3iz
+5emniz
+emo4g
+emoni5o
+em3pi
+e4mul
+em5ula
+emu3n
+e3my
+en5amo
+e4nant
+ench4er
+en3dic
+e5nea
+e5nee
+en3em
+en5ero
+en5esi
+en5est
+en3etr
+e3new
+en5ics
+e5nie
+e5nil
+e3nio
+en3ish
+en3it
+e5niu
+5eniz
+4enn
+4eno
+eno4g
+e4nos
+en3ov
+en4sw
+ent5age
+4enthes
+en3ua
+en5uf
+e3ny.
+4en3z
+e5of
+eo2g
+e4oi4
+e3ol
+eop3ar
+e1or
+eo3re
+eo5rol
+eos4
+e4ot
+eo4to
+e5out
+e5ow
+e2pa
+e3pai
+ep5anc
+e5pel
+e3pent
+ep5etitio
+ephe4
+e4pli
+e1po
+e4prec
+ep5reca
+e4pred
+ep3reh
+e3pro
+e4prob
+ep4sh
+ep5ti5b
+e4put
+ep5uta
+e1q
+equi3l
+e4q3ui3s
+er1a
+era4b
+4erand
+er3ar
+4erati.
+2erb
+er4bl
+er3ch
+er4che
+2ere.
+e3real
+ere5co
+ere3in
+er5el.
+er3emo
+er5ena
+er5ence
+4erene
+er3ent
+ere4q
+er5ess
+er3est
+eret4
+er1h
+er1i
+e1ria4
+5erick
+e3rien
+eri4er
+er3ine
+e1rio
+4erit
+er4iu
+eri4v
+e4riva
+er3m4
+er4nis
+4ernit
+5erniz
+er3no
+2ero
+er5ob
+e5roc
+ero4r
+er1ou
+er1s
+er3set
+ert3er
+4ertl
+er3tw
+4eru
+eru4t
+5erwau
+e1s4a
+e4sage.
+e4sages
+es2c
+e2sca
+es5can
+e3scr
+es5cu
+e1s2e
+e2sec
+es5ecr
+es5enc
+e4sert.
+e4serts
+e4serva
+4esh
+e3sha
+esh5en
+e1si
+e2sic
+e2sid
+es5iden
+es5igna
+e2s5im
+es4i4n
+esis4te
+esi4u
+e5skin
+es4mi
+e2sol
+es3olu
+e2son
+es5ona
+e1sp
+es3per
+es5pira
+es4pre
+2ess
+es4si4b
+estan4
+es3tig
+es5tim
+4es2to
+e3ston
+2estr
+e5stro
+estruc5
+e2sur
+es5urr
+es4w
+eta4b
+eten4d
+e3teo
+ethod3
+et1ic
+e5tide
+etin4
+eti4no
+e5tir
+e5titio
+et5itiv
+4etn
+et5ona
+e3tra
+e3tre
+et3ric
+et5rif
+et3rog
+et5ros
+et3ua
+et5ym
+et5z
+4eu
+e5un
+e3up
+eu3ro
+eus4
+eute4
+euti5l
+eu5tr
+eva2p5
+e2vas
+ev5ast
+e5vea
+ev3ell
+evel3o
+e5veng
+even4i
+ev1er
+e5verb
+e1vi
+ev3id
+evi4l
+e4vin
+evi4v
+e5voc
+e5vu
+e1wa
+e4wag
+e5wee
+e3wh
+ewil5
+ew3ing
+e3wit
+1exp
+5eyc
+5eye.
+eys4
+1fa
+fa3bl
+fab3r
+fa4ce
+4fag
+fain4
+fall5e
+4fa4ma
+fam5is
+5far
+far5th
+fa3ta
+fa3the
+4fato
+fault5
+4f5b
+4fd
+4fe.
+feas4
+feath3
+fe4b
+4feca
+5fect
+2fed
+fe3li
+fe4mo
+fen2d
+fend5e
+fer1
+5ferr
+fev4
+4f1f
+f4fes
+f4fie
+f5fin.
+f2f5is
+f4fly
+f2fy
+4fh
+1fi
+fi3a
+2f3ic.
+4f3ical
+f3ican
+4ficate
+f3icen
+fi3cer
+fic4i
+5ficia
+5ficie
+4fics
+fi3cu
+fi5del
+fight5
+fil5i
+fill5in
+4fily
+2fin
+5fina
+fin2d5
+fi2ne
+f1in3g
+fin4n
+fis4ti
+f4l2
+f5less
+flin4
+flo3re
+f2ly5
+4fm
+4fn
+1fo
+5fon
+fon4de
+fon4t
+fo2r
+fo5rat
+for5ay
+fore5t
+for4i
+fort5a
+fos5
+4f5p
+fra4t
+f5rea
+fres5c
+fri2
+fril4
+frol5
+2f3s
+2ft
+f4to
+f2ty
+3fu
+fu5el
+4fug
+fu4min
+fu5ne
+fu3ri
+fusi4
+fus4s
+4futa
+1fy
+1ga
+gaf4
+5gal.
+3gali
+ga3lo
+2gam
+ga5met
+g5amo
+gan5is
+ga3niz
+gani5za
+4gano
+gar5n4
+gass4
+gath3
+4gativ
+4gaz
+g3b
+gd4
+2ge.
+2ged
+geez4
+gel4in
+ge5lis
+ge5liz
+4gely
+1gen
+ge4nat
+ge5niz
+4geno
+4geny
+1geo
+ge3om
+g4ery
+5gesi
+geth5
+4geto
+ge4ty
+ge4v
+4g1g2
+g2ge
+g3ger
+gglu5
+ggo4
+gh3in
+gh5out
+gh4to
+5gi.
+1gi4a
+gia5r
+g1ic
+5gicia
+g4ico
+gien5
+5gies.
+gil4
+g3imen
+3g4in.
+gin5ge
+5g4ins
+5gio
+3gir
+gir4l
+g3isl
+gi4u
+5giv
+3giz
+gl2
+gla4
+glad5i
+5glas
+1gle
+gli4b
+g3lig
+3glo
+glo3r
+g1m
+g4my
+gn4a
+g4na.
+gnet4t
+g1ni
+g2nin
+g4nio
+g1no
+g4non
+1go
+3go.
+gob5
+5goe
+3g4o4g
+go3is
+gon2
+4g3o3na
+gondo5
+go3ni
+5goo
+go5riz
+gor5ou
+5gos.
+gov1
+g3p
+1gr
+4grada
+g4rai
+gran2
+5graph.
+g5rapher
+5graphic
+4graphy
+4gray
+gre4n
+4gress.
+4grit
+g4ro
+gruf4
+gs2
+g5ste
+gth3
+gu4a
+3guard
+2gue
+5gui5t
+3gun
+3gus
+4gu4t
+g3w
+1gy
+2g5y3n
+gy5ra
+h3ab4l
+hach4
+hae4m
+hae4t
+h5agu
+ha3la
+hala3m
+ha4m
+han4ci
+han4cy
+5hand.
+han4g
+hang5er
+hang5o
+h5a5niz
+han4k
+han4te
+hap3l
+hap5t
+ha3ran
+ha5ras
+har2d
+hard3e
+har4le
+harp5en
+har5ter
+has5s
+haun4
+5haz
+haz3a
+h1b
+1head
+3hear
+he4can
+h5ecat
+h4ed
+he5do5
+he3l4i
+hel4lis
+hel4ly
+h5elo
+hem4p
+he2n
+hena4
+hen5at
+heo5r
+hep5
+h4era
+hera3p
+her4ba
+here5a
+h3ern
+h5erou
+h3ery
+h1es
+he2s5p
+he4t
+het4ed
+heu4
+h1f
+h1h
+hi5an
+hi4co
+high5
+h4il2
+himer4
+h4ina
+hion4e
+hi4p
+hir4l
+hi3ro
+hir4p
+hir4r
+his3el
+his4s
+hith5er
+hi2v
+4hk
+4h1l4
+hlan4
+h2lo
+hlo3ri
+4h1m
+hmet4
+2h1n
+h5odiz
+h5ods
+ho4g
+hoge4
+hol5ar
+3hol4e
+ho4ma
+home3
+hon4a
+ho5ny
+3hood
+hoon4
+hor5at
+ho5ris
+hort3e
+ho5ru
+hos4e
+ho5sen
+hos1p
+1hous
+house3
+hov5el
+4h5p
+4hr4
+hree5
+hro5niz
+hro3po
+4h1s2
+h4sh
+h4tar
+ht1en
+ht5es
+h4ty
+hu4g
+hu4min
+hun5ke
+hun4t
+hus3t4
+hu4t
+h1w
+h4wart
+hy3pe
+hy3ph
+hy2s
+2i1a
+i2al
+iam4
+iam5ete
+i2an
+4ianc
+ian3i
+4ian4t
+ia5pe
+iass4
+i4ativ
+ia4tric
+i4atu
+ibe4
+ib3era
+ib5ert
+ib5ia
+ib3in
+ib5it.
+ib5ite
+i1bl
+ib3li
+i5bo
+i1br
+i2b5ri
+i5bun
+4icam
+5icap
+4icar
+i4car.
+i4cara
+icas5
+i4cay
+iccu4
+4iceo
+4ich
+2ici
+i5cid
+ic5ina
+i2cip
+ic3ipa
+i4cly
+i2c5oc
+4i1cr
+5icra
+i4cry
+ic4te
+ictu2
+ic4t3ua
+ic3ula
+ic4um
+ic5uo
+i3cur
+2id
+i4dai
+id5anc
+id5d
+ide3al
+ide4s
+i2di
+id5ian
+idi4ar
+i5die
+id3io
+idi5ou
+id1it
+id5iu
+i3dle
+i4dom
+id3ow
+i4dr
+i2du
+id5uo
+2ie4
+ied4e
+5ie5ga
+ield3
+ien5a4
+ien4e
+i5enn
+i3enti
+i1er.
+i3esc
+i1est
+i3et
+4if.
+if5ero
+iff5en
+if4fr
+4ific.
+i3fie
+i3fl
+4ift
+2ig
+iga5b
+ig3era
+ight3i
+4igi
+i3gib
+ig3il
+ig3in
+ig3it
+i4g4l
+i2go
+ig3or
+ig5ot
+i5gre
+igu5i
+ig1ur
+i3h
+4i5i4
+i3j
+4ik
+i1la
+il3a4b
+i4lade
+i2l5am
+ila5ra
+i3leg
+il1er
+ilev4
+il5f
+il1i
+il3ia
+il2ib
+il3io
+il4ist
+2ilit
+il2iz
+ill5ab
+4iln
+il3oq
+il4ty
+il5ur
+il3v
+i4mag
+im3age
+ima5ry
+imenta5r
+4imet
+im1i
+im5ida
+imi5le
+i5mini
+4imit
+im4ni
+i3mon
+i2mu
+im3ula
+2in.
+i4n3au
+4inav
+incel4
+in3cer
+4ind
+in5dling
+2ine
+i3nee
+iner4ar
+i5ness
+4inga
+4inge
+in5gen
+4ingi
+in5gling
+4ingo
+4ingu
+2ini
+i5ni.
+i4nia
+in3io
+in1is
+i5nite.
+5initio
+in3ity
+4ink
+4inl
+2inn
+2i1no
+i4no4c
+ino4s
+i4not
+2ins
+in3se
+insur5a
+2int.
+2in4th
+in1u
+i5nus
+4iny
+2io
+4io.
+ioge4
+io2gr
+i1ol
+io4m
+ion3at
+ion4ery
+ion3i
+io5ph
+ior3i
+i4os
+io5th
+i5oti
+io4to
+i4our
+2ip
+ipe4
+iphras4
+ip3i
+ip4ic
+ip4re4
+ip3ul
+i3qua
+iq5uef
+iq3uid
+iq3ui3t
+4ir
+i1ra
+ira4b
+i4rac
+ird5e
+ire4de
+i4ref
+i4rel4
+i4res
+ir5gi
+ir1i
+iri5de
+ir4is
+iri3tu
+5i5r2iz
+ir4min
+iro4g
+5iron.
+ir5ul
+2is.
+is5ag
+is3ar
+isas5
+2is1c
+is3ch
+4ise
+is3er
+3isf
+is5han
+is3hon
+ish5op
+is3ib
+isi4d
+i5sis
+is5itiv
+4is4k
+islan4
+4isms
+i2so
+iso5mer
+is1p
+is2pi
+is4py
+4is1s
+is4sal
+issen4
+is4ses
+is4ta.
+is1te
+is1ti
+ist4ly
+4istral
+i2su
+is5us
+4ita.
+ita4bi
+i4tag
+4ita5m
+i3tan
+i3tat
+2ite
+it3era
+i5teri
+it4es
+2ith
+i1ti
+4itia
+4i2tic
+it3ica
+5i5tick
+it3ig
+it5ill
+i2tim
+2itio
+4itis
+i4tism
+i2t5o5m
+4iton
+i4tram
+it5ry
+4itt
+it3uat
+i5tud
+it3ul
+4itz.
+i1u
+2iv
+iv3ell
+iv3en.
+i4v3er.
+i4vers.
+iv5il.
+iv5io
+iv1it
+i5vore
+iv3o3ro
+i4v3ot
+4i5w
+ix4o
+4iy
+4izar
+izi4
+5izont
+5ja
+jac4q
+ja4p
+1je
+jer5s
+4jestie
+4jesty
+jew3
+jo4p
+5judg
+3ka.
+k3ab
+k5ag
+kais4
+kal4
+k1b
+k2ed
+1kee
+ke4g
+ke5li
+k3en4d
+k1er
+kes4
+k3est.
+ke4ty
+k3f
+kh4
+k1i
+5ki.
+5k2ic
+k4ill
+kilo5
+k4im
+k4in.
+kin4de
+k5iness
+kin4g
+ki4p
+kis4
+k5ish
+kk4
+k1l
+4kley
+4kly
+k1m
+k5nes
+1k2no
+ko5r
+kosh4
+k3ou
+kro5n
+4k1s2
+k4sc
+ks4l
+k4sy
+k5t
+k1w
+lab3ic
+l4abo
+laci4
+l4ade
+la3dy
+lag4n
+lam3o
+3land
+lan4dl
+lan5et
+lan4te
+lar4g
+lar3i
+las4e
+la5tan
+4lateli
+4lativ
+4lav
+la4v4a
+2l1b
+lbin4
+4l1c2
+lce4
+l3ci
+2ld
+l2de
+ld4ere
+ld4eri
+ldi4
+ld5is
+l3dr
+l4dri
+le2a
+le4bi
+left5
+5leg.
+5legg
+le4mat
+lem5atic
+4len.
+3lenc
+5lene.
+1lent
+le3ph
+le4pr
+lera5b
+ler4e
+3lerg
+3l4eri
+l4ero
+les2
+le5sco
+5lesq
+3less
+5less.
+l3eva
+lev4er.
+lev4era
+lev4ers
+3ley
+4leye
+2lf
+l5fr
+4l1g4
+l5ga
+lgar3
+l4ges
+lgo3
+2l3h
+li4ag
+li2am
+liar5iz
+li4as
+li4ato
+li5bi
+5licio
+li4cor
+4lics
+4lict.
+l4icu
+l3icy
+l3ida
+lid5er
+3lidi
+lif3er
+l4iff
+li4fl
+5ligate
+3ligh
+li4gra
+3lik
+4l4i4l
+lim4bl
+lim3i
+li4mo
+l4im4p
+l4ina
+1l4ine
+lin3ea
+lin3i
+link5er
+li5og
+4l4iq
+lis4p
+l1it
+l2it.
+5litica
+l5i5tics
+liv3er
+l1iz
+4lj
+lka3
+l3kal
+lka4t
+l1l
+l4law
+l2le
+l5lea
+l3lec
+l3leg
+l3lel
+l3le4n
+l3le4t
+ll2i
+l2lin4
+l5lina
+ll4o
+lloqui5
+ll5out
+l5low
+2lm
+l5met
+lm3ing
+l4mod
+lmon4
+2l1n2
+3lo.
+lob5al
+lo4ci
+4lof
+3logic
+l5ogo
+3logu
+lom3er
+5long
+lon4i
+l3o3niz
+lood5
+5lope.
+lop3i
+l3opm
+lora4
+lo4rato
+lo5rie
+lor5ou
+5los.
+los5et
+5losophiz
+5losophy
+los4t
+lo4ta
+loun5d
+2lout
+4lov
+2lp
+lpa5b
+l3pha
+l5phi
+lp5ing
+l3pit
+l4pl
+l5pr
+4l1r
+2l1s2
+l4sc
+l2se
+l4sie
+4lt
+lt5ag
+ltane5
+l1te
+lten4
+ltera4
+lth3i
+l5ties.
+ltis4
+l1tr
+ltu2
+ltur3a
+lu5a
+lu3br
+luch4
+lu3ci
+lu3en
+luf4
+lu5id
+lu4ma
+5lumi
+l5umn.
+5lumnia
+lu3o
+luo3r
+4lup
+luss4
+lus3te
+1lut
+l5ven
+l5vet4
+2l1w
+1ly
+4lya
+4lyb
+ly5me
+ly3no
+2lys4
+l5yse
+1ma
+2mab
+ma2ca
+ma5chine
+ma4cl
+mag5in
+5magn
+2mah
+maid5
+4mald
+ma3lig
+ma5lin
+mal4li
+mal4ty
+5mania
+man5is
+man3iz
+4map
+ma5rine.
+ma5riz
+mar4ly
+mar3v
+ma5sce
+mas4e
+mas1t
+5mate
+math3
+ma3tis
+4matiza
+4m1b
+mba4t5
+m5bil
+m4b3ing
+mbi4v
+4m5c
+4me.
+2med
+4med.
+5media
+me3die
+m5e5dy
+me2g
+mel5on
+mel4t
+me2m
+mem1o3
+1men
+men4a
+men5ac
+men4de
+4mene
+men4i
+mens4
+mensu5
+3ment
+men4te
+me5on
+m5ersa
+2mes
+3mesti
+me4ta
+met3al
+me1te
+me5thi
+m4etr
+5metric
+me5trie
+me3try
+me4v
+4m1f
+2mh
+5mi.
+mi3a
+mid4a
+mid4g
+mig4
+3milia
+m5i5lie
+m4ill
+min4a
+3mind
+m5inee
+m4ingl
+min5gli
+m5ingly
+min4t
+m4inu
+miot4
+m2is
+mis4er.
+mis5l
+mis4ti
+m5istry
+4mith
+m2iz
+4mk
+4m1l
+m1m
+mma5ry
+4m1n
+mn4a
+m4nin
+mn4o
+1mo
+4mocr
+5mocratiz
+mo2d1
+mo4go
+mois2
+moi5se
+4mok
+mo5lest
+mo3me
+mon5et
+mon5ge
+moni3a
+mon4ism
+mon4ist
+mo3niz
+monol4
+mo3ny.
+mo2r
+4mora.
+mos2
+mo5sey
+mo3sp
+moth3
+m5ouf
+3mous
+mo2v
+4m1p
+mpara5
+mpa5rab
+mpar5i
+m3pet
+mphas4
+m2pi
+mpi4a
+mp5ies
+m4p1in
+m5pir
+mp5is
+mpo3ri
+mpos5ite
+m4pous
+mpov5
+mp4tr
+m2py
+4m3r
+4m1s2
+m4sh
+m5si
+4mt
+1mu
+mula5r4
+5mult
+multi3
+3mum
+mun2
+4mup
+mu4u
+4mw
+1na
+2n1a2b
+n4abu
+4nac.
+na4ca
+n5act
+nag5er.
+nak4
+na4li
+na5lia
+4nalt
+na5mit
+n2an
+nanci4
+nan4it
+nank4
+nar3c
+4nare
+nar3i
+nar4l
+n5arm
+n4as
+nas4c
+nas5ti
+n2at
+na3tal
+nato5miz
+n2au
+nau3se
+3naut
+nav4e
+4n1b4
+ncar5
+n4ces.
+n3cha
+n5cheo
+n5chil
+n3chis
+nc1in
+nc4it
+ncour5a
+n1cr
+n1cu
+n4dai
+n5dan
+n1de
+nd5est.
+ndi4b
+n5d2if
+n1dit
+n3diz
+n5duc
+ndu4r
+nd2we
+2ne.
+n3ear
+ne2b
+neb3u
+ne2c
+5neck
+2ned
+ne4gat
+neg5ativ
+5nege
+ne4la
+nel5iz
+ne5mi
+ne4mo
+1nen
+4nene
+3neo
+ne4po
+ne2q
+n1er
+nera5b
+n4erar
+n2ere
+n4er5i
+ner4r
+1nes
+2nes.
+4nesp
+2nest
+4nesw
+3netic
+ne4v
+n5eve
+ne4w
+n3f
+n4gab
+n3gel
+nge4n4e
+n5gere
+n3geri
+ng5ha
+n3gib
+ng1in
+n5git
+n4gla
+ngov4
+ng5sh
+n1gu
+n4gum
+n2gy
+4n1h4
+nha4
+nhab3
+nhe4
+3n4ia
+ni3an
+ni4ap
+ni3ba
+ni4bl
+ni4d
+ni5di
+ni4er
+ni2fi
+ni5ficat
+n5igr
+nik4
+n1im
+ni3miz
+n1in
+5nine.
+nin4g
+ni4o
+5nis.
+nis4ta
+n2it
+n4ith
+3nitio
+n3itor
+ni3tr
+n1j
+4nk2
+n5kero
+n3ket
+nk3in
+n1kl
+4n1l
+n5m
+nme4
+nmet4
+4n1n2
+nne4
+nni3al
+nni4v
+nob4l
+no3ble
+n5ocl
+4n3o2d
+3noe
+4nog
+noge4
+nois5i
+no5l4i
+5nologis
+3nomic
+n5o5miz
+no4mo
+no3my
+no4n
+non4ag
+non5i
+n5oniz
+4nop
+5nop5o5li
+nor5ab
+no4rary
+4nosc
+nos4e
+nos5t
+no5ta
+1nou
+3noun
+nov3el3
+nowl3
+n1p4
+npi4
+npre4c
+n1q
+n1r
+nru4
+2n1s2
+ns5ab
+nsati4
+ns4c
+n2se
+n4s3es
+nsid1
+nsig4
+n2sl
+ns3m
+n4soc
+ns4pe
+n5spi
+nsta5bl
+n1t
+nta4b
+nter3s
+nt2i
+n5tib
+nti4er
+nti2f
+n3tine
+n4t3ing
+nti4p
+ntrol5li
+nt4s
+ntu3me
+nu1a
+nu4d
+nu5en
+nuf4fe
+n3uin
+3nu3it
+n4um
+nu1me
+n5umi
+3nu4n
+n3uo
+nu3tr
+n1v2
+n1w4
+nym4
+nyp4
+4nz
+n3za
+4oa
+oad3
+o5a5les
+oard3
+oas4e
+oast5e
+oat5i
+ob3a3b
+o5bar
+obe4l
+o1bi
+o2bin
+ob5ing
+o3br
+ob3ul
+o1ce
+och4
+o3chet
+ocif3
+o4cil
+o4clam
+o4cod
+oc3rac
+oc5ratiz
+ocre3
+5ocrit
+octor5a
+oc3ula
+o5cure
+od5ded
+od3ic
+odi3o
+o2do4
+odor3
+od5uct.
+od5ucts
+o4el
+o5eng
+o3er
+oe4ta
+o3ev
+o2fi
+of5ite
+ofit4t
+o2g5a5r
+og5ativ
+o4gato
+o1ge
+o5gene
+o5geo
+o4ger
+o3gie
+1o1gis
+og3it
+o4gl
+o5g2ly
+3ogniz
+o4gro
+ogu5i
+1ogy
+2ogyn
+o1h2
+ohab5
+oi2
+oic3es
+oi3der
+oiff4
+oig4
+oi5let
+o3ing
+oint5er
+o5ism
+oi5son
+oist5en
+oi3ter
+o5j
+2ok
+o3ken
+ok5ie
+o1la
+o4lan
+olass4
+ol2d
+old1e
+ol3er
+o3lesc
+o3let
+ol4fi
+ol2i
+o3lia
+o3lice
+ol5id.
+o3li4f
+o5lil
+ol3ing
+o5lio
+o5lis.
+ol3ish
+o5lite
+o5litio
+o5liv
+olli4e
+ol5ogiz
+olo4r
+ol5pl
+ol2t
+ol3ub
+ol3ume
+ol3un
+o5lus
+ol2v
+o2ly
+om5ah
+oma5l
+om5atiz
+om2be
+om4bl
+o2me
+om3ena
+om5erse
+o4met
+om5etry
+o3mia
+om3ic.
+om3ica
+o5mid
+om1in
+o5mini
+5ommend
+omo4ge
+o4mon
+om3pi
+ompro5
+o2n
+on1a
+on4ac
+o3nan
+on1c
+3oncil
+2ond
+on5do
+o3nen
+on5est
+on4gu
+on1ic
+o3nio
+on1is
+o5niu
+on3key
+on4odi
+on3omy
+on3s
+onspi4
+onspir5a
+onsu4
+onten4
+on3t4i
+ontif5
+on5um
+onva5
+oo2
+ood5e
+ood5i
+oo4k
+oop3i
+o3ord
+oost5
+o2pa
+ope5d
+op1er
+3opera
+4operag
+2oph
+o5phan
+o5pher
+op3ing
+o3pit
+o5pon
+o4posi
+o1pr
+op1u
+opy5
+o1q
+o1ra
+o5ra.
+o4r3ag
+or5aliz
+or5ange
+ore5a
+o5real
+or3ei
+ore5sh
+or5est.
+orew4
+or4gu
+4o5ria
+or3ica
+o5ril
+or1in
+o1rio
+or3ity
+o3riu
+or2mi
+orn2e
+o5rof
+or3oug
+or5pe
+3orrh
+or4se
+ors5en
+orst4
+or3thi
+or3thy
+or4ty
+o5rum
+o1ry
+os3al
+os2c
+os4ce
+o3scop
+4oscopi
+o5scr
+os4i4e
+os5itiv
+os3ito
+os3ity
+osi4u
+os4l
+o2so
+os4pa
+os4po
+os2ta
+o5stati
+os5til
+os5tit
+o4tan
+otele4g
+ot3er.
+ot5ers
+o4tes
+4oth
+oth5esi
+oth3i4
+ot3ic.
+ot5ica
+o3tice
+o3tif
+o3tis
+oto5s
+ou2
+ou3bl
+ouch5i
+ou5et
+ou4l
+ounc5er
+oun2d
+ou5v
+ov4en
+over4ne
+over3s
+ov4ert
+o3vis
+oviti4
+o5v4ol
+ow3der
+ow3el
+ow5est
+ow1i
+own5i
+o4wo
+oy1a
+1pa
+pa4ca
+pa4ce
+pac4t
+p4ad
+5pagan
+p3agat
+p4ai
+pain4
+p4al
+pan4a
+pan3el
+pan4ty
+pa3ny
+pa1p
+pa4pu
+para5bl
+par5age
+par5di
+3pare
+par5el
+p4a4ri
+par4is
+pa2te
+pa5ter
+5pathic
+pa5thy
+pa4tric
+pav4
+3pay
+4p1b
+pd4
+4pe.
+3pe4a
+pear4l
+pe2c
+2p2ed
+3pede
+3pedi
+pedia4
+ped4ic
+p4ee
+pee4d
+pek4
+pe4la
+peli4e
+pe4nan
+p4enc
+pen4th
+pe5on
+p4era.
+pera5bl
+p4erag
+p4eri
+peri5st
+per4mal
+perme5
+p4ern
+per3o
+per3ti
+pe5ru
+per1v
+pe2t
+pe5ten
+pe5tiz
+4pf
+4pg
+4ph.
+phar5i
+phe3no
+ph4er
+ph4es.
+ph1ic
+5phie
+ph5ing
+5phisti
+3phiz
+ph2l
+3phob
+3phone
+5phoni
+pho4r
+4phs
+ph3t
+5phu
+1phy
+pi3a
+pian4
+pi4cie
+pi4cy
+p4id
+p5ida
+pi3de
+5pidi
+3piec
+pi3en
+pi4grap
+pi3lo
+pi2n
+p4in.
+pind4
+p4ino
+3pi1o
+pion4
+p3ith
+pi5tha
+pi2tu
+2p3k2
+1p2l2
+3plan
+plas5t
+pli3a
+pli5er
+4plig
+pli4n
+ploi4
+plu4m
+plum4b
+4p1m
+2p3n
+po4c
+5pod.
+po5em
+po3et5
+5po4g
+poin2
+5point
+poly5t
+po4ni
+po4p
+1p4or
+po4ry
+1pos
+pos1s
+p4ot
+po4ta
+5poun
+4p1p
+ppa5ra
+p2pe
+p4ped
+p5pel
+p3pen
+p3per
+p3pet
+ppo5site
+pr2
+pray4e
+5preci
+pre5co
+pre3em
+pref5ac
+pre4la
+pre3r
+p3rese
+3press
+pre5ten
+pre3v
+5pri4e
+prin4t3
+pri4s
+pris3o
+p3roca
+prof5it
+pro3l
+pros3e
+pro1t
+2p1s2
+p2se
+ps4h
+p4sib
+2p1t
+pt5a4b
+p2te
+p2th
+pti3m
+ptu4r
+p4tw
+pub3
+pue4
+puf4
+pul3c
+pu4m
+pu2n
+pur4r
+5pus
+pu2t
+5pute
+put3er
+pu3tr
+put4ted
+put4tin
+p3w
+qu2
+qua5v
+2que.
+3quer
+3quet
+2rab
+ra3bi
+rach4e
+r5acl
+raf5fi
+raf4t
+r2ai
+ra4lo
+ram3et
+r2ami
+rane5o
+ran4ge
+r4ani
+ra5no
+rap3er
+3raphy
+rar5c
+rare4
+rar5ef
+4raril
+r2as
+ration4
+rau4t
+ra5vai
+rav3el
+ra5zie
+r1b
+r4bab
+r4bag
+rbi2
+rbi4f
+r2bin
+r5bine
+rb5ing.
+rb4o
+r1c
+r2ce
+rcen4
+r3cha
+rch4er
+r4ci4b
+rc4it
+rcum3
+r4dal
+rd2i
+rdi4a
+rdi4er
+rdin4
+rd3ing
+2re.
+re1al
+re3an
+re5arr
+5reav
+re4aw
+r5ebrat
+rec5oll
+rec5ompe
+re4cre
+2r2ed
+re1de
+re3dis
+red5it
+re4fac
+re2fe
+re5fer.
+re3fi
+re4fy
+reg3is
+re5it
+re1li
+re5lu
+r4en4ta
+ren4te
+re1o
+re5pin
+re4posi
+re1pu
+r1er4
+r4eri
+rero4
+re5ru
+r4es.
+re4spi
+ress5ib
+res2t
+re5stal
+re3str
+re4ter
+re4ti4z
+re3tri
+reu2
+re5uti
+rev2
+re4val
+rev3el
+r5ev5er.
+re5vers
+re5vert
+re5vil
+rev5olu
+re4wh
+r1f
+rfu4
+r4fy
+rg2
+rg3er
+r3get
+r3gic
+rgi4n
+rg3ing
+r5gis
+r5git
+r1gl
+rgo4n
+r3gu
+rh4
+4rh.
+4rhal
+ri3a
+ria4b
+ri4ag
+r4ib
+rib3a
+ric5as
+r4ice
+4rici
+5ricid
+ri4cie
+r4ico
+rid5er
+ri3enc
+ri3ent
+ri1er
+ri5et
+rig5an
+5rigi
+ril3iz
+5riman
+rim5i
+3rimo
+rim4pe
+r2ina
+5rina.
+rin4d
+rin4e
+rin4g
+ri1o
+5riph
+riph5e
+ri2pl
+rip5lic
+r4iq
+r2is
+r4is.
+ris4c
+r3ish
+ris4p
+ri3ta3b
+r5ited.
+rit5er.
+rit5ers
+rit3ic
+ri2tu
+rit5ur
+riv5el
+riv3et
+riv3i
+r3j
+r3ket
+rk4le
+rk4lin
+r1l
+rle4
+r2led
+r4lig
+r4lis
+rl5ish
+r3lo4
+r1m
+rma5c
+r2me
+r3men
+rm5ers
+rm3ing
+r4ming.
+r4mio
+r3mit
+r4my
+r4nar
+r3nel
+r4ner
+r5net
+r3ney
+r5nic
+r1nis4
+r3nit
+r3niv
+rno4
+r4nou
+r3nu
+rob3l
+r2oc
+ro3cr
+ro4e
+ro1fe
+ro5fil
+rok2
+ro5ker
+5role.
+rom5ete
+rom4i
+rom4p
+ron4al
+ron4e
+ro5n4is
+ron4ta
+1room
+5root
+ro3pel
+rop3ic
+ror3i
+ro5ro
+ros5per
+ros4s
+ro4the
+ro4ty
+ro4va
+rov5el
+rox5
+r1p
+r4pea
+r5pent
+rp5er.
+r3pet
+rp4h4
+rp3ing
+r3po
+r1r4
+rre4c
+rre4f
+r4reo
+rre4st
+rri4o
+rri4v
+rron4
+rros4
+rrys4
+4rs2
+r1sa
+rsa5ti
+rs4c
+r2se
+r3sec
+rse4cr
+rs5er.
+rs3es
+rse5v2
+r1sh
+r5sha
+r1si
+r4si4b
+rson3
+r1sp
+r5sw
+rtach4
+r4tag
+r3teb
+rten4d
+rte5o
+r1ti
+rt5ib
+rti4d
+r4tier
+r3tig
+rtil3i
+rtil4l
+r4tily
+r4tist
+r4tiv
+r3tri
+rtroph4
+rt4sh
+ru3a
+ru3e4l
+ru3en
+ru4gl
+ru3in
+rum3pl
+ru2n
+runk5
+run4ty
+r5usc
+ruti5n
+rv4e
+rvel4i
+r3ven
+rv5er.
+r5vest
+r3vey
+r3vic
+rvi4v
+r3vo
+r1w
+ry4c
+5rynge
+ry3t
+sa2
+2s1ab
+5sack
+sac3ri
+s3act
+5sai
+salar4
+sal4m
+sa5lo
+sal4t
+3sanc
+san4de
+s1ap
+sa5ta
+5sa3tio
+sat3u
+sau4
+sa5vor
+5saw
+4s5b
+scan4t5
+sca4p
+scav5
+s4ced
+4scei
+s4ces
+sch2
+s4cho
+3s4cie
+5scin4d
+scle5
+s4cli
+scof4
+4scopy
+scour5a
+s1cu
+4s5d
+4se.
+se4a
+seas4
+sea5w
+se2c3o
+3sect
+4s4ed
+se4d4e
+s5edl
+se2g
+seg3r
+5sei
+se1le
+5self
+5selv
+4seme
+se4mol
+sen5at
+4senc
+sen4d
+s5ened
+sen5g
+s5enin
+4sentd
+4sentl
+sep3a3
+4s1er.
+s4erl
+ser4o
+4servo
+s1e4s
+se5sh
+ses5t
+5se5um
+5sev
+sev3en
+sew4i
+5sex
+4s3f
+2s3g
+s2h
+2sh.
+sh1er
+5shev
+sh1in
+sh3io
+3ship
+shiv5
+sho4
+sh5old
+shon3
+shor4
+short5
+4shw
+si1b
+s5icc
+3side.
+5sides
+5sidi
+si5diz
+4signa
+sil4e
+4sily
+2s1in
+s2ina
+5sine.
+s3ing
+1sio
+5sion
+sion5a
+si2r
+sir5a
+1sis
+3sitio
+5siu
+1siv
+5siz
+sk2
+4ske
+s3ket
+sk5ine
+sk5ing
+s1l2
+s3lat
+s2le
+slith5
+2s1m
+s3ma
+small3
+sman3
+smel4
+s5men
+5smith
+smol5d4
+s1n4
+1so
+so4ce
+soft3
+so4lab
+sol3d2
+so3lic
+5solv
+3som
+3s4on.
+sona4
+son4g
+s4op
+5sophic
+s5ophiz
+s5ophy
+sor5c
+sor5d
+4sov
+so5vi
+2spa
+5spai
+spa4n
+spen4d
+2s5peo
+2sper
+s2phe
+3spher
+spho5
+spil4
+sp5ing
+4spio
+s4ply
+s4pon
+spor4
+4spot
+squal4l
+s1r
+2ss
+s1sa
+ssas3
+s2s5c
+s3sel
+s5seng
+s4ses.
+s5set
+s1si
+s4sie
+ssi4er
+ss5ily
+s4sl
+ss4li
+s4sn
+sspend4
+ss2t
+ssur5a
+ss5w
+2st.
+s2tag
+s2tal
+stam4i
+5stand
+s4ta4p
+5stat.
+s4ted
+stern5i
+s5tero
+ste2w
+stew5a
+s3the
+st2i
+s4ti.
+s5tia
+s1tic
+5stick
+s4tie
+s3tif
+st3ing
+5stir
+s1tle
+5stock
+stom3a
+5stone
+s4top
+3store
+st4r
+s4trad
+5stratu
+s4tray
+s4trid
+4stry
+4st3w
+s2ty
+1su
+su1al
+su4b3
+su2g3
+su5is
+suit3
+s4ul
+su2m
+sum3i
+su2n
+su2r
+4sv
+sw2
+4swo
+s4y
+4syc
+3syl
+syn5o
+sy5rin
+1ta
+3ta.
+2tab
+ta5bles
+5taboliz
+4taci
+ta5do
+4taf4
+tai5lo
+ta2l
+ta5la
+tal5en
+tal3i
+4talk
+tal4lis
+ta5log
+ta5mo
+tan4de
+tanta3
+ta5per
+ta5pl
+tar4a
+4tarc
+4tare
+ta3riz
+tas4e
+ta5sy
+4tatic
+ta4tur
+taun4
+tav4
+2taw
+tax4is
+2t1b
+4tc
+t4ch
+tch5et
+4t1d
+4te.
+tead4i
+4teat
+tece4
+5tect
+2t1ed
+te5di
+1tee
+teg4
+te5ger
+te5gi
+3tel.
+teli4
+5tels
+te2ma2
+tem3at
+3tenan
+3tenc
+3tend
+4tenes
+1tent
+ten4tag
+1teo
+te4p
+te5pe
+ter3c
+5ter3d
+1teri
+ter5ies
+ter3is
+teri5za
+5ternit
+ter5v
+4tes.
+4tess
+t3ess.
+teth5e
+3teu
+3tex
+4tey
+2t1f
+4t1g
+2th.
+than4
+th2e
+4thea
+th3eas
+the5at
+the3is
+3thet
+th5ic.
+th5ica
+4thil
+5think
+4thl
+th5ode
+5thodic
+4thoo
+thor5it
+tho5riz
+2ths
+1tia
+ti4ab
+ti4ato
+2ti2b
+4tick
+t4ico
+t4ic1u
+5tidi
+3tien
+tif2
+ti5fy
+2tig
+5tigu
+till5in
+1tim
+4timp
+tim5ul
+2t1in
+t2ina
+3tine.
+3tini
+1tio
+ti5oc
+tion5ee
+5tiq
+ti3sa
+3tise
+tis4m
+ti5so
+tis4p
+5tistica
+ti3tl
+ti4u
+1tiv
+tiv4a
+1tiz
+ti3za
+ti3zen
+2tl
+t5la
+tlan4
+3tle.
+3tled
+3tles.
+t5let.
+t5lo
+4t1m
+tme4
+2t1n2
+1to
+to3b
+to5crat
+4todo
+2tof
+to2gr
+to5ic
+to2ma
+tom4b
+to3my
+ton4ali
+to3nat
+4tono
+4tony
+to2ra
+to3rie
+tor5iz
+tos2
+5tour
+4tout
+to3war
+4t1p
+1tra
+tra3b
+tra5ch
+traci4
+trac4it
+trac4te
+tras4
+tra5ven
+trav5es5
+tre5f
+tre4m
+trem5i
+5tria
+tri5ces
+5tricia
+4trics
+2trim
+tri4v
+tro5mi
+tron5i
+4trony
+tro5phe
+tro3sp
+tro3v
+tru5i
+trus4
+4t1s2
+t4sc
+tsh4
+t4sw
+4t3t2
+t4tes
+t5to
+ttu4
+1tu
+tu1a
+tu3ar
+tu4bi
+tud2
+4tue
+4tuf4
+5tu3i
+3tum
+tu4nis
+2t3up.
+3ture
+5turi
+tur3is
+tur5o
+tu5ry
+3tus
+4tv
+tw4
+4t1wa
+twis4
+4two
+1ty
+4tya
+2tyl
+type3
+ty5ph
+4tz
+tz4e
+4uab
+uac4
+ua5na
+uan4i
+uar5ant
+uar2d
+uar3i
+uar3t
+u1at
+uav4
+ub4e
+u4bel
+u3ber
+u4bero
+u1b4i
+u4b5ing
+u3ble.
+u3ca
+uci4b
+uc4it
+ucle3
+u3cr
+u3cu
+u4cy
+ud5d
+ud3er
+ud5est
+udev4
+u1dic
+ud3ied
+ud3ies
+ud5is
+u5dit
+u4don
+ud4si
+u4du
+u4ene
+uens4
+uen4te
+uer4il
+3ufa
+u3fl
+ugh3en
+ug5in
+2ui2
+uil5iz
+ui4n
+u1ing
+uir4m
+uita4
+uiv3
+uiv4er.
+u5j
+4uk
+u1la
+ula5b
+u5lati
+ulch4
+5ulche
+ul3der
+ul4e
+u1len
+ul4gi
+ul2i
+u5lia
+ul3ing
+ul5ish
+ul4lar
+ul4li4b
+ul4lis
+4ul3m
+u1l4o
+4uls
+uls5es
+ul1ti
+ultra3
+4ultu
+u3lu
+ul5ul
+ul5v
+um5ab
+um4bi
+um4bly
+u1mi
+u4m3ing
+umor5o
+um2p
+unat4
+u2ne
+un4er
+u1ni
+un4im
+u2nin
+un5ish
+uni3v
+un3s4
+un4sw
+unt3ab
+un4ter.
+un4tes
+unu4
+un5y
+un5z
+u4ors
+u5os
+u1ou
+u1pe
+uper5s
+u5pia
+up3ing
+u3pl
+up3p
+upport5
+upt5ib
+uptu4
+u1ra
+4ura.
+u4rag
+u4ras
+ur4be
+urc4
+ur1d
+ure5at
+ur4fer
+ur4fr
+u3rif
+uri4fic
+ur1in
+u3rio
+u1rit
+ur3iz
+ur2l
+url5ing.
+ur4no
+uros4
+ur4pe
+ur4pi
+urs5er
+ur5tes
+ur3the
+urti4
+ur4tie
+u3ru
+2us
+u5sad
+u5san
+us4ap
+usc2
+us3ci
+use5a
+u5sia
+u3sic
+us4lin
+us1p
+us5sl
+us5tere
+us1tr
+u2su
+usur4
+uta4b
+u3tat
+4ute.
+4utel
+4uten
+uten4i
+4u1t2i
+uti5liz
+u3tine
+ut3ing
+ution5a
+u4tis
+5u5tiz
+u4t1l
+ut5of
+uto5g
+uto5matic
+u5ton
+u4tou
+uts4
+u3u
+uu4m
+u1v2
+uxu3
+uz4e
+1va
+5va.
+2v1a4b
+vac5il
+vac3u
+vag4
+va4ge
+va5lie
+val5o
+val1u
+va5mo
+va5niz
+va5pi
+var5ied
+3vat
+4ve.
+4ved
+veg3
+v3el.
+vel3li
+ve4lo
+v4ely
+ven3om
+v5enue
+v4erd
+5vere.
+v4erel
+v3eren
+ver5enc
+v4eres
+ver3ie
+vermi4n
+3verse
+ver3th
+v4e2s
+4ves.
+ves4te
+ve4te
+vet3er
+ve4ty
+vi5ali
+5vian
+5vide.
+5vided
+4v3iden
+5vides
+5vidi
+v3if
+vi5gn
+vik4
+2vil
+5vilit
+v3i3liz
+v1in
+4vi4na
+v2inc
+vin5d
+4ving
+vio3l
+v3io4r
+vi1ou
+vi4p
+vi5ro
+vis3it
+vi3so
+vi3su
+4viti
+vit3r
+4vity
+3viv
+5vo.
+voi4
+3vok
+vo4la
+v5ole
+5volt
+3volv
+vom5i
+vor5ab
+vori4
+vo4ry
+vo4ta
+4votee
+4vv4
+v4y
+w5abl
+2wac
+wa5ger
+wag5o
+wait5
+w5al.
+wam4
+war4t
+was4t
+wa1te
+wa5ver
+w1b
+wea5rie
+weath3
+wed4n
+weet3
+wee5v
+wel4l
+w1er
+west3
+w3ev
+whi4
+wi2
+wil2
+will5in
+win4de
+win4g
+wir4
+3wise
+with3
+wiz5
+w4k
+wl4es
+wl3in
+w4no
+1wo2
+wom1
+wo5ven
+w5p
+wra4
+wri4
+writa4
+w3sh
+ws4l
+ws4pe
+w5s4t
+4wt
+wy4
+x1a
+xac5e
+x4ago
+xam3
+x4ap
+xas5
+x3c2
+x1e
+xe4cuto
+x2ed
+xer4i
+xe5ro
+x1h
+xhi2
+xhil5
+xhu4
+x3i
+xi5a
+xi5c
+xi5di
+x4ime
+xi5miz
+x3o
+x4ob
+x3p
+xpan4d
+xpecto5
+xpe3d
+x1t2
+x3ti
+x1u
+xu3a
+xx4
+y5ac
+3yar4
+y5at
+y1b
+y1c
+y2ce
+yc5er
+y3ch
+ych4e
+ycom4
+ycot4
+y1d
+y5ee
+y1er
+y4erf
+yes4
+ye4t
+y5gi
+4y3h
+y1i
+y3la
+ylla5bl
+y3lo
+y5lu
+ymbol5
+yme4
+ympa3
+yn3chr
+yn5d
+yn5g
+yn5ic
+5ynx
+y1o4
+yo5d
+y4o5g
+yom4
+yo5net
+y4ons
+y4os
+y4ped
+yper5
+yp3i
+y3po
+y4poc
+yp2ta
+y5pu
+yra5m
+yr5ia
+y3ro
+yr4r
+ys4c
+y3s2e
+ys3ica
+ys3io
+3ysis
+y4so
+yss4
+ys1t
+ys3ta
+ysur4
+y3thin
+yt3ic
+y1w
+za1
+z5a2b
+zar2
+4zb
+2ze
+ze4n
+ze4p
+z1er
+ze3ro
+zet4
+2z1i
+z4il
+z4is
+5zl
+4zm
+1zo
+zo4m
+zo5ol
+zte4
+4z1z2
+z4zy
diff --git a/src/roff/troff/input.cc b/src/roff/troff/input.cc
new file mode 100644
index 00000000..a4565904
--- /dev/null
+++ b/src/roff/troff/input.cc
@@ -0,0 +1,6323 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "troff.h"
+#include "symbol.h"
+#include "dictionary.h"
+#include "hvunits.h"
+#include "env.h"
+#include "request.h"
+#include "node.h"
+#include "reg.h"
+#include "token.h"
+#include "div.h"
+#include "charinfo.h"
+#include "font.h"
+#include "searchpath.h"
+#include "macropath.h"
+#include "defs.h"
+
+// Needed for getpid().
+#include "posix.h"
+
+#ifdef ISATTY_MISSING
+#undef isatty
+#define isatty(n) (1)
+#else /* not ISATTY_MISSING */
+#ifndef isatty
+extern "C" {
+ int isatty(int);
+}
+#endif /* not isatty */
+#endif /* not ISATTY_MISSING */
+
+#define USAGE_EXIT_CODE 1
+#define MACRO_PREFIX "tmac."
+#define INITIAL_STARTUP_FILE "troffrc"
+#define FINAL_STARTUP_FILE "troffrc-end"
+#define DEFAULT_INPUT_STACK_LIMIT 1000
+
+#ifndef DEFAULT_WARNING_MASK
+// warnings that are enabled by default
+#define DEFAULT_WARNING_MASK \
+ (WARN_CHAR|WARN_NUMBER|WARN_BREAK|WARN_SPACE|WARN_FONT)
+#endif
+
+// initial size of buffer for reading names; expanded as necessary
+#define ABUF_SIZE 16
+
+#ifdef COLUMN
+void init_column_requests();
+#endif /* COLUMN */
+
+static node *read_draw_node();
+void handle_first_page_transition();
+static void push_token(const token &);
+void copy_file();
+#ifdef COLUMN
+void vjustify();
+#endif /* COLUMN */
+void transparent();
+void transparent_file();
+
+const char *program_name = 0;
+token tok;
+int break_flag = 0;
+static int backtrace_flag = 0;
+#ifndef POPEN_MISSING
+char *pipe_command = 0;
+#endif
+charinfo *charset_table[256];
+
+static int warning_mask = DEFAULT_WARNING_MASK;
+static int inhibit_errors = 0;
+static int ignoring = 0;
+
+static void enable_warning(const char *);
+static void disable_warning(const char *);
+
+static int escape_char = '\\';
+static symbol end_macro_name;
+static symbol blank_line_macro_name;
+static int compatible_flag = 0;
+int ascii_output_flag = 0;
+int suppress_output_flag = 0;
+
+int tcommand_flag = 0;
+
+static int get_copy(node**, int = 0);
+static void copy_mode_error(const char *,
+ const errarg & = empty_errarg,
+ const errarg & = empty_errarg,
+ const errarg & = empty_errarg);
+
+static symbol read_escape_name();
+static void interpolate_string(symbol);
+static void interpolate_macro(symbol);
+static void interpolate_number_format(symbol);
+static void interpolate_environment_variable(symbol);
+
+static void interpolate_arg(symbol);
+static request_or_macro *lookup_request(symbol);
+static int get_delim_number(units *, int);
+static int get_delim_number(units *, int, units);
+static int get_line_arg(units *res, int si, charinfo **cp);
+static int read_size(int *);
+static symbol get_delim_name();
+static void init_registers();
+static void trapping_blank_line();
+
+struct input_iterator;
+input_iterator *make_temp_iterator(const char *);
+const char *input_char_description(int);
+
+const int ESCAPE_QUESTION = 015;
+const int BEGIN_TRAP = 016;
+const int END_TRAP = 017;
+const int PAGE_EJECTOR = 020;
+const int ESCAPE_NEWLINE = 021;
+const int ESCAPE_AMPERSAND = 022;
+const int ESCAPE_UNDERSCORE = 023;
+const int ESCAPE_BAR = 024;
+const int ESCAPE_CIRCUMFLEX = 025;
+const int ESCAPE_LEFT_BRACE = 026;
+const int ESCAPE_RIGHT_BRACE = 027;
+const int ESCAPE_LEFT_QUOTE = 030;
+const int ESCAPE_RIGHT_QUOTE = 031;
+const int ESCAPE_HYPHEN = 032;
+const int ESCAPE_BANG = 033;
+const int ESCAPE_c = 034;
+const int ESCAPE_e = 035;
+const int ESCAPE_PERCENT = 036;
+const int ESCAPE_SPACE = 037;
+
+const int TITLE_REQUEST = 0200;
+const int COPY_FILE_REQUEST = 0201;
+const int TRANSPARENT_FILE_REQUEST = 0202;
+#ifdef COLUMN
+const int VJUSTIFY_REQUEST = 0203;
+#endif /* COLUMN */
+const int ESCAPE_E = 0204;
+const int LAST_PAGE_EJECTOR = 0205;
+const int ESCAPE_RIGHT_PARENTHESIS = 0206;
+
+void set_escape_char()
+{
+ if (has_arg()) {
+ if (tok.ch() == 0) {
+ error("bad escape character");
+ escape_char = '\\';
+ }
+ else
+ escape_char = tok.ch();
+ }
+ else
+ escape_char = '\\';
+ skip_line();
+}
+
+void escape_off()
+{
+ escape_char = 0;
+ skip_line();
+}
+
+class input_iterator {
+public:
+ input_iterator();
+ virtual ~input_iterator();
+ int get(node **);
+ friend class input_stack;
+protected:
+ const unsigned char *ptr;
+ const unsigned char *eptr;
+ input_iterator *next;
+private:
+ virtual int fill(node **);
+ virtual int peek();
+ virtual int has_args() { return 0; }
+ virtual int nargs() { return 0; }
+ virtual input_iterator *get_arg(int) { return NULL; }
+ virtual int get_location(int, const char **, int *)
+ { return 0; }
+ virtual void backtrace() {}
+ virtual int set_location(const char *, int)
+ { return 0; }
+ virtual int next_file(FILE *, const char *) { return 0; }
+ virtual void shift(int) {}
+ virtual int is_boundary();
+ virtual int internal_level() { return 0; }
+ virtual int is_file() { return 0; }
+};
+
+input_iterator::input_iterator()
+: ptr(0), eptr(0)
+{
+}
+
+input_iterator::~input_iterator()
+{
+}
+
+int input_iterator::fill(node **)
+{
+ return EOF;
+}
+
+int input_iterator::peek()
+{
+ return EOF;
+}
+
+int input_iterator::is_boundary()
+{
+ return 0;
+}
+
+inline int input_iterator::get(node **p)
+{
+ return ptr < eptr ? *ptr++ : fill(p);
+}
+
+
+class input_boundary : public input_iterator {
+public:
+ int is_boundary() { return 1; }
+};
+
+class file_iterator : public input_iterator {
+ FILE *fp;
+ int lineno;
+ const char *filename;
+ int popened;
+ int newline_flag;
+ enum { BUF_SIZE = 512 };
+ unsigned char buf[BUF_SIZE];
+ void close();
+public:
+ file_iterator(FILE *, const char *, int = 0);
+ ~file_iterator();
+ int fill(node **);
+ int peek();
+ int get_location(int, const char **, int *);
+ void backtrace();
+ int set_location(const char *, int);
+ int next_file(FILE *, const char *);
+ int is_file();
+};
+
+file_iterator::file_iterator(FILE *f, const char *fn, int po)
+: fp(f), lineno(1), filename(fn), popened(po), newline_flag(0)
+{
+ if ((font::use_charnames_in_special) && (fn != 0)) {
+ if (!the_output)
+ init_output();
+ the_output->put_filename(fn);
+ }
+}
+
+file_iterator::~file_iterator()
+{
+ close();
+}
+
+void file_iterator::close()
+{
+ if (fp == stdin)
+ clearerr(stdin);
+#ifndef POPEN_MISSING
+ else if (popened)
+ pclose(fp);
+#endif /* not POPEN_MISSING */
+ else
+ fclose(fp);
+}
+
+int file_iterator::is_file()
+{
+ return 1;
+}
+
+int file_iterator::next_file(FILE *f, const char *s)
+{
+ close();
+ filename = s;
+ fp = f;
+ lineno = 1;
+ newline_flag = 0;
+ popened = 0;
+ ptr = 0;
+ eptr = 0;
+ return 1;
+}
+
+int file_iterator::fill(node **)
+{
+ if (newline_flag)
+ lineno++;
+ newline_flag = 0;
+ unsigned char *p = buf;
+ ptr = p;
+ unsigned char *e = p + BUF_SIZE;
+ while (p < e) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ if (illegal_input_char(c))
+ warning(WARN_INPUT, "illegal input character code %1", int(c));
+ else {
+ *p++ = c;
+ if (c == '\n') {
+ newline_flag = 1;
+ break;
+ }
+ }
+ }
+ if (p > buf) {
+ eptr = p;
+ return *ptr++;
+ }
+ else {
+ eptr = p;
+ return EOF;
+ }
+}
+
+int file_iterator::peek()
+{
+ int c = getc(fp);
+ while (illegal_input_char(c)) {
+ warning(WARN_INPUT, "illegal input character code %1", int(c));
+ c = getc(fp);
+ }
+ if (c != EOF)
+ ungetc(c, fp);
+ return c;
+}
+
+int file_iterator::get_location(int /*allow_macro*/,
+ const char **filenamep, int *linenop)
+{
+ *linenop = lineno;
+ if (filename != 0 && strcmp(filename, "-") == 0)
+ *filenamep = "<standard input>";
+ else
+ *filenamep = filename;
+ return 1;
+}
+
+void file_iterator::backtrace()
+{
+ errprint("%1:%2: backtrace: %3 `%1'\n", filename, lineno,
+ popened ? "process" : "file");
+}
+
+int file_iterator::set_location(const char *f, int ln)
+{
+ if (f) {
+ filename = f;
+ if (!the_output)
+ init_output();
+ the_output->put_filename(f);
+ }
+ lineno = ln;
+ return 1;
+}
+
+input_iterator nil_iterator;
+
+class input_stack {
+public:
+ static int get(node **);
+ static int peek();
+ static void push(input_iterator *);
+ static input_iterator *get_arg(int);
+ static int nargs();
+ static int get_location(int, const char **, int *);
+ static int set_location(const char *, int);
+ static void backtrace();
+ static void backtrace_all();
+ static void next_file(FILE *, const char *);
+ static void end_file();
+ static void shift(int n);
+ static void add_boundary();
+ static void remove_boundary();
+ static int get_level();
+ static void clear();
+
+ static int limit;
+private:
+ static input_iterator *top;
+ static int level;
+
+ static int finish_get(node **);
+ static int finish_peek();
+};
+
+input_iterator *input_stack::top = &nil_iterator;
+int input_stack::level = 0;
+int input_stack::limit = DEFAULT_INPUT_STACK_LIMIT;
+
+inline int input_stack::get_level()
+{
+ return level + top->internal_level();
+}
+
+inline int input_stack::get(node **np)
+{
+ return (top->ptr < top->eptr) ? *top->ptr++ : finish_get(np);
+}
+
+int input_stack::finish_get(node **np)
+{
+ for (;;) {
+ int c = top->fill(np);
+ if (c != EOF || top->is_boundary())
+ return c;
+ if (top == &nil_iterator)
+ break;
+ input_iterator *tem = top;
+ top = top->next;
+ level--;
+ delete tem;
+ if (top->ptr < top->eptr)
+ return *top->ptr++;
+ }
+ assert(level == 0);
+ return EOF;
+}
+
+inline int input_stack::peek()
+{
+ return (top->ptr < top->eptr) ? *top->ptr : finish_peek();
+}
+
+int input_stack::finish_peek()
+{
+ for (;;) {
+ int c = top->peek();
+ if (c != EOF || top->is_boundary())
+ return c;
+ if (top == &nil_iterator)
+ break;
+ input_iterator *tem = top;
+ top = top->next;
+ level--;
+ delete tem;
+ if (top->ptr < top->eptr)
+ return *top->ptr;
+ }
+ assert(level == 0);
+ return EOF;
+}
+
+void input_stack::add_boundary()
+{
+ push(new input_boundary);
+}
+
+void input_stack::remove_boundary()
+{
+ assert(top->is_boundary());
+ input_iterator *temp = top->next;
+ delete top;
+ top = temp;
+ level--;
+}
+
+void input_stack::push(input_iterator *in)
+{
+ if (in == 0)
+ return;
+ if (++level > limit && limit > 0)
+ fatal("input stack limit exceeded (probable infinite loop)");
+ in->next = top;
+ top = in;
+}
+
+input_iterator *input_stack::get_arg(int i)
+{
+ input_iterator *p;
+ for (p = top; p != NULL; p = p->next)
+ if (p->has_args())
+ return p->get_arg(i);
+ return 0;
+}
+
+void input_stack::shift(int n)
+{
+ for (input_iterator *p = top; p; p = p->next)
+ if (p->has_args()) {
+ p->shift(n);
+ return;
+ }
+}
+
+int input_stack::nargs()
+{
+ for (input_iterator *p =top; p != 0; p = p->next)
+ if (p->has_args())
+ return p->nargs();
+ return 0;
+}
+
+int input_stack::get_location(int allow_macro, const char **filenamep, int *linenop)
+{
+ for (input_iterator *p = top; p; p = p->next)
+ if (p->get_location(allow_macro, filenamep, linenop))
+ return 1;
+ return 0;
+}
+
+void input_stack::backtrace()
+{
+ const char *f;
+ int n;
+ // only backtrace down to (not including) the topmost file
+ for (input_iterator *p = top;
+ p && !p->get_location(0, &f, &n);
+ p = p->next)
+ p->backtrace();
+}
+
+void input_stack::backtrace_all()
+{
+ for (input_iterator *p = top; p; p = p->next)
+ p->backtrace();
+}
+
+int input_stack::set_location(const char *filename, int lineno)
+{
+ for (input_iterator *p = top; p; p = p->next)
+ if (p->set_location(filename, lineno))
+ return 1;
+ return 0;
+}
+
+void input_stack::next_file(FILE *fp, const char *s)
+{
+ input_iterator **pp;
+ for (pp = &top; *pp != &nil_iterator; pp = &(*pp)->next)
+ if ((*pp)->next_file(fp, s))
+ return;
+ if (++level > limit && limit > 0)
+ fatal("input stack limit exceeded");
+ *pp = new file_iterator(fp, s);
+ (*pp)->next = &nil_iterator;
+}
+
+void input_stack::end_file()
+{
+ for (input_iterator **pp = &top; *pp != &nil_iterator; pp = &(*pp)->next)
+ if ((*pp)->is_file()) {
+ input_iterator *tem = *pp;
+ *pp = (*pp)->next;
+ delete tem;
+ level--;
+ return;
+ }
+}
+
+void input_stack::clear()
+{
+ int nboundaries = 0;
+ while (top != &nil_iterator) {
+ if (top->is_boundary())
+ nboundaries++;
+ input_iterator *tem = top;
+ top = top->next;
+ level--;
+ delete tem;
+ }
+ // Keep while_request happy.
+ for (; nboundaries > 0; --nboundaries)
+ add_boundary();
+}
+
+void backtrace_request()
+{
+ input_stack::backtrace_all();
+ fflush(stderr);
+ skip_line();
+}
+
+void next_file()
+{
+ symbol nm = get_long_name(0);
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (nm.is_null())
+ input_stack::end_file();
+ else {
+ errno = 0;
+ FILE *fp = fopen(nm.contents(), "r");
+ if (!fp)
+ error("can't open `%1': %2", nm.contents(), strerror(errno));
+ else
+ input_stack::next_file(fp, nm.contents());
+ }
+ tok.next();
+}
+
+void shift()
+{
+ int n;
+ if (!has_arg() || !get_integer(&n))
+ n = 1;
+ input_stack::shift(n);
+ skip_line();
+}
+
+static int get_char_for_escape_name()
+{
+ int c = get_copy(NULL);
+ switch (c) {
+ case EOF:
+ copy_mode_error("end of input in escape name");
+ return '\0';
+ default:
+ if (!illegal_input_char(c))
+ break;
+ // fall through
+ case '\n':
+ if (c == '\n')
+ input_stack::push(make_temp_iterator("\n"));
+ case ' ':
+ case '\t':
+ case '\001':
+ case '\b':
+ copy_mode_error("%1 is not allowed in an escape name",
+ input_char_description(c));
+ return '\0';
+ }
+ return c;
+}
+
+static symbol read_two_char_escape_name()
+{
+ char buf[3];
+ buf[0] = get_char_for_escape_name();
+ if (buf[0] != '\0') {
+ buf[1] = get_char_for_escape_name();
+ if (buf[1] == '\0')
+ buf[0] = 0;
+ else
+ buf[2] = 0;
+ }
+ return symbol(buf);
+}
+
+static symbol read_long_escape_name()
+{
+ int start_level = input_stack::get_level();
+ char abuf[ABUF_SIZE];
+ char *buf = abuf;
+ int buf_size = ABUF_SIZE;
+ int i = 0;
+ for (;;) {
+ int c = get_char_for_escape_name();
+ if (c == 0) {
+ if (buf != abuf)
+ a_delete buf;
+ return NULL_SYMBOL;
+ }
+ if (i + 2 > buf_size) {
+ if (buf == abuf) {
+ buf = new char [ABUF_SIZE*2];
+ memcpy(buf, abuf, buf_size);
+ buf_size = ABUF_SIZE*2;
+ }
+ else {
+ char *old_buf = buf;
+ buf = new char[buf_size*2];
+ memcpy(buf, old_buf, buf_size);
+ buf_size *= 2;
+ a_delete old_buf;
+ }
+ }
+ if (c == ']' && input_stack::get_level() == start_level)
+ break;
+ buf[i++] = c;
+ }
+ buf[i] = 0;
+ if (buf == abuf) {
+ if (i == 0) {
+ copy_mode_error("empty escape name");
+ return NULL_SYMBOL;
+ }
+ return symbol(abuf);
+ }
+ else {
+ symbol s(buf);
+ a_delete buf;
+ return s;
+ }
+}
+
+static symbol read_escape_name()
+{
+ int c = get_char_for_escape_name();
+ if (c == 0)
+ return NULL_SYMBOL;
+ if (c == '(')
+ return read_two_char_escape_name();
+ if (c == '[' && !compatible_flag)
+ return read_long_escape_name();
+ char buf[2];
+ buf[0] = c;
+ buf[1] = '\0';
+ return symbol(buf);
+}
+
+static symbol read_increment_and_escape_name(int *incp)
+{
+ int c = get_char_for_escape_name();
+ switch (c) {
+ case 0:
+ *incp = 0;
+ return NULL_SYMBOL;
+ case '(':
+ *incp = 0;
+ return read_two_char_escape_name();
+ case '+':
+ *incp = 1;
+ return read_escape_name();
+ case '-':
+ *incp = -1;
+ return read_escape_name();
+ case '[':
+ if (!compatible_flag) {
+ *incp = 0;
+ return read_long_escape_name();
+ }
+ break;
+ }
+ *incp = 0;
+ char buf[2];
+ buf[0] = c;
+ buf[1] = '\0';
+ return symbol(buf);
+}
+
+static int get_copy(node **nd, int defining)
+{
+ for (;;) {
+ int c = input_stack::get(nd);
+ if (c == ESCAPE_NEWLINE) {
+ if (defining)
+ return c;
+ do {
+ c = input_stack::get(nd);
+ } while (c == ESCAPE_NEWLINE);
+ }
+ if (c != escape_char || escape_char <= 0)
+ return c;
+ c = input_stack::peek();
+ switch(c) {
+ case 0:
+ return escape_char;
+ case '"':
+ (void)input_stack::get(NULL);
+ while ((c = input_stack::get(NULL)) != '\n' && c != EOF)
+ ;
+ return c;
+ case '#': // Like \" but newline is ignored.
+ (void)input_stack::get(NULL);
+ while ((c = input_stack::get(NULL)) != '\n')
+ if (c == EOF)
+ return EOF;
+ break;
+ case '$':
+ {
+ (void)input_stack::get(NULL);
+ symbol s = read_escape_name();
+ if (!s.is_null())
+ interpolate_arg(s);
+ break;
+ }
+ case '*':
+ {
+ (void)input_stack::get(NULL);
+ symbol s = read_escape_name();
+ if (!s.is_null())
+ interpolate_string(s);
+ break;
+ }
+ case 'a':
+ (void)input_stack::get(NULL);
+ return '\001';
+ case 'e':
+ (void)input_stack::get(NULL);
+ return ESCAPE_e;
+ case 'E':
+ (void)input_stack::get(NULL);
+ return ESCAPE_E;
+ case 'n':
+ {
+ (void)input_stack::get(NULL);
+ int inc;
+ symbol s = read_increment_and_escape_name(&inc);
+ if (!s.is_null())
+ interpolate_number_reg(s, inc);
+ break;
+ }
+ case 'g':
+ {
+ (void)input_stack::get(NULL);
+ symbol s = read_escape_name();
+ if (!s.is_null())
+ interpolate_number_format(s);
+ break;
+ }
+ case 't':
+ (void)input_stack::get(NULL);
+ return '\t';
+ case 'V':
+ {
+ (void)input_stack::get(NULL);
+ symbol s = read_escape_name();
+ if (!s.is_null())
+ interpolate_environment_variable(s);
+ break;
+ }
+ case '\n':
+ (void)input_stack::get(NULL);
+ if (defining)
+ return ESCAPE_NEWLINE;
+ break;
+ case ' ':
+ (void)input_stack::get(NULL);
+ return ESCAPE_SPACE;
+ case '|':
+ (void)input_stack::get(NULL);
+ return ESCAPE_BAR;
+ case '^':
+ (void)input_stack::get(NULL);
+ return ESCAPE_CIRCUMFLEX;
+ case '{':
+ (void)input_stack::get(NULL);
+ return ESCAPE_LEFT_BRACE;
+ case '}':
+ (void)input_stack::get(NULL);
+ return ESCAPE_RIGHT_BRACE;
+ case '`':
+ (void)input_stack::get(NULL);
+ return ESCAPE_LEFT_QUOTE;
+ case '\'':
+ (void)input_stack::get(NULL);
+ return ESCAPE_RIGHT_QUOTE;
+ case '-':
+ (void)input_stack::get(NULL);
+ return ESCAPE_HYPHEN;
+ case '_':
+ (void)input_stack::get(NULL);
+ return ESCAPE_UNDERSCORE;
+ case 'c':
+ (void)input_stack::get(NULL);
+ return ESCAPE_c;
+ case '!':
+ (void)input_stack::get(NULL);
+ return ESCAPE_BANG;
+ case '?':
+ (void)input_stack::get(NULL);
+ return ESCAPE_QUESTION;
+ case '&':
+ (void)input_stack::get(NULL);
+ return ESCAPE_AMPERSAND;
+ case ')':
+ (void)input_stack::get(NULL);
+ return ESCAPE_RIGHT_PARENTHESIS;
+ case '.':
+ (void)input_stack::get(NULL);
+ return c;
+ case '%':
+ (void)input_stack::get(NULL);
+ return ESCAPE_PERCENT;
+ default:
+ if (c == escape_char) {
+ (void)input_stack::get(NULL);
+ return c;
+ }
+ else
+ return escape_char;
+ }
+ }
+}
+
+class non_interpreted_char_node : public node {
+ unsigned char c;
+public:
+ non_interpreted_char_node(unsigned char);
+ node *copy();
+ int interpret(macro *);
+ int same(node *);
+ const char *type();
+};
+
+int non_interpreted_char_node::same(node *nd)
+{
+ return c == ((non_interpreted_char_node *)nd)->c;
+}
+
+const char *non_interpreted_char_node::type()
+{
+ return "non_interpreted_char_node";
+}
+
+non_interpreted_char_node::non_interpreted_char_node(unsigned char n) : c(n)
+{
+ assert(n != 0);
+}
+
+node *non_interpreted_char_node::copy()
+{
+ return new non_interpreted_char_node(c);
+}
+
+int non_interpreted_char_node::interpret(macro *mac)
+{
+ mac->append(c);
+ return 1;
+}
+
+static void do_width();
+static node *do_non_interpreted();
+static node *do_special();
+static void do_register();
+
+static node *do_overstrike()
+{
+ token start;
+ overstrike_node *on = new overstrike_node;
+ start.next();
+ tok.next();
+ while (tok != start) {
+ if (tok.newline() || tok.eof()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ break;
+ }
+ charinfo *ci = tok.get_char(1);
+ if (ci) {
+ node *n = curenv->make_char_node(ci);
+ if (n)
+ on->overstrike(n);
+ }
+ tok.next();
+ }
+ return on;
+}
+
+static node *do_bracket()
+{
+ token start;
+ bracket_node *bn = new bracket_node;
+ start.next();
+ tok.next();
+ while (tok != start) {
+ if (tok.eof()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ break;
+ }
+ if (tok.newline()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ input_stack::push(make_temp_iterator("\n"));
+ break;
+ }
+ charinfo *ci = tok.get_char(1);
+ if (ci) {
+ node *n = curenv->make_char_node(ci);
+ if (n)
+ bn->bracket(n);
+ }
+ tok.next();
+ }
+ return bn;
+}
+
+static int do_name_test()
+{
+ token start;
+ start.next();
+ int start_level = input_stack::get_level();
+ int bad_char = 0;
+ int some_char = 0;
+ for (;;) {
+ tok.next();
+ if (tok.newline() || tok.eof()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ break;
+ }
+ if (tok == start
+ && (compatible_flag || input_stack::get_level() == start_level))
+ break;
+ if (!tok.ch())
+ bad_char = 1;
+ some_char = 1;
+ }
+ return some_char && !bad_char;
+}
+
+#if 0
+static node *do_zero_width()
+{
+ token start;
+ start.next();
+ int start_level = input_stack::get_level();
+ environment env(curenv);
+ environment *oldenv = curenv;
+ curenv = &env;
+ for (;;) {
+ tok.next();
+ if (tok.newline() || tok.eof()) {
+ error("missing closing delimiter");
+ break;
+ }
+ if (tok == start
+ && (compatible_flag || input_stack::get_level() == start_level))
+ break;
+ tok.process();
+ }
+ curenv = oldenv;
+ node *rev = env.extract_output_line();
+ node *n = 0;
+ while (rev) {
+ node *tem = rev;
+ rev = rev->next;
+ tem->next = n;
+ n = tem;
+ }
+ return new zero_width_node(n);
+}
+
+#else
+
+// It's undesirable for \Z to change environments, because then
+// \n(.w won't work as expected.
+
+static node *do_zero_width()
+{
+ node *rev = new dummy_node;
+ token start;
+ start.next();
+ int start_level = input_stack::get_level();
+ for (;;) {
+ tok.next();
+ if (tok.newline() || tok.eof()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ break;
+ }
+ if (tok == start
+ && (compatible_flag || input_stack::get_level() == start_level))
+ break;
+ if (!tok.add_to_node_list(&rev))
+ error("illegal token in argument to \\Z");
+ }
+ node *n = 0;
+ while (rev) {
+ node *tem = rev;
+ rev = rev->next;
+ tem->next = n;
+ n = tem;
+ }
+ return new zero_width_node(n);
+}
+
+#endif
+
+token_node *node::get_token_node()
+{
+ return 0;
+}
+
+class token_node : public node {
+public:
+ token tk;
+ token_node(const token &t);
+ node *copy();
+ token_node *get_token_node();
+ int same(node *);
+ const char *type();
+};
+
+token_node::token_node(const token &t) : tk(t)
+{
+}
+
+node *token_node::copy()
+{
+ return new token_node(tk);
+}
+
+token_node *token_node::get_token_node()
+{
+ return this;
+}
+
+int token_node::same(node *nd)
+{
+ return tk == ((token_node *)nd)->tk;
+}
+
+const char *token_node::type()
+{
+ return "token_node";
+}
+
+token::token() : nd(0), type(TOKEN_EMPTY)
+{
+}
+
+token::~token()
+{
+ delete nd;
+}
+
+token::token(const token &t)
+: nm(t.nm), c(t.c), val(t.val), dim(t.dim), type(t.type)
+{
+ // Use two statements to work around bug in SGI C++.
+ node *tem = t.nd;
+ nd = tem ? tem->copy() : 0;
+}
+
+void token::operator=(const token &t)
+{
+ delete nd;
+ nm = t.nm;
+ // Use two statements to work around bug in SGI C++.
+ node *tem = t.nd;
+ nd = tem ? tem->copy() : 0;
+ c = t.c;
+ val = t.val;
+ dim = t.dim;
+ type = t.type;
+}
+
+void token::skip()
+{
+ while (space())
+ next();
+}
+
+int has_arg()
+{
+ while (tok.space())
+ tok.next();
+ return !tok.newline();
+}
+
+void token::make_space()
+{
+ type = TOKEN_SPACE;
+}
+
+void token::make_newline()
+{
+ type = TOKEN_NEWLINE;
+}
+
+void token::next()
+{
+ if (nd) {
+ delete nd;
+ nd = 0;
+ }
+ units x;
+ for (;;) {
+ node *n;
+ int cc = input_stack::get(&n);
+ if (cc != escape_char || escape_char == 0) {
+ handle_normal_char:
+ switch(cc) {
+ case EOF:
+ type = TOKEN_EOF;
+ return;
+ case TRANSPARENT_FILE_REQUEST:
+ case TITLE_REQUEST:
+ case COPY_FILE_REQUEST:
+#ifdef COLUMN
+ case VJUSTIFY_REQUEST:
+#endif /* COLUMN */
+ type = TOKEN_REQUEST;
+ c = cc;
+ return;
+ case BEGIN_TRAP:
+ type = TOKEN_BEGIN_TRAP;
+ return;
+ case END_TRAP:
+ type = TOKEN_END_TRAP;
+ return;
+ case LAST_PAGE_EJECTOR:
+ seen_last_page_ejector = 1;
+ // fall through
+ case PAGE_EJECTOR:
+ type = TOKEN_PAGE_EJECTOR;
+ return;
+ case ESCAPE_PERCENT:
+ ESCAPE_PERCENT:
+ type = TOKEN_HYPHEN_INDICATOR;
+ return;
+ case ESCAPE_SPACE:
+ ESCAPE_SPACE:
+ type = TOKEN_NODE;
+ nd = new space_char_hmotion_node(curenv->get_space_width());
+ return;
+ case ESCAPE_e:
+ ESCAPE_e:
+ type = TOKEN_ESCAPE;
+ return;
+ case ESCAPE_E:
+ goto handle_escape_char;
+ case ESCAPE_BAR:
+ ESCAPE_BAR:
+ type = TOKEN_NODE;
+ nd = new hmotion_node(curenv->get_narrow_space_width());
+ return;
+ case ESCAPE_CIRCUMFLEX:
+ ESCAPE_CIRCUMFLEX:
+ type = TOKEN_NODE;
+ nd = new hmotion_node(curenv->get_half_narrow_space_width());
+ return;
+ case ESCAPE_NEWLINE:
+ break;
+ case ESCAPE_LEFT_BRACE:
+ ESCAPE_LEFT_BRACE:
+ type = TOKEN_LEFT_BRACE;
+ return;
+ case ESCAPE_RIGHT_BRACE:
+ ESCAPE_RIGHT_BRACE:
+ type = TOKEN_RIGHT_BRACE;
+ return;
+ case ESCAPE_LEFT_QUOTE:
+ ESCAPE_LEFT_QUOTE:
+ type = TOKEN_SPECIAL;
+ nm = symbol("ga");
+ return;
+ case ESCAPE_RIGHT_QUOTE:
+ ESCAPE_RIGHT_QUOTE:
+ type = TOKEN_SPECIAL;
+ nm = symbol("aa");
+ return;
+ case ESCAPE_HYPHEN:
+ ESCAPE_HYPHEN:
+ type = TOKEN_SPECIAL;
+ nm = symbol("-");
+ return;
+ case ESCAPE_UNDERSCORE:
+ ESCAPE_UNDERSCORE:
+ type = TOKEN_SPECIAL;
+ nm = symbol("ul");
+ return;
+ case ESCAPE_c:
+ ESCAPE_c:
+ type = TOKEN_INTERRUPT;
+ return;
+ case ESCAPE_BANG:
+ ESCAPE_BANG:
+ type = TOKEN_TRANSPARENT;
+ return;
+ case ESCAPE_QUESTION:
+ ESCAPE_QUESTION:
+ nd = do_non_interpreted();
+ if (nd) {
+ type = TOKEN_NODE;
+ return;
+ }
+ break;
+ case ESCAPE_AMPERSAND:
+ ESCAPE_AMPERSAND:
+ type = TOKEN_DUMMY;
+ return;
+ case ESCAPE_RIGHT_PARENTHESIS:
+ ESCAPE_RIGHT_PARENTHESIS:
+ type = TOKEN_NODE;
+ nd = new transparent_dummy_node;
+ return;
+ case '\b':
+ type = TOKEN_BACKSPACE;
+ return;
+ case ' ':
+ type = TOKEN_SPACE;
+ return;
+ case '\t':
+ type = TOKEN_TAB;
+ return;
+ case '\n':
+ type = TOKEN_NEWLINE;
+ return;
+ case '\001':
+ type = TOKEN_LEADER;
+ return;
+ case 0:
+ {
+ assert(n != 0);
+ token_node *tn = n->get_token_node();
+ if (tn) {
+ *this = tn->tk;
+ delete tn;
+ }
+ else {
+ nd = n;
+ type = TOKEN_NODE;
+ }
+ }
+ return;
+ default:
+ type = TOKEN_CHAR;
+ c = cc;
+ return;
+ }
+ }
+ else {
+ handle_escape_char:
+ cc = input_stack::get(NULL);
+ switch(cc) {
+ case '(':
+ nm = read_two_char_escape_name();
+ type = TOKEN_SPECIAL;
+ return;
+ case EOF:
+ type = TOKEN_EOF;
+ error("end of input after escape character");
+ return;
+ case '`':
+ goto ESCAPE_LEFT_QUOTE;
+ case '\'':
+ goto ESCAPE_RIGHT_QUOTE;
+ case '-':
+ goto ESCAPE_HYPHEN;
+ case '_':
+ goto ESCAPE_UNDERSCORE;
+ case '%':
+ goto ESCAPE_PERCENT;
+ case ' ':
+ goto ESCAPE_SPACE;
+ case '0':
+ nd = new hmotion_node(curenv->get_digit_width());
+ type = TOKEN_NODE;
+ return;
+ case '|':
+ goto ESCAPE_BAR;
+ case '^':
+ goto ESCAPE_CIRCUMFLEX;
+ case '/':
+ type = TOKEN_ITALIC_CORRECTION;
+ return;
+ case ',':
+ type = TOKEN_NODE;
+ nd = new left_italic_corrected_node;
+ return;
+ case '&':
+ goto ESCAPE_AMPERSAND;
+ case ')':
+ goto ESCAPE_RIGHT_PARENTHESIS;
+ case '!':
+ goto ESCAPE_BANG;
+ case '?':
+ goto ESCAPE_QUESTION;
+ case '~':
+ nd = new unbreakable_space_node(curenv->get_space_width());
+ type = TOKEN_NODE;
+ return;
+ case '"':
+ while ((cc = input_stack::get(NULL)) != '\n' && cc != EOF)
+ ;
+ if (cc == '\n')
+ type = TOKEN_NEWLINE;
+ else
+ type = TOKEN_EOF;
+ return;
+ case '#': // Like \" but newline is ignored.
+ while ((cc = input_stack::get(NULL)) != '\n')
+ if (cc == EOF) {
+ type = TOKEN_EOF;
+ return;
+ }
+ break;
+ case '$':
+ {
+ symbol nm = read_escape_name();
+ if (!nm.is_null())
+ interpolate_arg(nm);
+ break;
+ }
+ case '*':
+ {
+ symbol nm = read_escape_name();
+ if (!nm.is_null())
+ interpolate_string(nm);
+ break;
+ }
+ case 'a':
+ nd = new non_interpreted_char_node('\001');
+ type = TOKEN_NODE;
+ return;
+ case 'A':
+ c = '0' + do_name_test();
+ type = TOKEN_CHAR;
+ return;
+ case 'b':
+ nd = do_bracket();
+ type = TOKEN_NODE;
+ return;
+ case 'c':
+ goto ESCAPE_c;
+ case 'C':
+ nm = get_delim_name();
+ if (nm.is_null())
+ break;
+ type = TOKEN_SPECIAL;
+ return;
+ case 'd':
+ type = TOKEN_NODE;
+ nd = new vmotion_node(curenv->get_size()/2);
+ return;
+ case 'D':
+ nd = read_draw_node();
+ if (!nd)
+ break;
+ type = TOKEN_NODE;
+ return;
+ case 'e':
+ goto ESCAPE_e;
+ case 'E':
+ goto handle_escape_char;
+ case 'f':
+ {
+ symbol s = read_escape_name();
+ if (s.is_null())
+ break;
+ const char *p;
+ for (p = s.contents(); *p != '\0'; p++)
+ if (!csdigit(*p))
+ break;
+ if (*p)
+ curenv->set_font(s);
+ else
+ curenv->set_font(atoi(s.contents()));
+ break;
+ }
+ case 'g':
+ {
+ symbol s = read_escape_name();
+ if (!s.is_null())
+ interpolate_number_format(s);
+ break;
+ }
+ case 'h':
+ if (!get_delim_number(&x, 'm'))
+ break;
+ type = TOKEN_NODE;
+ nd = new hmotion_node(x);
+ return;
+ case 'H':
+ if (get_delim_number(&x, 'z', curenv->get_requested_point_size()))
+ curenv->set_char_height(x);
+ break;
+ case 'k':
+ nm = read_escape_name();
+ if (nm.is_null())
+ break;
+ type = TOKEN_MARK_INPUT;
+ return;
+ case 'l':
+ case 'L':
+ {
+ charinfo *s = 0;
+ if (!get_line_arg(&x, (cc == 'l' ? 'm': 'v'), &s))
+ break;
+ if (s == 0)
+ s = get_charinfo(cc == 'l' ? "ru" : "br");
+ type = TOKEN_NODE;
+ node *n = curenv->make_char_node(s);
+ if (cc == 'l')
+ nd = new hline_node(x, n);
+ else
+ nd = new vline_node(x, n);
+ return;
+ }
+ case 'n':
+ {
+ int inc;
+ symbol nm = read_increment_and_escape_name(&inc);
+ if (!nm.is_null())
+ interpolate_number_reg(nm, inc);
+ break;
+ }
+ case 'N':
+ if (!get_delim_number(&val, 0))
+ break;
+ type = TOKEN_NUMBERED_CHAR;
+ return;
+ case 'o':
+ nd = do_overstrike();
+ type = TOKEN_NODE;
+ return;
+ case 'p':
+ type = TOKEN_SPREAD;
+ return;
+ case 'r':
+ type = TOKEN_NODE;
+ nd = new vmotion_node(-curenv->get_size());
+ return;
+ case 'R':
+ do_register();
+ break;
+ case 's':
+ if (read_size(&x))
+ curenv->set_size(x);
+ break;
+ case 'S':
+ if (get_delim_number(&x, 0))
+ curenv->set_char_slant(x);
+ break;
+ case 't':
+ type = TOKEN_NODE;
+ nd = new non_interpreted_char_node('\t');
+ return;
+ case 'u':
+ type = TOKEN_NODE;
+ nd = new vmotion_node(-curenv->get_size()/2);
+ return;
+ case 'v':
+ if (!get_delim_number(&x, 'v'))
+ break;
+ type = TOKEN_NODE;
+ nd = new vmotion_node(x);
+ return;
+ case 'V':
+ {
+ symbol nm = read_escape_name();
+ if (!nm.is_null())
+ interpolate_environment_variable(nm);
+ break;
+ }
+ case 'w':
+ do_width();
+ break;
+ case 'x':
+ if (!get_delim_number(&x, 'v'))
+ break;
+ type = TOKEN_NODE;
+ nd = new extra_size_node(x);
+ return;
+ case 'X':
+ nd = do_special();
+ if (!nd)
+ break;
+ type = TOKEN_NODE;
+ return;
+ case 'Y':
+ {
+ symbol s = read_escape_name();
+ if (s.is_null())
+ break;
+ request_or_macro *p = lookup_request(s);
+ macro *m = p->to_macro();
+ if (!m) {
+ error("can't transparently throughput a request");
+ break;
+ }
+ nd = new special_node(*m);
+ type = TOKEN_NODE;
+ return;
+ }
+ case 'z':
+ {
+ next();
+ if (type == TOKEN_NODE)
+ nd = new zero_width_node(nd);
+ else {
+ charinfo *ci = get_char(1);
+ if (ci == 0)
+ break;
+ node *gn = curenv->make_char_node(ci);
+ if (gn == 0)
+ break;
+ nd = new zero_width_node(gn);
+ type = TOKEN_NODE;
+ }
+ return;
+ }
+ case 'Z':
+ nd = do_zero_width();
+ if (nd == 0)
+ break;
+ type = TOKEN_NODE;
+ return;
+ case '{':
+ goto ESCAPE_LEFT_BRACE;
+ case '}':
+ goto ESCAPE_RIGHT_BRACE;
+ case '\n':
+ break;
+ case '[':
+ if (!compatible_flag) {
+ nm = read_long_escape_name();
+ if (nm.is_null())
+ break;
+ type = TOKEN_SPECIAL;
+ return;
+ }
+ goto handle_normal_char;
+ default:
+ if (cc != escape_char && cc != '.')
+ warning(WARN_ESCAPE, "escape character ignored before %1",
+ input_char_description(cc));
+ goto handle_normal_char;
+ }
+ }
+ }
+}
+
+int token::operator==(const token &t)
+{
+ if (type != t.type)
+ return 0;
+ switch(type) {
+ case TOKEN_CHAR:
+ return c == t.c;
+ case TOKEN_SPECIAL:
+ return nm == t.nm;
+ case TOKEN_NUMBERED_CHAR:
+ return val == t.val;
+ default:
+ return 1;
+ }
+}
+
+int token::operator!=(const token &t)
+{
+ return !(*this == t);
+}
+
+// is token a suitable delimiter (like ')?
+
+int token::delimiter(int err)
+{
+ switch(type) {
+ case TOKEN_CHAR:
+ switch(c) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '+':
+ case '-':
+ case '/':
+ case '*':
+ case '%':
+ case '<':
+ case '>':
+ case '=':
+ case '&':
+ case ':':
+ case '(':
+ case ')':
+ case '.':
+ if (err)
+ error("cannot use character `%1' as a starting delimiter", char(c));
+ return 0;
+ default:
+ return 1;
+ }
+ case TOKEN_NODE:
+ case TOKEN_SPACE:
+ case TOKEN_TAB:
+ case TOKEN_NEWLINE:
+ if (err)
+ error("cannot use %1 as a starting delimiter", description());
+ return 0;
+ default:
+ return 1;
+ }
+}
+
+const char *token::description()
+{
+ static char buf[4];
+ switch (type) {
+ case TOKEN_BACKSPACE:
+ return "a backspace character";
+ case TOKEN_CHAR:
+ buf[0] = '`';
+ buf[1] = c;
+ buf[2] = '\'';
+ buf[3] = '\0';
+ return buf;
+ case TOKEN_DUMMY:
+ return "`\\&'";
+ case TOKEN_ESCAPE:
+ return "`\\e'";
+ case TOKEN_HYPHEN_INDICATOR:
+ return "`\\%'";
+ case TOKEN_INTERRUPT:
+ return "`\\c'";
+ case TOKEN_ITALIC_CORRECTION:
+ return "`\\/'";
+ case TOKEN_LEADER:
+ return "a leader character";
+ case TOKEN_LEFT_BRACE:
+ return "`\\{'";
+ case TOKEN_MARK_INPUT:
+ return "`\\k'";
+ case TOKEN_NEWLINE:
+ return "newline";
+ case TOKEN_NODE:
+ return "a node";
+ case TOKEN_NUMBERED_CHAR:
+ return "`\\N'";
+ case TOKEN_RIGHT_BRACE:
+ return "`\\}'";
+ case TOKEN_SPACE:
+ return "a space";
+ case TOKEN_SPECIAL:
+ return "a special character";
+ case TOKEN_SPREAD:
+ return "`\\p'";
+ case TOKEN_TAB:
+ return "a tab character";
+ case TOKEN_TRANSPARENT:
+ return "`\\!'";
+ case TOKEN_EOF:
+ return "end of input";
+ default:
+ break;
+ }
+ return "a magic token";
+}
+
+void skip_line()
+{
+ while (!tok.newline())
+ if (tok.eof())
+ return;
+ else
+ tok.next();
+ tok.next();
+}
+
+void compatible()
+{
+ int n;
+ if (has_arg() && get_integer(&n))
+ compatible_flag = n != 0;
+ else
+ compatible_flag = 1;
+ skip_line();
+}
+
+static void empty_name_warning(int required)
+{
+ if (tok.newline() || tok.eof()) {
+ if (required)
+ warning(WARN_MISSING, "missing name");
+ }
+ else if (tok.right_brace() || tok.tab()) {
+ const char *start = tok.description();
+ do {
+ tok.next();
+ } while (tok.space() || tok.right_brace() || tok.tab());
+ if (!tok.newline() && !tok.eof())
+ error("%1 is not allowed before an argument", start);
+ else if (required)
+ warning(WARN_MISSING, "missing name");
+ }
+ else if (required)
+ error("name expected (got %1)", tok.description());
+ else
+ error("name expected (got %1): treated as missing", tok.description());
+}
+
+static void non_empty_name_warning()
+{
+ if (!tok.newline() && !tok.eof() && !tok.space() && !tok.tab()
+ && !tok.right_brace()
+ // We don't want to give a warning for .el\{
+ && !tok.left_brace())
+ error("%1 is not allowed in a name", tok.description());
+}
+
+symbol get_name(int required)
+{
+ if (compatible_flag) {
+ char buf[3];
+ tok.skip();
+ if ((buf[0] = tok.ch()) != 0) {
+ tok.next();
+ if ((buf[1] = tok.ch()) != 0) {
+ buf[2] = 0;
+ tok.make_space();
+ }
+ else
+ non_empty_name_warning();
+ return symbol(buf);
+ }
+ else {
+ empty_name_warning(required);
+ return NULL_SYMBOL;
+ }
+ }
+ else
+ return get_long_name(required);
+}
+
+symbol get_long_name(int required)
+{
+ while (tok.space())
+ tok.next();
+ char abuf[ABUF_SIZE];
+ char *buf = abuf;
+ int buf_size = ABUF_SIZE;
+ int i = 0;
+ for (;;) {
+ if (i + 1 > buf_size) {
+ if (buf == abuf) {
+ buf = new char [ABUF_SIZE*2];
+ memcpy(buf, abuf, buf_size);
+ buf_size = ABUF_SIZE*2;
+ }
+ else {
+ char *old_buf = buf;
+ buf = new char[buf_size*2];
+ memcpy(buf, old_buf, buf_size);
+ buf_size *= 2;
+ a_delete old_buf;
+ }
+ }
+ if ((buf[i] = tok.ch()) == 0)
+ break;
+ i++;
+ tok.next();
+ }
+ if (i == 0) {
+ empty_name_warning(required);
+ return NULL_SYMBOL;
+ }
+ non_empty_name_warning();
+ if (buf == abuf)
+ return symbol(buf);
+ else {
+ symbol s(buf);
+ a_delete buf;
+ return s;
+ }
+}
+
+void exit_troff()
+{
+ exit_started = 1;
+ topdiv->set_last_page();
+ if (!end_macro_name.is_null()) {
+ spring_trap(end_macro_name);
+ tok.next();
+ process_input_stack();
+ }
+ curenv->final_break();
+ tok.next();
+ process_input_stack();
+ end_diversions();
+ done_end_macro = 1;
+ topdiv->set_ejecting();
+ static unsigned char buf[2] = { LAST_PAGE_EJECTOR, '\0' };
+ input_stack::push(make_temp_iterator((char *)buf));
+ topdiv->space(topdiv->get_page_length(), 1);
+ tok.next();
+ process_input_stack();
+ seen_last_page_ejector = 1; // should be set already
+ topdiv->set_ejecting();
+ push_page_ejector();
+ topdiv->space(topdiv->get_page_length(), 1);
+ tok.next();
+ process_input_stack();
+ // This will only happen if a trap-invoked macro starts a diversion,
+ // or if vertical position traps have been disabled.
+ cleanup_and_exit(0);
+}
+
+// This implements .ex. The input stack must be cleared before calling
+// exit_troff().
+
+void exit_request()
+{
+ input_stack::clear();
+ if (exit_started)
+ tok.next();
+ else
+ exit_troff();
+}
+
+void end_macro()
+{
+ end_macro_name = get_name();
+ skip_line();
+}
+
+void blank_line_macro()
+{
+ blank_line_macro_name = get_name();
+ skip_line();
+}
+
+static void trapping_blank_line()
+{
+ if (!blank_line_macro_name.is_null())
+ spring_trap(blank_line_macro_name);
+ else
+ blank_line();
+}
+
+void do_request()
+{
+ int saved_compatible_flag = compatible_flag;
+ compatible_flag = 0;
+ symbol nm = get_name();
+ if (nm.is_null())
+ skip_line();
+ else
+ interpolate_macro(nm);
+ compatible_flag = saved_compatible_flag;
+}
+
+inline int possibly_handle_first_page_transition()
+{
+ if (topdiv->before_first_page && curdiv == topdiv && !curenv->is_dummy()) {
+ handle_first_page_transition();
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static int transparent_translate(int cc)
+{
+ if (!illegal_input_char(cc)) {
+ charinfo *ci = charset_table[cc];
+ switch (ci->get_special_translation(1)) {
+ case charinfo::TRANSLATE_SPACE:
+ return ' ';
+ case charinfo::TRANSLATE_DUMMY:
+ return ESCAPE_AMPERSAND;
+ case charinfo::TRANSLATE_HYPHEN_INDICATOR:
+ return ESCAPE_PERCENT;
+ }
+ // This is really ugly.
+ ci = ci->get_translation(1);
+ if (ci) {
+ int c = ci->get_ascii_code();
+ if (c != '\0')
+ return c;
+ error("can't translate %1 to special character `%2'"
+ " in transparent throughput",
+ input_char_description(cc),
+ ci->nm.contents());
+ }
+ }
+ return cc;
+}
+
+class int_stack {
+ struct int_stack_element {
+ int n;
+ int_stack_element *next;
+ } *top;
+public:
+ int_stack();
+ ~int_stack();
+ void push(int);
+ int is_empty();
+ int pop();
+};
+
+int_stack::int_stack()
+{
+ top = 0;
+}
+
+int_stack::~int_stack()
+{
+ while (top != 0) {
+ int_stack_element *temp = top;
+ top = top->next;
+ delete temp;
+ }
+
+}
+
+int int_stack::is_empty()
+{
+ return top == 0;
+}
+
+void int_stack::push(int n)
+{
+ int_stack_element *p = new int_stack_element;
+ p->next = top;
+ p->n = n;
+ top = p;
+}
+
+
+int int_stack::pop()
+{
+ assert(top != 0);
+ int_stack_element *p = top;
+ top = top->next;
+ int n = p->n;
+ delete p;
+ return n;
+}
+
+int node::reread(int *)
+{
+ return 0;
+}
+
+int diverted_space_node::reread(int *bolp)
+{
+ if (curenv->get_fill())
+ trapping_blank_line();
+ else
+ curdiv->space(n);
+ *bolp = 1;
+ return 1;
+}
+
+int diverted_copy_file_node::reread(int *bolp)
+{
+ curdiv->copy_file(filename.contents());
+ *bolp = 1;
+ return 1;
+}
+
+void process_input_stack()
+{
+ int_stack trap_bol_stack;
+ int bol = 1;
+ for (;;) {
+ int suppress_next = 0;
+ switch (tok.type) {
+ case token::TOKEN_CHAR:
+ {
+ unsigned char ch = tok.c;
+ if (bol &&
+ (ch == curenv->control_char
+ || ch == curenv->no_break_control_char)) {
+ break_flag = ch == curenv->control_char;
+ // skip tabs as well as spaces here
+ do {
+ tok.next();
+ } while (tok.white_space());
+ symbol nm = get_name();
+ if (nm.is_null())
+ skip_line();
+ else
+ interpolate_macro(nm);
+ suppress_next = 1;
+ }
+ else {
+ if (possibly_handle_first_page_transition())
+ ;
+ else {
+ for (;;) {
+ curenv->add_char(charset_table[ch]);
+ tok.next();
+ if (tok.type != token::TOKEN_CHAR)
+ break;
+ ch = tok.c;
+ }
+ suppress_next = 1;
+ bol = 0;
+ }
+ }
+ break;
+ }
+ case token::TOKEN_TRANSPARENT:
+ {
+ if (bol) {
+ if (possibly_handle_first_page_transition())
+ ;
+ else {
+ int cc;
+ do {
+ node *n;
+ cc = get_copy(&n);
+ if (cc != EOF)
+ if (cc != '\0')
+ curdiv->transparent_output(transparent_translate(cc));
+ else
+ curdiv->transparent_output(n);
+ } while (cc != '\n' && cc != EOF);
+ if (cc == EOF)
+ curdiv->transparent_output('\n');
+ }
+ }
+ break;
+ }
+ case token::TOKEN_NEWLINE:
+ {
+ if (bol && !curenv->get_prev_line_interrupted())
+ trapping_blank_line();
+ else {
+ curenv->newline();
+ bol = 1;
+ }
+ break;
+ }
+ case token::TOKEN_REQUEST:
+ {
+ int request_code = tok.c;
+ tok.next();
+ switch (request_code) {
+ case TITLE_REQUEST:
+ title();
+ break;
+ case COPY_FILE_REQUEST:
+ copy_file();
+ break;
+ case TRANSPARENT_FILE_REQUEST:
+ transparent_file();
+ break;
+#ifdef COLUMN
+ case VJUSTIFY_REQUEST:
+ vjustify();
+ break;
+#endif /* COLUMN */
+ default:
+ assert(0);
+ break;
+ }
+ suppress_next = 1;
+ break;
+ }
+ case token::TOKEN_SPACE:
+ {
+ if (possibly_handle_first_page_transition())
+ ;
+ else if (bol && !curenv->get_prev_line_interrupted()) {
+ int nspaces = 0;
+ do {
+ nspaces += tok.nspaces();
+ tok.next();
+ } while (tok.space());
+ if (tok.newline())
+ trapping_blank_line();
+ else {
+ push_token(tok);
+ curenv->do_break();
+ curenv->add_node(new hmotion_node(curenv->get_space_width()*nspaces));
+ bol = 0;
+ }
+ }
+ else {
+ curenv->space();
+ bol = 0;
+ }
+ break;
+ }
+ case token::TOKEN_EOF:
+ return;
+ case token::TOKEN_NODE:
+ {
+ if (possibly_handle_first_page_transition())
+ ;
+ else if (tok.nd->reread(&bol)) {
+ delete tok.nd;
+ tok.nd = 0;
+ }
+ else {
+ curenv->add_node(tok.nd);
+ tok.nd = 0;
+ bol = 0;
+ }
+ break;
+ }
+ case token::TOKEN_PAGE_EJECTOR:
+ {
+ continue_page_eject();
+ // I think we just want to preserve bol.
+ // bol = 1;
+ break;
+ }
+ case token::TOKEN_BEGIN_TRAP:
+ {
+ trap_bol_stack.push(bol);
+ bol = 1;
+ break;
+ }
+ case token::TOKEN_END_TRAP:
+ {
+ if (trap_bol_stack.is_empty())
+ error("spurious end trap token detected!");
+ else
+ bol = trap_bol_stack.pop();
+
+ /* I'm not totally happy about this. But I can't think of any other
+ way to do it. Doing an output_pending_lines() whenever a
+ TOKEN_END_TRAP is detected doesn't work: for example,
+
+ .wh -1i x
+ .de x
+ 'bp
+ ..
+ .wh -.5i y
+ .de y
+ .tl ''-%-''
+ ..
+ .br
+ .ll .5i
+ .sp |\n(.pu-1i-.5v
+ a\%very\%very\%long\%word
+
+ will print all but the first lines from the word immediately
+ after the footer, rather than on the next page. */
+
+ if (trap_bol_stack.is_empty())
+ curenv->output_pending_lines();
+ break;
+ }
+ default:
+ {
+ bol = 0;
+ tok.process();
+ break;
+ }
+ }
+ if (!suppress_next)
+ tok.next();
+ trap_sprung_flag = 0;
+ }
+}
+
+#ifdef WIDOW_CONTROL
+
+void flush_pending_lines()
+{
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ curenv->output_pending_lines();
+ tok.next();
+}
+
+#endif /* WIDOW_CONTROL */
+
+request_or_macro::request_or_macro()
+{
+}
+
+macro *request_or_macro::to_macro()
+{
+ return 0;
+}
+
+request::request(REQUEST_FUNCP pp) : p(pp)
+{
+}
+
+void request::invoke(symbol)
+{
+ (*p)();
+}
+
+struct char_block {
+ enum { SIZE = 128 };
+ unsigned char s[SIZE];
+ char_block *next;
+ char_block();
+};
+
+char_block::char_block()
+: next(0)
+{
+}
+
+class char_list {
+public:
+ char_list();
+ ~char_list();
+ void append(unsigned char);
+ int length();
+private:
+ unsigned char *ptr;
+ int len;
+ char_block *head;
+ char_block *tail;
+ friend class macro_header;
+ friend class string_iterator;
+};
+
+char_list::char_list()
+: ptr(0), len(0), head(0), tail(0)
+{
+}
+
+char_list::~char_list()
+{
+ while (head != 0) {
+ char_block *tem = head;
+ head = head->next;
+ delete tem;
+ }
+}
+
+int char_list::length()
+{
+ return len;
+}
+
+void char_list::append(unsigned char c)
+{
+ if (tail == 0) {
+ head = tail = new char_block;
+ ptr = tail->s;
+ }
+ else {
+ if (ptr >= tail->s + char_block::SIZE) {
+ tail->next = new char_block;
+ tail = tail->next;
+ ptr = tail->s;
+ }
+ }
+ *ptr++ = c;
+ len++;
+}
+
+class node_list {
+ node *head;
+ node *tail;
+public:
+ node_list();
+ ~node_list();
+ void append(node *);
+ int length();
+ node *extract();
+
+ friend class macro_header;
+ friend class string_iterator;
+};
+
+void node_list::append(node *n)
+{
+ if (head == 0) {
+ n->next = 0;
+ head = tail = n;
+ }
+ else {
+ n->next = 0;
+ tail = tail->next = n;
+ }
+}
+
+int node_list::length()
+{
+ int total = 0;
+ for (node *n = head; n != 0; n = n->next)
+ ++total;
+ return total;
+}
+
+node_list::node_list()
+{
+ head = tail = 0;
+}
+
+node *node_list::extract()
+{
+ node *temp = head;
+ head = tail = 0;
+ return temp;
+}
+
+
+node_list::~node_list()
+{
+ delete_node_list(head);
+}
+
+struct macro_header {
+ int count;
+ char_list cl;
+ node_list nl;
+ macro_header() { count = 1; }
+ macro_header *copy(int);
+};
+
+
+macro::~macro()
+{
+ if (p != 0 && --(p->count) <= 0)
+ delete p;
+}
+
+macro::macro()
+{
+ if (!input_stack::get_location(1, &filename, &lineno)) {
+ filename = 0;
+ lineno = 0;
+ }
+ length = 0;
+ p = 0;
+}
+
+macro::macro(const macro &m)
+: p(m.p), filename(m.filename), lineno(m.lineno), length(m.length)
+{
+ if (p != 0)
+ p->count++;
+}
+
+macro &macro::operator=(const macro &m)
+{
+ // don't assign object
+ if (m.p != 0)
+ m.p->count++;
+ if (p != 0 && --(p->count) <= 0)
+ delete p;
+ p = m.p;
+ filename = m.filename;
+ lineno = m.lineno;
+ length = m.length;
+ return *this;
+}
+
+void macro::append(unsigned char c)
+{
+ assert(c != 0);
+ if (p == 0)
+ p = new macro_header;
+ if (p->cl.length() != length) {
+ macro_header *tem = p->copy(length);
+ if (--(p->count) <= 0)
+ delete p;
+ p = tem;
+ }
+ p->cl.append(c);
+ ++length;
+}
+
+void macro::append(node *n)
+{
+ assert(n != 0);
+ if (p == 0)
+ p = new macro_header;
+ if (p->cl.length() != length) {
+ macro_header *tem = p->copy(length);
+ if (--(p->count) <= 0)
+ delete p;
+ p = tem;
+ }
+ p->cl.append(0);
+ p->nl.append(n);
+ ++length;
+}
+
+void macro::print_size()
+{
+ errprint("%1", length);
+}
+
+// make a copy of the first n bytes
+
+macro_header *macro_header::copy(int n)
+{
+ macro_header *p = new macro_header;
+ char_block *bp = cl.head;
+ unsigned char *ptr = bp->s;
+ node *nd = nl.head;
+ while (--n >= 0) {
+ if (ptr >= bp->s + char_block::SIZE) {
+ bp = bp->next;
+ ptr = bp->s;
+ }
+ int c = *ptr++;
+ p->cl.append(c);
+ if (c == 0) {
+ p->nl.append(nd->copy());
+ nd = nd->next;
+ }
+ }
+ return p;
+}
+
+void print_macros()
+{
+ object_dictionary_iterator iter(request_dictionary);
+ request_or_macro *rm;
+ symbol s;
+ while (iter.get(&s, (object **)&rm)) {
+ assert(!s.is_null());
+ macro *m = rm->to_macro();
+ if (m) {
+ errprint("%1\t", s.contents());
+ m->print_size();
+ errprint("\n");
+ }
+ }
+ fflush(stderr);
+ skip_line();
+}
+
+class string_iterator : public input_iterator {
+ macro mac;
+ const char *how_invoked;
+ int newline_flag;
+ int lineno;
+ char_block *bp;
+ int count; // of characters remaining
+ node *nd;
+protected:
+ symbol nm;
+ string_iterator();
+public:
+ string_iterator(const macro &m, const char *p = 0, symbol s = NULL_SYMBOL);
+ int fill(node **);
+ int peek();
+ int get_location(int, const char **, int *);
+ void backtrace();
+};
+
+string_iterator::string_iterator(const macro &m, const char *p, symbol s)
+: mac(m), how_invoked(p), newline_flag(0), lineno(1), nm(s)
+{
+ count = mac.length;
+ if (count != 0) {
+ bp = mac.p->cl.head;
+ nd = mac.p->nl.head;
+ ptr = eptr = bp->s;
+ }
+ else {
+ bp = 0;
+ nd = 0;
+ ptr = eptr = 0;
+ }
+}
+
+string_iterator::string_iterator()
+{
+ bp = 0;
+ nd = 0;
+ ptr = eptr = 0;
+ newline_flag = 0;
+ how_invoked = 0;
+ lineno = 1;
+ count = 0;
+}
+
+int string_iterator::fill(node **np)
+{
+ if (newline_flag)
+ lineno++;
+ newline_flag = 0;
+ if (count <= 0)
+ return EOF;
+ const unsigned char *p = eptr;
+ if (p >= bp->s + char_block::SIZE) {
+ bp = bp->next;
+ p = bp->s;
+ }
+ if (*p == '\0') {
+ if (np)
+ *np = nd->copy();
+ nd = nd->next;
+ eptr = ptr = p + 1;
+ count--;
+ return 0;
+ }
+ const unsigned char *e = bp->s + char_block::SIZE;
+ if (e - p > count)
+ e = p + count;
+ ptr = p;
+ while (p < e) {
+ unsigned char c = *p;
+ if (c == '\n' || c == ESCAPE_NEWLINE) {
+ newline_flag = 1;
+ p++;
+ break;
+ }
+ if (c == '\0')
+ break;
+ p++;
+ }
+ eptr = p;
+ count -= p - ptr;
+ return *ptr++;
+}
+
+int string_iterator::peek()
+{
+ if (count <= 0)
+ return EOF;
+ const unsigned char *p = eptr;
+ if (count <= 0)
+ return EOF;
+ if (p >= bp->s + char_block::SIZE) {
+ p = bp->next->s;
+ }
+ return *p;
+}
+
+int string_iterator::get_location(int allow_macro,
+ const char **filep, int *linep)
+{
+ if (!allow_macro)
+ return 0;
+ if (mac.filename == 0)
+ return 0;
+ *filep = mac.filename;
+ *linep = mac.lineno + lineno - 1;
+ return 1;
+}
+
+void string_iterator::backtrace()
+{
+ if (mac.filename) {
+ errprint("%1:%2: backtrace", mac.filename, mac.lineno + lineno - 1);
+ if (how_invoked) {
+ if (!nm.is_null())
+ errprint(": %1 `%2'\n", how_invoked, nm.contents());
+ else
+ errprint(": %1\n", how_invoked);
+ }
+ else
+ errprint("\n");
+ }
+}
+
+class temp_iterator : public input_iterator {
+ unsigned char *base;
+ temp_iterator(const char *, int len);
+public:
+ ~temp_iterator();
+ friend input_iterator *make_temp_iterator(const char *);
+};
+
+#ifdef __GNUG__
+inline
+#endif
+temp_iterator::temp_iterator(const char *s, int len)
+{
+ base = new unsigned char[len];
+ memcpy(base, s, len);
+ ptr = base;
+ eptr = base + len;
+}
+
+temp_iterator::~temp_iterator()
+{
+ a_delete base;
+}
+
+class small_temp_iterator : public input_iterator {
+private:
+ small_temp_iterator(const char *, int);
+ ~small_temp_iterator();
+ enum { BLOCK = 16 };
+ static small_temp_iterator *free_list;
+ void *operator new(size_t);
+ void operator delete(void *);
+ enum { SIZE = 12 };
+ unsigned char buf[SIZE];
+ friend input_iterator *make_temp_iterator(const char *);
+};
+
+small_temp_iterator *small_temp_iterator::free_list = 0;
+
+void *small_temp_iterator::operator new(size_t n)
+{
+ assert(n == sizeof(small_temp_iterator));
+ if (!free_list) {
+ free_list = (small_temp_iterator *)new char[sizeof(small_temp_iterator)*BLOCK];
+ for (int i = 0; i < BLOCK - 1; i++)
+ free_list[i].next = free_list + i + 1;
+ free_list[BLOCK-1].next = 0;
+ }
+ small_temp_iterator *p = free_list;
+ free_list = (small_temp_iterator *)(free_list->next);
+ p->next = 0;
+ return p;
+}
+
+#ifdef __GNUG__
+inline
+#endif
+void small_temp_iterator::operator delete(void *p)
+{
+ if (p) {
+ ((small_temp_iterator *)p)->next = free_list;
+ free_list = (small_temp_iterator *)p;
+ }
+}
+
+small_temp_iterator::~small_temp_iterator()
+{
+}
+
+
+#ifdef __GNUG__
+inline
+#endif
+small_temp_iterator::small_temp_iterator(const char *s, int len)
+{
+ for (int i = 0; i < len; i++)
+ buf[i] = s[i];
+ ptr = buf;
+ eptr = buf + len;
+}
+
+input_iterator *make_temp_iterator(const char *s)
+{
+ if (s == 0)
+ return new small_temp_iterator(s, 0);
+ else {
+ int n = strlen(s);
+ if (n <= small_temp_iterator::SIZE)
+ return new small_temp_iterator(s, n);
+ else
+ return new temp_iterator(s, n);
+ }
+}
+
+// this is used when macros are interpolated using the .macro_name notation
+
+struct arg_list {
+ macro mac;
+ arg_list *next;
+ arg_list(const macro &);
+ ~arg_list();
+};
+
+arg_list::arg_list(const macro &m) : mac(m), next(0)
+{
+}
+
+arg_list::~arg_list()
+{
+}
+
+class macro_iterator : public string_iterator {
+ arg_list *args;
+ int argc;
+public:
+ macro_iterator(symbol, macro &, const char *how_invoked = "macro");
+ macro_iterator();
+ ~macro_iterator();
+ int has_args() { return 1; }
+ input_iterator *get_arg(int i);
+ int nargs() { return argc; }
+ void add_arg(const macro &m);
+ void shift(int n);
+};
+
+input_iterator *macro_iterator::get_arg(int i)
+{
+ if (i == 0)
+ return make_temp_iterator(nm.contents());
+ if (i > 0 && i <= argc) {
+ arg_list *p = args;
+ for (int j = 1; j < i; j++) {
+ assert(p != 0);
+ p = p->next;
+ }
+ return new string_iterator(p->mac);
+ }
+ else
+ return 0;
+}
+
+void macro_iterator::add_arg(const macro &m)
+{
+ arg_list **p;
+ for (p = &args; *p; p = &((*p)->next))
+ ;
+ *p = new arg_list(m);
+ ++argc;
+}
+
+void macro_iterator::shift(int n)
+{
+ while (n > 0 && argc > 0) {
+ arg_list *tem = args;
+ args = args->next;
+ delete tem;
+ --argc;
+ --n;
+ }
+}
+
+// This gets used by eg .if '\?xxx\?''.
+
+int operator==(const macro &m1, const macro &m2)
+{
+ if (m1.length != m2.length)
+ return 0;
+ string_iterator iter1(m1);
+ string_iterator iter2(m2);
+ int n = m1.length;
+ while (--n >= 0) {
+ node *nd1 = 0;
+ int c1 = iter1.get(&nd1);
+ assert(c1 != EOF);
+ node *nd2 = 0;
+ int c2 = iter2.get(&nd2);
+ assert(c2 != EOF);
+ if (c1 != c2) {
+ if (c1 == 0)
+ delete nd1;
+ else if (c2 == 0)
+ delete nd2;
+ return 0;
+ }
+ if (c1 == 0) {
+ assert(nd1 != 0);
+ assert(nd2 != 0);
+ int are_same = nd1->type() == nd2->type() && nd1->same(nd2);
+ delete nd1;
+ delete nd2;
+ if (!are_same)
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void interpolate_macro(symbol nm)
+{
+ request_or_macro *p = (request_or_macro *)request_dictionary.lookup(nm);
+ if (p == 0) {
+ int warned = 0;
+ const char *s = nm.contents();
+ if (strlen(s) > 2) {
+ request_or_macro *r;
+ char buf[3];
+ buf[0] = s[0];
+ buf[1] = s[1];
+ buf[2] = '\0';
+ r = (request_or_macro *)request_dictionary.lookup(symbol(buf));
+ if (r) {
+ macro *m = r->to_macro();
+ if (!m || !m->empty())
+ warned = warning(WARN_SPACE,
+ "`%1' not defined (probable missing space after `%2')",
+ nm.contents(), buf);
+ }
+ }
+ if (!warned) {
+ warning(WARN_MAC, "`%1' not defined", nm.contents());
+ p = new macro;
+ request_dictionary.define(nm, p);
+ }
+ }
+ if (p)
+ p->invoke(nm);
+ else {
+ skip_line();
+ return;
+ }
+}
+
+static void decode_args(macro_iterator *mi)
+{
+ if (!tok.newline() && !tok.eof()) {
+ node *n;
+ int c = get_copy(&n);
+ for (;;) {
+ while (c == ' ')
+ c = get_copy(&n);
+ if (c == '\n' || c == EOF)
+ break;
+ macro arg;
+ int quote_input_level = 0;
+ int done_tab_warning = 0;
+ if (c == '\"') {
+ quote_input_level = input_stack::get_level();
+ c = get_copy(&n);
+ }
+ while (c != EOF && c != '\n' && !(c == ' ' && quote_input_level == 0)) {
+ if (quote_input_level > 0 && c == '\"'
+ && (compatible_flag
+ || input_stack::get_level() == quote_input_level)) {
+ c = get_copy(&n);
+ if (c == '"') {
+ arg.append(c);
+ c = get_copy(&n);
+ }
+ else
+ break;
+ }
+ else {
+ if (c == 0)
+ arg.append(n);
+ else {
+ if (c == '\t' && quote_input_level == 0 && !done_tab_warning) {
+ warning(WARN_TAB, "tab character in unquoted macro argument");
+ done_tab_warning = 1;
+ }
+ arg.append(c);
+ }
+ c = get_copy(&n);
+ }
+ }
+ mi->add_arg(arg);
+ }
+ }
+}
+
+void macro::invoke(symbol nm)
+{
+ macro_iterator *mi = new macro_iterator(nm, *this);
+ decode_args(mi);
+ input_stack::push(mi);
+ tok.next();
+}
+
+macro *macro::to_macro()
+{
+ return this;
+}
+
+int macro::empty()
+{
+ return length == 0;
+}
+
+macro_iterator::macro_iterator(symbol s, macro &m, const char *how_invoked)
+: string_iterator(m, how_invoked, s), args(0), argc(0)
+{
+}
+
+macro_iterator::macro_iterator() : args(0), argc(0)
+{
+}
+
+macro_iterator::~macro_iterator()
+{
+ while (args != 0) {
+ arg_list *tem = args;
+ args = args->next;
+ delete tem;
+ }
+}
+
+int trap_sprung_flag = 0;
+int postpone_traps_flag = 0;
+symbol postponed_trap;
+
+void spring_trap(symbol nm)
+{
+ assert(!nm.is_null());
+ trap_sprung_flag = 1;
+ if (postpone_traps_flag) {
+ postponed_trap = nm;
+ return;
+ }
+ static char buf[2] = { BEGIN_TRAP, 0 };
+ static char buf2[2] = { END_TRAP, '\0' };
+ input_stack::push(make_temp_iterator(buf2));
+ request_or_macro *p = lookup_request(nm);
+ macro *m = p->to_macro();
+ if (m)
+ input_stack::push(new macro_iterator(nm, *m, "trap-invoked macro"));
+ else
+ error("you can't invoke a request with a trap");
+ input_stack::push(make_temp_iterator(buf));
+}
+
+void postpone_traps()
+{
+ postpone_traps_flag = 1;
+}
+
+int unpostpone_traps()
+{
+ postpone_traps_flag = 0;
+ if (!postponed_trap.is_null()) {
+ spring_trap(postponed_trap);
+ postponed_trap = NULL_SYMBOL;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+void read_request()
+{
+ macro_iterator *mi = new macro_iterator;
+ int reading_from_terminal = isatty(fileno(stdin));
+ int had_prompt = 0;
+ if (!tok.newline() && !tok.eof()) {
+ int c = get_copy(NULL);
+ while (c == ' ')
+ c = get_copy(NULL);
+ while (c != EOF && c != '\n' && c != ' ') {
+ if (!illegal_input_char(c)) {
+ if (reading_from_terminal)
+ fputc(c, stderr);
+ had_prompt = 1;
+ }
+ c = get_copy(NULL);
+ }
+ if (c == ' ') {
+ tok.make_space();
+ decode_args(mi);
+ }
+ }
+ if (reading_from_terminal) {
+ fputc(had_prompt ? ':' : '\007', stderr);
+ fflush(stderr);
+ }
+ input_stack::push(mi);
+ macro mac;
+ int nl = 0;
+ int c;
+ while ((c = getchar()) != EOF) {
+ if (illegal_input_char(c))
+ warning(WARN_INPUT, "illegal input character code %1", int(c));
+ else {
+ if (c == '\n') {
+ if (nl)
+ break;
+ else
+ nl = 1;
+ }
+ else
+ nl = 0;
+ mac.append(c);
+ }
+ }
+ if (reading_from_terminal)
+ clearerr(stdin);
+ input_stack::push(new string_iterator(mac));
+ tok.next();
+}
+
+void do_define_string(int append)
+{
+ symbol nm;
+ node *n;
+ int c;
+ nm = get_name(1);
+ if (nm.is_null()) {
+ skip_line();
+ return;
+ }
+ if (tok.newline())
+ c = '\n';
+ else if (tok.tab())
+ c = '\t';
+ else if (!tok.space()) {
+ error("bad string definition");
+ skip_line();
+ return;
+ }
+ else
+ c = get_copy(&n);
+ while (c == ' ')
+ c = get_copy(&n);
+ if (c == '"')
+ c = get_copy(&n);
+ macro mac;
+ request_or_macro *rm = (request_or_macro *)request_dictionary.lookup(nm);
+ macro *mm = rm ? rm->to_macro() : 0;
+ if (append && mm)
+ mac = *mm;
+ while (c != '\n' && c != EOF) {
+ if (c == 0)
+ mac.append(n);
+ else
+ mac.append((unsigned char)c);
+ c = get_copy(&n);
+ }
+ if (!mm) {
+ mm = new macro;
+ request_dictionary.define(nm, mm);
+ }
+ *mm = mac;
+ tok.next();
+}
+
+void define_string()
+{
+ do_define_string(0);
+}
+
+void append_string()
+{
+ do_define_string(1);
+}
+
+void define_character()
+{
+ node *n;
+ int c;
+ tok.skip();
+ charinfo *ci = tok.get_char(1);
+ if (ci == 0) {
+ skip_line();
+ return;
+ }
+ tok.next();
+ if (tok.newline())
+ c = '\n';
+ else if (tok.tab())
+ c = '\t';
+ else if (!tok.space()) {
+ error("bad character definition");
+ skip_line();
+ return;
+ }
+ else
+ c = get_copy(&n);
+ while (c == ' ' || c == '\t')
+ c = get_copy(&n);
+ if (c == '"')
+ c = get_copy(&n);
+ macro *m = new macro;
+ while (c != '\n' && c != EOF) {
+ if (c == 0)
+ m->append(n);
+ else
+ m->append((unsigned char)c);
+ c = get_copy(&n);
+ }
+ m = ci->set_macro(m);
+ if (m)
+ delete m;
+ tok.next();
+}
+
+
+static void remove_character()
+{
+ tok.skip();
+ while (!tok.newline() && !tok.eof()) {
+ if (!tok.space() && !tok.tab()) {
+ charinfo *ci = tok.get_char(1);
+ if (!ci)
+ break;
+ macro *m = ci->set_macro(0);
+ if (m)
+ delete m;
+ }
+ tok.next();
+ }
+ skip_line();
+}
+
+static void interpolate_string(symbol nm)
+{
+ request_or_macro *p = lookup_request(nm);
+ macro *m = p->to_macro();
+ if (!m)
+ error("you can only invoke a string using \\*");
+ else {
+ string_iterator *si = new string_iterator(*m, "string", nm);
+ input_stack::push(si);
+ }
+}
+
+/* This class is used for the implementation of \$@. It is used for
+each of the closing double quotes. It artificially increases the
+input level by 2, so that the closing double quote will appear to have
+the same input level as the opening quote. */
+
+class end_quote_iterator : public input_iterator {
+ unsigned char buf[1];
+public:
+ end_quote_iterator();
+ ~end_quote_iterator() { }
+ int internal_level() { return 2; }
+};
+
+end_quote_iterator::end_quote_iterator()
+{
+ buf[0] = '"';
+ ptr = buf;
+ eptr = buf + 1;
+}
+
+static void interpolate_arg(symbol nm)
+{
+ const char *s = nm.contents();
+ if (!s || *s == '\0')
+ copy_mode_error("missing argument name");
+ else if (s[1] == 0 && csdigit(s[0]))
+ input_stack::push(input_stack::get_arg(s[0] - '0'));
+ else if (s[0] == '*' && s[1] == '\0') {
+ for (int i = input_stack::nargs(); i > 0; i--) {
+ input_stack::push(input_stack::get_arg(i));
+ if (i != 1)
+ input_stack::push(make_temp_iterator(" "));
+ }
+ }
+ else if (s[0] == '@' && s[1] == '\0') {
+ for (int i = input_stack::nargs(); i > 0; i--) {
+ input_stack::push(new end_quote_iterator);
+ input_stack::push(input_stack::get_arg(i));
+ input_stack::push(make_temp_iterator(i == 1 ? "\"" : " \""));
+ }
+ }
+ else {
+ const char *p;
+ for (p = s; *p && csdigit(*p); p++)
+ ;
+ if (*p)
+ copy_mode_error("bad argument name `%1'", s);
+ else
+ input_stack::push(input_stack::get_arg(atoi(s)));
+ }
+}
+
+void handle_first_page_transition()
+{
+ push_token(tok);
+ topdiv->begin_page();
+}
+
+// We push back a token by wrapping it up in a token_node, and
+// wrapping that up in a string_iterator.
+
+static void push_token(const token &t)
+{
+ macro m;
+ m.append(new token_node(t));
+ input_stack::push(new string_iterator(m));
+}
+
+void push_page_ejector()
+{
+ static char buf[2] = { PAGE_EJECTOR, '\0' };
+ input_stack::push(make_temp_iterator(buf));
+}
+
+void handle_initial_request(unsigned char code)
+{
+ char buf[2];
+ buf[0] = code;
+ buf[1] = '\0';
+ macro mac;
+ mac.append(new token_node(tok));
+ input_stack::push(new string_iterator(mac));
+ input_stack::push(make_temp_iterator(buf));
+ topdiv->begin_page();
+ tok.next();
+}
+
+void handle_initial_title()
+{
+ handle_initial_request(TITLE_REQUEST);
+}
+
+// this should be local to define_macro, but cfront 1.2 doesn't support that
+static symbol dot_symbol(".");
+
+enum define_mode { DEFINE_NORMAL, DEFINE_APPEND, DEFINE_IGNORE };
+
+void do_define_macro(define_mode mode)
+{
+ symbol nm;
+ if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND) {
+ nm = get_name(1);
+ if (nm.is_null()) {
+ skip_line();
+ return;
+ }
+ }
+ symbol term = get_name(); // the request that terminates the definition
+ if (term.is_null())
+ term = dot_symbol;
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ const char *start_filename;
+ int start_lineno;
+ int have_start_location = input_stack::get_location(0, &start_filename,
+ &start_lineno);
+ node *n;
+ // doing this here makes the line numbers come out right
+ int c = get_copy(&n, 1);
+ macro mac;
+ macro *mm = 0;
+ if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND) {
+ request_or_macro *rm =
+ (request_or_macro *)request_dictionary.lookup(nm);
+ if (rm)
+ mm = rm->to_macro();
+ if (mm && mode == DEFINE_APPEND)
+ mac = *mm;
+ }
+ int bol = 1;
+ for (;;) {
+ while (c == ESCAPE_NEWLINE) {
+ if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND)
+ mac.append(c);
+ c = get_copy(&n, 1);
+ }
+ if (bol && c == '.') {
+ const char *s = term.contents();
+ int d;
+ // see if it matches term
+ int i;
+ for (i = 0; s[i] != 0; i++) {
+ d = get_copy(&n);
+ if ((unsigned char)s[i] != d)
+ break;
+ }
+ if (s[i] == 0
+ && ((i == 2 && compatible_flag)
+ || (d = get_copy(&n)) == ' '
+ || d == '\n')) { // we found it
+ if (d == '\n')
+ tok.make_newline();
+ else
+ tok.make_space();
+ if (mode == DEFINE_APPEND || mode == DEFINE_NORMAL) {
+ if (!mm) {
+ mm = new macro;
+ request_dictionary.define(nm, mm);
+ }
+ *mm = mac;
+ }
+ if (term != dot_symbol) {
+ ignoring = 0;
+ interpolate_macro(term);
+ }
+ else
+ skip_line();
+ return;
+ }
+ if (mode == DEFINE_APPEND || mode == DEFINE_NORMAL) {
+ mac.append(c);
+ for (int j = 0; j < i; j++)
+ mac.append(s[j]);
+ }
+ c = d;
+ }
+ if (c == EOF) {
+ if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND) {
+ if (have_start_location)
+ error_with_file_and_line(start_filename, start_lineno,
+ "end of file while defining macro `%1'",
+ nm.contents());
+ else
+ error("end of file while defining macro `%1'", nm.contents());
+ }
+ else {
+ if (have_start_location)
+ error_with_file_and_line(start_filename, start_lineno,
+ "end of file while ignoring input lines");
+ else
+ error("end of file while ignoring input lines");
+ }
+ tok.next();
+ return;
+ }
+ if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND) {
+ if (c == 0)
+ mac.append(n);
+ else
+ mac.append(c);
+ }
+ bol = (c == '\n');
+ c = get_copy(&n, 1);
+ }
+}
+
+void define_macro()
+{
+ do_define_macro(DEFINE_NORMAL);
+}
+
+void append_macro()
+{
+ do_define_macro(DEFINE_APPEND);
+}
+
+void ignore()
+{
+ ignoring = 1;
+ do_define_macro(DEFINE_IGNORE);
+ ignoring = 0;
+}
+
+void remove_macro()
+{
+ for (;;) {
+ symbol s = get_name();
+ if (s.is_null())
+ break;
+ request_dictionary.remove(s);
+ }
+ skip_line();
+}
+
+void rename_macro()
+{
+ symbol s1 = get_name(1);
+ if (!s1.is_null()) {
+ symbol s2 = get_name(1);
+ if (!s2.is_null())
+ request_dictionary.rename(s1, s2);
+ }
+ skip_line();
+}
+
+void alias_macro()
+{
+ symbol s1 = get_name(1);
+ if (!s1.is_null()) {
+ symbol s2 = get_name(1);
+ if (!s2.is_null()) {
+ if (!request_dictionary.alias(s1, s2))
+ warning(WARN_MAC, "`%1' not defined", s2.contents());
+ }
+ }
+ skip_line();
+}
+
+void chop_macro()
+{
+ symbol s = get_name(1);
+ if (!s.is_null()) {
+ request_or_macro *p = lookup_request(s);
+ macro *m = p->to_macro();
+ if (!m)
+ error("cannot chop request");
+ else if (m->length == 0)
+ error("cannot chop empty macro");
+ else
+ m->length -= 1;
+ }
+ skip_line();
+}
+
+void substring_macro()
+{
+ int start;
+ symbol s = get_name(1);
+ if (!s.is_null() && get_integer(&start)) {
+ request_or_macro *p = lookup_request(s);
+ macro *m = p->to_macro();
+ if (!m)
+ error("cannot substring request");
+ else {
+ if (start <= 0)
+ start += m->length;
+ else
+ start--;
+ int end = 0;
+ if (!has_arg() || get_integer(&end)) {
+ if (end <= 0)
+ end += m->length;
+ else
+ end--;
+ if (start > end) {
+ int tem = start;
+ start = end;
+ end = tem;
+ }
+ if (start >= m->length || start == end) {
+ m->length = 0;
+ if (m->p) {
+ if (--(m->p->count) <= 0)
+ delete m->p;
+ m->p = 0;
+ }
+ }
+ else if (start == 0)
+ m->length = end;
+ else {
+ string_iterator iter(*m);
+ int i;
+ for (i = 0; i < start; i++)
+ if (iter.get(0) == EOF)
+ break;
+ macro mac;
+ for (; i < end; i++) {
+ node *nd;
+ int c = iter.get(&nd);
+ if (c == EOF)
+ break;
+ if (c == 0)
+ mac.append(nd);
+ else
+ mac.append((unsigned char)c);
+ }
+ *m = mac;
+ }
+ }
+ }
+ }
+ skip_line();
+}
+
+void asciify_macro()
+{
+ symbol s = get_name(1);
+ if (!s.is_null()) {
+ request_or_macro *p = lookup_request(s);
+ macro *m = p->to_macro();
+ if (!m)
+ error("cannot asciify request");
+ else {
+ macro am;
+ string_iterator iter(*m);
+ for (;;) {
+ node *nd;
+ int c = iter.get(&nd);
+ if (c == EOF)
+ break;
+ if (c != 0)
+ am.append(c);
+ else
+ nd->asciify(&am);
+ }
+ *m = am;
+ }
+ }
+ skip_line();
+}
+
+static void interpolate_environment_variable(symbol nm)
+{
+ const char *s = getenv(nm.contents());
+ if (s && *s)
+ input_stack::push(make_temp_iterator(s));
+}
+
+void interpolate_number_reg(symbol nm, int inc)
+{
+ reg *r = lookup_number_reg(nm);
+ if (inc < 0)
+ r->decrement();
+ else if (inc > 0)
+ r->increment();
+ input_stack::push(make_temp_iterator(r->get_string()));
+}
+
+static void interpolate_number_format(symbol nm)
+{
+ reg *r = (reg *)number_reg_dictionary.lookup(nm);
+ if (r)
+ input_stack::push(make_temp_iterator(r->get_format()));
+}
+
+static int get_delim_number(units *n, int si, int prev_value)
+{
+ token start;
+ start.next();
+ if (start.delimiter(1)) {
+ tok.next();
+ if (get_number(n, si, prev_value)) {
+ if (start != tok)
+ warning(WARN_DELIM, "closing delimiter does not match");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int get_delim_number(units *n, int si)
+{
+ token start;
+ start.next();
+ if (start.delimiter(1)) {
+ tok.next();
+ if (get_number(n, si)) {
+ if (start != tok)
+ warning(WARN_DELIM, "closing delimiter does not match");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int get_line_arg(units *n, int si, charinfo **cp)
+{
+ token start;
+ start.next();
+ if (start.delimiter(1)) {
+ tok.next();
+ if (get_number(n, si)) {
+ if (tok.dummy())
+ tok.next();
+ if (start != tok) {
+ *cp = tok.get_char(1);
+ tok.next();
+ }
+ if (start != tok)
+ warning(WARN_DELIM, "closing delimiter does not match");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int read_size(int *x)
+{
+ tok.next();
+ int c = tok.ch();
+ int inc = 0;
+ if (c == '-') {
+ inc = -1;
+ tok.next();
+ c = tok.ch();
+ }
+ else if (c == '+') {
+ inc = 1;
+ tok.next();
+ c = tok.ch();
+ }
+ int val;
+ int bad = 0;
+ if (c == '(') {
+ tok.next();
+ c = tok.ch();
+ if (!inc) {
+ // allow an increment either before or after the left parenthesis
+ if (c == '-') {
+ inc = -1;
+ tok.next();
+ c = tok.ch();
+ }
+ else if (c == '+') {
+ inc = 1;
+ tok.next();
+ c = tok.ch();
+ }
+ }
+ if (!csdigit(c))
+ bad = 1;
+ else {
+ val = c - '0';
+ tok.next();
+ c = tok.ch();
+ if (!csdigit(c))
+ bad = 1;
+ else {
+ val = val*10 + (c - '0');
+ val *= sizescale;
+ }
+ }
+ }
+ else if (csdigit(c)) {
+ val = c - '0';
+ if (!inc && c != '0' && c < '4') {
+ tok.next();
+ c = tok.ch();
+ if (!csdigit(c))
+ bad = 1;
+ else
+ val = val*10 + (c - '0');
+ }
+ val *= sizescale;
+ }
+ else if (!tok.delimiter(1))
+ return 0;
+ else {
+ token start(tok);
+ tok.next();
+ if (!(inc
+ ? get_number(&val, 'z')
+ : get_number(&val, 'z', curenv->get_requested_point_size())))
+ return 0;
+ if (!(start.ch() == '[' && tok.ch() == ']') && start != tok) {
+ if (start.ch() == '[')
+ error("missing `]'");
+ else
+ error("missing closing delimiter");
+ return 0;
+ }
+ }
+ if (!bad) {
+ switch (inc) {
+ case 0:
+ *x = val;
+ break;
+ case 1:
+ *x = curenv->get_requested_point_size() + val;
+ break;
+ case -1:
+ *x = curenv->get_requested_point_size() - val;
+ break;
+ default:
+ assert(0);
+ }
+ return 1;
+ }
+ else {
+ error("bad digit in point size");
+ return 0;
+ }
+}
+
+static symbol get_delim_name()
+{
+ token start;
+ start.next();
+ if (start.eof()) {
+ error("end of input at start of delimited name");
+ return NULL_SYMBOL;
+ }
+ if (start.newline()) {
+ error("can't delimit name with a newline");
+ return NULL_SYMBOL;
+ }
+ int start_level = input_stack::get_level();
+ char abuf[ABUF_SIZE];
+ char *buf = abuf;
+ int buf_size = ABUF_SIZE;
+ int i = 0;
+ for (;;) {
+ if (i + 1 > buf_size) {
+ if (buf == abuf) {
+ buf = new char [ABUF_SIZE*2];
+ memcpy(buf, abuf, buf_size);
+ buf_size = ABUF_SIZE*2;
+ }
+ else {
+ char *old_buf = buf;
+ buf = new char[buf_size*2];
+ memcpy(buf, old_buf, buf_size);
+ buf_size *= 2;
+ a_delete old_buf;
+ }
+ }
+ tok.next();
+ if (tok == start
+ && (compatible_flag || input_stack::get_level() == start_level))
+ break;
+ if ((buf[i] = tok.ch()) == 0) {
+ error("missing delimiter (got %1)", tok.description());
+ if (buf != abuf)
+ a_delete buf;
+ return NULL_SYMBOL;
+ }
+ i++;
+ }
+ buf[i] = '\0';
+ if (buf == abuf) {
+ if (i == 0) {
+ error("empty delimited name");
+ return NULL_SYMBOL;
+ }
+ else
+ return symbol(buf);
+ }
+ else {
+ symbol s(buf);
+ a_delete buf;
+ return s;
+ }
+}
+
+
+// Implement \R
+
+static void do_register()
+{
+ token start;
+ start.next();
+ if (!start.delimiter(1))
+ return;
+ tok.next();
+ symbol nm = get_long_name(1);
+ if (nm.is_null())
+ return;
+ while (tok.space())
+ tok.next();
+ reg *r = (reg *)number_reg_dictionary.lookup(nm);
+ int prev_value;
+ if (!r || !r->get_value(&prev_value))
+ prev_value = 0;
+ int val;
+ if (!get_number(&val, 'u', prev_value))
+ return;
+ if (start != tok)
+ warning(WARN_DELIM, "closing delimiter does not match");
+ if (r)
+ r->set_value(val);
+ else
+ set_number_reg(nm, val);
+}
+
+// this implements the \w escape sequence
+
+static void do_width()
+{
+ token start;
+ start.next();
+ int start_level = input_stack::get_level();
+ environment env(curenv);
+ environment *oldenv = curenv;
+ curenv = &env;
+ for (;;) {
+ tok.next();
+ if (tok.eof()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ break;
+ }
+ if (tok.newline()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ input_stack::push(make_temp_iterator("\n"));
+ break;
+ }
+ if (tok == start
+ && (compatible_flag || input_stack::get_level() == start_level))
+ break;
+ tok.process();
+ }
+ env.wrap_up_tab();
+ units x = env.get_input_line_position().to_units();
+ input_stack::push(make_temp_iterator(itoa(x)));
+ env.width_registers();
+ curenv = oldenv;
+}
+
+charinfo *page_character;
+
+void set_page_character()
+{
+ page_character = get_optional_char();
+ skip_line();
+}
+
+static const symbol percent_symbol("%");
+
+void read_title_parts(node **part, hunits *part_width)
+{
+ tok.skip();
+ if (tok.newline() || tok.eof())
+ return;
+ token start(tok);
+ int start_level = input_stack::get_level();
+ tok.next();
+ for (int i = 0; i < 3; i++) {
+ while (!tok.newline() && !tok.eof()) {
+ if (tok == start
+ && (compatible_flag || input_stack::get_level() == start_level)) {
+ tok.next();
+ break;
+ }
+ if (page_character != 0 && tok.get_char() == page_character)
+ interpolate_number_reg(percent_symbol, 0);
+ else
+ tok.process();
+ tok.next();
+ }
+ curenv->wrap_up_tab();
+ part_width[i] = curenv->get_input_line_position();
+ part[i] = curenv->extract_output_line();
+ }
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+}
+
+class non_interpreted_node : public node {
+ macro mac;
+public:
+ non_interpreted_node(const macro &);
+ int interpret(macro *);
+ node *copy();
+ int same(node *);
+ const char *type();
+};
+
+non_interpreted_node::non_interpreted_node(const macro &m) : mac(m)
+{
+}
+
+int non_interpreted_node::same(node *nd)
+{
+ return mac == ((non_interpreted_node *)nd)->mac;
+}
+
+const char *non_interpreted_node::type()
+{
+ return "non_interpreted_node";
+}
+
+node *non_interpreted_node::copy()
+{
+ return new non_interpreted_node(mac);
+}
+
+int non_interpreted_node::interpret(macro *m)
+{
+ string_iterator si(mac);
+ node *n;
+ for (;;) {
+ int c = si.get(&n);
+ if (c == EOF)
+ break;
+ if (c == 0)
+ m->append(n);
+ else
+ m->append(c);
+ }
+ return 1;
+}
+
+static node *do_non_interpreted()
+{
+ node *n;
+ int c;
+ macro mac;
+ while ((c = get_copy(&n)) != ESCAPE_QUESTION && c != EOF && c != '\n')
+ if (c == 0)
+ mac.append(n);
+ else
+ mac.append(c);
+ if (c == EOF || c == '\n') {
+ error("missing \\?");
+ return 0;
+ }
+ return new non_interpreted_node(mac);
+}
+
+static void encode_char (macro *mac, char c)
+{
+ if (c == '\0') {
+ if ((font::use_charnames_in_special) && tok.special()) {
+ charinfo *ci=tok.get_char(1);
+ const char *s=ci->get_symbol()->contents();
+
+ if (s[0] != (char)0) {
+ mac->append('\\');
+ mac->append('(');
+ int i=0;
+ while (s[i] != (char)0) {
+ mac->append(s[i]);
+ i++;
+ }
+ mac->append('\\');
+ mac->append(')');
+ }
+ } else {
+ error("%1 is illegal within \\X", tok.description());
+ }
+ } else {
+ if ((font::use_charnames_in_special) && (c == '\\')) {
+ /*
+ * add escape escape sequence
+ */
+ mac->append(c);
+ }
+ mac->append(c);
+ }
+}
+
+node *do_special()
+{
+ token start;
+ start.next();
+ int start_level = input_stack::get_level();
+ macro mac;
+ for (tok.next();
+ tok != start || input_stack::get_level() != start_level;
+ tok.next()) {
+ if (tok.eof()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ return 0;
+ }
+ if (tok.newline()) {
+ input_stack::push(make_temp_iterator("\n"));
+ warning(WARN_DELIM, "missing closing delimiter");
+ break;
+ }
+ unsigned char c;
+ if (tok.space())
+ c = ' ';
+ else if (tok.tab())
+ c = '\t';
+ else if (tok.leader())
+ c = '\001';
+ else if (tok.backspace())
+ c = '\b';
+ else
+ c = tok.ch();
+ encode_char(&mac, c);
+ }
+ return new special_node(mac);
+}
+
+void special_node::tprint(troff_output_file *out)
+{
+ tprint_start(out);
+ string_iterator iter(mac);
+ for (;;) {
+ int c = iter.get(NULL);
+ if (c == EOF)
+ break;
+ for (const char *s = ::asciify(c); *s; s++)
+ tprint_char(out, *s);
+ }
+ tprint_end(out);
+}
+
+int get_file_line(const char **filename, int *lineno)
+{
+ return input_stack::get_location(0, filename, lineno);
+}
+
+void line_file()
+{
+ int n;
+ if (get_integer(&n)) {
+ const char *filename = 0;
+ if (has_arg()) {
+ symbol s = get_long_name();
+ filename = s.contents();
+ }
+ (void)input_stack::set_location(filename, n-1);
+ }
+ skip_line();
+}
+
+static int nroff_mode = 0;
+
+static void nroff_request()
+{
+ nroff_mode = 1;
+ skip_line();
+}
+
+static void troff_request()
+{
+ nroff_mode = 0;
+ skip_line();
+}
+
+static void skip_alternative()
+{
+ int level = 0;
+ // ensure that ``.if 0\{'' works as expected
+ if (tok.left_brace())
+ level++;
+ int c;
+ for (;;) {
+ c = input_stack::get(NULL);
+ if (c == EOF)
+ break;
+ if (c == ESCAPE_LEFT_BRACE)
+ ++level;
+ else if (c == ESCAPE_RIGHT_BRACE)
+ --level;
+ else if (c == escape_char && escape_char > 0)
+ switch(input_stack::get(NULL)) {
+ case '{':
+ ++level;
+ break;
+ case '}':
+ --level;
+ break;
+ case '"':
+ while ((c = input_stack::get(NULL)) != '\n' && c != EOF)
+ ;
+ }
+ /*
+ Note that the level can properly be < 0, eg
+
+ .if 1 \{\
+ .if 0 \{\
+ .\}\}
+
+ So don't give an error message in this case.
+ */
+ if (level <= 0 && c == '\n')
+ break;
+ }
+ tok.next();
+}
+
+static void begin_alternative()
+{
+ while (tok.space() || tok.left_brace())
+ tok.next();
+}
+
+
+static int_stack if_else_stack;
+
+int do_if_request()
+{
+ int invert = 0;
+ while (tok.space())
+ tok.next();
+ while (tok.ch() == '!') {
+ tok.next();
+ invert = !invert;
+ }
+ int result;
+ unsigned char c = tok.ch();
+ if (c == 't') {
+ tok.next();
+ result = !nroff_mode;
+ }
+ else if (c == 'n') {
+ tok.next();
+ result = nroff_mode;
+ }
+ else if (c == 'v') {
+ tok.next();
+ result = 0;
+ }
+ else if (c == 'o') {
+ result = (topdiv->get_page_number() & 1);
+ tok.next();
+ }
+ else if (c == 'e') {
+ result = !(topdiv->get_page_number() & 1);
+ tok.next();
+ }
+ else if (c == 'd' || c == 'r') {
+ tok.next();
+ symbol nm = get_name(1);
+ if (nm.is_null()) {
+ skip_alternative();
+ return 0;
+ }
+ result = (c == 'd'
+ ? request_dictionary.lookup(nm) != 0
+ : number_reg_dictionary.lookup(nm) != 0);
+ }
+ else if (c == 'c') {
+ tok.next();
+ tok.skip();
+ charinfo *ci = tok.get_char(1);
+ if (ci == 0) {
+ skip_alternative();
+ return 0;
+ }
+ result = character_exists(ci, curenv);
+ tok.next();
+ }
+ else if (tok.space())
+ result = 0;
+ else if (tok.delimiter()) {
+ token delim = tok;
+ int delim_level = input_stack::get_level();
+ environment env1(curenv);
+ environment env2(curenv);
+ environment *oldenv = curenv;
+ curenv = &env1;
+ for (int i = 0; i < 2; i++) {
+ for (;;) {
+ tok.next();
+ if (tok.newline() || tok.eof()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ tok.next();
+ curenv = oldenv;
+ return 0;
+ }
+ if (tok == delim
+ && (compatible_flag || input_stack::get_level() == delim_level))
+ break;
+ tok.process();
+ }
+ curenv = &env2;
+ }
+ node *n1 = env1.extract_output_line();
+ node *n2 = env2.extract_output_line();
+ result = same_node_list(n1, n2);
+ delete_node_list(n1);
+ delete_node_list(n2);
+ curenv = oldenv;
+ tok.next();
+ }
+ else {
+ units n;
+ if (!get_number(&n, 'u')) {
+ skip_alternative();
+ return 0;
+ }
+ else
+ result = n > 0;
+ }
+ if (invert)
+ result = !result;
+ if (result)
+ begin_alternative();
+ else
+ skip_alternative();
+ return result;
+}
+
+void if_else_request()
+{
+ if_else_stack.push(do_if_request());
+}
+
+void if_request()
+{
+ do_if_request();
+}
+
+void else_request()
+{
+ if (if_else_stack.is_empty()) {
+ warning(WARN_EL, "unbalanced .el request");
+ skip_alternative();
+ }
+ else {
+ if (if_else_stack.pop())
+ skip_alternative();
+ else
+ begin_alternative();
+ }
+}
+
+static int while_depth = 0;
+static int while_break_flag = 0;
+
+void while_request()
+{
+ macro mac;
+ int escaped = 0;
+ int level = 0;
+ mac.append(new token_node(tok));
+ for (;;) {
+ node *n;
+ int c = input_stack::get(&n);
+ if (c == EOF)
+ break;
+ if (c == 0) {
+ escaped = 0;
+ mac.append(n);
+ }
+ else if (escaped) {
+ if (c == '{')
+ level += 1;
+ else if (c == '}')
+ level -= 1;
+ escaped = 0;
+ mac.append(c);
+ }
+ else {
+ if (c == ESCAPE_LEFT_BRACE)
+ level += 1;
+ else if (c == ESCAPE_RIGHT_BRACE)
+ level -= 1;
+ else if (c == escape_char)
+ escaped = 1;
+ mac.append(c);
+ if (c == '\n' && level <= 0)
+ break;
+ }
+ }
+ if (level != 0)
+ error("unbalanced \\{ \\}");
+ else {
+ while_depth++;
+ input_stack::add_boundary();
+ for (;;) {
+ input_stack::push(new string_iterator(mac, "while loop"));
+ tok.next();
+ if (!do_if_request()) {
+ while (input_stack::get(NULL) != EOF)
+ ;
+ break;
+ }
+ process_input_stack();
+ if (while_break_flag) {
+ while_break_flag = 0;
+ break;
+ }
+ }
+ input_stack::remove_boundary();
+ while_depth--;
+ }
+ tok.next();
+}
+
+void while_break_request()
+{
+ if (!while_depth) {
+ error("no while loop");
+ skip_line();
+ }
+ else {
+ while_break_flag = 1;
+ while (input_stack::get(NULL) != EOF)
+ ;
+ tok.next();
+ }
+}
+
+void while_continue_request()
+{
+ if (!while_depth) {
+ error("no while loop");
+ skip_line();
+ }
+ else {
+ while (input_stack::get(NULL) != EOF)
+ ;
+ tok.next();
+ }
+}
+
+// .so
+
+void source()
+{
+ symbol nm = get_long_name(1);
+ if (nm.is_null())
+ skip_line();
+ else {
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ errno = 0;
+ FILE *fp = fopen(nm.contents(), "r");
+ if (fp)
+ input_stack::push(new file_iterator(fp, nm.contents()));
+ else
+ error("can't open `%1': %2", nm.contents(), strerror(errno));
+ tok.next();
+ }
+}
+
+// like .so but use popen()
+
+void pipe_source()
+{
+#ifdef POPEN_MISSING
+ error("pipes not available on this system");
+ skip_line();
+#else /* not POPEN_MISSING */
+ if (tok.newline() || tok.eof())
+ error("missing command");
+ else {
+ int c;
+ while ((c = get_copy(NULL)) == ' ' || c == '\t')
+ ;
+ int buf_size = 24;
+ char *buf = new char[buf_size];
+ int buf_used = 0;
+ for (; c != '\n' && c != EOF; c = get_copy(NULL)) {
+ const char *s = asciify(c);
+ int slen = strlen(s);
+ if (buf_used + slen + 1> buf_size) {
+ char *old_buf = buf;
+ int old_buf_size = buf_size;
+ buf_size *= 2;
+ buf = new char[buf_size];
+ memcpy(buf, old_buf, old_buf_size);
+ a_delete old_buf;
+ }
+ strcpy(buf + buf_used, s);
+ buf_used += slen;
+ }
+ buf[buf_used] = '\0';
+ errno = 0;
+ FILE *fp = popen(buf, "r");
+ if (fp)
+ input_stack::push(new file_iterator(fp, symbol(buf).contents(), 1));
+ else
+ error("can't open pipe to process `%1': %2", buf, strerror(errno));
+ a_delete buf;
+ }
+ tok.next();
+#endif /* not POPEN_MISSING */
+}
+
+
+// .psbb
+
+static int llx_reg_contents = 0;
+static int lly_reg_contents = 0;
+static int urx_reg_contents = 0;
+static int ury_reg_contents = 0;
+
+struct bounding_box {
+ int llx, lly, urx, ury;
+};
+
+/* Parse the argument to a %%BoundingBox comment. Return 1 if it
+contains 4 numbers, 2 if it contains (atend), 0 otherwise. */
+
+int parse_bounding_box(char *p, bounding_box *bb)
+{
+ if (sscanf(p, "%d %d %d %d",
+ &bb->llx, &bb->lly, &bb->urx, &bb->ury) == 4)
+ return 1;
+ else {
+ /* The Document Structuring Conventions say that the numbers
+ should be integers. Unfortunately some broken applications
+ get this wrong. */
+ double x1, x2, x3, x4;
+ if (sscanf(p, "%lf %lf %lf %lf", &x1, &x2, &x3, &x4) == 4) {
+ bb->llx = (int)x1;
+ bb->lly = (int)x2;
+ bb->urx = (int)x3;
+ bb->ury = (int)x4;
+ return 1;
+ }
+ else {
+ for (; *p == ' ' || *p == '\t'; p++)
+ ;
+ if (strncmp(p, "(atend)", 7) == 0) {
+ return 2;
+ }
+ }
+ }
+ bb->llx = bb->lly = bb->urx = bb->ury = 0;
+ return 0;
+}
+
+// This version is taken from psrm.cc
+
+#define PS_LINE_MAX 255
+cset white_space("\n\r \t");
+
+int ps_get_line(char *buf, FILE *fp, const char* filename)
+{
+ int c = getc(fp);
+ if (c == EOF) {
+ buf[0] = '\0';
+ return 0;
+ }
+ int i = 0;
+ int err = 0;
+ while (c != '\r' && c != '\n' && c != EOF) {
+ if ((c < 0x1b && !white_space(c)) || c == 0x7f)
+ error("illegal input character code %1 in `%2'", int(c), filename);
+ else if (i < PS_LINE_MAX)
+ buf[i++] = c;
+ else if (!err) {
+ err = 1;
+ error("PostScript file `%1' is non-conforming "
+ "because length of line exceeds 255", filename);
+ }
+ c = getc(fp);
+ }
+ buf[i++] = '\n';
+ buf[i] = '\0';
+ if (c == '\r') {
+ c = getc(fp);
+ if (c != EOF && c != '\n')
+ ungetc(c, fp);
+ }
+ return 1;
+}
+
+void do_ps_file(FILE *fp, const char* filename)
+{
+ bounding_box bb;
+ int bb_at_end = 0;
+ char buf[PS_LINE_MAX];
+ llx_reg_contents = lly_reg_contents =
+ urx_reg_contents = ury_reg_contents = 0;
+ if (!ps_get_line(buf, fp, filename)) {
+ error("`%1' is empty", filename);
+ return;
+ }
+ if (strncmp("%!PS-Adobe-", buf, 11) != 0) {
+ error("`%1' is not conforming to the Document Structuring Conventions",
+ filename);
+ return;
+ }
+ while (ps_get_line(buf, fp, filename) != 0) {
+ if (buf[0] != '%' || buf[1] != '%'
+ || strncmp(buf + 2, "EndComments", 11) == 0)
+ break;
+ if (strncmp(buf + 2, "BoundingBox:", 12) == 0) {
+ int res = parse_bounding_box(buf + 14, &bb);
+ if (res == 1)
+ goto assign_registers;
+ else if (res == 2) {
+ bb_at_end = 1;
+ break;
+ }
+ else {
+ error("the arguments to the %%%%BoundingBox comment in `%1' are bad",
+ filename);
+ return;
+ }
+ }
+ }
+ if (bb_at_end) {
+ long offset;
+ int last_try = 0;
+ /* in the trailer, the last BoundingBox comment is significant */
+ for (offset = 512; !last_try; offset *= 2) {
+ int had_trailer = 0;
+ int got_bb = 0;
+ if (offset > 32768 || fseek(fp, -offset, 2) == -1) {
+ last_try = 1;
+ if (fseek(fp, 0L, 0) == -1)
+ break;
+ }
+ while (ps_get_line(buf, fp, filename) != 0) {
+ if (buf[0] == '%' && buf[1] == '%') {
+ if (!had_trailer) {
+ if (strncmp(buf + 2, "Trailer", 7) == 0)
+ had_trailer = 1;
+ }
+ else {
+ if (strncmp(buf + 2, "BoundingBox:", 12) == 0) {
+ int res = parse_bounding_box(buf + 14, &bb);
+ if (res == 1)
+ got_bb = 1;
+ else if (res == 2) {
+ error("`(atend)' not allowed in trailer of `%1'", filename);
+ return;
+ }
+ else {
+ error("the arguments to the %%%%BoundingBox comment in `%1' are bad",
+ filename);
+ return;
+ }
+ }
+ }
+ }
+ }
+ if (got_bb)
+ goto assign_registers;
+ }
+ }
+ error("%%%%BoundingBox comment not found in `%1'", filename);
+ return;
+
+assign_registers:
+ llx_reg_contents = bb.llx;
+ lly_reg_contents = bb.lly;
+ urx_reg_contents = bb.urx;
+ ury_reg_contents = bb.ury;
+}
+
+void ps_bbox_request()
+{
+ symbol nm = get_long_name(1);
+ if (nm.is_null())
+ skip_line();
+ else {
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ errno = 0;
+ FILE *fp = fopen(nm.contents(), "r");
+ if (fp)
+ do_ps_file(fp, nm.contents());
+ else
+ error("can't open `%1': %2", nm.contents(), strerror(errno));
+ tok.next();
+ }
+}
+
+const char *asciify(int c)
+{
+ static char buf[3];
+ buf[0] = escape_char == '\0' ? '\\' : escape_char;
+ buf[1] = buf[2] = '\0';
+ switch (c) {
+ case ESCAPE_QUESTION:
+ buf[1] = '?';
+ break;
+ case ESCAPE_AMPERSAND:
+ buf[1] = '&';
+ break;
+ case ESCAPE_UNDERSCORE:
+ buf[1] = '_';
+ break;
+ case ESCAPE_BAR:
+ buf[1] = '|';
+ break;
+ case ESCAPE_CIRCUMFLEX:
+ buf[1] = '^';
+ break;
+ case ESCAPE_LEFT_BRACE:
+ buf[1] = '{';
+ break;
+ case ESCAPE_RIGHT_BRACE:
+ buf[1] = '}';
+ break;
+ case ESCAPE_LEFT_QUOTE:
+ buf[1] = '`';
+ break;
+ case ESCAPE_RIGHT_QUOTE:
+ buf[1] = '\'';
+ break;
+ case ESCAPE_HYPHEN:
+ buf[1] = '-';
+ break;
+ case ESCAPE_BANG:
+ buf[1] = '!';
+ break;
+ case ESCAPE_c:
+ buf[1] = 'c';
+ break;
+ case ESCAPE_e:
+ buf[1] = 'e';
+ break;
+ case ESCAPE_E:
+ buf[1] = 'E';
+ break;
+ case ESCAPE_PERCENT:
+ buf[1] = '%';
+ break;
+ case ESCAPE_SPACE:
+ buf[1] = ' ';
+ break;
+ default:
+ if (illegal_input_char(c))
+ buf[0] = '\0';
+ else
+ buf[0] = c;
+ break;
+ }
+ return buf;
+}
+
+
+const char *input_char_description(int c)
+{
+ switch (c) {
+ case '\n':
+ return "a newline character";
+ case '\b':
+ return "a backspace character";
+ case '\001':
+ return "a leader character";
+ case '\t':
+ return "a tab character ";
+ case ' ':
+ return "a space character";
+ case '\0':
+ return "a node";
+ }
+ static char buf[sizeof("magic character code ") + 1 + INT_DIGITS];
+ if (illegal_input_char(c)) {
+ const char *s = asciify(c);
+ if (*s) {
+ buf[0] = '`';
+ strcpy(buf + 1, s);
+ strcat(buf, "'");
+ return buf;
+ }
+ sprintf(buf, "magic character code %d", c);
+ return buf;
+ }
+ if (csprint(c)) {
+ buf[0] = '`';
+ buf[1] = c;
+ buf[2] = '\'';
+ return buf;
+ }
+ sprintf(buf, "character code %d", c);
+ return buf;
+}
+
+// .tm
+
+void terminal()
+{
+ if (!tok.newline() && !tok.eof()) {
+ int c;
+ while ((c = get_copy(NULL)) == ' ' || c == '\t')
+ ;
+ for (; c != '\n' && c != EOF; c = get_copy(NULL))
+ fputs(asciify(c), stderr);
+ }
+ fputc('\n', stderr);
+ fflush(stderr);
+ tok.next();
+}
+
+dictionary stream_dictionary(20);
+
+void do_open(int append)
+{
+ symbol stream = get_name(1);
+ if (!stream.is_null()) {
+ symbol filename = get_long_name(1);
+ if (!filename.is_null()) {
+ errno = 0;
+ FILE *fp = fopen(filename.contents(), append ? "a" : "w");
+ if (!fp) {
+ error("can't open `%1' for %2: %3",
+ filename.contents(),
+ append ? "appending" : "writing",
+ strerror(errno));
+ fp = (FILE *)stream_dictionary.remove(stream);
+ }
+ else
+ fp = (FILE *)stream_dictionary.lookup(stream, fp);
+ if (fp)
+ fclose(fp);
+ }
+ }
+ skip_line();
+}
+
+void open_request()
+{
+ do_open(0);
+}
+
+void opena_request()
+{
+ do_open(1);
+}
+
+void close_request()
+{
+ symbol stream = get_name(1);
+ if (!stream.is_null()) {
+ FILE *fp = (FILE *)stream_dictionary.remove(stream);
+ if (!fp)
+ error("no stream named `%1'", stream.contents());
+ else
+ fclose(fp);
+ }
+ skip_line();
+}
+
+void write_request()
+{
+ symbol stream = get_name(1);
+ if (stream.is_null()) {
+ skip_line();
+ return;
+ }
+ FILE *fp = (FILE *)stream_dictionary.lookup(stream);
+ if (!fp) {
+ error("no stream named `%1'", stream.contents());
+ skip_line();
+ return;
+ }
+ int c;
+ while ((c = get_copy(NULL)) == ' ')
+ ;
+ if (c == '"')
+ c = get_copy(NULL);
+ for (; c != '\n' && c != EOF; c = get_copy(NULL))
+ fputs(asciify(c), fp);
+ fputc('\n', fp);
+ fflush(fp);
+ tok.next();
+}
+
+void write_macro_request()
+{
+ symbol stream = get_name(1);
+ if (stream.is_null()) {
+ skip_line();
+ return;
+ }
+ FILE *fp = (FILE *)stream_dictionary.lookup(stream);
+ if (!fp) {
+ error("no stream named `%1'", stream.contents());
+ skip_line();
+ return;
+ }
+ symbol s = get_name(1);
+ if (s.is_null()) {
+ skip_line();
+ return;
+ }
+ request_or_macro *p = lookup_request(s);
+ macro *m = p->to_macro();
+ if (!m)
+ error("cannot write request");
+ else {
+ string_iterator iter(*m);
+ for (;;) {
+ int c = iter.get(0);
+ if (c == EOF)
+ break;
+ fputs(asciify(c), fp);
+ }
+ fflush(fp);
+ }
+ skip_line();
+}
+
+static void init_charset_table()
+{
+ char buf[16];
+ strcpy(buf, "char");
+ for (int i = 0; i < 256; i++) {
+ strcpy(buf + 4, itoa(i));
+ charset_table[i] = get_charinfo(symbol(buf));
+ charset_table[i]->set_ascii_code(i);
+ if (csalpha(i))
+ charset_table[i]->set_hyphenation_code(cmlower(i));
+ }
+ charset_table['.']->set_flags(charinfo::ENDS_SENTENCE);
+ charset_table['?']->set_flags(charinfo::ENDS_SENTENCE);
+ charset_table['!']->set_flags(charinfo::ENDS_SENTENCE);
+ charset_table['-']->set_flags(charinfo::BREAK_AFTER);
+ charset_table['"']->set_flags(charinfo::TRANSPARENT);
+ charset_table['\'']->set_flags(charinfo::TRANSPARENT);
+ charset_table[')']->set_flags(charinfo::TRANSPARENT);
+ charset_table[']']->set_flags(charinfo::TRANSPARENT);
+ charset_table['*']->set_flags(charinfo::TRANSPARENT);
+ get_charinfo(symbol("dg"))->set_flags(charinfo::TRANSPARENT);
+ get_charinfo(symbol("rq"))->set_flags(charinfo::TRANSPARENT);
+ get_charinfo(symbol("em"))->set_flags(charinfo::BREAK_AFTER);
+ get_charinfo(symbol("ul"))->set_flags(charinfo::OVERLAPS_HORIZONTALLY);
+ get_charinfo(symbol("rn"))->set_flags(charinfo::OVERLAPS_HORIZONTALLY);
+ get_charinfo(symbol("radicalex"))->set_flags(charinfo::OVERLAPS_HORIZONTALLY);
+ get_charinfo(symbol("ru"))->set_flags(charinfo::OVERLAPS_HORIZONTALLY);
+ get_charinfo(symbol("br"))->set_flags(charinfo::OVERLAPS_VERTICALLY);
+ page_character = charset_table['%'];
+}
+
+static
+void do_translate(int translate_transparent)
+{
+ tok.skip();
+ while (!tok.newline() && !tok.eof()) {
+ if (tok.space()) {
+ // This is a really bizarre troff feature.
+ tok.next();
+ translate_space_to_dummy = tok.dummy();
+ if (tok.newline() || tok.eof())
+ break;
+ tok.next();
+ continue;
+ }
+ charinfo *ci1 = tok.get_char(1);
+ if (ci1 == 0)
+ break;
+ tok.next();
+ if (tok.newline() || tok.eof()) {
+ ci1->set_special_translation(charinfo::TRANSLATE_SPACE,
+ translate_transparent);
+ break;
+ }
+ if (tok.space())
+ ci1->set_special_translation(charinfo::TRANSLATE_SPACE,
+ translate_transparent);
+ else if (tok.dummy())
+ ci1->set_special_translation(charinfo::TRANSLATE_DUMMY,
+ translate_transparent);
+ else if (tok.hyphen_indicator())
+ ci1->set_special_translation(charinfo::TRANSLATE_HYPHEN_INDICATOR,
+ translate_transparent);
+ else {
+ charinfo *ci2 = tok.get_char(1);
+ if (ci2 == 0)
+ break;
+ if (ci1 == ci2)
+ ci1->set_translation(0, translate_transparent);
+ else
+ ci1->set_translation(ci2, translate_transparent);
+ }
+ tok.next();
+ }
+ skip_line();
+}
+
+void translate()
+{
+ do_translate(1);
+}
+
+void translate_no_transparent()
+{
+ do_translate(0);
+}
+
+void char_flags()
+{
+ int flags;
+ if (get_integer(&flags))
+ while (has_arg()) {
+ charinfo *ci = tok.get_char(1);
+ if (ci) {
+ charinfo *tem = ci->get_translation();
+ if (tem)
+ ci = tem;
+ ci->set_flags(flags);
+ }
+ tok.next();
+ }
+ skip_line();
+}
+
+void hyphenation_code()
+{
+ tok.skip();
+ while (!tok.newline() && !tok.eof()) {
+ charinfo *ci = tok.get_char(1);
+ if (ci == 0)
+ break;
+ tok.next();
+ tok.skip();
+ unsigned char c = tok.ch();
+ if (c == 0) {
+ error("hyphenation code must be ordinary character");
+ break;
+ }
+ if (csdigit(c)) {
+ error("hyphenation code cannot be digit");
+ break;
+ }
+ ci->set_hyphenation_code(c);
+ tok.next();
+ tok.skip();
+ }
+ skip_line();
+}
+
+charinfo *token::get_char(int required)
+{
+ if (type == TOKEN_CHAR)
+ return charset_table[c];
+ if (type == TOKEN_SPECIAL)
+ return get_charinfo(nm);
+ if (type == TOKEN_NUMBERED_CHAR)
+ return get_charinfo_by_number(val);
+ if (type == TOKEN_ESCAPE) {
+ if (escape_char != 0)
+ return charset_table[escape_char];
+ else {
+ error("`\\e' used while no current escape character");
+ return 0;
+ }
+ }
+ if (required) {
+ if (type == TOKEN_EOF || type == TOKEN_NEWLINE)
+ warning(WARN_MISSING, "missing normal or special character");
+ else
+ error("normal or special character expected (got %1)", description());
+ }
+ return 0;
+}
+
+charinfo *get_optional_char()
+{
+ while (tok.space())
+ tok.next();
+ charinfo *ci = tok.get_char();
+ if (!ci)
+ check_missing_character();
+ else
+ tok.next();
+ return ci;
+}
+
+void check_missing_character()
+{
+ if (!tok.newline() && !tok.eof() && !tok.right_brace() && !tok.tab())
+ error("normal or special character expected (got %1): "
+ "treated as missing",
+ tok.description());
+}
+
+int token::add_to_node_list(node **pp)
+{
+ hunits w;
+ node *n = 0;
+ switch (type) {
+ case TOKEN_CHAR:
+ *pp = (*pp)->add_char(charset_table[c], curenv, &w);
+ break;
+ case TOKEN_DUMMY:
+ n = new dummy_node;
+ break;
+ case TOKEN_ESCAPE:
+ if (escape_char != 0)
+ *pp = (*pp)->add_char(charset_table[escape_char], curenv, &w);
+ break;
+ case TOKEN_HYPHEN_INDICATOR:
+ *pp = (*pp)->add_discretionary_hyphen();
+ break;
+ case TOKEN_ITALIC_CORRECTION:
+ *pp = (*pp)->add_italic_correction(&w);
+ break;
+ case TOKEN_LEFT_BRACE:
+ break;
+ case TOKEN_MARK_INPUT:
+ set_number_reg(nm, curenv->get_input_line_position().to_units());
+ break;
+ case TOKEN_NODE:
+ n = nd;
+ nd = 0;
+ break;
+ case TOKEN_NUMBERED_CHAR:
+ *pp = (*pp)->add_char(get_charinfo_by_number(val), curenv, &w);
+ break;
+ case TOKEN_RIGHT_BRACE:
+ break;
+ case TOKEN_SPACE:
+ n = new hmotion_node(curenv->get_space_width());
+ break;
+ case TOKEN_SPECIAL:
+ *pp = (*pp)->add_char(get_charinfo(nm), curenv, &w);
+ break;
+ default:
+ return 0;
+ }
+ if (n) {
+ n->next = *pp;
+ *pp = n;
+ }
+ return 1;
+}
+
+void token::process()
+{
+ if (possibly_handle_first_page_transition())
+ return;
+ switch (type) {
+ case TOKEN_BACKSPACE:
+ curenv->add_node(new hmotion_node(-curenv->get_space_width()));
+ break;
+ case TOKEN_CHAR:
+ curenv->add_char(charset_table[c]);
+ break;
+ case TOKEN_DUMMY:
+ curenv->add_node(new dummy_node);
+ break;
+ case TOKEN_EOF:
+ assert(0);
+ break;
+ case TOKEN_EMPTY:
+ assert(0);
+ break;
+ case TOKEN_ESCAPE:
+ if (escape_char != 0)
+ curenv->add_char(charset_table[escape_char]);
+ break;
+ case TOKEN_BEGIN_TRAP:
+ case TOKEN_END_TRAP:
+ case TOKEN_PAGE_EJECTOR:
+ // these are all handled in process_input_stack()
+ break;
+ case TOKEN_HYPHEN_INDICATOR:
+ curenv->add_hyphen_indicator();
+ break;
+ case TOKEN_INTERRUPT:
+ curenv->interrupt();
+ break;
+ case TOKEN_ITALIC_CORRECTION:
+ curenv->add_italic_correction();
+ break;
+ case TOKEN_LEADER:
+ curenv->handle_tab(1);
+ break;
+ case TOKEN_LEFT_BRACE:
+ break;
+ case TOKEN_MARK_INPUT:
+ set_number_reg(nm, curenv->get_input_line_position().to_units());
+ break;
+ case TOKEN_NEWLINE:
+ curenv->newline();
+ break;
+ case TOKEN_NODE:
+ curenv->add_node(nd);
+ nd = 0;
+ break;
+ case TOKEN_NUMBERED_CHAR:
+ curenv->add_char(get_charinfo_by_number(val));
+ break;
+ case TOKEN_REQUEST:
+ // handled in process_input_stack
+ break;
+ case TOKEN_RIGHT_BRACE:
+ break;
+ case TOKEN_SPACE:
+ curenv->space();
+ break;
+ case TOKEN_SPECIAL:
+ curenv->add_char(get_charinfo(nm));
+ break;
+ case TOKEN_SPREAD:
+ curenv->spread();
+ break;
+ case TOKEN_TAB:
+ curenv->handle_tab(0);
+ break;
+ case TOKEN_TRANSPARENT:
+ break;
+ default:
+ assert(0);
+ }
+}
+
+class nargs_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *nargs_reg::get_string()
+{
+ return itoa(input_stack::nargs());
+}
+
+class lineno_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *lineno_reg::get_string()
+{
+ int line;
+ const char *file;
+ if (!input_stack::get_location(0, &file, &line))
+ line = 0;
+ return itoa(line);
+}
+
+
+class writable_lineno_reg : public general_reg {
+public:
+ writable_lineno_reg();
+ void set_value(units);
+ int get_value(units *);
+};
+
+writable_lineno_reg::writable_lineno_reg()
+{
+}
+
+int writable_lineno_reg::get_value(units *res)
+{
+ int line;
+ const char *file;
+ if (!input_stack::get_location(0, &file, &line))
+ return 0;
+ *res = line;
+ return 1;
+}
+
+void writable_lineno_reg::set_value(units n)
+{
+ input_stack::set_location(0, n);
+}
+
+class filename_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *filename_reg::get_string()
+{
+ int line;
+ const char *file;
+ if (input_stack::get_location(0, &file, &line))
+ return file;
+ else
+ return 0;
+}
+
+
+class constant_reg : public reg {
+ const char *s;
+public:
+ constant_reg(const char *);
+ const char *get_string();
+};
+
+constant_reg::constant_reg(const char *p) : s(p)
+{
+}
+
+const char *constant_reg::get_string()
+{
+ return s;
+}
+
+constant_int_reg::constant_int_reg(int *q) : p(q)
+{
+}
+
+const char *constant_int_reg::get_string()
+{
+ return itoa(*p);
+}
+
+void abort_request()
+{
+ int c;
+ if (tok.eof())
+ c = EOF;
+ else if (tok.newline())
+ c = '\n';
+ else {
+ while ((c = get_copy(0)) == ' ')
+ ;
+ }
+ if (c == EOF || c == '\n')
+ fputs("User Abort.", stderr);
+ else {
+ for (; c != '\n' && c != EOF; c = get_copy(NULL))
+ fputs(asciify(c), stderr);
+ }
+ fputc('\n', stderr);
+ cleanup_and_exit(1);
+}
+
+char *read_string()
+{
+ int len = 256;
+ char *s = new char[len];
+ int c;
+ while ((c = get_copy(0)) == ' ')
+ ;
+ int i = 0;
+ while (c != '\n' && c != EOF) {
+ if (!illegal_input_char(c)) {
+ if (i + 2 > len) {
+ char *tem = s;
+ s = new char[len*2];
+ memcpy(s, tem, len);
+ len *= 2;
+ a_delete tem;
+ }
+ s[i++] = c;
+ }
+ c = get_copy(0);
+ }
+ s[i] = '\0';
+ tok.next();
+ if (i == 0) {
+ a_delete s;
+ return 0;
+ }
+ return s;
+}
+
+void pipe_output()
+{
+#ifdef POPEN_MISSING
+ error("pipes not available on this system");
+ skip_line();
+#else /* not POPEN_MISSING */
+ if (the_output) {
+ error("can't pipe: output already started");
+ skip_line();
+ }
+ else {
+ if ((pipe_command = read_string()) == 0)
+ error("can't pipe to empty command");
+ }
+#endif /* not POPEN_MISSING */
+}
+
+static int system_status;
+
+void system_request()
+{
+ char *command = read_string();
+ if (!command)
+ error("empty command");
+ else {
+ system_status = system(command);
+ a_delete command;
+ }
+}
+
+void copy_file()
+{
+ if (curdiv == topdiv && topdiv->before_first_page) {
+ handle_initial_request(COPY_FILE_REQUEST);
+ return;
+ }
+ symbol filename = get_long_name(1);
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ if (!filename.is_null())
+ curdiv->copy_file(filename.contents());
+ tok.next();
+}
+
+#ifdef COLUMN
+
+void vjustify()
+{
+ if (curdiv == topdiv && topdiv->before_first_page) {
+ handle_initial_request(VJUSTIFY_REQUEST);
+ return;
+ }
+ symbol type = get_long_name(1);
+ if (!type.is_null())
+ curdiv->vjustify(type);
+ skip_line();
+}
+
+#endif /* COLUMN */
+
+void transparent_file()
+{
+ if (curdiv == topdiv && topdiv->before_first_page) {
+ handle_initial_request(TRANSPARENT_FILE_REQUEST);
+ return;
+ }
+ symbol filename = get_long_name(1);
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+ if (!filename.is_null()) {
+ errno = 0;
+ FILE *fp = fopen(filename.contents(), "r");
+ if (!fp)
+ error("can't open `%1': %2", filename.contents(), strerror(errno));
+ else {
+ int bol = 1;
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ if (illegal_input_char(c))
+ warning(WARN_INPUT, "illegal input character code %1", int(c));
+ else {
+ curdiv->transparent_output(c);
+ bol = c == '\n';
+ }
+ }
+ if (!bol)
+ curdiv->transparent_output('\n');
+ fclose(fp);
+ }
+ }
+ tok.next();
+}
+
+class page_range {
+ int first;
+ int last;
+public:
+ page_range *next;
+ page_range(int, int, page_range *);
+ int contains(int n);
+};
+
+page_range::page_range(int i, int j, page_range *p)
+: first(i), last(j), next(p)
+{
+}
+
+int page_range::contains(int n)
+{
+ return n >= first && (last <= 0 || n <= last);
+}
+
+page_range *output_page_list = 0;
+
+int in_output_page_list(int n)
+{
+ if (!output_page_list)
+ return 1;
+ for (page_range *p = output_page_list; p; p = p->next)
+ if (p->contains(n))
+ return 1;
+ return 0;
+}
+
+static void parse_output_page_list(char *p)
+{
+ for (;;) {
+ int i;
+ if (*p == '-')
+ i = 1;
+ else if (csdigit(*p)) {
+ i = 0;
+ do
+ i = i*10 + *p++ - '0';
+ while (csdigit(*p));
+ }
+ else
+ break;
+ int j;
+ if (*p == '-') {
+ p++;
+ j = 0;
+ if (csdigit(*p)) {
+ do
+ j = j*10 + *p++ - '0';
+ while (csdigit(*p));
+ }
+ }
+ else
+ j = i;
+ if (j == 0)
+ last_page_number = -1;
+ else if (last_page_number >= 0 && j > last_page_number)
+ last_page_number = j;
+ output_page_list = new page_range(i, j, output_page_list);
+ if (*p != ',')
+ break;
+ ++p;
+ }
+ if (*p != '\0') {
+ error("bad output page list");
+ output_page_list = 0;
+ }
+}
+
+static FILE *open_mac_file(const char *mac, char **path)
+{
+ char *s = new char[strlen(mac)+strlen(MACRO_PREFIX)+1];
+ strcpy(s, MACRO_PREFIX);
+ strcat(s, mac);
+ FILE *fp = macro_path.open_file(s, path);
+ a_delete s;
+ return fp;
+}
+
+static void process_macro_file(const char *mac)
+{
+ char *path;
+ FILE *fp = open_mac_file(mac, &path);
+ if (!fp)
+ fatal("can't find macro file %1", mac);
+ const char *s = symbol(path).contents();
+ a_delete path;
+ input_stack::push(new file_iterator(fp, s));
+ tok.next();
+ process_input_stack();
+}
+
+static void process_startup_file(char *filename)
+{
+ char *path;
+ FILE *fp = macro_path.open_file(filename, &path);
+ if (fp) {
+ input_stack::push(new file_iterator(fp, symbol(path).contents()));
+ a_delete path;
+ tok.next();
+ process_input_stack();
+ }
+}
+
+void macro_source()
+{
+ symbol nm = get_long_name(1);
+ if (nm.is_null())
+ skip_line();
+ else {
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ char *path;
+ FILE *fp = macro_path.open_file(nm.contents(), &path);
+ if (fp) {
+ input_stack::push(new file_iterator(fp, symbol(path).contents()));
+ a_delete path;
+ }
+ else
+ error("can't find macro file `%1'", nm.contents());
+ tok.next();
+ }
+}
+
+static void process_input_file(const char *name)
+{
+ FILE *fp;
+ if (strcmp(name, "-") == 0) {
+ clearerr(stdin);
+ fp = stdin;
+ }
+ else {
+ errno = 0;
+ fp = fopen(name, "r");
+ if (!fp)
+ fatal("can't open `%1': %2", name, strerror(errno));
+ }
+ input_stack::push(new file_iterator(fp, name));
+ tok.next();
+ process_input_stack();
+}
+
+// make sure the_input is empty before calling this
+
+static int evaluate_expression(const char *expr, units *res)
+{
+ input_stack::push(make_temp_iterator(expr));
+ tok.next();
+ int success = get_number(res, 'u');
+ while (input_stack::get(NULL) != EOF)
+ ;
+ return success;
+}
+
+static void do_register_assignment(const char *s)
+{
+ const char *p = strchr(s, '=');
+ if (!p) {
+ char buf[2];
+ buf[0] = s[0];
+ buf[1] = 0;
+ units n;
+ if (evaluate_expression(s + 1, &n))
+ set_number_reg(buf, n);
+ }
+ else {
+ char *buf = new char[p - s + 1];
+ memcpy(buf, s, p - s);
+ buf[p - s] = 0;
+ units n;
+ if (evaluate_expression(p + 1, &n))
+ set_number_reg(buf, n);
+ a_delete buf;
+ }
+}
+
+static void set_string(const char *name, const char *value)
+{
+ macro *m = new macro;
+ for (const char *p = value; *p; p++)
+ if (!illegal_input_char((unsigned char)*p))
+ m->append(*p);
+ request_dictionary.define(name, m);
+}
+
+
+static void do_string_assignment(const char *s)
+{
+ const char *p = strchr(s, '=');
+ if (!p) {
+ char buf[2];
+ buf[0] = s[0];
+ buf[1] = 0;
+ set_string(buf, s + 1);
+ }
+ else {
+ char *buf = new char[p - s + 1];
+ memcpy(buf, s, p - s);
+ buf[p - s] = 0;
+ set_string(buf, p + 1);
+ a_delete buf;
+ }
+}
+
+struct string_list {
+ const char *s;
+ string_list *next;
+ string_list(const char *ss) : s(ss), next(0) {}
+};
+
+static void prepend_string(const char *s, string_list **p)
+{
+ string_list *l = new string_list(s);
+ l->next = *p;
+ *p = l;
+}
+
+static void add_string(const char *s, string_list **p)
+{
+ while (*p)
+ p = &((*p)->next);
+ *p = new string_list(s);
+}
+
+void usage(const char *prog)
+{
+ errprint(
+"usage: %1 -abivzCERU -wname -Wname -dcs -ffam -mname -nnum -olist\n"
+" -rcn -Tname -Fdir -Mdir [files...]\n",
+ prog);
+ exit(USAGE_EXIT_CODE);
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int c;
+ string_list *macros = 0;
+ string_list *register_assignments = 0;
+ string_list *string_assignments = 0;
+ int iflag = 0;
+ int tflag = 0;
+ int fflag = 0;
+ int nflag = 0;
+ int safer_flag = 1; // safer by default
+ int no_rc = 0; // don't process troffrc
+ int next_page_number;
+ opterr = 0;
+ hresolution = vresolution = 1;
+ while ((c = getopt(argc, argv, "abivw:W:zCEf:m:n:o:r:d:F:M:T:tqs:RU"))
+ != EOF)
+ switch(c) {
+ case 'v':
+ {
+ extern const char *Version_string;
+ fprintf(stderr, "GNU troff version %s\n", Version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'T':
+ device = optarg;
+ tflag = 1;
+ break;
+ case 'C':
+ compatible_flag = 1;
+ break;
+ case 'M':
+ macro_path.command_line_dir(optarg);
+ break;
+ case 'F':
+ font::command_line_font_dir(optarg);
+ break;
+ case 'm':
+ add_string(optarg, &macros);
+ break;
+ case 'E':
+ inhibit_errors = 1;
+ break;
+ case 'R':
+ no_rc = 1;
+ break;
+ case 'w':
+ enable_warning(optarg);
+ break;
+ case 'W':
+ disable_warning(optarg);
+ break;
+ case 'i':
+ iflag = 1;
+ break;
+ case 'b':
+ backtrace_flag = 1;
+ break;
+ case 'a':
+ ascii_output_flag = 1;
+ break;
+ case 'z':
+ suppress_output_flag = 1;
+ break;
+ case 'n':
+ if (sscanf(optarg, "%d", &next_page_number) == 1)
+ nflag++;
+ else
+ error("bad page number");
+ break;
+ case 'o':
+ parse_output_page_list(optarg);
+ break;
+ case 'd':
+ if (*optarg == '\0')
+ error("`-d' requires non-empty argument");
+ else
+ add_string(optarg, &string_assignments);
+ break;
+ case 'r':
+ if (*optarg == '\0')
+ error("`-r' requires non-empty argument");
+ else
+ add_string(optarg, &register_assignments);
+ break;
+ case 'f':
+ default_family = symbol(optarg);
+ fflag = 1;
+ break;
+ case 'q':
+ case 's':
+ case 't':
+ // silently ignore these
+ break;
+ case 'U':
+ safer_flag = 0; // unsafe behaviour
+ break;
+ case '?':
+ usage(argv[0]);
+ default:
+ assert(0);
+ }
+ set_string(".T", device);
+ init_charset_table();
+ if (!font::load_desc())
+ fatal("sorry, I can't continue");
+ units_per_inch = font::res;
+ hresolution = font::hor;
+ vresolution = font::vert;
+ sizescale = font::sizescale;
+ tcommand_flag = font::tcommand;
+ if (!fflag && font::family != 0 && *font::family != '\0')
+ default_family = symbol(font::family);
+ font_size::init_size_table(font::sizes);
+ int i;
+ int j = 1;
+ if (font::style_table) {
+ for (i = 0; font::style_table[i]; i++)
+ mount_style(j++, symbol(font::style_table[i]));
+ }
+ for (i = 0; font::font_name_table[i]; i++, j++)
+ // In the DESC file a font name of 0 (zero) means leave this
+ // position empty.
+ if (strcmp(font::font_name_table[i], "0") != 0)
+ mount_font(j, symbol(font::font_name_table[i]));
+ curdiv = topdiv = new top_level_diversion;
+ if (nflag)
+ topdiv->set_next_page_number(next_page_number);
+ init_input_requests();
+ init_env_requests();
+ init_div_requests();
+#ifdef COLUMN
+ init_column_requests();
+#endif /* COLUMN */
+ init_node_requests();
+ number_reg_dictionary.define(".T", new constant_reg(tflag ? "1" : "0"));
+ init_registers();
+ init_reg_requests();
+ init_hyphen_requests();
+ init_environments();
+ while (string_assignments) {
+ do_string_assignment(string_assignments->s);
+ string_list *tem = string_assignments;
+ string_assignments = string_assignments->next;
+ delete tem;
+ }
+ while (register_assignments) {
+ do_register_assignment(register_assignments->s);
+ string_list *tem = register_assignments;
+ register_assignments = register_assignments->next;
+ delete tem;
+ }
+ if (!no_rc)
+ process_startup_file(INITIAL_STARTUP_FILE);
+ if (safer_flag)
+ prepend_string("safer", &macros);
+ while (macros) {
+ process_macro_file(macros->s);
+ string_list *tem = macros;
+ macros = macros->next;
+ delete tem;
+ }
+ if (!no_rc)
+ process_startup_file(FINAL_STARTUP_FILE);
+ for (i = optind; i < argc; i++)
+ process_input_file(argv[i]);
+ if (optind >= argc || iflag)
+ process_input_file("-");
+ exit_troff();
+ return 0; // not reached
+}
+
+void warn_request()
+{
+ int n;
+ if (has_arg() && get_integer(&n)) {
+ if (n & ~WARN_TOTAL) {
+ warning(WARN_RANGE, "warning mask must be between 0 and %1", WARN_TOTAL);
+ n &= WARN_TOTAL;
+ }
+ warning_mask = n;
+ }
+ else
+ warning_mask = WARN_TOTAL;
+ skip_line();
+}
+
+static void init_registers()
+{
+#ifdef LONG_FOR_TIME_T
+ long
+#else /* not LONG_FOR_TIME_T */
+ time_t
+#endif /* not LONG_FOR_TIME_T */
+ t = time(0);
+ // Use struct here to work around misfeature in old versions of g++.
+ struct tm *tt = localtime(&t);
+ set_number_reg("dw", int(tt->tm_wday + 1));
+ set_number_reg("dy", int(tt->tm_mday));
+ set_number_reg("mo", int(tt->tm_mon + 1));
+ set_number_reg("year", int(1900 + tt->tm_year));
+ set_number_reg("yr", int(tt->tm_year));
+ set_number_reg("$$", getpid());
+ number_reg_dictionary.define(".A",
+ new constant_reg(ascii_output_flag
+ ? "1"
+ : "0"));
+}
+
+void init_input_requests()
+{
+ init_request("ds", define_string);
+ init_request("as", append_string);
+ init_request("de", define_macro);
+ init_request("am", append_macro);
+ init_request("ig", ignore);
+ init_request("rm", remove_macro);
+ init_request("rn", rename_macro);
+ init_request("if", if_request);
+ init_request("ie", if_else_request);
+ init_request("el", else_request);
+ init_request("so", source);
+ init_request("nx", next_file);
+ init_request("pm", print_macros);
+ init_request("eo", escape_off);
+ init_request("ec", set_escape_char);
+ init_request("pc", set_page_character);
+ init_request("tm", terminal);
+ init_request("ex", exit_request);
+ init_request("em", end_macro);
+ init_request("blm", blank_line_macro);
+ init_request("tr", translate);
+ init_request("trnt", translate_no_transparent);
+ init_request("ab", abort_request);
+ init_request("pi", pipe_output);
+ init_request("cf", copy_file);
+ init_request("sy", system_request);
+ init_request("lf", line_file);
+ init_request("cflags", char_flags);
+ init_request("shift", shift);
+ init_request("rd", read_request);
+ init_request("cp", compatible);
+ init_request("char", define_character);
+ init_request("rchar", remove_character);
+ init_request("hcode", hyphenation_code);
+ init_request("while", while_request);
+ init_request("break", while_break_request);
+ init_request("continue", while_continue_request);
+ init_request("als", alias_macro);
+ init_request("backtrace", backtrace_request);
+ init_request("chop", chop_macro);
+ init_request("substring", substring_macro);
+ init_request("asciify", asciify_macro);
+ init_request("warn", warn_request);
+ init_request("open", open_request);
+ init_request("opena", opena_request);
+ init_request("close", close_request);
+ init_request("write", write_request);
+ init_request("writem", write_macro_request);
+ init_request("trf", transparent_file);
+#ifdef WIDOW_CONTROL
+ init_request("fpl", flush_pending_lines);
+#endif /* WIDOW_CONTROL */
+ init_request("nroff", nroff_request);
+ init_request("troff", troff_request);
+#ifdef COLUMN
+ init_request("vj", vjustify);
+#endif /* COLUMN */
+ init_request("mso", macro_source);
+ init_request("do", do_request);
+#ifndef POPEN_MISSING
+ init_request("pso", pipe_source);
+#endif /* not POPEN_MISSING */
+ init_request("psbb", ps_bbox_request);
+ number_reg_dictionary.define("systat", new variable_reg(&system_status));
+ number_reg_dictionary.define("slimit",
+ new variable_reg(&input_stack::limit));
+ number_reg_dictionary.define(".$", new nargs_reg);
+ number_reg_dictionary.define(".c", new lineno_reg);
+ number_reg_dictionary.define("c.", new writable_lineno_reg);
+ number_reg_dictionary.define(".F", new filename_reg);
+ number_reg_dictionary.define(".C", new constant_int_reg(&compatible_flag));
+ number_reg_dictionary.define(".H", new constant_int_reg(&hresolution));
+ number_reg_dictionary.define(".V", new constant_int_reg(&vresolution));
+ number_reg_dictionary.define(".R", new constant_reg("10000"));
+ extern const char *major_version;
+ number_reg_dictionary.define(".x", new constant_reg(major_version));
+ extern const char *minor_version;
+ number_reg_dictionary.define(".y", new constant_reg(minor_version));
+ extern const char *revision;
+ number_reg_dictionary.define(".Y", new constant_reg(revision));
+ number_reg_dictionary.define(".g", new constant_reg("1"));
+ number_reg_dictionary.define(".warn", new constant_int_reg(&warning_mask));
+ number_reg_dictionary.define("llx", new variable_reg(&llx_reg_contents));
+ number_reg_dictionary.define("lly", new variable_reg(&lly_reg_contents));
+ number_reg_dictionary.define("urx", new variable_reg(&urx_reg_contents));
+ number_reg_dictionary.define("ury", new variable_reg(&ury_reg_contents));
+}
+
+object_dictionary request_dictionary(501);
+
+void init_request(const char *s, REQUEST_FUNCP f)
+{
+ request_dictionary.define(s, new request(f));
+}
+
+static request_or_macro *lookup_request(symbol nm)
+{
+ assert(!nm.is_null());
+ request_or_macro *p = (request_or_macro *)request_dictionary.lookup(nm);
+ if (p == 0) {
+ warning(WARN_MAC, "`%1' not defined", nm.contents());
+ p = new macro;
+ request_dictionary.define(nm, p);
+ }
+ return p;
+}
+
+
+node *charinfo_to_node_list(charinfo *ci, const environment *envp)
+{
+ // Don't interpret character definitions in compatible mode.
+ int old_compatible_flag = compatible_flag;
+ compatible_flag = 0;
+ int old_escape_char = escape_char;
+ escape_char = '\\';
+ macro *mac = ci->set_macro(0);
+ assert(mac != 0);
+ environment *oldenv = curenv;
+ environment env(envp);
+ curenv = &env;
+ curenv->set_composite();
+ token old_tok = tok;
+ input_stack::add_boundary();
+ string_iterator *si = new string_iterator(*mac, "composite character", ci->nm);
+ input_stack::push(si);
+ // we don't use process_input_stack, because we don't want to recognise
+ // requests
+ for (;;) {
+ tok.next();
+ if (tok.eof())
+ break;
+ if (tok.newline()) {
+ error("composite character mustn't contain newline");
+ while (!tok.eof())
+ tok.next();
+ break;
+ }
+ else
+ tok.process();
+ }
+ node *n = curenv->extract_output_line();
+ input_stack::remove_boundary();
+ ci->set_macro(mac);
+ tok = old_tok;
+ curenv = oldenv;
+ compatible_flag = old_compatible_flag;
+ escape_char = old_escape_char;
+ return n;
+}
+
+static node *read_draw_node()
+{
+ token start;
+ start.next();
+ if (!start.delimiter(1)){
+ do {
+ tok.next();
+ } while (tok != start && !tok.newline() && !tok.eof());
+ }
+ else {
+ tok.next();
+ if (tok == start)
+ error("missing argument");
+ else {
+ unsigned char type = tok.ch();
+ tok.next();
+ int maxpoints = 10;
+ hvpair *point = new hvpair[maxpoints];
+ int npoints = 0;
+ int no_last_v = 0;
+ int err = 0;
+ int i;
+ for (i = 0; tok != start; i++) {
+ if (i == maxpoints) {
+ hvpair *oldpoint = point;
+ point = new hvpair[maxpoints*2];
+ for (int j = 0; j < maxpoints; j++)
+ point[j] = oldpoint[j];
+ maxpoints *= 2;
+ a_delete oldpoint;
+ }
+ if (!get_hunits(&point[i].h,
+ type == 'f' || type == 't' ? 'u' : 'm')) {
+ err = 1;
+ break;
+ }
+ ++npoints;
+ tok.skip();
+ point[i].v = V0;
+ if (tok == start) {
+ no_last_v = 1;
+ break;
+ }
+ if (!get_vunits(&point[i].v, 'v')) {
+ err = 1;
+ break;
+ }
+ tok.skip();
+ }
+ while (tok != start && !tok.newline() && !tok.eof())
+ tok.next();
+ if (!err) {
+ switch (type) {
+ case 'l':
+ if (npoints != 1 || no_last_v) {
+ error("two arguments needed for line");
+ npoints = 1;
+ }
+ break;
+ case 'c':
+ if (npoints != 1 || !no_last_v) {
+ error("one argument needed for circle");
+ npoints = 1;
+ point[0].v = V0;
+ }
+ break;
+ case 'e':
+ if (npoints != 1 || no_last_v) {
+ error("two arguments needed for ellipse");
+ npoints = 1;
+ }
+ break;
+ case 'a':
+ if (npoints != 2 || no_last_v) {
+ error("four arguments needed for arc");
+ npoints = 2;
+ }
+ break;
+ case '~':
+ if (no_last_v)
+ error("even number of arguments needed for spline");
+ break;
+ default:
+ // silently pass it through
+ break;
+ }
+ draw_node *dn = new draw_node(type, point, npoints,
+ curenv->get_font_size());
+ a_delete point;
+ return dn;
+ }
+ else {
+ a_delete point;
+ }
+ }
+ }
+ return 0;
+}
+
+static struct {
+ const char *name;
+ int mask;
+} warning_table[] = {
+ { "char", WARN_CHAR },
+ { "range", WARN_RANGE },
+ { "break", WARN_BREAK },
+ { "delim", WARN_DELIM },
+ { "el", WARN_EL },
+ { "scale", WARN_SCALE },
+ { "number", WARN_NUMBER },
+ { "syntax", WARN_SYNTAX },
+ { "tab", WARN_TAB },
+ { "right-brace", WARN_RIGHT_BRACE },
+ { "missing", WARN_MISSING },
+ { "input", WARN_INPUT },
+ { "escape", WARN_ESCAPE },
+ { "space", WARN_SPACE },
+ { "font", WARN_FONT },
+ { "di", WARN_DI },
+ { "mac", WARN_MAC },
+ { "reg", WARN_REG },
+ { "ig", WARN_IG },
+ { "all", WARN_TOTAL & ~(WARN_DI | WARN_MAC | WARN_REG) },
+ { "w", WARN_TOTAL },
+ { "default", DEFAULT_WARNING_MASK },
+};
+
+static int lookup_warning(const char *name)
+{
+ for (int i = 0;
+ i < sizeof(warning_table)/sizeof(warning_table[0]);
+ i++)
+ if (strcmp(name, warning_table[i].name) == 0)
+ return warning_table[i].mask;
+ return 0;
+}
+
+static void enable_warning(const char *name)
+{
+ int mask = lookup_warning(name);
+ if (mask)
+ warning_mask |= mask;
+ else
+ error("unknown warning `%1'", name);
+}
+
+static void disable_warning(const char *name)
+{
+ int mask = lookup_warning(name);
+ if (mask)
+ warning_mask &= ~mask;
+ else
+ error("unknown warning `%1'", name);
+}
+
+static void copy_mode_error(const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ if (ignoring) {
+ static const char prefix[] = "(in ignored input) ";
+ char *s = new char[sizeof(prefix) + strlen(format)];
+ strcpy(s, prefix);
+ strcat(s, format);
+ warning(WARN_IG, s, arg1, arg2, arg3);
+ a_delete s;
+ }
+ else
+ error(format, arg1, arg2, arg3);
+}
+
+enum error_type { WARNING, ERROR, FATAL };
+
+static void do_error(error_type type,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ const char *filename;
+ int lineno;
+ if (inhibit_errors && type < FATAL)
+ return;
+ if (backtrace_flag)
+ input_stack::backtrace();
+ if (!get_file_line(&filename, &lineno))
+ filename = 0;
+ if (filename)
+ errprint("%1:%2: ", filename, lineno);
+ else if (program_name)
+ fprintf(stderr, "%s: ", program_name);
+ switch (type) {
+ case FATAL:
+ fputs("fatal error: ", stderr);
+ break;
+ case ERROR:
+ break;
+ case WARNING:
+ fputs("warning: ", stderr);
+ break;
+ }
+ errprint(format, arg1, arg2, arg3);
+ fputc('\n', stderr);
+ fflush(stderr);
+ if (type == FATAL)
+ cleanup_and_exit(1);
+}
+
+int warning(warning_type t,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ if ((t & warning_mask) != 0) {
+ do_error(WARNING, format, arg1, arg2, arg3);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+void error(const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ do_error(ERROR, format, arg1, arg2, arg3);
+}
+
+void fatal(const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ do_error(FATAL, format, arg1, arg2, arg3);
+}
+
+void fatal_with_file_and_line(const char *filename, int lineno,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ fprintf(stderr, "%s:%d: fatal error: ", filename, lineno);
+ errprint(format, arg1, arg2, arg3);
+ fputc('\n', stderr);
+ fflush(stderr);
+ cleanup_and_exit(1);
+}
+
+void error_with_file_and_line(const char *filename, int lineno,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ fprintf(stderr, "%s:%d: error: ", filename, lineno);
+ errprint(format, arg1, arg2, arg3);
+ fputc('\n', stderr);
+ fflush(stderr);
+}
+
+dictionary charinfo_dictionary(501);
+
+charinfo *get_charinfo(symbol nm)
+{
+ void *p = charinfo_dictionary.lookup(nm);
+ if (p != 0)
+ return (charinfo *)p;
+ charinfo *cp = new charinfo(nm);
+ (void)charinfo_dictionary.lookup(nm, cp);
+ return cp;
+}
+
+int charinfo::next_index = 0;
+
+charinfo::charinfo(symbol s)
+: translation(0), mac(0), special_translation(TRANSLATE_NONE),
+ hyphenation_code(0), flags(0), ascii_code(0), not_found(0),
+ transparent_translate(1), nm(s)
+{
+ index = next_index++;
+}
+
+void charinfo::set_hyphenation_code(unsigned char c)
+{
+ hyphenation_code = c;
+}
+
+void charinfo::set_translation(charinfo *ci, int tt)
+{
+ translation = ci;
+ special_translation = TRANSLATE_NONE;
+ transparent_translate = tt;
+}
+
+void charinfo::set_special_translation(int c, int tt)
+{
+ special_translation = c;
+ translation = 0;
+ transparent_translate = tt;
+}
+
+void charinfo::set_ascii_code(unsigned char c)
+{
+ ascii_code = c;
+}
+
+macro *charinfo::set_macro(macro *m)
+{
+ macro *tem = mac;
+ mac = m;
+ return tem;
+}
+
+void charinfo::set_number(int n)
+{
+ number = n;
+ flags |= NUMBERED;
+}
+
+int charinfo::get_number()
+{
+ assert(flags & NUMBERED);
+ return number;
+}
+
+symbol UNNAMED_SYMBOL("---");
+
+// For numbered characters not between 0 and 255, we make a symbol out
+// of the number and store them in this dictionary.
+
+dictionary numbered_charinfo_dictionary(11);
+
+charinfo *get_charinfo_by_number(int n)
+{
+ static charinfo *number_table[256];
+
+ if (n >= 0 && n < 256) {
+ charinfo *ci = number_table[n];
+ if (!ci) {
+ ci = new charinfo(UNNAMED_SYMBOL);
+ ci->set_number(n);
+ number_table[n] = ci;
+ }
+ return ci;
+ }
+ else {
+ symbol ns(itoa(n));
+ charinfo *ci = (charinfo *)numbered_charinfo_dictionary.lookup(ns);
+ if (!ci) {
+ ci = new charinfo(UNNAMED_SYMBOL);
+ ci->set_number(n);
+ numbered_charinfo_dictionary.lookup(ns, ci);
+ }
+ return ci;
+ }
+}
+
+int font::name_to_index(const char *nm)
+{
+ charinfo *ci;
+ if (nm[1] == 0)
+ ci = charset_table[nm[0] & 0xff];
+ else if (nm[0] == '\\' && nm[2] == 0)
+ ci = get_charinfo(symbol(nm + 1));
+ else
+ ci = get_charinfo(symbol(nm));
+ if (ci == 0)
+ return -1;
+ else
+ return ci->get_index();
+}
+
+int font::number_to_index(int n)
+{
+ return get_charinfo_by_number(n)->get_index();
+}
diff --git a/src/roff/troff/node.cc b/src/roff/troff/node.cc
new file mode 100644
index 00000000..79da579e
--- /dev/null
+++ b/src/roff/troff/node.cc
@@ -0,0 +1,4896 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "troff.h"
+#include "symbol.h"
+#include "dictionary.h"
+#include "hvunits.h"
+#include "env.h"
+#include "request.h"
+#include "node.h"
+#include "token.h"
+#include "charinfo.h"
+#include "font.h"
+#include "reg.h"
+
+#define STORE_WIDTH 1
+
+symbol HYPHEN_SYMBOL("hy");
+
+// Character used when a hyphen is inserted at a line break.
+static charinfo *soft_hyphen_char;
+
+enum constant_space_type {
+ CONSTANT_SPACE_NONE,
+ CONSTANT_SPACE_RELATIVE,
+ CONSTANT_SPACE_ABSOLUTE
+ };
+
+struct special_font_list {
+ int n;
+ special_font_list *next;
+};
+
+special_font_list *global_special_fonts;
+static int global_ligature_mode = 1;
+static int global_kern_mode = 1;
+
+class track_kerning_function {
+ int non_zero;
+ units min_size;
+ hunits min_amount;
+ units max_size;
+ hunits max_amount;
+public:
+ track_kerning_function();
+ track_kerning_function(units, hunits, units, hunits);
+ int operator==(const track_kerning_function &);
+ int operator!=(const track_kerning_function &);
+ hunits compute(int point_size);
+};
+
+// embolden fontno when this is the current font
+
+struct conditional_bold {
+ conditional_bold *next;
+ int fontno;
+ hunits offset;
+ conditional_bold(int, hunits, conditional_bold * = 0);
+};
+
+struct tfont;
+
+class font_info {
+ tfont *last_tfont;
+ int number;
+ font_size last_size;
+ int last_height;
+ int last_slant;
+ symbol internal_name;
+ symbol external_name;
+ font *fm;
+ char is_bold;
+ hunits bold_offset;
+ track_kerning_function track_kern;
+ constant_space_type is_constant_spaced;
+ units constant_space;
+ int last_ligature_mode;
+ int last_kern_mode;
+ conditional_bold *cond_bold_list;
+ void flush();
+public:
+ special_font_list *sf;
+
+ font_info(symbol nm, int n, symbol enm, font *f);
+ int contains(charinfo *);
+ void set_bold(hunits);
+ void unbold();
+ void set_conditional_bold(int, hunits);
+ void conditional_unbold(int);
+ void set_track_kern(track_kerning_function &);
+ void set_constant_space(constant_space_type, units = 0);
+ int is_named(symbol);
+ symbol get_name();
+ tfont *get_tfont(font_size, int, int, int);
+ hunits get_space_width(font_size, int);
+ hunits get_narrow_space_width(font_size);
+ hunits get_half_narrow_space_width(font_size);
+ int get_bold(hunits *);
+ int is_special();
+ int is_style();
+};
+
+class tfont_spec {
+protected:
+ symbol name;
+ int input_position;
+ font *fm;
+ font_size size;
+ char is_bold;
+ char is_constant_spaced;
+ int ligature_mode;
+ int kern_mode;
+ hunits bold_offset;
+ hunits track_kern; // add this to the width
+ hunits constant_space_width;
+ int height;
+ int slant;
+public:
+ tfont_spec(symbol nm, int pos, font *, font_size, int, int);
+ tfont_spec(const tfont_spec &spec) { *this = spec; }
+ tfont_spec plain();
+ int operator==(const tfont_spec &);
+ friend tfont *font_info::get_tfont(font_size fs, int, int, int);
+};
+
+class tfont : public tfont_spec {
+ static tfont *tfont_list;
+ tfont *next;
+ tfont *plain_version;
+public:
+ tfont(tfont_spec &);
+ int contains(charinfo *);
+ hunits get_width(charinfo *c);
+ int get_bold(hunits *);
+ int get_constant_space(hunits *);
+ hunits get_track_kern();
+ tfont *get_plain();
+ font_size get_size();
+ symbol get_name();
+ charinfo *get_lig(charinfo *c1, charinfo *c2);
+ int get_kern(charinfo *c1, charinfo *c2, hunits *res);
+ int get_input_position();
+ int get_character_type(charinfo *);
+ int get_height();
+ int get_slant();
+ vunits get_char_height(charinfo *);
+ vunits get_char_depth(charinfo *);
+ hunits get_char_skew(charinfo *);
+ hunits get_italic_correction(charinfo *);
+ hunits get_left_italic_correction(charinfo *);
+ hunits get_subscript_correction(charinfo *);
+ friend tfont *make_tfont(tfont_spec &);
+};
+
+inline int env_definite_font(environment *env)
+{
+ return env->get_family()->make_definite(env->get_font());
+}
+
+/* font_info functions */
+
+static font_info **font_table = 0;
+static int font_table_size = 0;
+
+font_info::font_info(symbol nm, int n, symbol enm, font *f)
+: last_tfont(0), number(n), last_size(0),
+ internal_name(nm), external_name(enm), fm(f),
+ is_bold(0), is_constant_spaced(CONSTANT_SPACE_NONE), last_ligature_mode(1),
+ last_kern_mode(1), cond_bold_list(0), sf(0)
+{
+}
+
+inline int font_info::contains(charinfo *ci)
+{
+ return fm != 0 && fm->contains(ci->get_index());
+}
+
+inline int font_info::is_special()
+{
+ return fm != 0 && fm->is_special();
+}
+
+inline int font_info::is_style()
+{
+ return fm == 0;
+}
+
+// this is the current_font, fontno is where we found the character,
+// presumably a special font
+
+tfont *font_info::get_tfont(font_size fs, int height, int slant, int fontno)
+{
+ if (last_tfont == 0 || fs != last_size
+ || height != last_height || slant != last_slant
+ || global_ligature_mode != last_ligature_mode
+ || global_kern_mode != last_kern_mode
+ || fontno != number) {
+ font_info *f = font_table[fontno];
+ tfont_spec spec(f->external_name, f->number, f->fm, fs, height, slant);
+ for (conditional_bold *p = cond_bold_list; p; p = p->next)
+ if (p->fontno == fontno) {
+ spec.is_bold = 1;
+ spec.bold_offset = p->offset;
+ break;
+ }
+ if (!spec.is_bold && is_bold) {
+ spec.is_bold = 1;
+ spec.bold_offset = bold_offset;
+ }
+ spec.track_kern = track_kern.compute(fs.to_scaled_points());
+ spec.ligature_mode = global_ligature_mode;
+ spec.kern_mode = global_kern_mode;
+ switch (is_constant_spaced) {
+ case CONSTANT_SPACE_NONE:
+ break;
+ case CONSTANT_SPACE_ABSOLUTE:
+ spec.is_constant_spaced = 1;
+ spec.constant_space_width = constant_space;
+ break;
+ case CONSTANT_SPACE_RELATIVE:
+ spec.is_constant_spaced = 1;
+ spec.constant_space_width
+ = scale(constant_space*fs.to_scaled_points(),
+ units_per_inch,
+ 36*72*sizescale);
+ break;
+ default:
+ assert(0);
+ }
+ if (fontno != number)
+ return make_tfont(spec);
+ last_tfont = make_tfont(spec);
+ last_size = fs;
+ last_height = height;
+ last_slant = slant;
+ last_ligature_mode = global_ligature_mode;
+ last_kern_mode = global_kern_mode;
+ }
+ return last_tfont;
+}
+
+int font_info::get_bold(hunits *res)
+{
+ if (is_bold) {
+ *res = bold_offset;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+void font_info::unbold()
+{
+ if (is_bold) {
+ is_bold = 0;
+ flush();
+ }
+}
+
+void font_info::set_bold(hunits offset)
+{
+ if (!is_bold || offset != bold_offset) {
+ is_bold = 1;
+ bold_offset = offset;
+ flush();
+ }
+}
+
+void font_info::set_conditional_bold(int fontno, hunits offset)
+{
+ for (conditional_bold *p = cond_bold_list; p; p = p->next)
+ if (p->fontno == fontno) {
+ if (offset != p->offset) {
+ p->offset = offset;
+ flush();
+ }
+ return;
+ }
+ cond_bold_list = new conditional_bold(fontno, offset, cond_bold_list);
+}
+
+conditional_bold::conditional_bold(int f, hunits h, conditional_bold *x)
+ : next(x), fontno(f), offset(h)
+{
+}
+
+void font_info::conditional_unbold(int fontno)
+{
+ for (conditional_bold **p = &cond_bold_list; *p; p = &(*p)->next)
+ if ((*p)->fontno == fontno) {
+ conditional_bold *tem = *p;
+ *p = (*p)->next;
+ delete tem;
+ flush();
+ return;
+ }
+}
+
+void font_info::set_constant_space(constant_space_type type, units x)
+{
+ if (type != is_constant_spaced
+ || (type != CONSTANT_SPACE_NONE && x != constant_space)) {
+ flush();
+ is_constant_spaced = type;
+ constant_space = x;
+ }
+}
+
+void font_info::set_track_kern(track_kerning_function &tk)
+{
+ if (track_kern != tk) {
+ track_kern = tk;
+ flush();
+ }
+}
+
+void font_info::flush()
+{
+ last_tfont = 0;
+}
+
+int font_info::is_named(symbol s)
+{
+ return internal_name == s;
+}
+
+symbol font_info::get_name()
+{
+ return internal_name;
+}
+
+hunits font_info::get_space_width(font_size fs, int space_size)
+{
+ if (is_constant_spaced == CONSTANT_SPACE_NONE)
+ return scale(hunits(fm->get_space_width(fs.to_scaled_points())),
+ space_size, 12);
+ else if (is_constant_spaced == CONSTANT_SPACE_ABSOLUTE)
+ return constant_space;
+ else
+ return scale(constant_space*fs.to_scaled_points(),
+ units_per_inch, 36*72*sizescale);
+}
+
+hunits font_info::get_narrow_space_width(font_size fs)
+{
+ charinfo *ci = get_charinfo(symbol("|"));
+ if (fm->contains(ci->get_index()))
+ return hunits(fm->get_width(ci->get_index(), fs.to_scaled_points()));
+ else
+ return hunits(fs.to_units()/6);
+}
+
+hunits font_info::get_half_narrow_space_width(font_size fs)
+{
+ charinfo *ci = get_charinfo(symbol("^"));
+ if (fm->contains(ci->get_index()))
+ return hunits(fm->get_width(ci->get_index(), fs.to_scaled_points()));
+ else
+ return hunits(fs.to_units()/12);
+}
+
+/* tfont */
+
+tfont_spec::tfont_spec(symbol nm, int n, font *f,
+ font_size s, int h, int sl)
+ : name(nm), input_position(n), fm(f), size(s),
+ is_bold(0), is_constant_spaced(0), ligature_mode(1), kern_mode(1),
+ height(h), slant(sl)
+{
+ if (height == size.to_scaled_points())
+ height = 0;
+}
+
+int tfont_spec::operator==(const tfont_spec &spec)
+{
+ if (fm == spec.fm
+ && size == spec.size
+ && input_position == spec.input_position
+ && name == spec.name
+ && height == spec.height
+ && slant == spec.slant
+ && (is_bold
+ ? (spec.is_bold && bold_offset == spec.bold_offset)
+ : !spec.is_bold)
+ && track_kern == spec.track_kern
+ && (is_constant_spaced
+ ? (spec.is_constant_spaced
+ && constant_space_width == spec.constant_space_width)
+ : !spec.is_constant_spaced)
+ && ligature_mode == spec.ligature_mode
+ && kern_mode == spec.kern_mode)
+ return 1;
+ else
+ return 0;
+}
+
+tfont_spec tfont_spec::plain()
+{
+ return tfont_spec(name, input_position, fm, size, height, slant);
+}
+
+hunits tfont::get_width(charinfo *c)
+{
+ if (is_constant_spaced)
+ return constant_space_width;
+ else if (is_bold)
+ return (hunits(fm->get_width(c->get_index(), size.to_scaled_points()))
+ + track_kern + bold_offset);
+ else
+ return (hunits(fm->get_width(c->get_index(), size.to_scaled_points())) + track_kern);
+}
+
+vunits tfont::get_char_height(charinfo *c)
+{
+ vunits v = fm->get_height(c->get_index(), size.to_scaled_points());
+ if (height != 0 && height != size.to_scaled_points())
+ return scale(v, height, size.to_scaled_points());
+ else
+ return v;
+}
+
+vunits tfont::get_char_depth(charinfo *c)
+{
+ vunits v = fm->get_depth(c->get_index(), size.to_scaled_points());
+ if (height != 0 && height != size.to_scaled_points())
+ return scale(v, height, size.to_scaled_points());
+ else
+ return v;
+}
+
+hunits tfont::get_char_skew(charinfo *c)
+{
+ return hunits(fm->get_skew(c->get_index(), size.to_scaled_points(), slant));
+}
+
+hunits tfont::get_italic_correction(charinfo *c)
+{
+ return hunits(fm->get_italic_correction(c->get_index(), size.to_scaled_points()));
+}
+
+hunits tfont::get_left_italic_correction(charinfo *c)
+{
+ return hunits(fm->get_left_italic_correction(c->get_index(),
+ size.to_scaled_points()));
+}
+
+hunits tfont::get_subscript_correction(charinfo *c)
+{
+ return hunits(fm->get_subscript_correction(c->get_index(),
+ size.to_scaled_points()));
+}
+
+inline int tfont::get_input_position()
+{
+ return input_position;
+}
+
+inline int tfont::contains(charinfo *ci)
+{
+ return fm->contains(ci->get_index());
+}
+
+inline int tfont::get_character_type(charinfo *ci)
+{
+ return fm->get_character_type(ci->get_index());
+}
+
+inline int tfont::get_bold(hunits *res)
+{
+ if (is_bold) {
+ *res = bold_offset;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+inline int tfont::get_constant_space(hunits *res)
+{
+ if (is_constant_spaced) {
+ *res = constant_space_width;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+inline hunits tfont::get_track_kern()
+{
+ return track_kern;
+}
+
+inline tfont *tfont::get_plain()
+{
+ return plain_version;
+}
+
+inline font_size tfont::get_size()
+{
+ return size;
+}
+
+inline symbol tfont::get_name()
+{
+ return name;
+}
+
+inline int tfont::get_height()
+{
+ return height;
+}
+
+inline int tfont::get_slant()
+{
+ return slant;
+}
+
+symbol SYMBOL_ff("ff");
+symbol SYMBOL_fi("fi");
+symbol SYMBOL_fl("fl");
+symbol SYMBOL_Fi("Fi");
+symbol SYMBOL_Fl("Fl");
+
+charinfo *tfont::get_lig(charinfo *c1, charinfo *c2)
+{
+ if (ligature_mode == 0)
+ return 0;
+ charinfo *ci = 0;
+ if (c1->get_ascii_code() == 'f') {
+ switch (c2->get_ascii_code()) {
+ case 'f':
+ if (fm->has_ligature(font::LIG_ff))
+ ci = get_charinfo(SYMBOL_ff);
+ break;
+ case 'i':
+ if (fm->has_ligature(font::LIG_fi))
+ ci = get_charinfo(SYMBOL_fi);
+ break;
+ case 'l':
+ if (fm->has_ligature(font::LIG_fl))
+ ci = get_charinfo(SYMBOL_fl);
+ break;
+ }
+ }
+ else if (ligature_mode != 2 && c1->nm == SYMBOL_ff) {
+ switch (c2->get_ascii_code()) {
+ case 'i':
+ if (fm->has_ligature(font::LIG_ffi))
+ ci = get_charinfo(SYMBOL_Fi);
+ break;
+ case 'l':
+ if (fm->has_ligature(font::LIG_ffl))
+ ci = get_charinfo(SYMBOL_Fl);
+ break;
+ }
+ }
+ if (ci != 0 && fm->contains(ci->get_index()))
+ return ci;
+ return 0;
+}
+
+inline int tfont::get_kern(charinfo *c1, charinfo *c2, hunits *res)
+{
+ if (kern_mode == 0)
+ return 0;
+ else {
+ int n = fm->get_kern(c1->get_index(),
+ c2->get_index(),
+ size.to_scaled_points());
+ if (n) {
+ *res = hunits(n);
+ return 1;
+ }
+ else
+ return 0;
+ }
+}
+
+tfont *make_tfont(tfont_spec &spec)
+{
+ for (tfont *p = tfont::tfont_list; p; p = p->next)
+ if (*p == spec)
+ return p;
+ return new tfont(spec);
+}
+
+tfont *tfont::tfont_list = 0;
+
+tfont::tfont(tfont_spec &spec) : tfont_spec(spec)
+{
+ next = tfont_list;
+ tfont_list = this;
+ tfont_spec plain_spec = plain();
+ tfont *p;
+ for (p = tfont_list; p; p = p->next)
+ if (*p == plain_spec) {
+ plain_version = p;
+ break;
+ }
+ if (!p)
+ plain_version = new tfont(plain_spec);
+}
+
+/* output_file */
+
+class real_output_file : public output_file {
+#ifndef POPEN_MISSING
+ int piped;
+#endif
+ int printing;
+ virtual void really_transparent_char(unsigned char) = 0;
+ virtual void really_print_line(hunits x, vunits y, node *n,
+ vunits before, vunits after) = 0;
+ virtual void really_begin_page(int pageno, vunits page_length) = 0;
+ virtual void really_copy_file(hunits x, vunits y, const char *filename);
+ virtual void really_put_filename(const char *filename);
+protected:
+ FILE *fp;
+public:
+ real_output_file();
+ ~real_output_file();
+ void flush();
+ void transparent_char(unsigned char);
+ void print_line(hunits x, vunits y, node *n, vunits before, vunits after);
+ void begin_page(int pageno, vunits page_length);
+ void put_filename(const char *filename);
+ int is_printing();
+ void copy_file(hunits x, vunits y, const char *filename);
+};
+
+class suppress_output_file : public real_output_file {
+public:
+ suppress_output_file();
+ void really_transparent_char(unsigned char);
+ void really_print_line(hunits x, vunits y, node *n, vunits, vunits);
+ void really_begin_page(int pageno, vunits page_length);
+};
+
+class ascii_output_file : public real_output_file {
+public:
+ ascii_output_file();
+ void really_transparent_char(unsigned char);
+ void really_print_line(hunits x, vunits y, node *n, vunits, vunits);
+ void really_begin_page(int pageno, vunits page_length);
+ void outc(unsigned char c);
+ void outs(const char *s);
+};
+
+void ascii_output_file::outc(unsigned char c)
+{
+ fputc(c, fp);
+}
+
+void ascii_output_file::outs(const char *s)
+{
+ fputc('<', fp);
+ if (s)
+ fputs(s, fp);
+ fputc('>', fp);
+}
+
+struct hvpair;
+
+class troff_output_file : public real_output_file {
+ units hpos;
+ units vpos;
+ units output_vpos;
+ units output_hpos;
+ int force_motion;
+ int current_size;
+ int current_slant;
+ int current_height;
+ tfont *current_tfont;
+ int current_font_number;
+ symbol *font_position;
+ int nfont_positions;
+ enum { TBUF_SIZE = 256 };
+ char tbuf[TBUF_SIZE];
+ int tbuf_len;
+ int tbuf_kern;
+ int begun_page;
+ void do_motion();
+ void put(char c);
+ void put(unsigned char c);
+ void put(int i);
+ void put(const char *s);
+ void set_font(tfont *tf);
+ void flush_tbuf();
+public:
+ troff_output_file();
+ ~troff_output_file();
+ void trailer(vunits page_length);
+ void put_char(charinfo *ci, tfont *tf);
+ void put_char_width(charinfo *ci, tfont *tf, hunits w, hunits k);
+ void right(hunits);
+ void down(vunits);
+ void moveto(hunits, vunits);
+ void start_special();
+ void special_char(unsigned char c);
+ void end_special();
+ void word_marker();
+ void really_transparent_char(unsigned char c);
+ void really_print_line(hunits x, vunits y, node *n, vunits before, vunits after);
+ void really_begin_page(int pageno, vunits page_length);
+ void really_copy_file(hunits x, vunits y, const char *filename);
+ void really_put_filename(const char *filename);
+ void draw(char, hvpair *, int, font_size);
+ int get_hpos() { return hpos; }
+ int get_vpos() { return vpos; }
+};
+
+static void put_string(const char *s, FILE *fp)
+{
+ for (; *s != '\0'; ++s)
+ putc(*s, fp);
+}
+
+inline void troff_output_file::put(char c)
+{
+ putc(c, fp);
+}
+
+inline void troff_output_file::put(unsigned char c)
+{
+ putc(c, fp);
+}
+
+inline void troff_output_file::put(const char *s)
+{
+ put_string(s, fp);
+}
+
+inline void troff_output_file::put(int i)
+{
+ put_string(itoa(i), fp);
+}
+
+void troff_output_file::start_special()
+{
+ flush_tbuf();
+ do_motion();
+ put("x X ");
+}
+
+void troff_output_file::special_char(unsigned char c)
+{
+ put(c);
+ if (c == '\n')
+ put('+');
+}
+
+void troff_output_file::end_special()
+{
+ put('\n');
+}
+
+inline void troff_output_file::moveto(hunits h, vunits v)
+{
+ hpos = h.to_units();
+ vpos = v.to_units();
+}
+
+void troff_output_file::really_print_line(hunits x, vunits y, node *n,
+ vunits before, vunits after)
+{
+ moveto(x, y);
+ while (n != 0) {
+ n->tprint(this);
+ n = n->next;
+ }
+ flush_tbuf();
+ // This ensures that transparent throughput will have a more predictable
+ // position.
+ do_motion();
+ force_motion = 1;
+ hpos = 0;
+ put('n');
+ put(before.to_units());
+ put(' ');
+ put(after.to_units());
+ put('\n');
+}
+
+inline void troff_output_file::word_marker()
+{
+ flush_tbuf();
+ put('w');
+}
+
+inline void troff_output_file::right(hunits n)
+{
+ hpos += n.to_units();
+}
+
+inline void troff_output_file::down(vunits n)
+{
+ vpos += n.to_units();
+}
+
+void troff_output_file::do_motion()
+{
+ if (force_motion) {
+ put('V');
+ put(vpos);
+ put('\n');
+ put('H');
+ put(hpos);
+ put('\n');
+ }
+ else {
+ if (hpos != output_hpos) {
+ units n = hpos - output_hpos;
+ if (n > 0 && n < hpos) {
+ put('h');
+ put(n);
+ }
+ else {
+ put('H');
+ put(hpos);
+ }
+ put('\n');
+ }
+ if (vpos != output_vpos) {
+ units n = vpos - output_vpos;
+ if (n > 0 && n < vpos) {
+ put('v');
+ put(n);
+ }
+ else {
+ put('V');
+ put(vpos);
+ }
+ put('\n');
+ }
+ }
+ output_vpos = vpos;
+ output_hpos = hpos;
+ force_motion = 0;
+}
+
+void troff_output_file::flush_tbuf()
+{
+ if (tbuf_len == 0)
+ return;
+ if (tbuf_kern == 0)
+ put('t');
+ else {
+ put('u');
+ put(tbuf_kern);
+ put(' ');
+ }
+ for (int i = 0; i < tbuf_len; i++)
+ put(tbuf[i]);
+ put('\n');
+ tbuf_len = 0;
+}
+
+void troff_output_file::put_char_width(charinfo *ci, tfont *tf, hunits w,
+ hunits k)
+{
+ if (tf != current_tfont) {
+ flush_tbuf();
+ set_font(tf);
+ }
+ char c = ci->get_ascii_code();
+ int kk = k.to_units();
+ if (c == '\0') {
+ flush_tbuf();
+ do_motion();
+ if (ci->numbered()) {
+ put('N');
+ put(ci->get_number());
+ }
+ else {
+ put('C');
+ const char *s = ci->nm.contents();
+ if (s[1] == 0) {
+ put('\\');
+ put(s[0]);
+ }
+ else
+ put(s);
+ }
+ put('\n');
+ hpos += w.to_units() + kk;
+ }
+ else if (tcommand_flag) {
+ if (tbuf_len > 0 && hpos == output_hpos && vpos == output_vpos
+ && kk == tbuf_kern
+ && tbuf_len < TBUF_SIZE) {
+ tbuf[tbuf_len++] = c;
+ output_hpos += w.to_units() + kk;
+ hpos = output_hpos;
+ return;
+ }
+ flush_tbuf();
+ do_motion();
+ tbuf[tbuf_len++] = c;
+ output_hpos += w.to_units() + kk;
+ tbuf_kern = kk;
+ hpos = output_hpos;
+ }
+ else {
+ // flush_tbuf();
+ int n = hpos - output_hpos;
+ if (vpos == output_vpos && n > 0 && n < 100 && !force_motion) {
+ put(char(n/10 + '0'));
+ put(char(n%10 + '0'));
+ put(c);
+ output_hpos = hpos;
+ }
+ else {
+ do_motion();
+ put('c');
+ put(c);
+ }
+ hpos += w.to_units() + kk;
+ }
+}
+
+void troff_output_file::put_char(charinfo *ci, tfont *tf)
+{
+ flush_tbuf();
+ if (tf != current_tfont)
+ set_font(tf);
+ char c = ci->get_ascii_code();
+ if (c == '\0') {
+ do_motion();
+ if (ci->numbered()) {
+ put('N');
+ put(ci->get_number());
+ }
+ else {
+ put('C');
+ const char *s = ci->nm.contents();
+ if (s[1] == 0) {
+ put('\\');
+ put(s[0]);
+ }
+ else
+ put(s);
+ }
+ put('\n');
+ }
+ else {
+ int n = hpos - output_hpos;
+ if (vpos == output_vpos && n > 0 && n < 100) {
+ put(char(n/10 + '0'));
+ put(char(n%10 + '0'));
+ put(c);
+ output_hpos = hpos;
+ }
+ else {
+ do_motion();
+ put('c');
+ put(c);
+ }
+ }
+}
+
+void troff_output_file::set_font(tfont *tf)
+{
+ if (current_tfont == tf)
+ return;
+ int n = tf->get_input_position();
+ symbol nm = tf->get_name();
+ if (n >= nfont_positions || font_position[n] != nm) {
+ put("x font ");
+ put(n);
+ put(' ');
+ put(nm.contents());
+ put('\n');
+ if (n >= nfont_positions) {
+ int old_nfont_positions = nfont_positions;
+ symbol *old_font_position = font_position;
+ nfont_positions *= 3;
+ nfont_positions /= 2;
+ if (nfont_positions <= n)
+ nfont_positions = n + 10;
+ font_position = new symbol[nfont_positions];
+ memcpy(font_position, old_font_position,
+ old_nfont_positions*sizeof(symbol));
+ a_delete old_font_position;
+ }
+ font_position[n] = nm;
+ }
+ if (current_font_number != n) {
+ put('f');
+ put(n);
+ put('\n');
+ current_font_number = n;
+ }
+ int size = tf->get_size().to_scaled_points();
+ if (current_size != size) {
+ put('s');
+ put(size);
+ put('\n');
+ current_size = size;
+ }
+ int slant = tf->get_slant();
+ if (current_slant != slant) {
+ put("x Slant ");
+ put(slant);
+ put('\n');
+ current_slant = slant;
+ }
+ int height = tf->get_height();
+ if (current_height != height) {
+ put("x Height ");
+ put(height == 0 ? current_size : height);
+ put('\n');
+ current_height = height;
+ }
+ current_tfont = tf;
+}
+
+void troff_output_file::draw(char code, hvpair *point, int npoints,
+ font_size fsize)
+{
+ flush_tbuf();
+ do_motion();
+ int size = fsize.to_scaled_points();
+ if (current_size != size) {
+ put('s');
+ put(size);
+ put('\n');
+ current_size = size;
+ current_tfont = 0;
+ }
+ put('D');
+ put(code);
+ int i;
+ if (code == 'c') {
+ put(' ');
+ put(point[0].h.to_units());
+ }
+ else
+ for (i = 0; i < npoints; i++) {
+ put(' ');
+ put(point[i].h.to_units());
+ put(' ');
+ put(point[i].v.to_units());
+ }
+ for (i = 0; i < npoints; i++)
+ output_hpos += point[i].h.to_units();
+ hpos = output_hpos;
+ if (code != 'e') {
+ for (i = 0; i < npoints; i++)
+ output_vpos += point[i].v.to_units();
+ vpos = output_vpos;
+ }
+ put('\n');
+}
+
+void troff_output_file::really_put_filename(const char *filename)
+{
+ flush_tbuf();
+ put("F ");
+ put(filename);
+ put('\n');
+}
+
+void troff_output_file::really_begin_page(int pageno, vunits page_length)
+{
+ flush_tbuf();
+ if (begun_page) {
+ if (page_length > V0) {
+ put('V');
+ put(page_length.to_units());
+ put('\n');
+ }
+ }
+ else
+ begun_page = 1;
+ current_tfont = 0;
+ current_font_number = -1;
+ current_size = 0;
+ // current_height = 0;
+ // current_slant = 0;
+ hpos = 0;
+ vpos = 0;
+ output_hpos = 0;
+ output_vpos = 0;
+ force_motion = 1;
+ for (int i = 0; i < nfont_positions; i++)
+ font_position[i] = NULL_SYMBOL;
+ put('p');
+ put(pageno);
+ put('\n');
+}
+
+void troff_output_file::really_copy_file(hunits x, vunits y, const char *filename)
+{
+ moveto(x, y);
+ flush_tbuf();
+ do_motion();
+ errno = 0;
+ FILE *ifp = fopen(filename, "r");
+ if (ifp == 0)
+ error("can't open `%1': %2", filename, strerror(errno));
+ else {
+ int c;
+ while ((c = getc(ifp)) != EOF)
+ put(char(c));
+ fclose(ifp);
+ }
+ force_motion = 1;
+ current_size = 0;
+ current_tfont = 0;
+ current_font_number = -1;
+ for (int i = 0; i < nfont_positions; i++)
+ font_position[i] = NULL_SYMBOL;
+}
+
+void troff_output_file::really_transparent_char(unsigned char c)
+{
+ put(c);
+}
+
+troff_output_file::~troff_output_file()
+{
+ a_delete font_position;
+}
+
+void troff_output_file::trailer(vunits page_length)
+{
+ flush_tbuf();
+ if (page_length > V0) {
+ put("x trailer\n");
+ put('V');
+ put(page_length.to_units());
+ put('\n');
+ }
+ put("x stop\n");
+}
+
+troff_output_file::troff_output_file()
+: current_slant(0), current_height(0), nfont_positions(10), tbuf_len(0),
+ begun_page(0)
+{
+ font_position = new symbol[nfont_positions];
+ put("x T ");
+ put(device);
+ put('\n');
+ put("x res ");
+ put(units_per_inch);
+ put(' ');
+ put(hresolution);
+ put(' ');
+ put(vresolution);
+ put('\n');
+ put("x init\n");
+}
+
+/* output_file */
+
+output_file *the_output = 0;
+
+output_file::output_file()
+{
+}
+
+output_file::~output_file()
+{
+}
+
+void output_file::trailer(vunits)
+{
+}
+
+
+void output_file::put_filename(const char *filename)
+{
+}
+
+real_output_file::real_output_file()
+: printing(0)
+{
+#ifndef POPEN_MISSING
+ if (pipe_command) {
+ if ((fp = popen(pipe_command, "w")) != 0) {
+ piped = 1;
+ return;
+ }
+ error("pipe open failed: %1", strerror(errno));
+ }
+ piped = 0;
+#endif /* not POPEN_MISSING */
+ fp = stdout;
+}
+
+real_output_file::~real_output_file()
+{
+ if (!fp)
+ return;
+ // To avoid looping, set fp to 0 before calling fatal().
+ if (ferror(fp) || fflush(fp) < 0) {
+ fp = 0;
+ fatal("error writing output file");
+ }
+#ifndef POPEN_MISSING
+ if (piped) {
+ int result = pclose(fp);
+ fp = 0;
+ if (result < 0)
+ fatal("pclose failed");
+ if ((result & 0x7f) != 0)
+ error("output process `%1' got fatal signal %2",
+ pipe_command, result & 0x7f);
+ else {
+ int exit_status = (result >> 8) & 0xff;
+ if (exit_status != 0)
+ error("output process `%1' exited with status %2",
+ pipe_command, exit_status);
+ }
+ }
+ else
+#endif /* not POPEN MISSING */
+ if (fclose(fp) < 0) {
+ fp = 0;
+ fatal("error closing output file");
+ }
+}
+
+void real_output_file::flush()
+{
+ if (fflush(fp) < 0)
+ fatal("error writing output file");
+}
+
+int real_output_file::is_printing()
+{
+ return printing;
+}
+
+void real_output_file::begin_page(int pageno, vunits page_length)
+{
+ printing = in_output_page_list(pageno);
+ if (printing)
+ really_begin_page(pageno, page_length);
+}
+
+void real_output_file::copy_file(hunits x, vunits y, const char *filename)
+{
+ if (printing)
+ really_copy_file(x, y, filename);
+}
+
+void real_output_file::transparent_char(unsigned char c)
+{
+ if (printing)
+ really_transparent_char(c);
+}
+
+void real_output_file::print_line(hunits x, vunits y, node *n,
+ vunits before, vunits after)
+{
+ if (printing)
+ really_print_line(x, y, n, before, after);
+ delete_node_list(n);
+}
+
+void real_output_file::really_copy_file(hunits, vunits, const char *)
+{
+ // do nothing
+}
+
+void real_output_file::put_filename(const char *filename)
+{
+ really_put_filename(filename);
+}
+
+void real_output_file::really_put_filename(const char *filename)
+{
+}
+
+/* ascii_output_file */
+
+void ascii_output_file::really_transparent_char(unsigned char c)
+{
+ putc(c, fp);
+}
+
+void ascii_output_file::really_print_line(hunits, vunits, node *n, vunits, vunits)
+{
+ while (n != 0) {
+ n->ascii_print(this);
+ n = n->next;
+ }
+ fputc('\n', fp);
+}
+
+void ascii_output_file::really_begin_page(int /*pageno*/, vunits /*page_length*/)
+{
+ fputs("<beginning of page>\n", fp);
+}
+
+ascii_output_file::ascii_output_file()
+{
+}
+
+/* suppress_output_file */
+
+suppress_output_file::suppress_output_file()
+{
+}
+
+void suppress_output_file::really_print_line(hunits, vunits, node *, vunits, vunits)
+{
+}
+
+void suppress_output_file::really_begin_page(int, vunits)
+{
+}
+
+void suppress_output_file::really_transparent_char(unsigned char)
+{
+}
+
+/* glyphs, ligatures, kerns, discretionary breaks */
+
+class charinfo_node : public node {
+protected:
+ charinfo *ci;
+public:
+ charinfo_node(charinfo *, node * = 0);
+ int ends_sentence();
+ int overlaps_vertically();
+ int overlaps_horizontally();
+};
+
+charinfo_node::charinfo_node(charinfo *c, node *x)
+: node(x), ci(c)
+{
+}
+
+int charinfo_node::ends_sentence()
+{
+ if (ci->ends_sentence())
+ return 1;
+ else if (ci->transparent())
+ return 2;
+ else
+ return 0;
+}
+
+int charinfo_node::overlaps_horizontally()
+{
+ return ci->overlaps_horizontally();
+}
+
+int charinfo_node::overlaps_vertically()
+{
+ return ci->overlaps_vertically();
+}
+
+class glyph_node : public charinfo_node {
+ static glyph_node *free_list;
+protected:
+ tfont *tf;
+#ifdef STORE_WIDTH
+ hunits wid;
+ glyph_node(charinfo *, tfont *, hunits, node * = 0);
+#endif
+public:
+ void *operator new(size_t);
+ void operator delete(void *);
+ glyph_node(charinfo *, tfont *, node * = 0);
+ ~glyph_node() {}
+ node *copy();
+ node *merge_glyph_node(glyph_node *);
+ node *merge_self(node *);
+ hunits width();
+ node *last_char_node();
+ units size();
+ void vertical_extent(vunits *, vunits *);
+ hunits subscript_correction();
+ hunits italic_correction();
+ hunits left_italic_correction();
+ hunits skew();
+ hyphenation_type get_hyphenation_type();
+ tfont *get_tfont();
+ void tprint(troff_output_file *);
+ void zero_width_tprint(troff_output_file *);
+ hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
+ node *add_self(node *, hyphen_list **);
+ void ascii_print(ascii_output_file *);
+ void asciify(macro *);
+ int character_type();
+ int same(node *);
+ const char *type();
+};
+
+glyph_node *glyph_node::free_list = 0;
+
+class ligature_node : public glyph_node {
+ node *n1;
+ node *n2;
+#ifdef STORE_WIDTH
+ ligature_node(charinfo *, tfont *, hunits, node *gn1, node *gn2, node *x = 0);
+#endif
+public:
+ void *operator new(size_t);
+ void operator delete(void *);
+ ligature_node(charinfo *, tfont *, node *gn1, node *gn2, node *x = 0);
+ ~ligature_node();
+ node *copy();
+ node *add_self(node *, hyphen_list **);
+ hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
+ void ascii_print(ascii_output_file *);
+ void asciify(macro *);
+ int same(node *);
+ const char *type();
+};
+
+class kern_pair_node : public node {
+ hunits amount;
+ node *n1;
+ node *n2;
+public:
+ kern_pair_node(hunits n, node *first, node *second, node *x = 0);
+ ~kern_pair_node();
+ node *copy();
+ node *merge_glyph_node(glyph_node *);
+ node *add_self(node *, hyphen_list **);
+ hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
+ node *add_discretionary_hyphen();
+ hunits width();
+ node *last_char_node();
+ hunits italic_correction();
+ hunits subscript_correction();
+ void tprint(troff_output_file *);
+ hyphenation_type get_hyphenation_type();
+ int ends_sentence();
+ void ascii_print(ascii_output_file *);
+ void asciify(macro *);
+ int same(node *);
+ const char *type();
+ void vertical_extent(vunits *, vunits *);
+};
+
+class dbreak_node : public node {
+ node *none;
+ node *pre;
+ node *post;
+public:
+ dbreak_node(node *n, node *p, node *x = 0);
+ ~dbreak_node();
+ node *copy();
+ node *merge_glyph_node(glyph_node *);
+ node *add_discretionary_hyphen();
+ hunits width();
+ node *last_char_node();
+ hunits italic_correction();
+ hunits subscript_correction();
+ void tprint(troff_output_file *);
+ breakpoint *get_breakpoints(hunits width, int ns, breakpoint *rest = 0,
+ int is_inner = 0);
+ int nbreaks();
+ int ends_sentence();
+ void split(int, node **, node **);
+ hyphenation_type get_hyphenation_type();
+ void ascii_print(ascii_output_file *);
+ void asciify(macro *);
+ int same(node *);
+ const char *type();
+};
+
+void *glyph_node::operator new(size_t n)
+{
+ assert(n == sizeof(glyph_node));
+ if (!free_list) {
+ const int BLOCK = 1024;
+ free_list = (glyph_node *)new char[sizeof(glyph_node)*BLOCK];
+ for (int i = 0; i < BLOCK - 1; i++)
+ free_list[i].next = free_list + i + 1;
+ free_list[BLOCK-1].next = 0;
+ }
+ glyph_node *p = free_list;
+ free_list = (glyph_node *)(free_list->next);
+ p->next = 0;
+ return p;
+}
+
+void *ligature_node::operator new(size_t n)
+{
+ return new char[n];
+}
+
+void glyph_node::operator delete(void *p)
+{
+ if (p) {
+ ((glyph_node *)p)->next = free_list;
+ free_list = (glyph_node *)p;
+ }
+}
+
+void ligature_node::operator delete(void *p)
+{
+ delete[] (char *)p;
+}
+
+glyph_node::glyph_node(charinfo *c, tfont *t, node *x)
+: charinfo_node(c, x), tf(t)
+{
+#ifdef STORE_WIDTH
+ wid = tf->get_width(ci);
+#endif
+}
+
+#ifdef STORE_WIDTH
+glyph_node::glyph_node(charinfo *c, tfont *t, hunits w, node *x)
+: charinfo_node(c, x), tf(t), wid(w)
+{
+}
+#endif
+
+node *glyph_node::copy()
+{
+#ifdef STORE_WIDTH
+ return new glyph_node(ci, tf, wid);
+#else
+ return new glyph_node(ci, tf);
+#endif
+}
+
+node *glyph_node::merge_self(node *nd)
+{
+ return nd->merge_glyph_node(this);
+}
+
+int glyph_node::character_type()
+{
+ return tf->get_character_type(ci);
+}
+
+node *glyph_node::add_self(node *n, hyphen_list **p)
+{
+ assert(ci->get_hyphenation_code() == (*p)->hyphenation_code);
+ next = 0;
+ node *nn;
+ if (n == 0 || (nn = n->merge_glyph_node(this)) == 0) {
+ next = n;
+ nn = this;
+ }
+ if ((*p)->hyphen)
+ nn = nn->add_discretionary_hyphen();
+ hyphen_list *pp = *p;
+ *p = (*p)->next;
+ delete pp;
+ return nn;
+}
+
+units glyph_node::size()
+{
+ return tf->get_size().to_units();
+}
+
+hyphen_list *glyph_node::get_hyphen_list(hyphen_list *tail)
+{
+ return new hyphen_list(ci->get_hyphenation_code(), tail);
+}
+
+
+tfont *node::get_tfont()
+{
+ return 0;
+}
+
+tfont *glyph_node::get_tfont()
+{
+ return tf;
+}
+
+node *node::merge_glyph_node(glyph_node * /*gn*/)
+{
+ return 0;
+}
+
+node *glyph_node::merge_glyph_node(glyph_node *gn)
+{
+ if (tf == gn->tf) {
+ charinfo *lig;
+ if ((lig = tf->get_lig(ci, gn->ci)) != 0) {
+ node *next1 = next;
+ next = 0;
+ return new ligature_node(lig, tf, this, gn, next1);
+ }
+ hunits kern;
+ if (tf->get_kern(ci, gn->ci, &kern)) {
+ node *next1 = next;
+ next = 0;
+ return new kern_pair_node(kern, this, gn, next1);
+ }
+ }
+ return 0;
+}
+
+#ifdef STORE_WIDTH
+inline
+#endif
+hunits glyph_node::width()
+{
+#ifdef STORE_WIDTH
+ return wid;
+#else
+ return tf->get_width(ci);
+#endif
+}
+
+node *glyph_node::last_char_node()
+{
+ return this;
+}
+
+void glyph_node::vertical_extent(vunits *min, vunits *max)
+{
+ *min = -tf->get_char_height(ci);
+ *max = tf->get_char_depth(ci);
+}
+
+hunits glyph_node::skew()
+{
+ return tf->get_char_skew(ci);
+}
+
+hunits glyph_node::subscript_correction()
+{
+ return tf->get_subscript_correction(ci);
+}
+
+hunits glyph_node::italic_correction()
+{
+ return tf->get_italic_correction(ci);
+}
+
+hunits glyph_node::left_italic_correction()
+{
+ return tf->get_left_italic_correction(ci);
+}
+
+hyphenation_type glyph_node::get_hyphenation_type()
+{
+ return HYPHEN_MIDDLE;
+}
+
+void glyph_node::ascii_print(ascii_output_file *ascii)
+{
+ unsigned char c = ci->get_ascii_code();
+ if (c != 0)
+ ascii->outc(c);
+ else
+ ascii->outs(ci->nm.contents());
+}
+
+ligature_node::ligature_node(charinfo *c, tfont *t,
+ node *gn1, node *gn2, node *x)
+ : glyph_node(c, t, x), n1(gn1), n2(gn2)
+{
+}
+
+#ifdef STORE_WIDTH
+ligature_node::ligature_node(charinfo *c, tfont *t, hunits w,
+ node *gn1, node *gn2, node *x)
+ : glyph_node(c, t, w, x), n1(gn1), n2(gn2)
+{
+}
+#endif
+
+ligature_node::~ligature_node()
+{
+ delete n1;
+ delete n2;
+}
+
+node *ligature_node::copy()
+{
+#ifdef STORE_WIDTH
+ return new ligature_node(ci, tf, wid, n1->copy(), n2->copy());
+#else
+ return new ligature_node(ci, tf, n1->copy(), n2->copy());
+#endif
+}
+
+void ligature_node::ascii_print(ascii_output_file *ascii)
+{
+ n1->ascii_print(ascii);
+ n2->ascii_print(ascii);
+}
+
+hyphen_list *ligature_node::get_hyphen_list(hyphen_list *tail)
+{
+ return n1->get_hyphen_list(n2->get_hyphen_list(tail));
+}
+
+node *ligature_node::add_self(node *n, hyphen_list **p)
+{
+ n = n1->add_self(n, p);
+ n = n2->add_self(n, p);
+ n1 = n2 = 0;
+ delete this;
+ return n;
+}
+
+kern_pair_node::kern_pair_node(hunits n, node *first, node *second, node *x)
+ : node(x), amount(n), n1(first), n2(second)
+{
+}
+
+dbreak_node::dbreak_node(node *n, node *p, node *x)
+ : node(x), none(n), pre(p), post(0)
+{
+}
+
+node *dbreak_node::merge_glyph_node(glyph_node *gn)
+{
+ glyph_node *gn2 = (glyph_node *)gn->copy();
+ node *new_none = none ? none->merge_glyph_node(gn) : 0;
+ node *new_post = post ? post->merge_glyph_node(gn2) : 0;
+ if (new_none == 0 && new_post == 0) {
+ delete gn2;
+ return 0;
+ }
+ if (new_none != 0)
+ none = new_none;
+ else {
+ gn->next = none;
+ none = gn;
+ }
+ if (new_post != 0)
+ post = new_post;
+ else {
+ gn2->next = post;
+ post = gn2;
+ }
+ return this;
+}
+
+node *kern_pair_node::merge_glyph_node(glyph_node *gn)
+{
+ node *nd = n2->merge_glyph_node(gn);
+ if (nd == 0)
+ return 0;
+ n2 = nd;
+ nd = n2->merge_self(n1);
+ if (nd) {
+ nd->next = next;
+ n1 = 0;
+ n2 = 0;
+ delete this;
+ return nd;
+ }
+ return this;
+}
+
+
+hunits kern_pair_node::italic_correction()
+{
+ return n2->italic_correction();
+}
+
+hunits kern_pair_node::subscript_correction()
+{
+ return n2->subscript_correction();
+}
+
+void kern_pair_node::vertical_extent(vunits *min, vunits *max)
+{
+ n1->vertical_extent(min, max);
+ vunits min2, max2;
+ n2->vertical_extent(&min2, &max2);
+ if (min2 < *min)
+ *min = min2;
+ if (max2 > *max)
+ *max = max2;
+}
+
+node *kern_pair_node::add_discretionary_hyphen()
+{
+ tfont *tf = n2->get_tfont();
+ if (tf) {
+ if (tf->contains(soft_hyphen_char)) {
+ node *next1 = next;
+ next = 0;
+ node *n = copy();
+ glyph_node *gn = new glyph_node(soft_hyphen_char, tf);
+ node *nn = n->merge_glyph_node(gn);
+ if (nn == 0) {
+ gn->next = n;
+ nn = gn;
+ }
+ return new dbreak_node(this, nn, next1);
+ }
+ }
+ return this;
+}
+
+
+kern_pair_node::~kern_pair_node()
+{
+ if (n1 != 0)
+ delete n1;
+ if (n2 != 0)
+ delete n2;
+}
+
+dbreak_node::~dbreak_node()
+{
+ delete_node_list(pre);
+ delete_node_list(post);
+ delete_node_list(none);
+}
+
+node *kern_pair_node::copy()
+{
+ return new kern_pair_node(amount, n1->copy(), n2->copy());
+}
+
+node *copy_node_list(node *n)
+{
+ node *p = 0;
+ while (n != 0) {
+ node *nn = n->copy();
+ nn->next = p;
+ p = nn;
+ n = n->next;
+ }
+ while (p != 0) {
+ node *pp = p->next;
+ p->next = n;
+ n = p;
+ p = pp;
+ }
+ return n;
+}
+
+void delete_node_list(node *n)
+{
+ while (n != 0) {
+ node *tem = n;
+ n = n->next;
+ delete tem;
+ }
+}
+
+node *dbreak_node::copy()
+{
+ dbreak_node *p = new dbreak_node(copy_node_list(none), copy_node_list(pre));
+ p->post = copy_node_list(post);
+ return p;
+}
+
+hyphen_list *node::get_hyphen_list(hyphen_list *tail)
+{
+ return tail;
+}
+
+
+hyphen_list *kern_pair_node::get_hyphen_list(hyphen_list *tail)
+{
+ return n1->get_hyphen_list(n2->get_hyphen_list(tail));
+}
+
+class hyphen_inhibitor_node : public node {
+public:
+ hyphen_inhibitor_node(node *nd = 0);
+ node *copy();
+ int same(node *);
+ const char *type();
+ hyphenation_type get_hyphenation_type();
+};
+
+hyphen_inhibitor_node::hyphen_inhibitor_node(node *nd) : node(nd)
+{
+}
+
+node *hyphen_inhibitor_node::copy()
+{
+ return new hyphen_inhibitor_node;
+}
+
+int hyphen_inhibitor_node::same(node *)
+{
+ return 1;
+}
+
+const char *hyphen_inhibitor_node::type()
+{
+ return "hyphen_inhibitor_node";
+}
+
+hyphenation_type hyphen_inhibitor_node::get_hyphenation_type()
+{
+ return HYPHEN_INHIBIT;
+}
+
+/* add_discretionary_hyphen methods */
+
+node *dbreak_node::add_discretionary_hyphen()
+{
+ if (post)
+ post = post->add_discretionary_hyphen();
+ if (none)
+ none = none->add_discretionary_hyphen();
+ return this;
+}
+
+
+node *node::add_discretionary_hyphen()
+{
+ tfont *tf = get_tfont();
+ if (!tf)
+ return new hyphen_inhibitor_node(this);
+ if (tf->contains(soft_hyphen_char)) {
+ node *next1 = next;
+ next = 0;
+ node *n = copy();
+ glyph_node *gn = new glyph_node(soft_hyphen_char, tf);
+ node *n1 = n->merge_glyph_node(gn);
+ if (n1 == 0) {
+ gn->next = n;
+ n1 = gn;
+ }
+ return new dbreak_node(this, n1, next1);
+ }
+ return this;
+}
+
+
+node *node::merge_self(node *)
+{
+ return 0;
+}
+
+node *node::add_self(node *n, hyphen_list ** /*p*/)
+{
+ next = n;
+ return this;
+}
+
+node *kern_pair_node::add_self(node *n, hyphen_list **p)
+{
+ n = n1->add_self(n, p);
+ n = n2->add_self(n, p);
+ n1 = n2 = 0;
+ delete this;
+ return n;
+}
+
+
+hunits node::width()
+{
+ return H0;
+}
+
+node *node::last_char_node()
+{
+ return 0;
+}
+
+hunits hmotion_node::width()
+{
+ return n;
+}
+
+units node::size()
+{
+ return points_to_units(10);
+}
+
+hunits kern_pair_node::width()
+{
+ return n1->width() + n2->width() + amount;
+}
+
+node *kern_pair_node::last_char_node()
+{
+ node *nd = n2->last_char_node();
+ if (nd)
+ return nd;
+ return n1->last_char_node();
+}
+
+hunits dbreak_node::width()
+{
+ hunits x = H0;
+ for (node *n = none; n != 0; n = n->next)
+ x += n->width();
+ return x;
+}
+
+node *dbreak_node::last_char_node()
+{
+ for (node *n = none; n; n = n->next) {
+ node *last = n->last_char_node();
+ if (last)
+ return last;
+ }
+ return 0;
+}
+
+hunits dbreak_node::italic_correction()
+{
+ return none ? none->italic_correction() : H0;
+}
+
+hunits dbreak_node::subscript_correction()
+{
+ return none ? none->subscript_correction() : H0;
+}
+
+class italic_corrected_node : public node {
+ node *n;
+ hunits x;
+public:
+ italic_corrected_node(node *, hunits, node * = 0);
+ ~italic_corrected_node();
+ node *copy();
+ void ascii_print(ascii_output_file *);
+ void asciify(macro *m);
+ hunits width();
+ node *last_char_node();
+ void vertical_extent(vunits *, vunits *);
+ int ends_sentence();
+ int overlaps_horizontally();
+ int overlaps_vertically();
+ int same(node *);
+ hyphenation_type get_hyphenation_type();
+ tfont *get_tfont();
+ hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
+ int character_type();
+ void tprint(troff_output_file *);
+ hunits subscript_correction();
+ hunits skew();
+ node *add_self(node *, hyphen_list **);
+ const char *type();
+};
+
+node *node::add_italic_correction(hunits *width)
+{
+ hunits ic = italic_correction();
+ if (ic.is_zero())
+ return this;
+ else {
+ node *next1 = next;
+ next = 0;
+ *width += ic;
+ return new italic_corrected_node(this, ic, next1);
+ }
+}
+
+italic_corrected_node::italic_corrected_node(node *nn, hunits xx, node *p)
+: node(p), n(nn), x(xx)
+{
+ assert(n != 0);
+}
+
+italic_corrected_node::~italic_corrected_node()
+{
+ delete n;
+}
+
+node *italic_corrected_node::copy()
+{
+ return new italic_corrected_node(n->copy(), x);
+}
+
+hunits italic_corrected_node::width()
+{
+ return n->width() + x;
+}
+
+void italic_corrected_node::vertical_extent(vunits *min, vunits *max)
+{
+ n->vertical_extent(min, max);
+}
+
+void italic_corrected_node::tprint(troff_output_file *out)
+{
+ n->tprint(out);
+ out->right(x);
+}
+
+hunits italic_corrected_node::skew()
+{
+ return n->skew() - x/2;
+}
+
+hunits italic_corrected_node::subscript_correction()
+{
+ return n->subscript_correction() - x;
+}
+
+void italic_corrected_node::ascii_print(ascii_output_file *out)
+{
+ n->ascii_print(out);
+}
+
+int italic_corrected_node::ends_sentence()
+{
+ return n->ends_sentence();
+}
+
+int italic_corrected_node::overlaps_horizontally()
+{
+ return n->overlaps_horizontally();
+}
+
+int italic_corrected_node::overlaps_vertically()
+{
+ return n->overlaps_vertically();
+}
+
+node *italic_corrected_node::last_char_node()
+{
+ return n->last_char_node();
+}
+
+tfont *italic_corrected_node::get_tfont()
+{
+ return n->get_tfont();
+}
+
+hyphenation_type italic_corrected_node::get_hyphenation_type()
+{
+ return n->get_hyphenation_type();
+}
+
+node *italic_corrected_node::add_self(node *nd, hyphen_list **p)
+{
+ nd = n->add_self(nd, p);
+ hunits not_interested;
+ nd = nd->add_italic_correction(&not_interested);
+ n = 0;
+ delete this;
+ return nd;
+}
+
+hyphen_list *italic_corrected_node::get_hyphen_list(hyphen_list *tail)
+{
+ return n->get_hyphen_list(tail);
+}
+
+int italic_corrected_node::character_type()
+{
+ return n->character_type();
+}
+
+class break_char_node : public node {
+ node *ch;
+ char break_code;
+public:
+ break_char_node(node *, int, node * = 0);
+ ~break_char_node();
+ node *copy();
+ hunits width();
+ vunits vertical_width();
+ node *last_char_node();
+ int character_type();
+ int ends_sentence();
+ node *add_self(node *, hyphen_list **);
+ hyphen_list *get_hyphen_list(hyphen_list *s = 0);
+ void tprint(troff_output_file *);
+ void zero_width_tprint(troff_output_file *);
+ void ascii_print(ascii_output_file *);
+ void asciify(macro *m);
+ hyphenation_type get_hyphenation_type();
+ int overlaps_vertically();
+ int overlaps_horizontally();
+ units size();
+ tfont *get_tfont();
+ int same(node *);
+ const char *type();
+};
+
+break_char_node::break_char_node(node *n, int c, node *x)
+: node(x), ch(n), break_code(c)
+{
+}
+
+break_char_node::~break_char_node()
+{
+ delete ch;
+}
+
+node *break_char_node::copy()
+{
+ return new break_char_node(ch->copy(), break_code);
+}
+
+hunits break_char_node::width()
+{
+ return ch->width();
+}
+
+vunits break_char_node::vertical_width()
+{
+ return ch->vertical_width();
+}
+
+node *break_char_node::last_char_node()
+{
+ return ch->last_char_node();
+}
+
+int break_char_node::character_type()
+{
+ return ch->character_type();
+}
+
+int break_char_node::ends_sentence()
+{
+ return ch->ends_sentence();
+}
+
+node *break_char_node::add_self(node *n, hyphen_list **p)
+{
+ assert((*p)->hyphenation_code == 0);
+ if ((*p)->breakable && (break_code & 1)) {
+ n = new space_node(H0, n);
+ n->freeze_space();
+ }
+ next = n;
+ n = this;
+ if ((*p)->breakable && (break_code & 2)) {
+ n = new space_node(H0, n);
+ n->freeze_space();
+ }
+ hyphen_list *pp = *p;
+ *p = (*p)->next;
+ delete pp;
+ return n;
+}
+
+hyphen_list *break_char_node::get_hyphen_list(hyphen_list *tail)
+{
+ return new hyphen_list(0, tail);
+}
+
+hyphenation_type break_char_node::get_hyphenation_type()
+{
+ return HYPHEN_MIDDLE;
+}
+
+void break_char_node::ascii_print(ascii_output_file *ascii)
+{
+ ch->ascii_print(ascii);
+}
+
+int break_char_node::overlaps_vertically()
+{
+ return ch->overlaps_vertically();
+}
+
+int break_char_node::overlaps_horizontally()
+{
+ return ch->overlaps_horizontally();
+}
+
+units break_char_node::size()
+{
+ return ch->size();
+}
+
+tfont *break_char_node::get_tfont()
+{
+ return ch->get_tfont();
+}
+
+node *extra_size_node::copy()
+{
+ return new extra_size_node(n);
+}
+
+node *vertical_size_node::copy()
+{
+ return new vertical_size_node(n);
+}
+
+node *hmotion_node::copy()
+{
+ return new hmotion_node(n);
+}
+
+node *space_char_hmotion_node::copy()
+{
+ return new space_char_hmotion_node(n);
+}
+
+node *vmotion_node::copy()
+{
+ return new vmotion_node(n);
+}
+
+node *dummy_node::copy()
+{
+ return new dummy_node;
+}
+
+node *transparent_dummy_node::copy()
+{
+ return new transparent_dummy_node;
+}
+
+hline_node::~hline_node()
+{
+ if (n)
+ delete n;
+}
+
+node *hline_node::copy()
+{
+ return new hline_node(x, n ? n->copy() : 0);
+}
+
+hunits hline_node::width()
+{
+ return x < H0 ? H0 : x;
+}
+
+
+vline_node::~vline_node()
+{
+ if (n)
+ delete n;
+}
+
+node *vline_node::copy()
+{
+ return new vline_node(x, n ? n->copy() : 0);
+}
+
+hunits vline_node::width()
+{
+ return n == 0 ? H0 : n->width();
+}
+
+
+zero_width_node::zero_width_node(node *nd) : n(nd)
+{
+}
+
+zero_width_node::~zero_width_node()
+{
+ delete_node_list(n);
+}
+
+node *zero_width_node::copy()
+{
+ return new zero_width_node(copy_node_list(n));
+}
+
+int node_list_character_type(node *p)
+{
+ int t = 0;
+ for (; p; p = p->next)
+ t |= p->character_type();
+ return t;
+}
+
+int zero_width_node::character_type()
+{
+ return node_list_character_type(n);
+}
+
+void node_list_vertical_extent(node *p, vunits *min, vunits *max)
+{
+ *min = V0;
+ *max = V0;
+ vunits cur_vpos = V0;
+ vunits v1, v2;
+ for (; p; p = p->next) {
+ p->vertical_extent(&v1, &v2);
+ v1 += cur_vpos;
+ if (v1 < *min)
+ *min = v1;
+ v2 += cur_vpos;
+ if (v2 > *max)
+ *max = v2;
+ cur_vpos += p->vertical_width();
+ }
+}
+
+void zero_width_node::vertical_extent(vunits *min, vunits *max)
+{
+ node_list_vertical_extent(n, min, max);
+}
+
+overstrike_node::overstrike_node() : list(0), max_width(H0)
+{
+}
+
+overstrike_node::~overstrike_node()
+{
+ delete_node_list(list);
+}
+
+node *overstrike_node::copy()
+{
+ overstrike_node *on = new overstrike_node;
+ for (node *tem = list; tem; tem = tem->next)
+ on->overstrike(tem->copy());
+ return on;
+}
+
+void overstrike_node::overstrike(node *n)
+{
+ if (n == 0)
+ return;
+ hunits w = n->width();
+ if (w > max_width)
+ max_width = w;
+ node **p;
+ for (p = &list; *p; p = &(*p)->next)
+ ;
+ n->next = 0;
+ *p = n;
+}
+
+hunits overstrike_node::width()
+{
+ return max_width;
+}
+
+bracket_node::bracket_node() : list(0), max_width(H0)
+{
+}
+
+bracket_node::~bracket_node()
+{
+ delete_node_list(list);
+}
+
+node *bracket_node::copy()
+{
+ bracket_node *on = new bracket_node;
+ node *last = 0;
+ node *tem;
+ for (tem = list; tem; tem = tem->next) {
+ if (tem->next)
+ tem->next->last = tem;
+ last = tem;
+ }
+ for (tem = last; tem; tem = tem->last)
+ on->bracket(tem->copy());
+ return on;
+}
+
+
+void bracket_node::bracket(node *n)
+{
+ if (n == 0)
+ return;
+ hunits w = n->width();
+ if (w > max_width)
+ max_width = w;
+ n->next = list;
+ list = n;
+}
+
+hunits bracket_node::width()
+{
+ return max_width;
+}
+
+int node::nspaces()
+{
+ return 0;
+}
+
+int node::merge_space(hunits)
+{
+ return 0;
+}
+
+#if 0
+space_node *space_node::free_list = 0;
+
+void *space_node::operator new(size_t n)
+{
+ assert(n == sizeof(space_node));
+ if (!free_list) {
+ free_list = (space_node *)new char[sizeof(space_node)*BLOCK];
+ for (int i = 0; i < BLOCK - 1; i++)
+ free_list[i].next = free_list + i + 1;
+ free_list[BLOCK-1].next = 0;
+ }
+ space_node *p = free_list;
+ free_list = (space_node *)(free_list->next);
+ p->next = 0;
+ return p;
+}
+
+inline void space_node::operator delete(void *p)
+{
+ if (p) {
+ ((space_node *)p)->next = free_list;
+ free_list = (space_node *)p;
+ }
+}
+#endif
+
+space_node::space_node(hunits nn, node *p) : node(p), n(nn), set(0)
+{
+}
+
+space_node::space_node(hunits nn, int s, node *p) : node(p), n(nn), set(s)
+{
+}
+
+#if 0
+space_node::~space_node()
+{
+}
+#endif
+
+node *space_node::copy()
+{
+ return new space_node(n, set);
+}
+
+int space_node::nspaces()
+{
+ return set ? 0 : 1;
+}
+
+int space_node::merge_space(hunits h)
+{
+ n += h;
+ return 1;
+}
+
+hunits space_node::width()
+{
+ return n;
+}
+
+void node::spread_space(int*, hunits*)
+{
+}
+
+void space_node::spread_space(int *nspaces, hunits *desired_space)
+{
+ if (!set) {
+ assert(*nspaces > 0);
+ if (*nspaces == 1) {
+ n += *desired_space;
+ *desired_space = H0;
+ }
+ else {
+ hunits extra = *desired_space / *nspaces;
+ *desired_space -= extra;
+ n += extra;
+ }
+ *nspaces -= 1;
+ set = 1;
+ }
+}
+
+void node::freeze_space()
+{
+}
+
+void space_node::freeze_space()
+{
+ set = 1;
+}
+
+diverted_space_node::diverted_space_node(vunits d, node *p)
+: node(p), n(d)
+{
+}
+
+node *diverted_space_node::copy()
+{
+ return new diverted_space_node(n);
+}
+
+diverted_copy_file_node::diverted_copy_file_node(symbol s, node *p)
+: node(p), filename(s)
+{
+}
+
+node *diverted_copy_file_node::copy()
+{
+ return new diverted_copy_file_node(filename);
+}
+
+int node::ends_sentence()
+{
+ return 0;
+}
+
+int kern_pair_node::ends_sentence()
+{
+ switch (n2->ends_sentence()) {
+ case 0:
+ return 0;
+ case 1:
+ return 1;
+ case 2:
+ break;
+ default:
+ assert(0);
+ }
+ return n1->ends_sentence();
+}
+
+int node_list_ends_sentence(node *n)
+{
+ for (; n != 0; n = n->next)
+ switch (n->ends_sentence()) {
+ case 0:
+ return 0;
+ case 1:
+ return 1;
+ case 2:
+ break;
+ default:
+ assert(0);
+ }
+ return 2;
+}
+
+
+int dbreak_node::ends_sentence()
+{
+ return node_list_ends_sentence(none);
+}
+
+
+int node::overlaps_horizontally()
+{
+ return 0;
+}
+
+int node::overlaps_vertically()
+{
+ return 0;
+}
+
+int node::discardable()
+{
+ return 0;
+}
+
+int space_node::discardable()
+{
+ return set ? 0 : 1;
+}
+
+
+vunits node::vertical_width()
+{
+ return V0;
+}
+
+vunits vline_node::vertical_width()
+{
+ return x;
+}
+
+vunits vmotion_node::vertical_width()
+{
+ return n;
+}
+
+int node::character_type()
+{
+ return 0;
+}
+
+hunits node::subscript_correction()
+{
+ return H0;
+}
+
+hunits node::italic_correction()
+{
+ return H0;
+}
+
+hunits node::left_italic_correction()
+{
+ return H0;
+}
+
+hunits node::skew()
+{
+ return H0;
+}
+
+
+/* vertical_extent methods */
+
+void node::vertical_extent(vunits *min, vunits *max)
+{
+ vunits v = vertical_width();
+ if (v < V0) {
+ *min = v;
+ *max = V0;
+ }
+ else {
+ *max = v;
+ *min = V0;
+ }
+}
+
+void vline_node::vertical_extent(vunits *min, vunits *max)
+{
+ if (n == 0)
+ node::vertical_extent(min, max);
+ else {
+ vunits cmin, cmax;
+ n->vertical_extent(&cmin, &cmax);
+ vunits h = n->size();
+ if (x < V0) {
+ if (-x < h) {
+ *min = x;
+ *max = V0;
+ }
+ else {
+ // we print the first character and then move up, so
+ *max = cmax;
+ // we print the last character and then move up h
+ *min = cmin + h;
+ if (*min > V0)
+ *min = V0;
+ *min += x;
+ }
+ }
+ else {
+ if (x < h) {
+ *max = x;
+ *min = V0;
+ }
+ else {
+ // we move down by h and then print the first character, so
+ *min = cmin + h;
+ if (*min > V0)
+ *min = V0;
+ *max = x + cmax;
+ }
+ }
+ }
+}
+
+/* ascii_print methods */
+
+
+static void ascii_print_reverse_node_list(ascii_output_file *ascii, node *n)
+{
+ if (n == 0)
+ return;
+ ascii_print_reverse_node_list(ascii, n->next);
+ n->ascii_print(ascii);
+}
+
+void dbreak_node::ascii_print(ascii_output_file *ascii)
+{
+ ascii_print_reverse_node_list(ascii, none);
+}
+
+void kern_pair_node::ascii_print(ascii_output_file *ascii)
+{
+ n1->ascii_print(ascii);
+ n2->ascii_print(ascii);
+}
+
+
+void node::ascii_print(ascii_output_file *)
+{
+}
+
+void space_node::ascii_print(ascii_output_file *ascii)
+{
+ if (!n.is_zero())
+ ascii->outc(' ');
+}
+
+void hmotion_node::ascii_print(ascii_output_file *ascii)
+{
+ // this is pretty arbitrary
+ if (n >= points_to_units(2))
+ ascii->outc(' ');
+}
+
+void space_char_hmotion_node::ascii_print(ascii_output_file *ascii)
+{
+ ascii->outc(' ');
+}
+
+/* asciify methods */
+
+void node::asciify(macro *m)
+{
+ m->append(this);
+}
+
+void glyph_node::asciify(macro *m)
+{
+ unsigned char c = ci->get_ascii_code();
+ if (c != 0) {
+ m->append(c);
+ delete this;
+ }
+ else
+ m->append(this);
+}
+
+void kern_pair_node::asciify(macro *m)
+{
+ n1->asciify(m);
+ n2->asciify(m);
+ n1 = n2 = 0;
+ delete this;
+}
+
+static void asciify_reverse_node_list(macro *m, node *n)
+{
+ if (n == 0)
+ return;
+ asciify_reverse_node_list(m, n->next);
+ n->asciify(m);
+}
+
+void dbreak_node::asciify(macro *m)
+{
+ asciify_reverse_node_list(m, none);
+ none = 0;
+ delete this;
+}
+
+void ligature_node::asciify(macro *m)
+{
+ n1->asciify(m);
+ n2->asciify(m);
+ n1 = n2 = 0;
+ delete this;
+}
+
+void break_char_node::asciify(macro *m)
+{
+ ch->asciify(m);
+ ch = 0;
+ delete this;
+}
+
+void italic_corrected_node::asciify(macro *m)
+{
+ n->asciify(m);
+ n = 0;
+ delete this;
+}
+
+void left_italic_corrected_node::asciify(macro *m)
+{
+ if (n) {
+ n->asciify(m);
+ n = 0;
+ }
+ delete this;
+}
+
+space_char_hmotion_node::space_char_hmotion_node(hunits i, node *next)
+: hmotion_node(i, next)
+{
+}
+
+void space_char_hmotion_node::asciify(macro *m)
+{
+ m->append(' ');
+ delete this;
+}
+
+void line_start_node::asciify(macro *)
+{
+ delete this;
+}
+
+void vertical_size_node::asciify(macro *)
+{
+ delete this;
+}
+
+breakpoint *node::get_breakpoints(hunits /*width*/, int /*nspaces*/,
+ breakpoint *rest, int /*is_inner*/)
+{
+ return rest;
+}
+
+int node::nbreaks()
+{
+ return 0;
+}
+
+breakpoint *space_node::get_breakpoints(hunits width, int ns, breakpoint *rest,
+ int is_inner)
+{
+ if (next->discardable())
+ return rest;
+ breakpoint *bp = new breakpoint;
+ bp->next = rest;
+ bp->width = width;
+ bp->nspaces = ns;
+ bp->hyphenated = 0;
+ if (is_inner) {
+ assert(rest != 0);
+ bp->index = rest->index + 1;
+ bp->nd = rest->nd;
+ }
+ else {
+ bp->nd = this;
+ bp->index = 0;
+ }
+ return bp;
+}
+
+int space_node::nbreaks()
+{
+ if (next->discardable())
+ return 0;
+ else
+ return 1;
+}
+
+static breakpoint *node_list_get_breakpoints(node *p, hunits *widthp,
+ int ns, breakpoint *rest)
+{
+ if (p != 0) {
+ rest = p->get_breakpoints(*widthp,
+ ns,
+ node_list_get_breakpoints(p->next, widthp, ns,
+ rest),
+ 1);
+ *widthp += p->width();
+ }
+ return rest;
+}
+
+
+breakpoint *dbreak_node::get_breakpoints(hunits width, int ns,
+ breakpoint *rest, int is_inner)
+{
+ breakpoint *bp = new breakpoint;
+ bp->next = rest;
+ bp->width = width;
+ for (node *tem = pre; tem != 0; tem = tem->next)
+ bp->width += tem->width();
+ bp->nspaces = ns;
+ bp->hyphenated = 1;
+ if (is_inner) {
+ assert(rest != 0);
+ bp->index = rest->index + 1;
+ bp->nd = rest->nd;
+ }
+ else {
+ bp->nd = this;
+ bp->index = 0;
+ }
+ return node_list_get_breakpoints(none, &width, ns, bp);
+}
+
+int dbreak_node::nbreaks()
+{
+ int i = 1;
+ for (node *tem = none; tem != 0; tem = tem->next)
+ i += tem->nbreaks();
+ return i;
+}
+
+void node::split(int /*where*/, node ** /*prep*/, node ** /*postp*/)
+{
+ assert(0);
+}
+
+void space_node::split(int where, node **pre, node **post)
+{
+ assert(where == 0);
+ *pre = next;
+ *post = 0;
+ delete this;
+}
+
+static void node_list_split(node *p, int *wherep, node **prep, node **postp)
+{
+ if (p == 0)
+ return;
+ int nb = p->nbreaks();
+ node_list_split(p->next, wherep, prep, postp);
+ if (*wherep < 0) {
+ p->next = *postp;
+ *postp = p;
+ }
+ else if (*wherep < nb) {
+ p->next = *prep;
+ p->split(*wherep, prep, postp);
+ }
+ else {
+ p->next = *prep;
+ *prep = p;
+ }
+ *wherep -= nb;
+}
+
+void dbreak_node::split(int where, node **prep, node **postp)
+{
+ assert(where >= 0);
+ if (where == 0) {
+ *postp = post;
+ post = 0;
+ if (pre == 0)
+ *prep = next;
+ else {
+ node *tem;
+ for (tem = pre; tem->next != 0; tem = tem->next)
+ ;
+ tem->next = next;
+ *prep = pre;
+ }
+ pre = 0;
+ delete this;
+ }
+ else {
+ *prep = next;
+ where -= 1;
+ node_list_split(none, &where, prep, postp);
+ none = 0;
+ delete this;
+ }
+}
+
+
+hyphenation_type node::get_hyphenation_type()
+{
+ return HYPHEN_BOUNDARY;
+}
+
+
+hyphenation_type dbreak_node::get_hyphenation_type()
+{
+ return HYPHEN_INHIBIT;
+}
+
+hyphenation_type kern_pair_node::get_hyphenation_type()
+{
+ return HYPHEN_MIDDLE;
+}
+
+hyphenation_type dummy_node::get_hyphenation_type()
+{
+ return HYPHEN_MIDDLE;
+}
+
+hyphenation_type transparent_dummy_node::get_hyphenation_type()
+{
+ return HYPHEN_MIDDLE;
+}
+
+int node::interpret(macro *)
+{
+ return 0;
+}
+
+special_node::special_node(const macro &m)
+: mac(m)
+{
+}
+
+int special_node::same(node *n)
+{
+ return mac == ((special_node *)n)->mac;
+}
+
+const char *special_node::type()
+{
+ return "special_node";
+}
+
+node *special_node::copy()
+{
+ return new special_node(mac);
+}
+
+void special_node::tprint_start(troff_output_file *out)
+{
+ out->start_special();
+}
+
+void special_node::tprint_char(troff_output_file *out, unsigned char c)
+{
+ out->special_char(c);
+}
+
+void special_node::tprint_end(troff_output_file *out)
+{
+ out->end_special();
+}
+
+/* composite_node */
+
+class composite_node : public charinfo_node {
+ node *n;
+ tfont *tf;
+public:
+ composite_node(node *, charinfo *, tfont *, node * = 0);
+ ~composite_node();
+ node *copy();
+ hunits width();
+ node *last_char_node();
+ units size();
+ void tprint(troff_output_file *);
+ hyphenation_type get_hyphenation_type();
+ void ascii_print(ascii_output_file *);
+ void asciify(macro *);
+ hyphen_list *get_hyphen_list(hyphen_list *tail);
+ node *add_self(node *, hyphen_list **);
+ tfont *get_tfont();
+ int same(node *);
+ const char *type();
+ void vertical_extent(vunits *, vunits *);
+ vunits vertical_width();
+};
+
+composite_node::composite_node(node *p, charinfo *c, tfont *t, node *x)
+: charinfo_node(c, x), n(p), tf(t)
+{
+}
+
+composite_node::~composite_node()
+{
+ delete_node_list(n);
+}
+
+node *composite_node::copy()
+{
+ return new composite_node(copy_node_list(n), ci, tf);
+}
+
+hunits composite_node::width()
+{
+ hunits x;
+ if (tf->get_constant_space(&x))
+ return x;
+ x = H0;
+ for (node *tem = n; tem; tem = tem->next)
+ x += tem->width();
+ hunits offset;
+ if (tf->get_bold(&offset))
+ x += offset;
+ x += tf->get_track_kern();
+ return x;
+}
+
+node *composite_node::last_char_node()
+{
+ return this;
+}
+
+vunits composite_node::vertical_width()
+{
+ vunits v = V0;
+ for (node *tem = n; tem; tem = tem->next)
+ v += tem->vertical_width();
+ return v;
+}
+
+units composite_node::size()
+{
+ return tf->get_size().to_units();
+}
+
+hyphenation_type composite_node::get_hyphenation_type()
+{
+ return HYPHEN_MIDDLE;
+}
+
+void composite_node::asciify(macro *m)
+{
+ unsigned char c = ci->get_ascii_code();
+ if (c != 0) {
+ m->append(c);
+ delete this;
+ }
+ else
+ m->append(this);
+}
+
+void composite_node::ascii_print(ascii_output_file *ascii)
+{
+ unsigned char c = ci->get_ascii_code();
+ if (c != 0)
+ ascii->outc(c);
+ else
+ ascii->outs(ci->nm.contents());
+
+}
+
+hyphen_list *composite_node::get_hyphen_list(hyphen_list *tail)
+{
+ return new hyphen_list(ci->get_hyphenation_code(), tail);
+
+}
+
+node *composite_node::add_self(node *nn, hyphen_list **p)
+{
+ assert(ci->get_hyphenation_code() == (*p)->hyphenation_code);
+ next = nn;
+ nn = this;
+ if ((*p)->hyphen)
+ nn = nn->add_discretionary_hyphen();
+ hyphen_list *pp = *p;
+ *p = (*p)->next;
+ delete pp;
+ return nn;
+}
+
+tfont *composite_node::get_tfont()
+{
+ return tf;
+}
+
+node *reverse_node_list(node *n)
+{
+ node *r = 0;
+ while (n) {
+ node *tem = n;
+ n = n->next;
+ tem->next = r;
+ r = tem;
+ }
+ return r;
+}
+
+void composite_node::vertical_extent(vunits *min, vunits *max)
+{
+ n = reverse_node_list(n);
+ node_list_vertical_extent(n, min, max);
+ n = reverse_node_list(n);
+}
+
+word_space_node::word_space_node(hunits d, node *x) : space_node(d, x)
+{
+}
+
+word_space_node::word_space_node(hunits d, int s, node *x)
+: space_node(d, s, x)
+{
+}
+
+node *word_space_node::copy()
+{
+ return new word_space_node(n, set);
+}
+
+void word_space_node::tprint(troff_output_file *out)
+{
+ out->word_marker();
+ space_node::tprint(out);
+}
+
+unbreakable_space_node::unbreakable_space_node(hunits d, node *x)
+: word_space_node(d, x)
+{
+}
+
+unbreakable_space_node::unbreakable_space_node(hunits d, int s, node *x)
+: word_space_node(d, s, x)
+{
+}
+
+node *unbreakable_space_node::copy()
+{
+ return new unbreakable_space_node(n, set);
+}
+
+breakpoint *unbreakable_space_node::get_breakpoints(hunits, int,
+ breakpoint *rest, int)
+{
+ return rest;
+}
+
+int unbreakable_space_node::nbreaks()
+{
+ return 0;
+}
+
+void unbreakable_space_node::split(int, node **, node **)
+{
+ assert(0);
+}
+
+int unbreakable_space_node::merge_space(hunits)
+{
+ return 0;
+}
+
+hvpair::hvpair()
+{
+}
+
+draw_node::draw_node(char c, hvpair *p, int np, font_size s)
+ : npoints(np), sz(s), code(c)
+{
+ point = new hvpair[npoints];
+ for (int i = 0; i < npoints; i++)
+ point[i] = p[i];
+}
+
+int draw_node::same(node *n)
+{
+ draw_node *nd = (draw_node *)n;
+ if (code != nd->code || npoints != nd->npoints || sz != nd->sz)
+ return 0;
+ for (int i = 0; i < npoints; i++)
+ if (point[i].h != nd->point[i].h || point[i].v != nd->point[i].v)
+ return 0;
+ return 1;
+}
+
+const char *draw_node::type()
+{
+ return "draw_node";
+}
+
+draw_node::~draw_node()
+{
+ if (point)
+ a_delete point;
+}
+
+hunits draw_node::width()
+{
+ hunits x = H0;
+ for (int i = 0; i < npoints; i++)
+ x += point[i].h;
+ return x;
+}
+
+vunits draw_node::vertical_width()
+{
+ if (code == 'e')
+ return V0;
+ vunits x = V0;
+ for (int i = 0; i < npoints; i++)
+ x += point[i].v;
+ return x;
+}
+
+node *draw_node::copy()
+{
+ return new draw_node(code, point, npoints, sz);
+}
+
+void draw_node::tprint(troff_output_file *out)
+{
+ out->draw(code, point, npoints, sz);
+}
+
+/* tprint methods */
+
+void glyph_node::tprint(troff_output_file *out)
+{
+ tfont *ptf = tf->get_plain();
+ if (ptf == tf)
+ out->put_char_width(ci, ptf, width(), H0);
+ else {
+ hunits offset;
+ int bold = tf->get_bold(&offset);
+ hunits w = ptf->get_width(ci);
+ hunits k = H0;
+ hunits x;
+ int cs = tf->get_constant_space(&x);
+ if (cs) {
+ x -= w;
+ if (bold)
+ x -= offset;
+ hunits x2 = x/2;
+ out->right(x2);
+ k = x - x2;
+ }
+ else
+ k = tf->get_track_kern();
+ if (bold) {
+ out->put_char(ci, ptf);
+ out->right(offset);
+ }
+ out->put_char_width(ci, ptf, w, k);
+ }
+}
+
+void glyph_node::zero_width_tprint(troff_output_file *out)
+{
+ tfont *ptf = tf->get_plain();
+ hunits offset;
+ int bold = tf->get_bold(&offset);
+ hunits x;
+ int cs = tf->get_constant_space(&x);
+ if (cs) {
+ x -= ptf->get_width(ci);
+ if (bold)
+ x -= offset;
+ x = x/2;
+ out->right(x);
+ }
+ out->put_char(ci, ptf);
+ if (bold) {
+ out->right(offset);
+ out->put_char(ci, ptf);
+ out->right(-offset);
+ }
+ if (cs)
+ out->right(-x);
+}
+
+void break_char_node::tprint(troff_output_file *t)
+{
+ ch->tprint(t);
+}
+
+void break_char_node::zero_width_tprint(troff_output_file *t)
+{
+ ch->zero_width_tprint(t);
+}
+
+void hline_node::tprint(troff_output_file *out)
+{
+ if (x < H0) {
+ out->right(x);
+ x = -x;
+ }
+ if (n == 0) {
+ out->right(x);
+ return;
+ }
+ hunits w = n->width();
+ if (w <= H0) {
+ error("horizontal line drawing character must have positive width");
+ out->right(x);
+ return;
+ }
+ int i = int(x/w);
+ if (i == 0) {
+ hunits xx = x - w;
+ hunits xx2 = xx/2;
+ out->right(xx2);
+ n->tprint(out);
+ out->right(xx - xx2);
+ }
+ else {
+ hunits rem = x - w*i;
+ if (rem > H0)
+ if (n->overlaps_horizontally()) {
+ n->tprint(out);
+ out->right(rem - w);
+ }
+ else
+ out->right(rem);
+ while (--i >= 0)
+ n->tprint(out);
+ }
+}
+
+void vline_node::tprint(troff_output_file *out)
+{
+ if (n == 0) {
+ out->down(x);
+ return;
+ }
+ vunits h = n->size();
+ int overlaps = n->overlaps_vertically();
+ vunits y = x;
+ if (y < V0) {
+ y = -y;
+ int i = y / h;
+ vunits rem = y - i*h;
+ if (i == 0) {
+ out->right(n->width());
+ out->down(-rem);
+ }
+ else {
+ while (--i > 0) {
+ n->zero_width_tprint(out);
+ out->down(-h);
+ }
+ if (overlaps) {
+ n->zero_width_tprint(out);
+ out->down(-rem);
+ n->tprint(out);
+ out->down(-h);
+ }
+ else {
+ n->tprint(out);
+ out->down(-h - rem);
+ }
+ }
+ }
+ else {
+ int i = y / h;
+ vunits rem = y - i*h;
+ if (i == 0) {
+ out->down(rem);
+ out->right(n->width());
+ }
+ else {
+ out->down(h);
+ if (overlaps)
+ n->zero_width_tprint(out);
+ out->down(rem);
+ while (--i > 0) {
+ n->zero_width_tprint(out);
+ out->down(h);
+ }
+ n->tprint(out);
+ }
+ }
+}
+
+void zero_width_node::tprint(troff_output_file *out)
+{
+ if (!n)
+ return;
+ if (!n->next) {
+ n->zero_width_tprint(out);
+ return;
+ }
+ int hpos = out->get_hpos();
+ int vpos = out->get_vpos();
+ node *tem = n;
+ while (tem) {
+ tem->tprint(out);
+ tem = tem->next;
+ }
+ out->moveto(hpos, vpos);
+}
+
+void overstrike_node::tprint(troff_output_file *out)
+{
+ hunits pos = H0;
+ for (node *tem = list; tem; tem = tem->next) {
+ hunits x = (max_width - tem->width())/2;
+ out->right(x - pos);
+ pos = x;
+ tem->zero_width_tprint(out);
+ }
+ out->right(max_width - pos);
+}
+
+void bracket_node::tprint(troff_output_file *out)
+{
+ if (list == 0)
+ return;
+ int npieces = 0;
+ node *tem;
+ for (tem = list; tem; tem = tem->next)
+ ++npieces;
+ vunits h = list->size();
+ vunits totalh = h*npieces;
+ vunits y = (totalh - h)/2;
+ out->down(y);
+ for (tem = list; tem; tem = tem->next) {
+ tem->zero_width_tprint(out);
+ out->down(-h);
+ }
+ out->right(max_width);
+ out->down(totalh - y);
+}
+
+void node::tprint(troff_output_file *)
+{
+}
+
+void node::zero_width_tprint(troff_output_file *out)
+{
+ int hpos = out->get_hpos();
+ int vpos = out->get_vpos();
+ tprint(out);
+ out->moveto(hpos, vpos);
+}
+
+void space_node::tprint(troff_output_file *out)
+{
+ out->right(n);
+}
+
+void hmotion_node::tprint(troff_output_file *out)
+{
+ out->right(n);
+}
+
+void vmotion_node::tprint(troff_output_file *out)
+{
+ out->down(n);
+}
+
+void kern_pair_node::tprint(troff_output_file *out)
+{
+ n1->tprint(out);
+ out->right(amount);
+ n2->tprint(out);
+}
+
+static void tprint_reverse_node_list(troff_output_file *out, node *n)
+{
+ if (n == 0)
+ return;
+ tprint_reverse_node_list(out, n->next);
+ n->tprint(out);
+}
+
+void dbreak_node::tprint(troff_output_file *out)
+{
+ tprint_reverse_node_list(out, none);
+}
+
+void composite_node::tprint(troff_output_file *out)
+{
+ hunits bold_offset;
+ int is_bold = tf->get_bold(&bold_offset);
+ hunits track_kern = tf->get_track_kern();
+ hunits constant_space;
+ int is_constant_spaced = tf->get_constant_space(&constant_space);
+ hunits x = H0;
+ if (is_constant_spaced) {
+ x = constant_space;
+ for (node *tem = n; tem; tem = tem->next)
+ x -= tem->width();
+ if (is_bold)
+ x -= bold_offset;
+ hunits x2 = x/2;
+ out->right(x2);
+ x -= x2;
+ }
+ if (is_bold) {
+ int hpos = out->get_hpos();
+ int vpos = out->get_vpos();
+ tprint_reverse_node_list(out, n);
+ out->moveto(hpos, vpos);
+ out->right(bold_offset);
+ }
+ tprint_reverse_node_list(out, n);
+ if (is_constant_spaced)
+ out->right(x);
+ else
+ out->right(track_kern);
+}
+
+node *make_composite_node(charinfo *s, environment *env)
+{
+ int fontno = env_definite_font(env);
+ if (fontno < 0) {
+ error("no current font");
+ return 0;
+ }
+ assert(fontno < font_table_size && font_table[fontno] != 0);
+ node *n = charinfo_to_node_list(s, env);
+ font_size fs = env->get_font_size();
+ int char_height = env->get_char_height();
+ int char_slant = env->get_char_slant();
+ tfont *tf = font_table[fontno]->get_tfont(fs, char_height, char_slant,
+ fontno);
+ if (env->is_composite())
+ tf = tf->get_plain();
+ return new composite_node(n, s, tf);
+}
+
+node *make_glyph_node(charinfo *s, environment *env, int no_error_message = 0)
+{
+ int fontno = env_definite_font(env);
+ if (fontno < 0) {
+ error("no current font");
+ return 0;
+ }
+ assert(fontno < font_table_size && font_table[fontno] != 0);
+ int fn = fontno;
+ int found = font_table[fontno]->contains(s);
+ if (!found) {
+ if (s->numbered()) {
+ if (!no_error_message)
+ warning(WARN_CHAR, "can't find numbered character %1",
+ s->get_number());
+ return 0;
+ }
+ special_font_list *sf = font_table[fontno]->sf;
+ while (sf != 0 && !found) {
+ fn = sf->n;
+ if (font_table[fn])
+ found = font_table[fn]->contains(s);
+ sf = sf->next;
+ }
+ if (!found) {
+ sf = global_special_fonts;
+ while (sf != 0 && !found) {
+ fn = sf->n;
+ if (font_table[fn])
+ found = font_table[fn]->contains(s);
+ sf = sf->next;
+ }
+ }
+ if (!found
+#if 0
+ && global_special_fonts == 0 && font_table[fontno]->sf == 0
+#endif
+ ) {
+ for (fn = 0; fn < font_table_size; fn++)
+ if (font_table[fn]
+ && font_table[fn]->is_special()
+ && font_table[fn]->contains(s)) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ if (!no_error_message && s->first_time_not_found()) {
+ unsigned char input_code = s->get_ascii_code();
+ if (input_code != 0) {
+ if (csgraph(input_code))
+ warning(WARN_CHAR, "can't find character `%1'", input_code);
+ else
+ warning(WARN_CHAR, "can't find character with input code %1",
+ int(input_code));
+ }
+ else
+ warning(WARN_CHAR, "can't find special character `%1'",
+ s->nm.contents());
+ }
+ return 0;
+ }
+ }
+ font_size fs = env->get_font_size();
+ int char_height = env->get_char_height();
+ int char_slant = env->get_char_slant();
+ tfont *tf = font_table[fontno]->get_tfont(fs, char_height, char_slant, fn);
+ if (env->is_composite())
+ tf = tf->get_plain();
+ return new glyph_node(s, tf);
+}
+
+node *make_node(charinfo *ci, environment *env)
+{
+ switch (ci->get_special_translation()) {
+ case charinfo::TRANSLATE_SPACE:
+ return new space_char_hmotion_node(env->get_space_width());
+ case charinfo::TRANSLATE_DUMMY:
+ return new dummy_node;
+ case charinfo::TRANSLATE_HYPHEN_INDICATOR:
+ error("translation to \\% ignored in this context");
+ break;
+ }
+ charinfo *tem = ci->get_translation();
+ if (tem)
+ ci = tem;
+ macro *mac = ci->get_macro();
+ if (mac)
+ return make_composite_node(ci, env);
+ else
+ return make_glyph_node(ci, env);
+}
+
+int character_exists(charinfo *ci, environment *env)
+{
+ if (ci->get_special_translation() != charinfo::TRANSLATE_NONE)
+ return 1;
+ charinfo *tem = ci->get_translation();
+ if (tem)
+ ci = tem;
+ if (ci->get_macro())
+ return 1;
+ node *nd = make_glyph_node(ci, env, 1);
+ if (nd) {
+ delete nd;
+ return 1;
+ }
+ return 0;
+}
+
+node *node::add_char(charinfo *ci, environment *env, hunits *widthp)
+{
+ node *res;
+ switch (ci->get_special_translation()) {
+ case charinfo::TRANSLATE_SPACE:
+ res = new space_char_hmotion_node(env->get_space_width(), this);
+ *widthp += res->width();
+ return res;
+ case charinfo::TRANSLATE_DUMMY:
+ return new dummy_node(this);
+ case charinfo::TRANSLATE_HYPHEN_INDICATOR:
+ return add_discretionary_hyphen();
+ }
+ charinfo *tem = ci->get_translation();
+ if (tem)
+ ci = tem;
+ macro *mac = ci->get_macro();
+ if (mac) {
+ res = make_composite_node(ci, env);
+ if (res) {
+ res->next = this;
+ *widthp += res->width();
+ }
+ else
+ return this;
+ }
+ else {
+ node *gn = make_glyph_node(ci, env);
+ if (gn == 0)
+ return this;
+ else {
+ hunits old_width = width();
+ node *p = gn->merge_self(this);
+ if (p == 0) {
+ *widthp += gn->width();
+ gn->next = this;
+ res = gn;
+ }
+ else {
+ *widthp += p->width() - old_width;
+ res = p;
+ }
+ }
+ }
+ int break_code = 0;
+ if (ci->can_break_before())
+ break_code = 1;
+ if (ci->can_break_after())
+ break_code |= 2;
+ if (break_code) {
+ node *next1 = res->next;
+ res->next = 0;
+ res = new break_char_node(res, break_code, next1);
+ }
+ return res;
+}
+
+
+#ifdef __GNUG__
+inline
+#endif
+int same_node(node *n1, node *n2)
+{
+ if (n1 != 0) {
+ if (n2 != 0)
+ return n1->type() == n2->type() && n1->same(n2);
+ else
+ return 0;
+ }
+ else
+ return n2 == 0;
+}
+
+int same_node_list(node *n1, node *n2)
+{
+ while (n1 && n2) {
+ if (n1->type() != n2->type() || !n1->same(n2))
+ return 0;
+ n1 = n1->next;
+ n2 = n2->next;
+ }
+ return !n1 && !n2;
+}
+
+int extra_size_node::same(node *nd)
+{
+ return n == ((extra_size_node *)nd)->n;
+}
+
+const char *extra_size_node::type()
+{
+ return "extra_size_node";
+}
+
+int vertical_size_node::same(node *nd)
+{
+ return n == ((vertical_size_node *)nd)->n;
+}
+
+const char *vertical_size_node::type()
+{
+ return "vertical_size_node";
+}
+
+int hmotion_node::same(node *nd)
+{
+ return n == ((hmotion_node *)nd)->n;
+}
+
+const char *hmotion_node::type()
+{
+ return "hmotion_node";
+}
+
+int space_char_hmotion_node::same(node *nd)
+{
+ return n == ((space_char_hmotion_node *)nd)->n;
+}
+
+const char *space_char_hmotion_node::type()
+{
+ return "space_char_hmotion_node";
+}
+
+int vmotion_node::same(node *nd)
+{
+ return n == ((vmotion_node *)nd)->n;
+}
+
+const char *vmotion_node::type()
+{
+ return "vmotion_node";
+}
+
+int hline_node::same(node *nd)
+{
+ return x == ((hline_node *)nd)->x && same_node(n, ((hline_node *)nd)->n);
+}
+
+const char *hline_node::type()
+{
+ return "hline_node";
+}
+
+int vline_node::same(node *nd)
+{
+ return x == ((vline_node *)nd)->x && same_node(n, ((vline_node *)nd)->n);
+}
+
+const char *vline_node::type()
+{
+ return "vline_node";
+}
+
+int dummy_node::same(node * /*nd*/)
+{
+ return 1;
+}
+
+const char *dummy_node::type()
+{
+ return "dummy_node";
+}
+
+int transparent_dummy_node::same(node * /*nd*/)
+{
+ return 1;
+}
+
+const char *transparent_dummy_node::type()
+{
+ return "transparent_dummy_node";
+}
+
+int transparent_dummy_node::ends_sentence()
+{
+ return 2;
+}
+
+int zero_width_node::same(node *nd)
+{
+ return same_node_list(n, ((zero_width_node *)nd)->n);
+}
+
+const char *zero_width_node::type()
+{
+ return "zero_width_node";
+}
+
+int italic_corrected_node::same(node *nd)
+{
+ return (x == ((italic_corrected_node *)nd)->x
+ && same_node(n, ((italic_corrected_node *)nd)->n));
+}
+
+const char *italic_corrected_node::type()
+{
+ return "italic_corrected_node";
+}
+
+
+left_italic_corrected_node::left_italic_corrected_node(node *x)
+: node(x), n(0)
+{
+}
+
+left_italic_corrected_node::~left_italic_corrected_node()
+{
+ delete n;
+}
+
+node *left_italic_corrected_node::merge_glyph_node(glyph_node *gn)
+{
+ if (n == 0) {
+ hunits lic = gn->left_italic_correction();
+ if (!lic.is_zero()) {
+ x = lic;
+ n = gn;
+ return this;
+ }
+ }
+ else {
+ node *nd = n->merge_glyph_node(gn);
+ if (nd) {
+ n = nd;
+ x = n->left_italic_correction();
+ return this;
+ }
+ }
+ return 0;
+}
+
+node *left_italic_corrected_node::copy()
+{
+ left_italic_corrected_node *nd = new left_italic_corrected_node;
+ if (n) {
+ nd->n = n->copy();
+ nd->x = x;
+ }
+ return nd;
+}
+
+void left_italic_corrected_node::tprint(troff_output_file *out)
+{
+ if (n) {
+ out->right(x);
+ n->tprint(out);
+ }
+}
+
+const char *left_italic_corrected_node::type()
+{
+ return "left_italic_corrected_node";
+}
+
+int left_italic_corrected_node::same(node *nd)
+{
+ return (x == ((left_italic_corrected_node *)nd)->x
+ && same_node(n, ((left_italic_corrected_node *)nd)->n));
+}
+
+void left_italic_corrected_node::ascii_print(ascii_output_file *out)
+{
+ if (n)
+ n->ascii_print(out);
+}
+
+hunits left_italic_corrected_node::width()
+{
+ return n ? n->width() + x : H0;
+}
+
+void left_italic_corrected_node::vertical_extent(vunits *min, vunits *max)
+{
+ if (n)
+ n->vertical_extent(min, max);
+ else
+ node::vertical_extent(min, max);
+}
+
+hunits left_italic_corrected_node::skew()
+{
+ return n ? n->skew() + x/2 : H0;
+}
+
+hunits left_italic_corrected_node::subscript_correction()
+{
+ return n ? n->subscript_correction() : H0;
+}
+
+hunits left_italic_corrected_node::italic_correction()
+{
+ return n ? n->italic_correction() : H0;
+}
+
+int left_italic_corrected_node::ends_sentence()
+{
+ return n ? n->ends_sentence() : 0;
+}
+
+int left_italic_corrected_node::overlaps_horizontally()
+{
+ return n ? n->overlaps_horizontally() : 0;
+}
+
+int left_italic_corrected_node::overlaps_vertically()
+{
+ return n ? n->overlaps_vertically() : 0;
+}
+
+node *left_italic_corrected_node::last_char_node()
+{
+ return n ? n->last_char_node() : 0;
+}
+
+tfont *left_italic_corrected_node::get_tfont()
+{
+ return n ? n->get_tfont() : 0;
+}
+
+hyphenation_type left_italic_corrected_node::get_hyphenation_type()
+{
+ if (n)
+ return n->get_hyphenation_type();
+ else
+ return HYPHEN_MIDDLE;
+}
+
+hyphen_list *left_italic_corrected_node::get_hyphen_list(hyphen_list *tail)
+{
+ return n ? n->get_hyphen_list(tail) : tail;
+}
+
+node *left_italic_corrected_node::add_self(node *nd, hyphen_list **p)
+{
+ if (n) {
+ nd = new left_italic_corrected_node(nd);
+ nd = n->add_self(nd, p);
+ n = 0;
+ delete this;
+ }
+ return nd;
+}
+
+int left_italic_corrected_node::character_type()
+{
+ return n ? n->character_type() : 0;
+}
+
+int overstrike_node::same(node *nd)
+{
+ return same_node_list(list, ((overstrike_node *)nd)->list);
+}
+
+const char *overstrike_node::type()
+{
+ return "overstrike_node";
+}
+
+int bracket_node::same(node *nd)
+{
+ return same_node_list(list, ((bracket_node *)nd)->list);
+}
+
+const char *bracket_node::type()
+{
+ return "bracket_node";
+}
+
+int composite_node::same(node *nd)
+{
+ return ci == ((composite_node *)nd)->ci
+ && same_node_list(n, ((composite_node *)nd)->n);
+}
+
+const char *composite_node::type()
+{
+ return "composite_node";
+}
+
+int glyph_node::same(node *nd)
+{
+ return ci == ((glyph_node *)nd)->ci && tf == ((glyph_node *)nd)->tf;
+}
+
+const char *glyph_node::type()
+{
+ return "glyph_node";
+}
+
+int ligature_node::same(node *nd)
+{
+ return (same_node(n1, ((ligature_node *)nd)->n1)
+ && same_node(n2, ((ligature_node *)nd)->n2)
+ && glyph_node::same(nd));
+}
+
+const char *ligature_node::type()
+{
+ return "ligature_node";
+}
+
+int kern_pair_node::same(node *nd)
+{
+ return (amount == ((kern_pair_node *)nd)->amount
+ && same_node(n1, ((kern_pair_node *)nd)->n1)
+ && same_node(n2, ((kern_pair_node *)nd)->n2));
+}
+
+const char *kern_pair_node::type()
+{
+ return "kern_pair_node";
+}
+
+int dbreak_node::same(node *nd)
+{
+ return (same_node_list(none, ((dbreak_node *)nd)->none)
+ && same_node_list(pre, ((dbreak_node *)nd)->pre)
+ && same_node_list(post, ((dbreak_node *)nd)->post));
+}
+
+const char *dbreak_node::type()
+{
+ return "dbreak_node";
+}
+
+int break_char_node::same(node *nd)
+{
+ return (break_code == ((break_char_node *)nd)->break_code
+ && same_node(ch, ((break_char_node *)nd)->ch));
+}
+
+const char *break_char_node::type()
+{
+ return "break_char_node";
+}
+
+int line_start_node::same(node * /*nd*/)
+{
+ return 1;
+}
+
+const char *line_start_node::type()
+{
+ return "line_start_node";
+}
+
+int space_node::same(node *nd)
+{
+ return n == ((space_node *)nd)->n && set == ((space_node *)nd)->set;
+}
+
+const char *space_node::type()
+{
+ return "space_node";
+}
+
+int word_space_node::same(node *nd)
+{
+ return (n == ((word_space_node *)nd)->n
+ && set == ((word_space_node *)nd)->set);
+}
+
+const char *word_space_node::type()
+{
+ return "word_space_node";
+}
+
+int unbreakable_space_node::same(node *nd)
+{
+ return (n == ((unbreakable_space_node *)nd)->n
+ && set == ((unbreakable_space_node *)nd)->set);
+}
+
+const char *unbreakable_space_node::type()
+{
+ return "unbreakable_space_node";
+}
+
+int diverted_space_node::same(node *nd)
+{
+ return n == ((diverted_space_node *)nd)->n;
+}
+
+const char *diverted_space_node::type()
+{
+ return "diverted_space_node";
+}
+
+int diverted_copy_file_node::same(node *nd)
+{
+ return filename == ((diverted_copy_file_node *)nd)->filename;
+}
+
+const char *diverted_copy_file_node::type()
+{
+ return "diverted_copy_file_node";
+}
+
+// Grow the font_table so that its size is > n.
+
+static void grow_font_table(int n)
+{
+ assert(n >= font_table_size);
+ font_info **old_font_table = font_table;
+ int old_font_table_size = font_table_size;
+ font_table_size = font_table_size ? (font_table_size*3)/2 : 10;
+ if (font_table_size <= n)
+ font_table_size = n + 10;
+ font_table = new font_info *[font_table_size];
+ if (old_font_table_size)
+ memcpy(font_table, old_font_table,
+ old_font_table_size*sizeof(font_info *));
+ a_delete old_font_table;
+ for (int i = old_font_table_size; i < font_table_size; i++)
+ font_table[i] = 0;
+}
+
+dictionary font_translation_dictionary(17);
+
+static symbol get_font_translation(symbol nm)
+{
+ void *p = font_translation_dictionary.lookup(nm);
+ return p ? symbol((char *)p) : nm;
+}
+
+dictionary font_dictionary(50);
+
+static int mount_font_no_translate(int n, symbol name, symbol external_name)
+{
+ assert(n >= 0);
+ // We store the address of this char in font_dictionary to indicate
+ // that we've previously tried to mount the font and failed.
+ static char a_char;
+ font *fm = 0;
+ void *p = font_dictionary.lookup(external_name);
+ if (p == 0) {
+ int not_found;
+ fm = font::load_font(external_name.contents(), &not_found);
+ if (!fm) {
+ if (not_found)
+ warning(WARN_FONT, "can't find font `%1'", external_name.contents());
+ font_dictionary.lookup(external_name, &a_char);
+ return 0;
+ }
+ font_dictionary.lookup(name, fm);
+ }
+ else if (p == &a_char) {
+#if 0
+ error("invalid font `%1'", external_name.contents());
+#endif
+ return 0;
+ }
+ else
+ fm = (font*)p;
+ if (n >= font_table_size) {
+ if (n - font_table_size > 1000) {
+ error("font position too much larger than first unused position");
+ return 0;
+ }
+ grow_font_table(n);
+ }
+ else if (font_table[n] != 0)
+ delete font_table[n];
+ font_table[n] = new font_info(name, n, external_name, fm);
+ font_family::invalidate_fontno(n);
+ return 1;
+}
+
+int mount_font(int n, symbol name, symbol external_name)
+{
+ assert(n >= 0);
+ name = get_font_translation(name);
+ if (external_name.is_null())
+ external_name = name;
+ else
+ external_name = get_font_translation(external_name);
+ return mount_font_no_translate(n, name, external_name);
+}
+
+void mount_style(int n, symbol name)
+{
+ assert(n >= 0);
+ if (n >= font_table_size) {
+ if (n - font_table_size > 1000) {
+ error("font position too much larger than first unused position");
+ return;
+ }
+ grow_font_table(n);
+ }
+ else if (font_table[n] != 0)
+ delete font_table[n];
+ font_table[n] = new font_info(get_font_translation(name), n, NULL_SYMBOL, 0);
+ font_family::invalidate_fontno(n);
+}
+
+/* global functions */
+
+void font_translate()
+{
+ symbol from = get_name(1);
+ if (!from.is_null()) {
+ symbol to = get_name();
+ if (to.is_null() || from == to)
+ font_translation_dictionary.remove(from);
+ else
+ font_translation_dictionary.lookup(from, (void *)to.contents());
+ }
+ skip_line();
+}
+
+void font_position()
+{
+ int n;
+ if (get_integer(&n)) {
+ if (n < 0)
+ error("negative font position");
+ else {
+ symbol internal_name = get_name(1);
+ if (!internal_name.is_null()) {
+ symbol external_name = get_long_name(0);
+ mount_font(n, internal_name, external_name); // ignore error
+ }
+ }
+ }
+ skip_line();
+}
+
+font_family::font_family(symbol s)
+: map_size(10), nm(s)
+{
+ map = new int[map_size];
+ for (int i = 0; i < map_size; i++)
+ map[i] = -1;
+}
+
+font_family::~font_family()
+{
+ a_delete map;
+}
+
+int font_family::make_definite(int i)
+{
+ if (i >= 0) {
+ if (i < map_size && map[i] >= 0)
+ return map[i];
+ else {
+ if (i < font_table_size && font_table[i] != 0) {
+ if (i >= map_size) {
+ int old_map_size = map_size;
+ int *old_map = map;
+ map_size *= 3;
+ map_size /= 2;
+ if (i >= map_size)
+ map_size = i + 10;
+ map = new int[map_size];
+ memcpy(map, old_map, old_map_size*sizeof(int));
+ a_delete old_map;
+ for (int j = old_map_size; j < map_size; j++)
+ map[j] = -1;
+ }
+ if (font_table[i]->is_style()) {
+ symbol sty = font_table[i]->get_name();
+ symbol f = concat(nm, sty);
+ int n;
+ // don't use symbol_fontno, because that might return a style
+ // and because we don't want to translate the name
+ for (n = 0; n < font_table_size; n++)
+ if (font_table[n] != 0 && font_table[n]->is_named(f)
+ && !font_table[n]->is_style())
+ break;
+ if (n >= font_table_size) {
+ n = next_available_font_position();
+ if (!mount_font_no_translate(n, f, f))
+ return -1;
+ }
+ return map[i] = n;
+ }
+ else
+ return map[i] = i;
+ }
+ else
+ return -1;
+ }
+ }
+ else
+ return -1;
+}
+
+dictionary family_dictionary(5);
+
+font_family *lookup_family(symbol nm)
+{
+ font_family *f = (font_family *)family_dictionary.lookup(nm);
+ if (!f) {
+ f = new font_family(nm);
+ (void)family_dictionary.lookup(nm, f);
+ }
+ return f;
+}
+
+void font_family::invalidate_fontno(int n)
+{
+ assert(n >= 0 && n < font_table_size);
+ dictionary_iterator iter(family_dictionary);
+ symbol nm;
+ font_family *fam;
+ while (iter.get(&nm, (void **)&fam)) {
+ int map_size = fam->map_size;
+ if (n < map_size)
+ fam->map[n] = -1;
+ for (int i = 0; i < map_size; i++)
+ if (fam->map[i] == n)
+ fam->map[i] = -1;
+ }
+}
+
+void style()
+{
+ int n;
+ if (get_integer(&n)) {
+ if (n < 0)
+ error("negative font position");
+ else {
+ symbol internal_name = get_name(1);
+ if (!internal_name.is_null())
+ mount_style(n, internal_name);
+ }
+ }
+ skip_line();
+}
+
+static int get_fontno()
+{
+ int n;
+ tok.skip();
+ if (tok.delimiter()) {
+ symbol s = get_name(1);
+ if (!s.is_null()) {
+ n = symbol_fontno(s);
+ if (n < 0) {
+ n = next_available_font_position();
+ if (!mount_font(n, s))
+ return -1;
+ }
+ return curenv->get_family()->make_definite(n);
+ }
+ }
+ else if (get_integer(&n)) {
+ if (n < 0 || n >= font_table_size || font_table[n] == 0)
+ error("bad font number");
+ else
+ return curenv->get_family()->make_definite(n);
+ }
+ return -1;
+}
+
+static int underline_fontno = 2;
+
+void underline_font()
+{
+ int n = get_fontno();
+ if (n >= 0)
+ underline_fontno = n;
+ skip_line();
+}
+
+int get_underline_fontno()
+{
+ return underline_fontno;
+}
+
+static void read_special_fonts(special_font_list **sp)
+{
+ special_font_list *s = *sp;
+ *sp = 0;
+ while (s != 0) {
+ special_font_list *tem = s;
+ s = s->next;
+ delete tem;
+ }
+ special_font_list **p = sp;
+ while (has_arg()) {
+ int i = get_fontno();
+ if (i >= 0) {
+ special_font_list *tem = new special_font_list;
+ tem->n = i;
+ tem->next = 0;
+ *p = tem;
+ p = &(tem->next);
+ }
+ }
+}
+
+void font_special_request()
+{
+ int n = get_fontno();
+ if (n >= 0)
+ read_special_fonts(&font_table[n]->sf);
+ skip_line();
+}
+
+
+void special_request()
+{
+ read_special_fonts(&global_special_fonts);
+ skip_line();
+}
+
+int next_available_font_position()
+{
+ int i;
+ for (i = 1; i < font_table_size && font_table[i] != 0; i++)
+ ;
+ return i;
+}
+
+int symbol_fontno(symbol s)
+{
+ s = get_font_translation(s);
+ for (int i = 0; i < font_table_size; i++)
+ if (font_table[i] != 0 && font_table[i]->is_named(s))
+ return i;
+ return -1;
+}
+
+int is_good_fontno(int n)
+{
+ return n >= 0 && n < font_table_size && font_table[n] != NULL;
+}
+
+int get_bold_fontno(int n)
+{
+ if (n >= 0 && n < font_table_size && font_table[n] != 0) {
+ hunits offset;
+ if (font_table[n]->get_bold(&offset))
+ return offset.to_units() + 1;
+ else
+ return 0;
+ }
+ else
+ return 0;
+}
+
+hunits env_digit_width(environment *env)
+{
+ node *n = make_glyph_node(charset_table['0'], env);
+ if (n) {
+ hunits x = n->width();
+ delete n;
+ return x;
+ }
+ else
+ return H0;
+}
+
+hunits env_space_width(environment *env)
+{
+ int fn = env_definite_font(env);
+ font_size fs = env->get_font_size();
+ if (fn < 0 || fn >= font_table_size || font_table[fn] == 0)
+ return scale(fs.to_units()/3, env->get_space_size(), 12);
+ else
+ return font_table[fn]->get_space_width(fs, env->get_space_size());
+}
+
+hunits env_sentence_space_width(environment *env)
+{
+ int fn = env_definite_font(env);
+ font_size fs = env->get_font_size();
+ if (fn < 0 || fn >= font_table_size || font_table[fn] == 0)
+ return scale(fs.to_units()/3, env->get_sentence_space_size(), 12);
+ else
+ return font_table[fn]->get_space_width(fs, env->get_sentence_space_size());
+}
+
+hunits env_half_narrow_space_width(environment *env)
+{
+ int fn = env_definite_font(env);
+ font_size fs = env->get_font_size();
+ if (fn < 0 || fn >= font_table_size || font_table[fn] == 0)
+ return 0;
+ else
+ return font_table[fn]->get_half_narrow_space_width(fs);
+}
+
+hunits env_narrow_space_width(environment *env)
+{
+ int fn = env_definite_font(env);
+ font_size fs = env->get_font_size();
+ if (fn < 0 || fn >= font_table_size || font_table[fn] == 0)
+ return 0;
+ else
+ return font_table[fn]->get_narrow_space_width(fs);
+}
+
+void bold_font()
+{
+ int n = get_fontno();
+ if (n >= 0) {
+ if (has_arg()) {
+ if (tok.delimiter()) {
+ int f = get_fontno();
+ if (f >= 0) {
+ units offset;
+ if (has_arg() && get_number(&offset, 'u') && offset >= 1)
+ font_table[f]->set_conditional_bold(n, hunits(offset - 1));
+ else
+ font_table[f]->conditional_unbold(n);
+ }
+ }
+ else {
+ units offset;
+ if (get_number(&offset, 'u') && offset >= 1)
+ font_table[n]->set_bold(hunits(offset - 1));
+ else
+ font_table[n]->unbold();
+ }
+ }
+ else
+ font_table[n]->unbold();
+ }
+ skip_line();
+}
+
+track_kerning_function::track_kerning_function() : non_zero(0)
+{
+}
+
+track_kerning_function::track_kerning_function(int min_s, hunits min_a,
+ int max_s, hunits max_a)
+ : non_zero(1),
+ min_size(min_s), min_amount(min_a),
+ max_size(max_s), max_amount(max_a)
+{
+}
+
+int track_kerning_function::operator==(const track_kerning_function &tk)
+{
+ if (non_zero)
+ return (tk.non_zero
+ && min_size == tk.min_size
+ && min_amount == tk.min_amount
+ && max_size == tk.max_size
+ && max_amount == tk.max_amount);
+ else
+ return !tk.non_zero;
+}
+
+int track_kerning_function::operator!=(const track_kerning_function &tk)
+{
+ if (non_zero)
+ return (!tk.non_zero
+ || min_size != tk.min_size
+ || min_amount != tk.min_amount
+ || max_size != tk.max_size
+ || max_amount != tk.max_amount);
+ else
+ return tk.non_zero;
+}
+
+hunits track_kerning_function::compute(int size)
+{
+ if (non_zero) {
+ if (max_size <= min_size)
+ return min_amount;
+ else if (size <= min_size)
+ return min_amount;
+ else if (size >= max_size)
+ return max_amount;
+ else
+ return (scale(max_amount, size - min_size, max_size - min_size)
+ + scale(min_amount, max_size - size, max_size - min_size));
+ }
+ else
+ return H0;
+}
+
+void track_kern()
+{
+ int n = get_fontno();
+ if (n >= 0) {
+ int min_s, max_s;
+ hunits min_a, max_a;
+ if (has_arg()
+ && get_number(&min_s, 'z')
+ && get_hunits(&min_a, 'p')
+ && get_number(&max_s, 'z')
+ && get_hunits(&max_a, 'p')) {
+ track_kerning_function tk(min_s, min_a, max_s, max_a);
+ font_table[n]->set_track_kern(tk);
+ }
+ else {
+ track_kerning_function tk;
+ font_table[n]->set_track_kern(tk);
+ }
+ }
+ skip_line();
+}
+
+void constant_space()
+{
+ int n = get_fontno();
+ if (n >= 0) {
+ int x, y;
+ if (!has_arg() || !get_integer(&x))
+ font_table[n]->set_constant_space(CONSTANT_SPACE_NONE);
+ else {
+ if (!has_arg() || !get_number(&y, 'z'))
+ font_table[n]->set_constant_space(CONSTANT_SPACE_RELATIVE, x);
+ else
+ font_table[n]->set_constant_space(CONSTANT_SPACE_ABSOLUTE,
+ scale(y*x,
+ units_per_inch,
+ 36*72*sizescale));
+ }
+ }
+ skip_line();
+}
+
+void ligature()
+{
+ int lig;
+ if (has_arg() && get_integer(&lig) && lig >= 0 && lig <= 2)
+ global_ligature_mode = lig;
+ else
+ global_ligature_mode = 1;
+ skip_line();
+}
+
+void kern_request()
+{
+ int k;
+ if (has_arg() && get_integer(&k))
+ global_kern_mode = k != 0;
+ else
+ global_kern_mode = 1;
+ skip_line();
+}
+
+void set_soft_hyphen_char()
+{
+ soft_hyphen_char = get_optional_char();
+ if (!soft_hyphen_char)
+ soft_hyphen_char = get_charinfo(HYPHEN_SYMBOL);
+ skip_line();
+}
+
+void init_output()
+{
+ if (suppress_output_flag)
+ the_output = new suppress_output_file;
+ else if (ascii_output_flag)
+ the_output = new ascii_output_file;
+ else
+ the_output = new troff_output_file;
+}
+
+class next_available_font_position_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *next_available_font_position_reg::get_string()
+{
+ return itoa(next_available_font_position());
+}
+
+class printing_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *printing_reg::get_string()
+{
+ if (the_output)
+ return the_output->is_printing() ? "1" : "0";
+ else
+ return "0";
+}
+
+void init_node_requests()
+{
+ init_request("fp", font_position);
+ init_request("sty", style);
+ init_request("cs", constant_space);
+ init_request("bd", bold_font);
+ init_request("uf", underline_font);
+ init_request("lg", ligature);
+ init_request("kern", kern_request);
+ init_request("tkf", track_kern);
+ init_request("special", special_request);
+ init_request("fspecial", font_special_request);
+ init_request("ftr", font_translate);
+ init_request("shc", set_soft_hyphen_char);
+ number_reg_dictionary.define(".fp", new next_available_font_position_reg);
+ number_reg_dictionary.define(".kern",
+ new constant_int_reg(&global_kern_mode));
+ number_reg_dictionary.define(".lg",
+ new constant_int_reg(&global_ligature_mode));
+ number_reg_dictionary.define(".P", new printing_reg);
+ soft_hyphen_char = get_charinfo(HYPHEN_SYMBOL);
+}
diff --git a/src/roff/troff/node.h b/src/roff/troff/node.h
new file mode 100644
index 00000000..b5095575
--- /dev/null
+++ b/src/roff/troff/node.h
@@ -0,0 +1,495 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+struct hyphen_list {
+ unsigned char hyphen;
+ unsigned char breakable;
+ unsigned char hyphenation_code;
+ hyphen_list *next;
+ hyphen_list(unsigned char code, hyphen_list *p = 0);
+};
+
+void hyphenate(hyphen_list *, unsigned);
+
+enum hyphenation_type { HYPHEN_MIDDLE, HYPHEN_BOUNDARY, HYPHEN_INHIBIT };
+
+class ascii_output_file;
+
+struct breakpoint;
+struct vertical_size;
+struct charinfo;
+
+class macro;
+
+class troff_output_file;
+class tfont;
+class environment;
+
+class glyph_node;
+class diverted_space_node;
+class token_node;
+
+struct node {
+ node *next;
+ node *last;
+ node();
+ node(node *n);
+ node *add_char(charinfo *c, environment *, hunits *widthp);
+
+ virtual ~node();
+ virtual node *copy() = 0;
+ virtual hunits width();
+ virtual hunits subscript_correction();
+ virtual hunits italic_correction();
+ virtual hunits left_italic_correction();
+ virtual hunits skew();
+ virtual int nspaces();
+ virtual int merge_space(hunits);
+ virtual vunits vertical_width();
+ virtual node *last_char_node();
+ virtual void vertical_extent(vunits *min, vunits *max);
+ virtual int character_type();
+ virtual void set_vertical_size(vertical_size *);
+ virtual int ends_sentence();
+ virtual node *merge_self(node *);
+ virtual node *add_discretionary_hyphen();
+ virtual node *add_self(node *, hyphen_list **);
+ virtual hyphen_list *get_hyphen_list(hyphen_list *s = 0);
+ virtual void ascii_print(ascii_output_file *);
+ virtual void asciify(macro *);
+ virtual int discardable();
+ virtual void spread_space(int *, hunits *);
+ virtual void freeze_space();
+ virtual breakpoint *get_breakpoints(hunits width, int nspaces,
+ breakpoint *rest = 0,
+ int is_inner = 0);
+ virtual int nbreaks();
+ virtual void split(int, node **, node **);
+ virtual hyphenation_type get_hyphenation_type();
+ virtual int reread(int *);
+ virtual token_node *get_token_node();
+ virtual int overlaps_vertically();
+ virtual int overlaps_horizontally();
+ virtual units size();
+ virtual int interpret(macro *);
+
+ virtual node *merge_glyph_node(glyph_node *);
+ virtual tfont *get_tfont();
+ virtual void tprint(troff_output_file *);
+ virtual void zero_width_tprint(troff_output_file *);
+
+ node *add_italic_correction(hunits *);
+
+ virtual int same(node *) = 0;
+ virtual const char *type() = 0;
+};
+
+inline node::node() : next(0)
+{
+}
+
+inline node::node(node *n) : next(n)
+{
+}
+
+inline node::~node()
+{
+}
+
+// 0 means it doesn't, 1 means it does, 2 means it's transparent
+
+int node_list_ends_sentence(node *);
+
+struct breakpoint {
+ breakpoint *next;
+ hunits width;
+ int nspaces;
+ node *nd;
+ int index;
+ char hyphenated;
+};
+
+class line_start_node : public node {
+public:
+ line_start_node() {}
+ node *copy() { return new line_start_node; }
+ int same(node *);
+ const char *type();
+ void asciify(macro *);
+};
+
+class space_node : public node {
+private:
+#if 0
+ enum { BLOCK = 1024 };
+ static space_node *free_list;
+ void operator delete(void *);
+#endif
+protected:
+ hunits n;
+ char set;
+ space_node(hunits, int, node * = 0);
+public:
+ space_node(hunits d, node *p = 0);
+#if 0
+ ~space_node();
+ void *operator new(size_t);
+#endif
+ node *copy();
+ int nspaces();
+ hunits width();
+ int discardable();
+ int merge_space(hunits);
+ void freeze_space();
+ void spread_space(int*, hunits*);
+ void tprint(troff_output_file *);
+ breakpoint *get_breakpoints(hunits width, int nspaces, breakpoint *rest = 0,
+ int is_inner = 0);
+ int nbreaks();
+ void split(int, node **, node **);
+ void ascii_print(ascii_output_file *);
+ int same(node *);
+ const char *type();
+};
+
+class word_space_node : public space_node {
+protected:
+ word_space_node(hunits, int, node * = 0);
+public:
+ word_space_node(hunits, node * = 0);
+ node *copy();
+ void tprint(troff_output_file *);
+ int same(node *);
+ const char *type();
+};
+
+class unbreakable_space_node : public word_space_node {
+ unbreakable_space_node(hunits, int, node * = 0);
+public:
+ unbreakable_space_node(hunits, node * = 0);
+ node *copy();
+ int same(node *);
+ const char *type();
+ breakpoint *get_breakpoints(hunits width, int nspaces, breakpoint *rest = 0,
+ int is_inner = 0);
+ int nbreaks();
+ void split(int, node **, node **);
+ int merge_space(hunits);
+};
+
+class diverted_space_node : public node {
+public:
+ vunits n;
+ diverted_space_node(vunits d, node *p = 0);
+ node *copy();
+ int reread(int *);
+ int same(node *);
+ const char *type();
+};
+
+class diverted_copy_file_node : public node {
+ symbol filename;
+public:
+ vunits n;
+ diverted_copy_file_node(symbol s, node *p = 0);
+ node *copy();
+ int reread(int *);
+ int same(node *);
+ const char *type();
+};
+
+class extra_size_node : public node {
+ vunits n;
+ public:
+ extra_size_node(vunits i) : n(i) {}
+ void set_vertical_size(vertical_size *);
+ node *copy();
+ int same(node *);
+ const char *type();
+};
+
+class vertical_size_node : public node {
+ vunits n;
+ public:
+ vertical_size_node(vunits i) : n(i) {}
+ void set_vertical_size(vertical_size *);
+ void asciify(macro *);
+ node *copy();
+ int same(node *);
+ const char *type();
+};
+
+class hmotion_node : public node {
+protected:
+ hunits n;
+public:
+ hmotion_node(hunits i, node *next = 0) : node(next), n(i) {}
+ node *copy();
+ void tprint(troff_output_file *);
+ hunits width();
+ void ascii_print(ascii_output_file *);
+ int same(node *);
+ const char *type();
+};
+
+class space_char_hmotion_node : public hmotion_node {
+public:
+ space_char_hmotion_node(hunits i, node *next = 0);
+ node *copy();
+ void ascii_print(ascii_output_file *);
+ void asciify(macro *);
+ int same(node *);
+ const char *type();
+};
+
+class vmotion_node : public node {
+ vunits n;
+ public:
+ vmotion_node(vunits i) : n(i) {}
+ void tprint(troff_output_file *);
+ node *copy();
+ vunits vertical_width();
+ int same(node *);
+ const char *type();
+};
+
+
+class hline_node : public node {
+ hunits x;
+ node *n;
+ public:
+ hline_node(hunits i, node *c, node *next = 0) : node(next), x(i), n(c) {}
+ ~hline_node();
+ node *copy();
+ hunits width();
+ void tprint(troff_output_file *);
+ int same(node *);
+ const char *type();
+};
+
+class vline_node : public node {
+ vunits x;
+ node *n;
+ public:
+ vline_node(vunits i, node *c, node *next= 0) : node(next), x(i), n(c) {}
+ ~vline_node();
+ node *copy();
+ void tprint(troff_output_file *);
+ hunits width();
+ vunits vertical_width();
+ void vertical_extent(vunits *, vunits *);
+ int same(node *);
+ const char *type();
+};
+
+
+class dummy_node : public node {
+ public:
+ dummy_node(node *nd = 0) : node(nd) {}
+ node *copy();
+ int same(node *);
+ const char *type();
+ hyphenation_type get_hyphenation_type();
+};
+
+class transparent_dummy_node : public node {
+public:
+ transparent_dummy_node() {}
+ node *copy();
+ int same(node *);
+ const char *type();
+ int ends_sentence();
+ hyphenation_type get_hyphenation_type();
+};
+
+class zero_width_node : public node {
+ node *n;
+ public:
+ zero_width_node(node *gn);
+ ~zero_width_node();
+ node *copy();
+ void tprint(troff_output_file *);
+ int same(node *);
+ const char *type();
+ void append(node *);
+ int character_type();
+ void vertical_extent(vunits *min, vunits *max);
+};
+
+class left_italic_corrected_node : public node {
+ node *n;
+ hunits x;
+public:
+ left_italic_corrected_node(node * = 0);
+ ~left_italic_corrected_node();
+ void tprint(troff_output_file *);
+ void ascii_print(ascii_output_file *);
+ void asciify(macro *);
+ node *copy();
+ int same(node *);
+ const char *type();
+ hunits width();
+ node *last_char_node();
+ void vertical_extent(vunits *, vunits *);
+ int ends_sentence();
+ int overlaps_horizontally();
+ int overlaps_vertically();
+ hyphenation_type get_hyphenation_type();
+ tfont *get_tfont();
+ int character_type();
+ hunits skew();
+ hunits italic_correction();
+ hunits subscript_correction();
+ hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
+ node *add_self(node *, hyphen_list **);
+ node *merge_glyph_node(glyph_node *);
+};
+
+class overstrike_node : public node {
+ node *list;
+ hunits max_width;
+public:
+ overstrike_node();
+ ~overstrike_node();
+ node *copy();
+ void tprint(troff_output_file *);
+ void overstrike(node *); // add another node to be overstruck
+ hunits width();
+ int same(node *);
+ const char *type();
+};
+
+class bracket_node : public node {
+ node *list;
+ hunits max_width;
+public:
+ bracket_node();
+ ~bracket_node();
+ node *copy();
+ void tprint(troff_output_file *);
+ void bracket(node *); // add another node to be overstruck
+ hunits width();
+ int same(node *);
+ const char *type();
+};
+
+class special_node : public node {
+ macro mac;
+ void tprint_start(troff_output_file *);
+ void tprint_char(troff_output_file *, unsigned char);
+ void tprint_end(troff_output_file *);
+public:
+ special_node(const macro &);
+ node *copy();
+ void tprint(troff_output_file *);
+ int same(node *);
+ const char *type();
+};
+
+
+struct hvpair {
+ hunits h;
+ vunits v;
+
+ hvpair();
+};
+
+class draw_node : public node {
+ int npoints;
+ font_size sz;
+ char code;
+ hvpair *point;
+public:
+ draw_node(char, hvpair *, int, font_size);
+ ~draw_node();
+ hunits width();
+ vunits vertical_width();
+ node *copy();
+ void tprint(troff_output_file *);
+ int same(node *);
+ const char *type();
+};
+
+class charinfo;
+node *make_node(charinfo *ci, environment *);
+int character_exists(charinfo *, environment *);
+
+int same_node_list(node *n1, node *n2);
+node *reverse_node_list(node *n);
+void delete_node_list(node *);
+node *copy_node_list(node *);
+
+int get_bold_fontno(int f);
+
+inline hyphen_list::hyphen_list(unsigned char code, hyphen_list *p)
+: hyphen(0), breakable(0), hyphenation_code(code), next(p)
+{
+}
+
+extern void read_desc();
+extern int mount_font(int n, symbol, symbol = NULL_SYMBOL);
+extern void mount_style(int n, symbol);
+extern int is_good_fontno(int n);
+extern int symbol_fontno(symbol);
+extern int next_available_font_position();
+extern void init_size_table(int *);
+extern int get_underline_fontno();
+
+class output_file {
+ char make_g_plus_plus_shut_up;
+public:
+ output_file();
+ virtual ~output_file();
+ virtual void trailer(vunits page_length);
+ virtual void flush() = 0;
+ virtual void transparent_char(unsigned char) = 0;
+ virtual void print_line(hunits x, vunits y, node *n,
+ vunits before, vunits after) = 0;
+ virtual void begin_page(int pageno, vunits page_length) = 0;
+ virtual void copy_file(hunits x, vunits y, const char *filename) = 0;
+ virtual int is_printing() = 0;
+ virtual void put_filename (const char *filename);
+#ifdef COLUMN
+ virtual void vjustify(vunits, symbol);
+#endif /* COLUMN */
+};
+
+#ifndef POPEN_MISSING
+extern char *pipe_command;
+#endif
+
+extern output_file *the_output;
+extern void init_output();
+int in_output_page_list(int n);
+
+class font_family {
+ int *map;
+ int map_size;
+public:
+ const symbol nm;
+
+ font_family(symbol);
+ ~font_family();
+ int make_definite(int);
+ static void invalidate_fontno(int);
+};
+
+font_family *lookup_family(symbol);
diff --git a/src/roff/troff/number.cc b/src/roff/troff/number.cc
new file mode 100644
index 00000000..b4e3d1de
--- /dev/null
+++ b/src/roff/troff/number.cc
@@ -0,0 +1,669 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "troff.h"
+#include "symbol.h"
+#include "hvunits.h"
+#include "env.h"
+#include "token.h"
+#include "div.h"
+
+vunits V0;
+hunits H0;
+
+int hresolution = 1;
+int vresolution = 1;
+int units_per_inch;
+int sizescale;
+
+static int parse_expr(units *v, int scale_indicator, int parenthesised);
+static int start_number();
+
+int get_vunits(vunits *res, unsigned char si)
+{
+ if (!start_number())
+ return 0;
+ units x;
+ if (parse_expr(&x, si, 0)) {
+ *res = vunits(x);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+int get_hunits(hunits *res, unsigned char si)
+{
+ if (!start_number())
+ return 0;
+ units x;
+ if (parse_expr(&x, si, 0)) {
+ *res = hunits(x);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+int get_number(units *res, unsigned char si)
+{
+ if (!start_number())
+ return 0;
+ units x;
+ if (parse_expr(&x, si, 0)) {
+ *res = x;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+int get_integer(int *res)
+{
+ if (!start_number())
+ return 0;
+ units x;
+ if (parse_expr(&x, 0, 0)) {
+ *res = x;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+enum incr_number_result { BAD, ABSOLUTE, INCREMENT, DECREMENT };
+
+static incr_number_result get_incr_number(units *res, unsigned char);
+
+int get_vunits(vunits *res, unsigned char si, vunits prev_value)
+{
+ units v;
+ switch (get_incr_number(&v, si)) {
+ case BAD:
+ return 0;
+ case ABSOLUTE:
+ *res = v;
+ break;
+ case INCREMENT:
+ *res = prev_value + v;
+ break;
+ case DECREMENT:
+ *res = prev_value - v;
+ break;
+ default:
+ assert(0);
+ }
+ return 1;
+}
+
+int get_hunits(hunits *res, unsigned char si, hunits prev_value)
+{
+ units v;
+ switch (get_incr_number(&v, si)) {
+ case BAD:
+ return 0;
+ case ABSOLUTE:
+ *res = v;
+ break;
+ case INCREMENT:
+ *res = prev_value + v;
+ break;
+ case DECREMENT:
+ *res = prev_value - v;
+ break;
+ default:
+ assert(0);
+ }
+ return 1;
+}
+
+int get_number(units *res, unsigned char si, units prev_value)
+{
+ units v;
+ switch (get_incr_number(&v, si)) {
+ case BAD:
+ return 0;
+ case ABSOLUTE:
+ *res = v;
+ break;
+ case INCREMENT:
+ *res = prev_value + v;
+ break;
+ case DECREMENT:
+ *res = prev_value - v;
+ break;
+ default:
+ assert(0);
+ }
+ return 1;
+}
+
+int get_integer(int *res, int prev_value)
+{
+ units v;
+ switch (get_incr_number(&v, 0)) {
+ case BAD:
+ return 0;
+ case ABSOLUTE:
+ *res = v;
+ break;
+ case INCREMENT:
+ *res = prev_value + int(v);
+ break;
+ case DECREMENT:
+ *res = prev_value - int(v);
+ break;
+ default:
+ assert(0);
+ }
+ return 1;
+}
+
+
+static incr_number_result get_incr_number(units *res, unsigned char si)
+{
+ if (!start_number())
+ return BAD;
+ incr_number_result result = ABSOLUTE;
+ if (tok.ch() == '+') {
+ tok.next();
+ result = INCREMENT;
+ }
+ else if (tok.ch() == '-') {
+ tok.next();
+ result = DECREMENT;
+ }
+ if (parse_expr(res, si, 0))
+ return result;
+ else
+ return BAD;
+}
+
+static int start_number()
+{
+ while (tok.space())
+ tok.next();
+ if (tok.newline()) {
+ warning(WARN_MISSING, "missing number");
+ return 0;
+ }
+ if (tok.tab()) {
+ warning(WARN_TAB, "tab character where number expected");
+ return 0;
+ }
+ if (tok.right_brace()) {
+ warning(WARN_RIGHT_BRACE, "`\\}' where number expected");
+ return 0;
+ }
+ return 1;
+}
+
+enum { OP_LEQ = 'L', OP_GEQ = 'G', OP_MAX = 'X', OP_MIN = 'N' };
+
+#define SCALE_INDICATOR_CHARS "icPmnpuvMsz"
+
+static int parse_term(units *v, int scale_indicator, int parenthesised);
+
+static int parse_expr(units *v, int scale_indicator, int parenthesised)
+{
+ int result = parse_term(v, scale_indicator, parenthesised);
+ while (result) {
+ if (parenthesised)
+ tok.skip();
+ int op = tok.ch();
+ switch (op) {
+ case '+':
+ case '-':
+ case '/':
+ case '*':
+ case '%':
+ case ':':
+ case '&':
+ tok.next();
+ break;
+ case '>':
+ tok.next();
+ if (tok.ch() == '=') {
+ tok.next();
+ op = OP_GEQ;
+ }
+ else if (tok.ch() == '?') {
+ tok.next();
+ op = OP_MAX;
+ }
+ break;
+ case '<':
+ tok.next();
+ if (tok.ch() == '=') {
+ tok.next();
+ op = OP_LEQ;
+ }
+ else if (tok.ch() == '?') {
+ tok.next();
+ op = OP_MIN;
+ }
+ break;
+ case '=':
+ tok.next();
+ if (tok.ch() == '=')
+ tok.next();
+ break;
+ default:
+ return result;
+ }
+ units v2;
+ if (!parse_term(&v2, scale_indicator, parenthesised))
+ return 0;
+ int overflow = 0;
+ switch (op) {
+ case '<':
+ *v = *v < v2;
+ break;
+ case '>':
+ *v = *v > v2;
+ break;
+ case OP_LEQ:
+ *v = *v <= v2;
+ break;
+ case OP_GEQ:
+ *v = *v >= v2;
+ break;
+ case OP_MIN:
+ if (*v > v2)
+ *v = v2;
+ break;
+ case OP_MAX:
+ if (*v < v2)
+ *v = v2;
+ break;
+ case '=':
+ *v = *v == v2;
+ break;
+ case '&':
+ *v = *v > 0 && v2 > 0;
+ break;
+ case ':':
+ *v = *v > 0 || v2 > 0;
+ case '+':
+ if (v2 < 0) {
+ if (*v < INT_MIN - v2)
+ overflow = 1;
+ }
+ else if (v2 > 0) {
+ if (*v > INT_MAX - v2)
+ overflow = 1;
+ }
+ if (overflow) {
+ error("addition overflow");
+ return 0;
+ }
+ *v += v2;
+ break;
+ case '-':
+ if (v2 < 0) {
+ if (*v > INT_MAX + v2)
+ overflow = 1;
+ }
+ else if (v2 > 0) {
+ if (*v < INT_MIN + v2)
+ overflow = 1;
+ }
+ if (overflow) {
+ error("subtraction overflow");
+ return 0;
+ }
+ *v -= v2;
+ break;
+ case '*':
+ if (v2 < 0) {
+ if (*v > 0) {
+ if (*v > -(unsigned)INT_MIN / -(unsigned)v2)
+ overflow = 1;
+ }
+ else if (-(unsigned)*v > INT_MAX / -(unsigned)v2)
+ overflow = 1;
+ }
+ else if (v2 > 0) {
+ if (*v > 0) {
+ if (*v > INT_MAX / v2)
+ overflow = 1;
+ }
+ else if (-(unsigned)*v > -(unsigned)INT_MIN / v2)
+ overflow = 1;
+ }
+ if (overflow) {
+ error("multiplication overflow");
+ return 0;
+ }
+ *v *= v2;
+ break;
+ case '/':
+ if (v2 == 0) {
+ error("division by zero");
+ return 0;
+ }
+ *v /= v2;
+ break;
+ case '%':
+ if (v2 == 0) {
+ error("modulus by zero");
+ return 0;
+ }
+ *v %= v2;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ return result;
+}
+
+static int parse_term(units *v, int scale_indicator, int parenthesised)
+{
+ int negative = 0;
+ for (;;)
+ if (parenthesised && tok.space())
+ tok.next();
+ else if (tok.ch() == '+')
+ tok.next();
+ else if (tok.ch() == '-') {
+ tok.next();
+ negative = !negative;
+ }
+ else
+ break;
+ unsigned char c = tok.ch();
+ switch (c) {
+ case '|':
+ // | is not restricted to the outermost level
+ // tbl uses this
+ tok.next();
+ if (!parse_term(v, scale_indicator, parenthesised))
+ return 0;
+ int tem;
+ tem = (scale_indicator == 'v'
+ ? curdiv->get_vertical_position().to_units()
+ : curenv->get_input_line_position().to_units());
+ if (tem >= 0) {
+ if (*v < INT_MIN + tem) {
+ error("numeric overflow");
+ return 0;
+ }
+ }
+ else {
+ if (*v > INT_MAX + tem) {
+ error("numeric overflow");
+ return 0;
+ }
+ }
+ *v -= tem;
+ if (negative) {
+ if (*v == INT_MIN) {
+ error("numeric overflow");
+ return 0;
+ }
+ *v = -*v;
+ }
+ return 1;
+ case '(':
+ tok.next();
+ c = tok.ch();
+ if (c == ')') {
+ warning(WARN_SYNTAX, "empty parentheses");
+ tok.next();
+ *v = 0;
+ return 1;
+ }
+ else if (c != 0 && strchr(SCALE_INDICATOR_CHARS, c) != 0) {
+ tok.next();
+ if (tok.ch() == ';') {
+ tok.next();
+ scale_indicator = c;
+ }
+ else {
+ error("expected `;' after scale-indicator (got %1)",
+ tok.description());
+ return 0;
+ }
+ }
+ else if (c == ';') {
+ scale_indicator = 0;
+ tok.next();
+ }
+ if (!parse_expr(v, scale_indicator, 1))
+ return 0;
+ tok.skip();
+ if (tok.ch() != ')') {
+ warning(WARN_SYNTAX, "missing `)' (got %1)", tok.description());
+ }
+ else
+ tok.next();
+ if (negative) {
+ if (*v == INT_MIN) {
+ error("numeric overflow");
+ return 0;
+ }
+ *v = -*v;
+ }
+ return 1;
+ case '.':
+ *v = 0;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ *v = 0;
+ do {
+ if (*v > INT_MAX/10) {
+ error("numeric overflow");
+ return 0;
+ }
+ *v *= 10;
+ if (*v > INT_MAX - (int(c) - '0')) {
+ error("numeric overflow");
+ return 0;
+ }
+ *v += c - '0';
+ tok.next();
+ c = tok.ch();
+ } while (csdigit(c));
+ break;
+ case '/':
+ case '*':
+ case '%':
+ case ':':
+ case '&':
+ case '>':
+ case '<':
+ case '=':
+ warning(WARN_SYNTAX, "empty left operand");
+ *v = 0;
+ return 1;
+ default:
+ warning(WARN_NUMBER, "numeric expression expected (got %1)",
+ tok.description());
+ return 0;
+ }
+ int divisor = 1;
+ if (tok.ch() == '.') {
+ tok.next();
+ for (;;) {
+ c = tok.ch();
+ if (!csdigit(c))
+ break;
+ // we may multiply the divisor by 254 later on
+ if (divisor <= INT_MAX/2540 && *v <= (INT_MAX - 9)/10) {
+ *v *= 10;
+ *v += c - '0';
+ divisor *= 10;
+ }
+ tok.next();
+ }
+ }
+ int si = scale_indicator;
+ int do_next = 0;
+ if ((c = tok.ch()) != 0 && strchr(SCALE_INDICATOR_CHARS, c) != 0) {
+ switch (scale_indicator) {
+ case 'z':
+ if (c != 'u' && c != 'z') {
+ warning(WARN_SCALE,
+ "only `z' and `u' scale indicators valid in this context");
+ break;
+ }
+ si = c;
+ break;
+ case 0:
+ warning(WARN_SCALE, "scale indicator invalid in this context");
+ break;
+ case 'u':
+ si = c;
+ break;
+ default:
+ if (c == 'z') {
+ warning(WARN_SCALE, "`z' scale indicator invalid in this context");
+ break;
+ }
+ si = c;
+ break;
+ }
+ // Don't do tok.next() here because the next token might be \s, which
+ // would affect the interpretation of m.
+ do_next = 1;
+ }
+ switch (si) {
+ case 'i':
+ *v = scale(*v, units_per_inch, divisor);
+ break;
+ case 'c':
+ *v = scale(*v, units_per_inch*100, divisor*254);
+ break;
+ case 0:
+ case 'u':
+ if (divisor != 1)
+ *v /= divisor;
+ break;
+ case 'p':
+ *v = scale(*v, units_per_inch, divisor*72);
+ break;
+ case 'P':
+ *v = scale(*v, units_per_inch, divisor*6);
+ break;
+ case 'm':
+ {
+ // Convert to hunits so that with -Tascii `m' behaves as in nroff.
+ hunits em = curenv->get_size();
+ *v = scale(*v, em.is_zero() ? hresolution : em.to_units(), divisor);
+ }
+ break;
+ case 'M':
+ {
+ hunits em = curenv->get_size();
+ *v = scale(*v, em.is_zero() ? hresolution : em.to_units(), divisor*100);
+ }
+ break;
+ case 'n':
+ {
+ // Convert to hunits so that with -Tascii `n' behaves as in nroff.
+ hunits en = curenv->get_size()/2;
+ *v = scale(*v, en.is_zero() ? hresolution : en.to_units(), divisor);
+ }
+ break;
+ case 'v':
+ *v = scale(*v, curenv->get_vertical_spacing().to_units(), divisor);
+ break;
+ case 's':
+ while (divisor > INT_MAX/(sizescale*72)) {
+ divisor /= 10;
+ *v /= 10;
+ }
+ *v = scale(*v, units_per_inch, divisor*sizescale*72);
+ break;
+ case 'z':
+ *v = scale(*v, sizescale, divisor);
+ break;
+ default:
+ assert(0);
+ }
+ if (do_next)
+ tok.next();
+ if (negative) {
+ if (*v == INT_MIN) {
+ error("numeric overflow");
+ return 0;
+ }
+ *v = -*v;
+ }
+ return 1;
+}
+
+units scale(units n, units x, units y)
+{
+ assert(x >= 0 && y > 0);
+ if (x == 0)
+ return 0;
+ if (n >= 0) {
+ if (n <= INT_MAX/x)
+ return (n*x)/y;
+ }
+ else {
+ if (-(unsigned)n <= -(unsigned)INT_MIN/x)
+ return (n*x)/y;
+ }
+ double res = n*double(x)/double(y);
+ if (res > INT_MAX) {
+ error("numeric overflow");
+ return INT_MAX;
+ }
+ else if (res < INT_MIN) {
+ error("numeric overflow");
+ return INT_MIN;
+ }
+ return int(res);
+}
+
+vunits::vunits(units x)
+{
+ // don't depend on the rounding direction for division of negative integers
+ if (vresolution == 1)
+ n = x;
+ else
+ n = (x < 0
+ ? -((-x + vresolution/2 - 1)/vresolution)
+ : (x + vresolution/2 - 1)/vresolution);
+}
+
+hunits::hunits(units x)
+{
+ // don't depend on the rounding direction for division of negative integers
+ if (hresolution == 1)
+ n = x;
+ else
+ n = (x < 0
+ ? -((-x + hresolution/2 - 1)/hresolution)
+ : (x + hresolution/2 - 1)/hresolution);
+}
diff --git a/src/roff/troff/reg.cc b/src/roff/troff/reg.cc
new file mode 100644
index 00000000..1aa27f82
--- /dev/null
+++ b/src/roff/troff/reg.cc
@@ -0,0 +1,458 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "troff.h"
+#include "symbol.h"
+#include "dictionary.h"
+#include "token.h"
+#include "request.h"
+#include "reg.h"
+
+object_dictionary number_reg_dictionary(101);
+
+int reg::get_value(units * /*d*/)
+{
+ return 0;
+}
+
+void reg::increment()
+{
+ error("can't increment read-only register");
+}
+
+void reg::decrement()
+{
+ error("can't decrement read-only register");
+}
+
+void reg::set_increment(units /*n*/)
+{
+ error("can't auto increment read-only register");
+}
+
+void reg::alter_format(char /*f*/, int /*w*/)
+{
+ error("can't alter format of read-only register");
+}
+
+const char *reg::get_format()
+{
+ return "0";
+}
+
+void reg::set_value(units /*n*/)
+{
+ error("can't write read-only register");
+}
+
+general_reg::general_reg() : format('1'), width(0), inc(0)
+{
+}
+
+static const char *number_value_to_ascii(int value, char format, int width)
+{
+ static char buf[128]; // must be at least 21
+ switch(format) {
+ case '1':
+ if (width <= 0)
+ return itoa(value);
+ else if (width > sizeof(buf) - 2)
+ sprintf(buf, "%.*d", int(sizeof(buf) - 2), int(value));
+ else
+ sprintf(buf, "%.*d", width, int(value));
+ break;
+ case 'i':
+ case 'I':
+ {
+ char *p = buf;
+ // troff uses z and w to represent 10000 and 5000 in Roman
+ // numerals; I can find no historical basis for this usage
+ const char *s = format == 'i' ? "zwmdclxvi" : "ZWMDCLXVI";
+ int n = int(value);
+ if (n >= 40000 || n <= -40000) {
+ error("magnitude of `%1' too big for i or I format", n);
+ return itoa(n);
+ }
+ if (n == 0) {
+ *p++ = '0';
+ *p = 0;
+ break;
+ }
+ if (n < 0) {
+ *p++ = '-';
+ n = -n;
+ }
+ while (n >= 10000) {
+ *p++ = s[0];
+ n -= 10000;
+ }
+ for (int i = 1000; i > 0; i /= 10, s += 2) {
+ int m = n/i;
+ n -= m*i;
+ switch (m) {
+ case 3:
+ *p++ = s[2];
+ /* falls through */
+ case 2:
+ *p++ = s[2];
+ /* falls through */
+ case 1:
+ *p++ = s[2];
+ break;
+ case 4:
+ *p++ = s[2];
+ *p++ = s[1];
+ break;
+ case 8:
+ *p++ = s[1];
+ *p++ = s[2];
+ *p++ = s[2];
+ *p++ = s[2];
+ break;
+ case 7:
+ *p++ = s[1];
+ *p++ = s[2];
+ *p++ = s[2];
+ break;
+ case 6:
+ *p++ = s[1];
+ *p++ = s[2];
+ break;
+ case 5:
+ *p++ = s[1];
+ break;
+ case 9:
+ *p++ = s[2];
+ *p++ = s[0];
+ }
+ }
+ *p = 0;
+ break;
+ }
+ case 'a':
+ case 'A':
+ {
+ int n = value;
+ char *p = buf;
+ if (n == 0) {
+ *p++ = '0';
+ *p = 0;
+ }
+ else {
+ if (n < 0) {
+ n = -n;
+ *p++ = '-';
+ }
+ // this is a bit tricky
+ while (n > 0) {
+ int d = n % 26;
+ if (d == 0)
+ d = 26;
+ n -= d;
+ n /= 26;
+ *p++ = format + d - 1;
+ }
+ *p-- = 0;
+ char *q = buf[0] == '-' ? buf+1 : buf;
+ while (q < p) {
+ char temp = *q;
+ *q = *p;
+ *p = temp;
+ --p;
+ ++q;
+ }
+ }
+ break;
+ }
+ default:
+ assert(0);
+ break;
+ }
+ return buf;
+}
+
+const char *general_reg::get_string()
+{
+ units n;
+ if (!get_value(&n))
+ return "";
+ return number_value_to_ascii(n, format, width);
+}
+
+
+void general_reg::increment()
+{
+ int n;
+ if (get_value(&n))
+ set_value(n + inc);
+}
+
+void general_reg::decrement()
+{
+ int n;
+ if (get_value(&n))
+ set_value(n - inc);
+}
+
+void general_reg::set_increment(units n)
+{
+ inc = n;
+}
+
+void general_reg::alter_format(char f, int w)
+{
+ format = f;
+ width = w;
+}
+
+static const char *number_format_to_ascii(char format, int width)
+{
+ static char buf[24];
+ if (format == '1') {
+ if (width > 0) {
+ int n = width;
+ if (n > int(sizeof(buf)) - 1)
+ n = int(sizeof(buf)) - 1;
+ sprintf(buf, "%.*d", n, 0);
+ return buf;
+ }
+ else
+ return "0";
+ }
+ else {
+ buf[0] = format;
+ buf[1] = '\0';
+ return buf;
+ }
+}
+
+const char *general_reg::get_format()
+{
+ return number_format_to_ascii(format, width);
+}
+
+class number_reg : public general_reg {
+ units value;
+public:
+ number_reg();
+ int get_value(units *);
+ void set_value(units);
+};
+
+number_reg::number_reg() : value(0)
+{
+}
+
+int number_reg::get_value(units *res)
+{
+ *res = value;
+ return 1;
+}
+
+void number_reg::set_value(units n)
+{
+ value = n;
+}
+
+variable_reg::variable_reg(units *p) : ptr(p)
+{
+}
+
+void variable_reg::set_value(units n)
+{
+ *ptr = n;
+}
+
+int variable_reg::get_value(units *res)
+{
+ *res = *ptr;
+ return 1;
+}
+
+void define_number_reg()
+{
+ symbol nm = get_name(1);
+ if (nm.is_null()) {
+ skip_line();
+ return;
+ }
+ reg *r = (reg *)number_reg_dictionary.lookup(nm);
+ units v;
+ units prev_value;
+ if (!r || !r->get_value(&prev_value))
+ prev_value = 0;
+ if (get_number(&v, 'u', prev_value)) {
+ if (r == 0) {
+ r = new number_reg;
+ number_reg_dictionary.define(nm, r);
+ }
+ r->set_value(v);
+ if (tok.space() && has_arg() && get_number(&v, 'u'))
+ r->set_increment(v);
+ }
+ skip_line();
+}
+
+#if 0
+void inline_define_reg()
+{
+ token start;
+ start.next();
+ if (!start.delimiter(1))
+ return;
+ tok.next();
+ symbol nm = get_name(1);
+ if (nm.is_null())
+ return;
+ reg *r = (reg *)number_reg_dictionary.lookup(nm);
+ if (r == 0) {
+ r = new number_reg;
+ number_reg_dictionary.define(nm, r);
+ }
+ units v;
+ units prev_value;
+ if (!r->get_value(&prev_value))
+ prev_value = 0;
+ if (get_number(&v, 'u', prev_value)) {
+ r->set_value(v);
+ if (start != tok) {
+ if (get_number(&v, 'u')) {
+ r->set_increment(v);
+ if (start != tok)
+ warning(WARN_DELIM, "closing delimiter does not match");
+ }
+ }
+ }
+}
+#endif
+
+void set_number_reg(symbol nm, units n)
+{
+ reg *r = (reg *)number_reg_dictionary.lookup(nm);
+ if (r == 0) {
+ r = new number_reg;
+ number_reg_dictionary.define(nm, r);
+ }
+ r->set_value(n);
+}
+
+reg *lookup_number_reg(symbol nm)
+{
+ reg *r = (reg *)number_reg_dictionary.lookup(nm);
+ if (r == 0) {
+ warning(WARN_REG, "number register `%1' not defined", nm.contents());
+ r = new number_reg;
+ number_reg_dictionary.define(nm, r);
+ }
+ return r;
+}
+
+void alter_format()
+{
+ symbol nm = get_name(1);
+ if (nm.is_null()) {
+ skip_line();
+ return;
+ }
+ reg *r = (reg *)number_reg_dictionary.lookup(nm);
+ if (r == 0) {
+ r = new number_reg;
+ number_reg_dictionary.define(nm, r);
+ }
+ tok.skip();
+ char c = tok.ch();
+ if (csdigit(c)) {
+ int n = 0;
+ do {
+ ++n;
+ tok.next();
+ } while (csdigit(tok.ch()));
+ r->alter_format('1', n);
+ }
+ else if (c == 'i' || c == 'I' || c == 'a' || c == 'A')
+ r->alter_format(c);
+ else if (tok.newline() || tok.eof())
+ warning(WARN_MISSING, "missing number register format");
+ else
+ error("bad number register format (got %1)", tok.description());
+ skip_line();
+}
+
+void remove_reg()
+{
+ for (;;) {
+ symbol s = get_name();
+ if (s.is_null())
+ break;
+ number_reg_dictionary.remove(s);
+ }
+ skip_line();
+}
+
+void alias_reg()
+{
+ symbol s1 = get_name(1);
+ if (!s1.is_null()) {
+ symbol s2 = get_name(1);
+ if (!s2.is_null()) {
+ if (!number_reg_dictionary.alias(s1, s2))
+ warning(WARN_REG, "number register `%1' not defined", s2.contents());
+ }
+ }
+ skip_line();
+}
+
+void rename_reg()
+{
+ symbol s1 = get_name(1);
+ if (!s1.is_null()) {
+ symbol s2 = get_name(1);
+ if (!s2.is_null())
+ number_reg_dictionary.rename(s1, s2);
+ }
+ skip_line();
+}
+
+void print_number_regs()
+{
+ object_dictionary_iterator iter(number_reg_dictionary);
+ reg *r;
+ symbol s;
+ while (iter.get(&s, (object **)&r)) {
+ assert(!s.is_null());
+ errprint("%1\t", s.contents());
+ const char *p = r->get_string();
+ if (p)
+ errprint(p);
+ errprint("\n");
+ }
+ fflush(stderr);
+ skip_line();
+}
+
+void init_reg_requests()
+{
+ init_request("rr", remove_reg);
+ init_request("nr", define_number_reg);
+ init_request("af", alter_format);
+ init_request("aln", alias_reg);
+ init_request("rnn", rename_reg);
+ init_request("pnr", print_number_regs);
+}
diff --git a/src/roff/troff/reg.h b/src/roff/troff/reg.h
new file mode 100644
index 00000000..51d5b9a1
--- /dev/null
+++ b/src/roff/troff/reg.h
@@ -0,0 +1,73 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+class reg : public object {
+public:
+ virtual const char *get_string() = 0;
+ virtual int get_value(units *);
+ virtual void increment();
+ virtual void decrement();
+ virtual void set_increment(units);
+ virtual void alter_format(char f, int w = 0);
+ virtual const char *get_format();
+ virtual void set_value(units);
+};
+
+class constant_int_reg : public reg {
+ int *p;
+public:
+ constant_int_reg(int *);
+ const char *get_string();
+};
+
+class general_reg : public reg {
+ char format;
+ int width;
+ int inc;
+public:
+ general_reg();
+ const char *get_string();
+ void increment();
+ void decrement();
+ void alter_format(char f, int w = 0);
+ void set_increment(units);
+ const char *get_format();
+ void add_value(units);
+
+ void set_value(units) = 0;
+ int get_value(units *) = 0;
+};
+
+class variable_reg : public general_reg {
+ units *ptr;
+public:
+ variable_reg(int *);
+ void set_value(units);
+ int get_value(units *);
+};
+
+extern object_dictionary number_reg_dictionary;
+extern void set_number_reg(symbol nm, units n);
+
+reg *lookup_number_reg(symbol);
+#if 0
+void inline_define_reg();
+#endif
diff --git a/src/roff/troff/request.h b/src/roff/troff/request.h
new file mode 100644
index 00000000..2334a463
--- /dev/null
+++ b/src/roff/troff/request.h
@@ -0,0 +1,81 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+typedef void (*REQUEST_FUNCP)();
+
+class macro;
+
+class request_or_macro : public object {
+public:
+ request_or_macro();
+ virtual void invoke(symbol s) = 0;
+ virtual macro *to_macro();
+};
+
+class request : public request_or_macro {
+ REQUEST_FUNCP p;
+public:
+ void invoke(symbol);
+ request(REQUEST_FUNCP);
+};
+
+void delete_request_or_macro(request_or_macro *);
+
+extern object_dictionary request_dictionary;
+
+struct macro_header;
+struct node;
+
+class macro : public request_or_macro {
+ macro_header *p;
+ const char *filename; // where was it defined?
+ int lineno;
+ int length;
+public:
+ macro();
+ ~macro();
+ macro(const macro &);
+ macro &operator=(const macro &);
+ void append(unsigned char);
+ void append(node *);
+ void invoke(symbol);
+ macro *to_macro();
+ void print_size();
+ int empty();
+ friend class string_iterator;
+ friend void chop_macro();
+ friend void substring_macro();
+ friend int operator==(const macro &, const macro &);
+};
+
+extern void init_input_requests();
+extern void init_div_requests();
+extern void init_node_requests();
+extern void init_reg_requests();
+extern void init_env_requests();
+extern void init_hyphen_requests();
+extern void init_request(const char *s, REQUEST_FUNCP f);
+
+extern int no_break_flag; // indicates whether request was invoked with . or '
+
+class charinfo;
+class environment;
+
+node *charinfo_to_node_list(charinfo *, const environment *);
diff --git a/src/roff/troff/symbol.cc b/src/roff/troff/symbol.cc
new file mode 100644
index 00000000..ce09e393
--- /dev/null
+++ b/src/roff/troff/symbol.cc
@@ -0,0 +1,150 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "troff.h"
+#include "symbol.h"
+
+const char **symbol::table = 0;
+int symbol::table_used = 0;
+int symbol::table_size = 0;
+char *symbol::block = 0;
+int symbol::block_size = 0;
+
+const symbol NULL_SYMBOL;
+
+#ifdef BLOCK_SIZE
+#undef BLOCK_SIZE
+#endif
+
+const int BLOCK_SIZE = 1024;
+// the table will increase in size as necessary
+// the size will be chosen from the following array
+// add some more if you want
+// I think it unlikely that we'll need more than a million symbols
+static const unsigned int table_sizes[] = {
+101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009, 80021, 160001, 500009, 1000003, 0
+};
+const double FULL_MAX = 0.3; // don't let the table get more than this full
+
+static unsigned int hash_string(const char *p)
+{
+ // compute a hash code; this assumes 32-bit unsigned ints
+ // see p436 of Compilers by Aho, Sethi & Ullman
+ // give special treatment to two-character names
+ unsigned int hc = 0, g;
+ if (*p != 0) {
+ hc = *p++;
+ if (*p != 0) {
+ hc <<= 7;
+ hc += *p++;
+ for (; *p != 0; p++) {
+ hc <<= 4;
+ hc += *p;
+ if ((g = (hc & 0xf0000000)) == 0) {
+ hc ^= g >> 24;
+ hc ^= g;
+ }
+ }
+ }
+ }
+ return hc;
+}
+
+// Tell compiler that a variable is intentionally unused.
+inline void unused(void *) { }
+
+symbol::symbol(const char *p, int how)
+{
+ if (p == 0 || *p == 0) {
+ s = 0;
+ return;
+ }
+ if (table == 0) {
+ table_size = table_sizes[0];
+ table = (const char **)new char*[table_size];
+ for (int i = 0; i < table_size; i++)
+ table[i] = 0;
+ table_used = 0;
+ }
+ unsigned int hc = hash_string(p);
+ const char **pp;
+ for (pp = table + hc % table_size;
+ *pp != 0;
+ (pp == table ? pp = table + table_size - 1 : --pp))
+ if (strcmp(p, *pp) == 0) {
+ s = *pp;
+ return;
+ }
+ if (how == MUST_ALREADY_EXIST) {
+ s = 0;
+ return;
+ }
+ if (table_used >= table_size - 1 || table_used >= table_size*FULL_MAX) {
+ const char **old_table = table;
+ unsigned int old_table_size = table_size;
+ int i;
+ for (i = 1; table_sizes[i] <= old_table_size; i++)
+ if (table_sizes[i] == 0)
+ fatal("too many symbols");
+ table_size = table_sizes[i];
+ table_used = 0;
+ table = (const char **)new char*[table_size];
+ for (i = 0; i < table_size; i++)
+ table[i] = 0;
+ for (pp = old_table + old_table_size - 1;
+ pp >= old_table;
+ --pp) {
+ symbol temp(*pp, 1); /* insert it into the new table */
+ unused(&temp);
+ }
+ a_delete old_table;
+ for (pp = table + hc % table_size;
+ *pp != 0;
+ (pp == table ? pp = table + table_size - 1 : --pp))
+ ;
+ }
+ ++table_used;
+ if (how == DONT_STORE) {
+ s = *pp = p;
+ }
+ else {
+ int len = strlen(p)+1;
+ if (block == 0 || block_size < len) {
+ block_size = len > BLOCK_SIZE ? len : BLOCK_SIZE;
+ block = new char [block_size];
+ }
+ (void)strcpy(block, p);
+ s = *pp = block;
+ block += len;
+ block_size -= len;
+ }
+}
+
+symbol concat(symbol s1, symbol s2)
+{
+ char *buf = new char [strlen(s1.contents()) + strlen(s2.contents()) + 1];
+ strcpy(buf, s1.contents());
+ strcat(buf, s2.contents());
+ symbol res(buf);
+ a_delete buf;
+ return res;
+}
+
diff --git a/src/roff/troff/symbol.h b/src/roff/troff/symbol.h
new file mode 100644
index 00000000..88e0fff3
--- /dev/null
+++ b/src/roff/troff/symbol.h
@@ -0,0 +1,73 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define DONT_STORE 1
+#define MUST_ALREADY_EXIST 2
+
+class symbol {
+ static const char **table;
+ static int table_used;
+ static int table_size;
+ static char *block;
+ static int block_size;
+ const char *s;
+public:
+ symbol(const char *p, int how = 0);
+ symbol();
+ unsigned long hash() const;
+ int operator ==(symbol) const;
+ int operator !=(symbol) const;
+ const char *contents() const;
+ int is_null() const;
+};
+
+
+extern const symbol NULL_SYMBOL;
+
+inline symbol::symbol() : s(0)
+{
+}
+
+inline int symbol::operator==(symbol p) const
+{
+ return s == p.s;
+}
+
+inline int symbol::operator!=(symbol p) const
+{
+ return s != p.s;
+}
+
+inline unsigned long symbol::hash() const
+{
+ return (unsigned long)s;
+}
+
+inline const char *symbol::contents() const
+{
+ return s;
+}
+
+inline int symbol::is_null() const
+{
+ return s == 0;
+}
+
+symbol concat(symbol, symbol);
diff --git a/src/roff/troff/token.h b/src/roff/troff/token.h
new file mode 100644
index 00000000..f6707f2a
--- /dev/null
+++ b/src/roff/troff/token.h
@@ -0,0 +1,201 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+struct charinfo;
+struct node;
+struct vunits;
+
+class token {
+ symbol nm;
+ node *nd;
+ unsigned char c;
+ int val;
+ units dim;
+ enum token_type {
+ TOKEN_BACKSPACE,
+ TOKEN_BEGIN_TRAP,
+ TOKEN_CHAR, // a normal printing character
+ TOKEN_DUMMY,
+ TOKEN_EMPTY, // this is the initial value
+ TOKEN_END_TRAP,
+ TOKEN_ESCAPE, // \e
+ TOKEN_HYPHEN_INDICATOR,
+ TOKEN_INTERRUPT, // \c
+ TOKEN_ITALIC_CORRECTION, // \/
+ TOKEN_LEADER, // ^A
+ TOKEN_LEFT_BRACE,
+ TOKEN_MARK_INPUT, // \k -- `nm' is the name of the register
+ TOKEN_NEWLINE, // newline
+ TOKEN_NODE,
+ TOKEN_NUMBERED_CHAR,
+ TOKEN_PAGE_EJECTOR,
+ TOKEN_REQUEST,
+ TOKEN_RIGHT_BRACE,
+ TOKEN_SPACE, // ` ' -- ordinary space
+ TOKEN_SPECIAL, // a special character -- \' \` \- \(xx
+ TOKEN_SPREAD, // \p -- break and spread output line
+ TOKEN_TAB, // tab
+ TOKEN_TRANSPARENT, // \!
+ TOKEN_EOF // end of file
+ } type;
+public:
+ token();
+ ~token();
+ token(const token &);
+ void operator=(const token &);
+ void next();
+ void process();
+ void skip();
+ int eof();
+ int nspaces(); // 1 if space, 2 if double space, 0 otherwise
+ int space(); // is it a space or double space?
+ int white_space(); // is the current token space or tab?
+ int special(); // is the current token a special character?
+ int newline(); // is the current token a newline?
+ int tab(); // is the current token a tab?
+ int leader();
+ int backspace();
+ int delimiter(int warn = 0); // is it suitable for use as a delimiter?
+ int dummy();
+ int transparent();
+ int left_brace();
+ int right_brace();
+ int page_ejector();
+ int hyphen_indicator();
+ int operator==(const token &); // need this for delimiters, and for conditions
+ int operator!=(const token &); // ditto
+ unsigned char ch();
+ charinfo *get_char(int required = 0);
+ int add_to_node_list(node **);
+ int title();
+ void make_space();
+ void make_newline();
+ const char *description();
+
+ friend void process_input_stack();
+};
+
+extern token tok; // the current token
+
+extern symbol get_name(int required = 0);
+extern symbol get_long_name(int required = 0);
+extern charinfo *get_optional_char();
+extern void check_missing_character();
+extern void skip_line();
+extern void handle_initial_title();
+
+struct hunits;
+extern void read_title_parts(node **part, hunits *part_width);
+
+extern int get_number(units *result, unsigned char si);
+extern int get_integer(int *result);
+
+extern int get_number(units *result, unsigned char si, units prev_value);
+extern int get_integer(int *result, int prev_value);
+
+void interpolate_number_reg(symbol, int);
+
+const char *asciify(int c);
+
+inline int token::newline()
+{
+ return type == TOKEN_NEWLINE;
+}
+
+inline int token::space()
+{
+ return type == TOKEN_SPACE;
+}
+
+inline int token::special()
+{
+ return type == TOKEN_SPECIAL;
+}
+
+inline int token::nspaces()
+{
+ if (type == TOKEN_SPACE)
+ return 1;
+ else
+ return 0;
+}
+
+inline int token::white_space()
+{
+ return type == TOKEN_SPACE || type == TOKEN_TAB;
+}
+
+inline int token::transparent()
+{
+ return type == TOKEN_TRANSPARENT;
+}
+
+inline int token::page_ejector()
+{
+ return type == TOKEN_PAGE_EJECTOR;
+}
+
+inline unsigned char token::ch()
+{
+ return type == TOKEN_CHAR ? c : 0;
+}
+
+inline int token::eof()
+{
+ return type == TOKEN_EOF;
+}
+
+inline int token::dummy()
+{
+ return type == TOKEN_DUMMY;
+}
+
+inline int token::left_brace()
+{
+ return type == TOKEN_LEFT_BRACE;
+}
+
+inline int token::right_brace()
+{
+ return type == TOKEN_RIGHT_BRACE;
+}
+
+inline int token::tab()
+{
+ return type == TOKEN_TAB;
+}
+
+inline int token::leader()
+{
+ return type == TOKEN_LEADER;
+}
+
+inline int token::backspace()
+{
+ return type == TOKEN_BACKSPACE;
+}
+
+inline int token::hyphen_indicator()
+{
+ return type == TOKEN_HYPHEN_INDICATOR;
+}
+
+int has_arg();
diff --git a/src/roff/troff/troff.h b/src/roff/troff/troff.h
new file mode 100644
index 00000000..c5585016
--- /dev/null
+++ b/src/roff/troff/troff.h
@@ -0,0 +1,83 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "lib.h"
+#include "assert.h"
+#include "device.h"
+
+void cleanup_and_exit(int n);
+
+typedef int units;
+
+extern units scale(units n, units x, units y); // scale n by x/y
+
+extern units units_per_inch;
+
+extern int ascii_output_flag;
+extern int suppress_output_flag;
+
+extern int tcommand_flag;
+extern int vresolution;
+extern int hresolution;
+extern int sizescale;
+
+#include "cset.h"
+#include "cmap.h"
+#include "errarg.h"
+#include "error.h"
+
+enum warning_type {
+ WARN_CHAR = 01,
+ WARN_NUMBER = 02,
+ WARN_BREAK = 04,
+ WARN_DELIM = 010,
+ WARN_EL = 020,
+ WARN_SCALE = 040,
+ WARN_RANGE = 0100,
+ WARN_SYNTAX = 0200,
+ WARN_DI = 0400,
+ WARN_MAC = 01000,
+ WARN_REG = 02000,
+ WARN_TAB = 04000,
+ WARN_RIGHT_BRACE = 010000,
+ WARN_MISSING = 020000,
+ WARN_INPUT = 040000,
+ WARN_ESCAPE = 0100000,
+ WARN_SPACE = 0200000,
+ WARN_FONT = 0400000,
+ WARN_IG = 01000000
+ // change WARN_TOTAL if you add more warning types
+};
+
+const int WARN_TOTAL = 01777777;
+
+int warning(warning_type, const char *,
+ const errarg & = empty_errarg,
+ const errarg & = empty_errarg,
+ const errarg & = empty_errarg);
diff --git a/src/roff/troff/troff.man b/src/roff/troff/troff.man
new file mode 100644
index 00000000..82d373ba
--- /dev/null
+++ b/src/roff/troff/troff.man
@@ -0,0 +1,2102 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1999 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.\" define a string tx for the TeX logo
+.ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X
+.el .ds tx TeX
+.de TQ
+.br
+.ns
+.TP \\$1
+..
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.\" The BSD man macros can't handle " in arguments to font change macros,
+.\" so use \(ts instead of ".
+.tr \(ts"
+.TH @G@TROFF 1 "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+@g@troff \- format documents
+.SH SYNOPSIS
+.nr a \n(.j
+.ad l
+.nr i \n(.i
+.in +\w'\fB@g@troff 'u
+.ti \niu
+.B @g@troff
+.de OP
+.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
+.el .RB "[\ " "\\$1" "\ ]"
+..
+.OP \-abivzCERU
+.OP \-w name
+.OP \-W name
+.OP \-d cs
+.OP \-f fam
+.OP \-m name
+.OP \-n num
+.OP \-o list
+.OP \-r cn
+.OP \-T name
+.OP \-F dir
+.OP \-M dir
+.RI "[\ " files\|.\|.\|. "\ ]"
+.br
+.ad \na
+.SH DESCRIPTION
+This manual page describes the GNU version of
+.BR troff ,
+which is part of the groff document formatting system.
+It is highly compatible with Unix troff.
+Usually it should be invoked using the groff command, which will
+also run preprocessors and postprocessors in the appropriate
+order and with the appropriate options.
+.SH OPTIONS
+.TP \w'\-dname=s'u+2n
+.B \-a
+Generate an
+.SM ASCII
+approximation of the typeset output.
+.TP
+.B \-b
+Print a backtrace with each warning or error message. This backtrace
+should help track down the cause of the error. The line numbers given
+in the backtrace may not always be correct:
+.B troff 's
+idea of line numbers
+gets confused by
+.B as
+or
+.B am
+requests.
+.TP
+.B \-i
+Read the standard input after all the named input files have been
+processed.
+.TP
+.B \-v
+Print the version number.
+.TP
+.BI \-w name
+Enable warning
+.IR name .
+Available warnings are described in
+the Warnings subsection below.
+Multiple
+.B \-w
+options are allowed.
+.TP
+.BI \-W name
+Inhibit warning
+.IR name .
+Multiple
+.B \-W
+options are allowed.
+.TP
+.B \-E
+Inhibit all error messages.
+.TP
+.B \-z
+Suppress formatted output.
+.TP
+.B \-C
+Enable compatibility mode.
+.TP
+.BI \-d cs
+.TQ
+.BI \-d name = s
+Define
+.I c
+or
+.I name
+to be a string
+.IR s ;
+.I c
+must be a one letter name.
+.TP
+.BI \-f fam
+Use
+.I fam
+as the default font family.
+.TP
+.BI \-m name
+Read in the file
+.BI tmac. name\fR.
+Normally this will be searched for in @MACRODIR@.
+By default is used the
+.I safer
+macro (reverted using -U ).
+.TP
+.B \-U
+Unsafe option, avoids default use of
+.I safer
+macro.
+.TP
+.B \-R
+Don't load
+.BR troffrc .
+.TP
+.BI \-n num
+Number the first page
+.IR num .
+.TP
+.BI \-o list
+Output only pages in
+.IR list ,
+which is a comma-separated list of page ranges;
+.I n
+means print page
+.IR n ,
+.IB m \- n
+means print every page between
+.I m
+and
+.IR n ,
+.BI \- n
+means print every page up to
+.IR n ,
+.IB n \-
+means print every page from
+.IR n .
+.B Troff
+will exit after printing the last page in the list.
+.TP
+.BI \-r cn
+.TQ
+.BI \-r name = n
+Set number register
+.I c
+or
+.I name
+to
+.IR n ;
+.I c
+must be a one character name;
+.I n
+can be any troff numeric expression.
+.TP
+.BI \-T name
+Prepare output for device
+.IR name ,
+rather than the default
+.BR @DEVICE@ .
+.TP
+.BI \-F dir
+Search
+.I dir
+for subdirectories
+.BI dev name
+.RI ( name
+is the name of the device)
+for the
+.B DESC
+file and font files before the normal
+.BR @FONTDIR@ .
+.TP
+.BI \-M dir
+Search directory
+.I dir
+for macro files before the normal
+.BR @MACRODIR@ .
+.SH USAGE
+Only the features not in Unix troff are described here.
+.SS Long names
+The names of number registers, fonts, strings/macros/diversions,
+special characters can be of any length. In escape sequences, where
+you can use
+.BI ( xx
+for a two character name, you can use
+.BI [ xxx ]
+for a name of arbitrary length:
+.TP
+.BI \e[ xxx ]
+Print the special character called
+.IR xxx .
+.TP
+.BI \ef[ xxx ]
+Set font
+.IR xxx .
+.TP
+.BI \e*[ xxx ]
+Interpolate string
+.IR xxx .
+.TP
+.BI \en[ xxx ]
+Interpolate number register
+.IR xxx .
+.SS Fractional pointsizes
+A
+.I
+scaled point
+is equal to 1/sizescale
+points, where
+sizescale is specified in the
+.B DESC
+file (1 by default.)
+There is a new scale indicator
+.B z
+which has the effect of multiplying by sizescale.
+Requests and escape sequences in troff
+interpret arguments that represent a pointsize as being in units
+of scaled points, but they evaluate each such argument
+using a default scale indicator of
+.BR z .
+Arguments treated in this way are
+the argument to the
+.B ps
+request,
+the third argument to the
+.B cs
+request,
+the second and fourth arguments to the
+.B tkf
+request,
+the argument to the
+.B \eH
+escape sequence,
+and those variants of the
+.B \es
+escape sequence that take a numeric expression as their argument.
+.LP
+For example, suppose sizescale is 1000;
+then a scaled point will be equivalent to a millipoint;
+the request
+.B .ps 10.25
+is equivalent to
+.B .ps 10.25z
+and so sets the pointsize to 10250 scaled points,
+which is equal to 10.25 points.
+.LP
+The number register
+.B \en(.s
+returns the pointsize in points as decimal fraction.
+There is also a new number register
+.B \en[.ps]
+that returns the pointsize in scaled points.
+.LP
+It would make no sense to use the
+.B z
+scale indicator in a numeric expression
+whose default scale indicator was neither
+.B u
+nor
+.BR z ,
+and so
+.B troff
+disallows this.
+Similarly it would make no sense to use a scaling indicator
+other than
+.B z
+or
+.B u
+in a numeric expression whose default scale indicator was
+.BR z ,
+and so
+.B troff
+disallows this as well.
+.LP
+There is also new scale indicator
+.B s
+which multiplies by the number of units in a scaled point.
+So, for example,
+.B \en[.ps]s
+is equal to
+.BR 1m .
+Be sure not to confuse the
+.B s
+and
+.B z
+scale indicators.
+.SS Numeric expressions
+.LP
+Spaces are permitted in a number expression within parentheses.
+.LP
+.B M
+indicates a scale of 100ths of an em.
+.TP
+.IB e1 >? e2
+The maximum of
+.I e1
+and
+.IR e2 .
+.TP
+.IB e1 <? e2
+The minimum of
+.I e1
+and
+.IR e2 .
+.TP
+.BI ( c ; e )
+Evaluate
+.I e
+using
+.I c
+as the default scaling indicator.
+If
+.I c
+is missing, ignore scaling indicators in the evaluation of
+.IR e .
+.SS New escape sequences
+.TP
+.BI \eA' anything '
+This expands to
+.B 1
+or
+.B 0
+according as
+.I anything
+is or is not acceptable as the name of a string, macro, diversion,
+number register, environment or font.
+It will return
+.B 0
+if
+.I anything
+is empty.
+This is useful if you want to lookup user input in some sort of
+associative table.
+.TP
+.BI \eC' xxx '
+Typeset character named
+.IR xxx .
+Normally it is more convenient to use
+.BI \e[ xxx ]\fR.
+But
+.B \eC
+has the advantage that it is compatible with recent versions of
+.SM UNIX
+and is available in compatibility mode.
+.TP
+.B \eE
+This is equivalent to an escape character,
+but it's not interpreted in copy-mode.
+For example, strings to start and end superscripting could be defined
+like this:
+.RS
+.IP
+\&.ds { \ev'\-.3m'\es'\eEn[.s]*6u/10u'
+.br
+\&.ds } \es0\ev'.3m'
+.LP
+The use of
+.B \eE
+ensures that these definitions will work even if
+.B \e*{
+gets interpreted in copy-mode
+(for example, by being used in a macro argument.)
+.RE
+.TP
+.BI \eN' n '
+Typeset the character with code
+.I n
+in the current font.
+.I n
+can be any integer.
+Most devices only have characters with codes between 0 and 255.
+If the current font does not contain a character with that code,
+special fonts will
+.I not
+be searched.
+The
+.B \eN
+escape sequence can be conveniently used on conjunction with the
+.B char
+request:
+.RS
+.IP
+.B
+\&.char \e[phone] \ef(ZD\eN'37'
+.RE
+.IP
+The code of each character is given in the fourth column in the font
+description file after the
+.B charset
+command.
+It is possible to include unnamed characters in the font description
+file by using a name of
+.BR \-\-\- ;
+the
+.B \eN
+escape sequence is the only way to use these.
+.TP
+.BI \eR' name\ \(+-n '
+This has the same effect as
+.RS
+.IP
+.BI .nr\ name\ \(+-n
+.RE
+.TP
+.BI \es( nn
+.TQ
+.BI \es\(+-( nn
+Set the point size to
+.I nn
+points;
+.I nn
+must be exactly two digits.
+.TP
+.BI \es[\(+- n ]
+.TQ
+.BI \es\(+-[ n ]
+.TQ
+.BI \es'\(+- n '
+.TQ
+.BI \es\(+-' n '
+Set the point size to
+.I n
+scaled points;
+.I n
+is a numeric expression with a default scale indicator of
+.BR z .
+.TP
+.BI \eV x
+.TQ
+.BI \eV( xx
+.TQ
+.BI \eV[ xxx ]
+Interpolate the contents of the environment variable
+.I xxx ,
+as returned by
+.BR getenv (3).
+.B \eV
+is interpreted in copy-mode.
+.TP
+.BI \eY x
+.TQ
+.BI \eY( xx
+.TQ
+.BI \eY[ xxx ]
+This is approximately equivalent to
+.BI \eX'\e*[ xxx ]'\fR.
+However the contents of the string or macro
+.I xxx
+are not interpreted;
+also it is permitted for
+.I xxx
+to have been defined as a macro and thus contain newlines
+(it is not permitted for the argument to
+.B \eX
+to contain newlines).
+The inclusion of newlines requires an extension to the Unix troff output
+format, and will confuse drivers that do not know about this
+extension.
+.TP
+.BI \eZ' anything '
+Print anything and then restore the horizontal and vertical
+position;
+.I anything
+may not contain tabs or leaders.
+.TP
+.B \e$0
+The name by which the current macro was invoked.
+The
+.B als
+request can make a macro have more than one name.
+.TP
+.B \e$*
+In a macro, the concatenation of all the arguments separated by spaces.
+.TP
+.B \e$@
+In a macro, the concatenation of all the arguments with each surrounded by
+double quotes, and separated by spaces.
+.TP
+.BI \e$( nn
+.TQ
+.BI \e$[ nnn ]
+In a macro, this gives the
+.IR nn -th
+or
+.IR nnn -th
+argument.
+Macros can have a unlimited number of arguments.
+.TP
+.BI \e? anything \e?
+When used in a diversion, this will transparently embed
+.I anything
+in the diversion.
+.I anything
+is read in copy mode.
+When the diversion is reread,
+.I anything
+will be interpreted.
+.I anything
+may not contain newlines; use
+.B \e!
+if you want to embed newlines in a diversion.
+The escape sequence
+.B \e?
+is also recognised in copy mode and turned into a single internal
+code; it is this code that terminates
+.IR anything .
+Thus
+.RS
+.RS
+.ft B
+.nf
+.ne 15
+\&.nr x 1
+\&.nf
+\&.di d
+\e?\e\e?\e\e\e\e?\e\e\e\e\e\e\e\enx\e\e\e\e?\e\e?\e?
+\&.di
+\&.nr x 2
+\&.di e
+\&.d
+\&.di
+\&.nr x 3
+\&.di f
+\&.e
+\&.di
+\&.nr x 4
+\&.f
+.fi
+.ft
+.RE
+.RE
+.IP
+will print
+.BR 4 .
+.TP
+.B \e/
+This increases the width of the preceding character so that
+the spacing between that character and the following character
+will be correct if the following character is a roman character.
+For example, if an italic f is immediately followed by a roman
+right parenthesis, then in many fonts the top right portion of the f
+will overlap the top left of the right parenthesis producing \fIf\fR)\fR,
+which is ugly.
+Inserting
+.B \e/
+produces
+.ie \n(.g \fIf\/\fR)\fR
+.el \fIf\|\fR)\fR
+and avoids this problem.
+It is a good idea to use this escape sequence whenever an
+italic character is immediately followed by a roman character without any
+intervening space.
+.TP
+.B \e,
+This modifies the spacing of the following character so that the spacing
+between that character and the preceding character will correct if
+the preceding character is a roman character.
+For example, inserting
+.B \e,
+between the parenthesis and the f changes
+\fR(\fIf\fR to
+.ie \n(.g \fR(\,\fIf\fR.
+.el \fR(\^\fIf\fR.
+It is a good idea to use this escape sequence whenever a
+roman character is immediately followed by an italic character without any
+intervening space.
+.TP
+.B \e)
+Like
+.B \e&
+except that it behaves like a character declared with the
+.B cflags
+request to be transparent for the purposes of end of sentence recognition.
+.TP
+.B \e~
+This produces an unbreakable space that stretches like a normal inter-word
+space when a line is adjusted.
+.TP
+.B \e#
+Everything up to and including the next newline is ignored.
+This is interpreted in copy mode.
+This is like
+.B \e"
+except that
+.B \e"
+does not ignore the terminating newline.
+.SS New requests
+.TP
+.BI .aln\ xx\ yy
+Create an alias
+.I xx
+for number register object named
+.IR yy .
+The new name and the old name will be exactly equivalent.
+If
+.I yy
+is undefined, a warning of type
+.B reg
+will be generated, and the request will be ignored.
+.TP
+.BI .als\ xx\ yy
+Create an alias
+.I xx
+for request, string, macro, or diversion object named
+.IR yy .
+The new name and the old name will be exactly equivalent (it is similar to a
+hard rather than a soft link).
+If
+.I yy
+is undefined, a warning of type
+.B mac
+will be generated, and the request will be ignored.
+The
+.BR de ,
+.BR am ,
+.BR di ,
+.BR da ,
+.BR ds ,
+and
+.B as
+requests only create a new object if the name of the macro, diversion
+or string diversion is currently undefined or if it is defined to be a
+request; normally they modify the value of an existing object.
+.TP
+.BI .asciify\ xx
+This request only exists in order to make it possible
+to make certain gross hacks work with GNU troff.
+It `unformats' the diversion
+.I xx
+in such a way that
+.SM ASCII
+characters that were formatted and diverted into
+.I xx
+will be treated like ordinary input characters when
+.I xx
+is reread.
+For example, this
+.RS
+.IP
+.ne 7v+\n(.Vu
+.ft B
+.nf
+.ss 24
+\&.tr @.
+\&.di x
+\&@nr\e n\e 1
+\&.br
+\&.di
+\&.tr @@
+\&.asciify x
+\&.x
+.ss 12
+.fi
+.RE
+.IP
+will set register
+.B n
+to 1.
+.TP
+.B .backtrace
+Print a backtrace of the input stack on stderr.
+.TP
+.BI .blm\ xx
+Set the blank line macro to
+.IR xx .
+If there is a blank line macro,
+it will be invoked when a blank line is encountered instead of the usual
+troff behaviour.
+.TP
+.B .break
+Break out of a while loop.
+See also the
+.B while
+and
+.B continue
+requests.
+Be sure not to confuse this with the
+.B br
+request.
+.TP
+.BI .cflags\ n\ c1\ c2\|.\|.\|.
+Characters
+.IR c1 ,
+.IR c2 ,\|.\|.\|.
+have properties determined by
+.IR n ,
+which is ORed from the following:
+.RS
+.TP
+1
+the character ends sentences
+(initially characters
+.B .?!
+have this property);
+.TP
+2
+lines can be broken before the character
+(initially no characters have this property);
+a line will not be broken at a character with this property
+unless the characters on each side both have non-zero
+hyphenation codes.
+.TP
+4
+lines can be broken after the character
+(initially characters
+.B \-\e(hy\e(em
+have this property);
+a line will not be broken at a character with this property
+unless the characters on each side both have non-zero
+hyphenation codes.
+.TP
+8
+the character overlaps horizontally
+(initially characters
+.B \e(ul\e(rn\e(ru
+have this property);
+.TP
+16
+the character overlaps vertically
+(initially character
+.B \e(br
+has this property);
+.TP
+32
+an end of sentence character followed by any number of characters
+with this property will be treated
+as the end of a sentence if followed by a newline or two spaces;
+in other words
+the character is transparent for the purposes of end of sentence
+recognition;
+this is the same as having a zero space factor in \*(tx
+(initially characters
+.B \(ts')]*\e(dg\e(rq
+have this property).
+.RE
+.TP
+.BI .char\ c\ string
+Define character
+.I c
+to be
+.IR string .
+Every time character
+.I c
+needs to be printed,
+.I string
+will be processed in a temporary environment and the result
+will be wrapped up into a single object.
+Compatibility mode will be turned off
+and the escape character will be set to
+.B \e
+while
+.I string
+is being processed.
+Any emboldening, constant spacing or track kerning will be applied
+to this object rather than to individual characters in
+.IR string .
+A character defined by this request can be used just like
+a normal character provided by the output device.
+In particular other characters can be translated to it
+with the
+.B tr
+request;
+it can be made the leader character by the
+.B lc
+request;
+repeated patterns can be drawn with the character using the
+.B \el
+and
+.B \eL
+escape sequences;
+words containing the character can be hyphenated
+correctly, if the
+.B hcode
+request is used to give the character a hyphenation code.
+There is a special anti-recursion feature:
+use of character within the character's definition
+will be handled like normal characters not defined with
+.BR char .
+A character definition can be removed with the
+.B rchar
+request.
+.TP
+.BI .chop\ xx
+Chop the last character off macro, string, or diversion
+.IR xx .
+This is useful for removing the newline from the end of diversions
+that are to be interpolated as strings.
+.TP
+.BI .close\ stream
+Close the stream named
+.IR stream ;
+.I stream
+will no longer be an acceptable argument to the
+.B write
+request.
+See the
+.B open
+request.
+.TP
+.B .continue
+Finish the current iteration of a while loop.
+See also the
+.B while
+and
+.B break
+requests.
+.TP
+.BI .cp\ n
+If
+.I n
+is non-zero or missing, enable compatibility mode, otherwise
+disable it.
+In compatibility mode, long names are not recognised, and the
+incompatibilities caused by long names do not arise.
+.TP
+.BI .do\ xxx
+Interpret
+.I .xxx
+with compatibility mode disabled.
+For example,
+.RS
+.IP
+.B
+\&.do fam T
+.LP
+would have the same effect as
+.IP
+.B
+\&.fam T
+.LP
+except that it would work even if compatibility mode had been enabled.
+Note that the previous compatibility mode is restored before any files
+sourced by
+.I xxx
+are interpreted.
+.RE
+.TP
+.BI .fam\ xx
+Set the current font family to
+.IR xx .
+The current font family is part of the current environment.
+See the description of the
+.B sty
+request for more information on font families.
+.TP
+.BI .fspecial\ f\ s1\ s2\|.\|.\|.
+When the current font is
+.IR f ,
+fonts
+.IR s1 ,
+.IR s2 ,\|.\|.\|.
+will be special, that is, they will searched for characters not in
+the current font.
+Any fonts specified in the
+.B special
+request will be searched after fonts specified in the
+.B fspecial
+request.
+.TP
+.BI .ftr\ f\ g
+Translate font
+.I f
+to
+.IR g .
+Whenever a font named
+.I f
+is referred to in
+.B \ef
+escape sequence,
+or in the
+.BR ft ,
+.BR ul ,
+.BR bd ,
+.BR cs ,
+.BR tkf ,
+.BR special ,
+.BR fspecial ,
+.BR fp ,
+or
+.BR sty
+requests,
+font
+.I g
+will be used.
+If
+.I g
+is missing,
+or equal to
+.I f
+then font
+.I f
+will not be translated.
+.TP
+.BI .hcode \ c1\ code1\ c2\ code2\|.\|.\|.
+Set the hyphenation code of character
+.I c1
+to
+.I code1
+and that of
+.I c2
+to
+.IR code2 .
+A hyphenation code must be a single input
+character (not a special character) other than a digit or a space.
+Initially each lower-case letter has a hyphenation code, which
+is itself, and each upper-case letter has a hyphenation code
+which is the lower case version of itself.
+See also the
+.B hpf
+request.
+.TP
+.BI .hla\ lang
+Set the current hyphenation language to
+.IR lang .
+Hyphenation exceptions specified with the
+.B hw
+request and hyphenation patterns specified with the
+.B hpf
+request are both associated with the current hyphenation language.
+The
+.B hla
+request is usually invoked by the
+.B troffrc
+file.
+.TP
+.BI .hlm\ n
+Set the maximum number of consecutive hyphenated lines to
+.IR n .
+If
+.I n
+is negative, there is no maximum.
+The default value is \-1.
+This value is associated with the current environment.
+Only lines output from an environment count towards the maximum associated
+with that environment.
+Hyphens resulting from
+.B \e%
+are counted; explicit hyphens are not.
+.TP
+.BI .hpf\ file
+Read hyphenation patterns from
+.IR file ;
+this will be searched for in the same way that
+.BI tmac. name
+is searched for when the
+.BI \-m name
+option is specified.
+It should have the same format as the argument to
+the \epatterns primitive in \*(tx;
+the letters appearing in this file are interpreted as hyphenation
+codes.
+A
+.B %
+character in the patterns file introduces a comment that continues
+to the end of the line.
+The set of hyphenation patterns is associated with the current language
+set by the
+.B hla
+request.
+The
+.B hpf
+request
+is usually invoked by the
+.B troffrc
+file.
+.TP
+.BI .hym\ n
+Set the
+.I hyphenation margin
+to
+.IR n :
+when the current adjustment mode is not
+.BR b ,
+the line will not be hyphenated if the line is no more than
+.I n
+short.
+The default hyphenation margin is 0.
+The default scaling indicator for this request is
+.IR m .
+The hyphenation margin is associated with the current environment.
+The current hyphenation margin is available in the
+.B \en[.hym]
+register.
+.TP
+.BI .hys\ n
+Set the
+.I hyphenation space
+to
+.IR n :
+when the current adjustment mode is
+.B b
+don't hyphenate the line if the line can be justified by adding no more than
+.I n
+extra space to each word space.
+The default hyphenation space is 0.
+The default scaling indicator for this request is
+.BR m .
+The hyphenation space is associated with the current environment.
+The current hyphenation space is available in the
+.B \en[.hys]
+register.
+.TP
+.BI .kern\ n
+If
+.I n
+is non-zero or missing, enable pairwise kerning, otherwise disable it.
+.TP
+.BI .mso\ file
+The same as the
+.B so
+request except that
+.I file
+is searched for in the same way that
+.BI tmac. name
+is searched for when the
+.BI \-m name
+option is specified.
+.TP
+.B .nroff
+Make the
+.B n
+built-in condition true
+and the
+.B t
+built-in condition false.
+This can be reversed using the
+.B troff
+request.
+.TP
+.BI .open\ stream\ filename
+Open
+.I filename
+for writing and associate the stream named
+.I stream
+with it.
+See also the
+.B close
+and
+.B write
+requests.
+.TP
+.BI .opena\ stream\ filename
+Like
+.BR open ,
+but if
+.I filename
+exists, append to it instead of truncating it.
+.TP
+.B .pnr
+Print the names and contents of all currently defined number registers
+on stderr.
+.TP
+.BI .psbb \ filename
+Get the bounding box of a PostScript image
+.IR filename .
+This file must conform to Adobe's Document Structuring Conventions; the
+command looks for a
+.B %%BoundingBox
+comment to extract the bounding box values.
+After a successful call, the coordinates (in PostScript units) of the lower
+left and upper right edge can be found in the registers
+.BR \en[llx] ,
+.BR \en[lly] ,
+.BR \en[urx] ,
+and
+.BR \en[ury] ,
+respectively.
+If some error has occurred, the four registers are set to zero.
+.TP
+.BI .pso \ command
+This behaves like the
+.B so
+request except that input comes from the standard output of
+.IR command .
+.TP
+.B .ptr
+Print the names and positions of all traps (not including input line
+traps and diversion traps) on stderr. Empty slots in the page trap
+list are printed as well, because they can affect the priority of
+subsequently planted traps.
+.TP
+.BI .rchar\ c1\ c2\|.\|.\|.
+Remove the definitions of characters
+.IR c1 ,
+.IR c2 ,\|.\|.\|.
+This undoes the effect of a
+.B char
+request.
+.TP
+.B .rj
+.TQ
+.BI .rj\ n
+Right justify the next
+.I n
+input lines.
+Without an argument right justify the next input line.
+The number of lines to be right justified is available in the
+.B \en[.rj]
+register.
+This implicitly does
+.BR .ce\ 0 .
+The
+.B ce
+request implicitly does
+.BR .rj\ 0 .
+.TP
+.BI .rnn \ xx\ yy
+Rename number register
+.I xx
+to
+.IR yy .
+.TP
+.BI .shc\ c
+Set the soft hyphen character to
+.IR c .
+If
+.I c
+is omitted,
+the soft hyphen character will be set to the default
+.BR \e(hy .
+The soft hyphen character is the character which will be inserted
+when a word is hyphenated at a line break.
+If the soft hyphen character does not exist in the font of the character
+immediately preceding a potential break point,
+then the line will not be broken at that point.
+Neither definitions (specified with the
+.B char
+request)
+nor translations (specified with the
+.B tr
+request)
+are considered when finding the soft hyphen character.
+.TP
+.BI .shift\ n
+In a macro, shift the arguments by
+.I n
+positions:
+argument
+.I i
+becomes argument
+.IR i \- n ;
+arguments 1 to
+.I n
+will no longer be available.
+If
+.I n
+is missing,
+arguments will be shifted by 1.
+Shifting by negative amounts is currently undefined.
+.TP
+.BI .special\ s1\ s2\|.\|.\|.
+Fonts
+.IR s1 ,
+.IR s2 ,
+are special and will be searched for characters not in the
+current font.
+.TP
+.BI .sty\ n\ f
+Associate style
+.I f
+with font position
+.IR n .
+A font position can be associated either with a font or
+with a style.
+The current font is the index of a font position and so is also
+either a font or a style.
+When it is a style, the font that is actually used is the font the
+name of which is the concatenation of the name of the current family
+and the name of the current style.
+For example, if the current font is 1 and font position 1 is
+associated with style
+.B R
+and the current
+font family is
+.BR T ,
+then font
+.BR TR
+will be used.
+If the current font is not a style, then the current family is ignored.
+When the requests
+.BR cs ,
+.BR bd ,
+.BR tkf ,
+.BR uf ,
+or
+.B fspecial
+are applied to a style,
+then they will instead be applied to the member of the
+current family corresponding to that style.
+The default family can be set with the
+.B \-f
+option.
+The styles command in the
+.SM DESC
+file controls which font positions
+(if any) are initially associated with styles rather than fonts.
+.TP
+.BI .tkf\ f\ s1\ n1\ s2\ n2
+Enable track kerning for font
+.IR f .
+When the current font is
+.I f
+the width of every character will be increased by an amount
+between
+.I n1
+and
+.IR n2 ;
+when the current point size is less than or equal to
+.I s1
+the width will be increased by
+.IR n1 ;
+when it is greater than or equal to
+.I s2
+the width will be increased by
+.IR n2 ;
+when the point size is greater than or equal to
+.I s1
+and less than or equal to
+.I s2
+the increase in width is a linear function of the point size.
+.TP
+.BI .trf\ filename
+Transparently output the contents of file
+.IR filename .
+Each line is output as it would be were it preceded by
+.BR \e! ;
+however, the lines are not subject to copy-mode interpretation.
+If the file does not end with a newline, then a newline will
+be added.
+For example, you can define a macro
+.I x
+containing the contents of file
+.IR f ,
+using
+.RS
+.IP
+.BI .di\ x
+.br
+.BI .trf\ f
+.br
+.B .di
+.LP
+Unlike with the
+.B cf
+request,
+the file cannot contain characters such as
+.SM NUL
+that are not legal troff input characters.
+.RE
+.TP
+.B .trnt abcd
+This is the same as the
+.B tr
+request except that the translations do not apply to text that is
+transparently throughput into a diversion with
+.BR \e! .
+For example,
+.RS
+.LP
+.nf
+.ft B
+\&.tr ab
+\&.di x
+\e!.tm a
+\&.di
+\&.x
+.fi
+.ft
+.LP
+will print
+.BR b ;
+if
+.B trnt
+is used instead of
+.B tr
+it will print
+.BR a .
+.RE
+.TP
+.B .troff
+Make the
+.B n
+built-in condition false,
+and the
+.B t
+built-in condition true.
+This undoes the effect of the
+.B nroff
+request.
+.TP
+.BI .vpt\ n
+Enable vertical position traps if
+.I n
+is non-zero, disable them otherwise.
+Vertical position traps are traps set by the
+.B wh
+or
+.B dt
+requests.
+Traps set by the
+.B it
+request are not vertical position traps.
+The parameter that controls whether vertical position traps are enabled
+is global.
+Initially vertical position traps are enabled.
+.TP
+.BI .warn\ n
+Control warnings.
+.I n
+is the sum of the numbers associated with each warning that is to be enabled;
+all other warnings will be disabled.
+The number associated with each warning is listed in the `Warnings' section.
+For example,
+.B .warn 0
+will disable all warnings, and
+.B .warn 1
+will disable all warnings except that about missing characters.
+If
+.I n
+is not given,
+all warnings will be enabled.
+.TP
+.BI .while \ c\ anything
+While condition
+.I c
+is true, accept
+.I anything
+as input;
+.I c
+can be any condition acceptable to an
+.B if
+request;
+.I anything
+can comprise multiple lines if the first line starts with
+.B \e{
+and the last line ends with
+.BR \e} .
+See also the
+.B break
+and
+.B continue
+requests.
+.TP
+.BI .write\ stream\ anything
+Write
+.I anything
+to the stream named
+.IR stream .
+.I stream
+must previously have been the subject of an
+.B open
+request.
+.I anything
+is read in copy mode;
+a leading
+.B \(ts
+will be stripped.
+.SS Extended requests
+.TP
+.BI .cf\ filename
+When used in a diversion, this will embed in the diversion an object which,
+when reread, will cause the contents of
+.I filename
+to be transparently copied through to the output.
+In Unix troff, the
+contents of
+.I filename
+is immediately copied through to the output regardless of whether
+there is a current diversion; this behaviour is so anomalous that it
+must be considered a bug.
+.TP
+.BI .ev\ xx
+If
+.I xx
+is not a number, this will switch to a named environment called
+.IR xx .
+The environment should be popped with a matching
+.B ev
+request without any arguments, just as for numbered environments.
+There is no limit on the number of named environments; they will be
+created the first time that they are referenced.
+.TP
+.BI .fp\ n\ f1\ f2
+The
+.B fp
+request has an optional third argument.
+This argument gives the external name of the font,
+which is used for finding the font description file.
+The second argument gives the internal name of the font
+which is used to refer to the font in troff after it has been mounted.
+If there is no third argument then the internal name will be used
+as the external name.
+This feature allows you to use fonts with long names in compatibility mode.
+.TP
+.BI .ss\ m\ n
+When two arguments are given to the
+.B ss
+request, the second argument gives the
+.IR "sentence space size" .
+If the second argument is not given, the sentence space size
+will be the same as the word space size.
+Like the word space size, the sentence space is in units of
+one twelfth of the spacewidth parameter for the current font.
+Initially both the word space size and the sentence
+space size are 12.
+The sentence space size is used in two circumstances:
+if the end of a sentence occurs at the end of a line in fill mode, then
+both an inter-word space and a sentence space will be added;
+if two spaces follow the end of a sentence in the middle of a line,
+then the second space will be a sentence space.
+Note that the behaviour of Unix troff will be exactly
+that exhibited by GNU troff if a second argument is never given to the
+.B ss
+request.
+In GNU troff, as in Unix troff, you should always
+follow a sentence with either a newline or two spaces.
+.TP
+.BI .ta\ n1\ n2\|.\|.\|.nn \ T\ r1\ r2\|.\|.\|.\|rn
+Set tabs at positions
+.IR n1 ,
+.IR n2 ,\|.\|.\|.\|,
+.I nn
+and then set tabs at
+.IR nn + r1 ,
+.IR nn + r2 ,\|.\|.\|.\|.\|,
+.IR nn + rn
+and then at
+.IR nn + rn + r1 ,
+.IR nn + rn + r2 ,\|.\|.\|.\|,
+.IR nn + rn + rn ,
+and so on.
+For example,
+.RS
+.IP
+.B
+\&.ta T .5i
+.LP
+will set tabs every half an inch.
+.RE
+.SS New number registers
+The following read-only registers are available:
+.TP
+.B \en[.C]
+1 if compatibility mode is in effect, 0 otherwise.
+.TP
+.B \en[.cdp]
+The depth of the last character added to the current environment.
+It is positive if the character extends below the baseline.
+.TP
+.B \en[.ce]
+The number of lines remaining to be centered, as set by the
+.B ce
+request.
+.TP
+.B \en[.cht]
+The height of the last character added to the current environment.
+It is positive if the character extends above the baseline.
+.TP
+.B \en[.csk]
+The skew of the last character added to the current environment.
+The
+.I skew
+of a character is how far to the right of the center of a character
+the center of an accent over that character should be placed.
+.TP
+.B \en[.ev]
+The name or number of the current environment.
+This is a string-valued register.
+.TP
+.B \en[.fam]
+The current font family.
+This is a string-valued register.
+.TP
+.B \en[.fp]
+The number of the next free font position.
+.TP
+.B \en[.g]
+Always 1.
+Macros should use this to determine whether they are running
+under GNU troff.
+.TP
+.B \en[.hla]
+The current hyphenation language as set by the
+.B hla
+request.
+.TP
+.B \en[.hlc]
+The number of immediately preceding consecutive hyphenated lines.
+.TP
+.B \en[.hlm]
+The maximum allowed number of consecutive hyphenated lines, as set by the
+.B hlm
+request.
+.TP
+.B \en[.hy]
+The current hyphenation flags (as set by the
+.B hy
+request.)
+.TP
+.B \en[.hym]
+The current hyphenation margin (as set by the
+.B hym
+request.)
+.TP
+.B \en[.hys]
+The current hyphenation space (as set by the
+.B hys
+request.)
+.TP
+.B \en[.in]
+The indent that applies to the current output line.
+.TP
+.B \en[.kern]
+.B 1
+if pairwise kerning is enabled,
+.B 0
+otherwise.
+.TP
+.B \en[.lg]
+The current ligature mode (as set by the
+.B lg
+request.)
+.TP
+.B \en[.ll]
+The line length that applies to the current output line.
+.TP
+.B \en[.lt]
+The title length as set by the
+.B lt
+request.
+.TP
+.B \en[.ne]
+The amount of space that was needed in the last
+.B ne
+request that caused a trap to be sprung.
+Useful in conjunction with the
+.B \en[.trunc]
+register.
+.TP
+.B \en[.pn]
+The number of the next page:
+either the value set by a
+.B pn
+request, or the number of the current page plus 1.
+.TP
+.B \en[.ps]
+The current pointsize in scaled points.
+.TP
+.B \en[.psr]
+The last-requested pointsize in scaled points.
+.TP
+.B \en[.rj]
+The number of lines to be right-justified as set by the
+.B rj
+request.
+.TP
+.B \en[.sr]
+The last requested pointsize in points as a decimal fraction.
+This is a string-valued register.
+.TP
+.B \en[.tabs]
+A string representation of the current tab settings suitable for use as
+an argument to the
+.B ta
+request.
+.TP
+.B \en[.trunc]
+The amount of vertical space truncated by the most recently sprung
+vertical position trap, or,
+if the trap was sprung by a
+.B ne
+request,
+minus the amount of vertical motion produced by the
+.B ne
+request.
+In other words, at the point a trap is sprung, it represents the difference
+of what the vertical position would have been but for the trap,
+and what the vertical position actually is.
+Useful in conjunction with the
+.B \en[.ne]
+register.
+.TP
+.B \en[.ss]
+.TQ
+.B \en[.sss]
+These give the values of the parameters set by the
+first and second arguments of the
+.B ss
+request.
+.TP
+.B \en[.vpt]
+1 if vertical position traps are enabled, 0 otherwise.
+.TP
+.B \en[.warn]
+The sum of the numbers associated with each of the currently enabled
+warnings.
+The number associated with each warning is listed in the `Warnings'
+subsection.
+.TP
+.B \en(.x
+The major version number.
+For example, if the version number is
+.B 1.03
+then
+.B \en(.x
+will contain
+.BR 1 .
+.TP
+.B \en(.y
+The minor version number.
+For example, if the version number is
+.B 1.03
+then
+.B \en(.y
+will contain
+.BR 03 .
+.TP
+.B \en(.Y
+The revision number of groff.
+.TP
+.B \en[llx]
+.TQ
+.B \en[lly]
+.TQ
+.B \en[urx]
+.TQ
+.B \en[ury]
+These four registers are set by the
+.B \&.psbb
+request and contain the bounding box values (in PostScript units) of a given
+PostScript image.
+.LP
+The following registers are set by the
+.B \ew
+escape sequence:
+.TP
+.B \en[rst]
+.TQ
+.B \en[rsb]
+Like the
+.B st
+and
+.B sb
+registers, but takes account of the heights and depths of characters.
+.TP
+.B \en[ssc]
+The amount of horizontal space (possibly negative) that should
+be added to the last character before a subscript.
+.TP
+.B \en[skw]
+How far to right of the center of the last character
+in the
+.B \ew
+argument,
+the center of an accent from a roman font should be placed over that character.
+.LP
+The following read/write number registers are available:
+.TP
+.B \en[systat]
+The return value of the system() function executed by the last
+.B sy
+request.
+.TP
+.B \en[slimit]
+If greater than 0, the maximum number of objects on the input stack.
+If less than or equal to 0, there is no limit on the number of objects
+on the input stack. With no limit, recursion can continue until
+virtual memory is exhausted.
+.TP
+.B \en[year]
+The current year.
+Note that the traditional
+.B troff
+number register
+.B \en[yr]
+is the current year minus 1900.
+.SS Miscellaneous
+.LP
+Fonts not listed in the
+.SM DESC
+file are automatically mounted on the next available font position
+when they are referenced.
+If a font is to be mounted explicitly with the
+.B fp
+request on an unused font position,
+it should be mounted on the first unused font position,
+which can be found in the
+.B \en[.fp]
+register;
+although
+.B troff
+does not enforce this strictly,
+it will not allow a font to be mounted at a position whose number is much
+greater than that of any currently used position.
+.LP
+Interpolating a string does not hide existing macro arguments.
+Thus in a macro, a more efficient way of doing
+.IP
+.BI . xx\ \e\e$@
+.LP
+is
+.IP
+.BI \e\e*[ xx ]\e\e
+.LP
+If the font description file contains pairwise kerning information,
+characters from that font will be kerned.
+Kerning between two characters can be inhibited by placing a
+.B \e&
+between them.
+.LP
+In a string comparison in a condition,
+characters that appear at different input levels
+to the first delimiter character will not be recognised
+as the second or third delimiters.
+This applies also to the
+.B tl
+request.
+In a
+.B \ew
+escape sequence,
+a character that appears at a different input level to
+the starting delimiter character will not be recognised
+as the closing delimiter character.
+When decoding a macro argument that is delimited
+by double quotes, a character that appears at a different
+input level to the starting delimiter character will not
+be recognised as the closing delimiter character.
+The implementation of
+.B \e$@
+ensures that the double quotes surrounding an argument
+will appear the same input level, which will be different
+to the input level of the argument itself.
+In a long escape name
+.B ]
+will not be recognized as a closing delimiter except
+when it occurs at the same input level as the opening
+.BR ] .
+In compatibility mode, no attention is paid to the input-level.
+.LP
+There are some new types of condition:
+.TP
+.BI .if\ r xxx
+True if there is a number register named
+.IR xxx .
+.TP
+.BI .if\ d xxx
+True if there is a string, macro, diversion, or request named
+.IR xxx .
+.TP
+.BI .if\ c ch
+True if there is a character
+.IR ch
+available;
+.I ch
+is either an
+.SM ASCII
+character
+or a special character
+.BI \e( xx
+or
+.BI \e[ xxx ]\fR;
+the condition will also be true if
+.I ch
+has been defined by the
+.B char
+request.
+.SS Warnings
+The warnings that can be given by
+.B troff
+are divided into the following categories.
+The name associated with each warning is used by the
+.B \-w
+and
+.B \-W
+options;
+the number is used by the
+.B warn
+request, and by the
+.B .warn
+register.
+.nr x \w'\fBright-brace'+1n+\w'0000'u
+.ta \nxuR
+.TP \nxu+3n
+.BR char \t1
+Non-existent characters.
+This is enabled by default.
+.TP
+.BR number \t2
+Invalid numeric expressions.
+This is enabled by default.
+.TP
+.BR break \t4
+In fill mode, lines which could not be broken so that their length was
+less than the line length.
+This is enabled by default.
+.TP
+.BR delim \t8
+Missing or mismatched closing delimiters.
+.TP
+.BR el \t16
+Use of the
+.B el
+request with no matching
+.B ie
+request.
+.TP
+.BR scale \t32
+Meaningless scaling indicators.
+.TP
+.BR range \t64
+Out of range arguments.
+.TP
+.BR syntax \t128
+Dubious syntax in numeric expressions.
+.TP
+.BR di \t256
+Use of
+.B di
+or
+.B da
+without an argument when there is no current diversion.
+.TP
+.BR mac \t512
+Use of undefined strings, macros and diversions.
+When an undefined string, macro or diversion is used,
+that string is automatically defined as empty.
+So, in most cases, at most one warning will be given for
+each name.
+.TP
+.BR reg \t1024
+Use of undefined number registers.
+When an undefined number register is used,
+that register is automatically defined to have a value of 0.
+a definition is automatically made with a value of 0.
+So, in most cases, at most one warning will be given for
+use of a particular name.
+.TP
+.BR tab \t2048
+Inappropriate use of a tab character.
+Either use of a tab character where a number was expected,
+or use of tab character in an unquoted macro argument.
+.TP
+.BR right-brace \t4096
+Use of
+.B \e}
+where a number was expected.
+.TP
+.BR missing \t8192
+Requests that are missing non-optional arguments.
+.TP
+.BR input \t16384
+Illegal input characters.
+.TP
+.BR escape \t32768
+Unrecognized escape sequences.
+When an unrecognized escape sequence is encountered,
+the escape character is ignored.
+.TP
+.BR space \t65536
+Missing space between a request or macro and its argument.
+This warning will be given
+when an undefined name longer than two characters is encountered,
+and the first two characters of the name make a defined name.
+The request or macro will not be invoked.
+When this warning is given, no macro is automatically defined.
+This is enabled by default.
+This warning will never occur in compatibility mode.
+.TP
+.BR font \t131072
+Non-existent fonts.
+This is enabled by default.
+.TP
+.BR ig \t262144
+Illegal escapes in text ignored with the
+.B ig
+request.
+These are conditions that are errors when they do not occur
+in ignored text.
+.LP
+There are also names that can be used to refer to groups of warnings:
+.TP
+.B all
+All warnings except
+.BR di ,
+.B mac
+and
+.BR reg .
+It is intended that this covers all warnings
+that are useful with traditional macro packages.
+.TP
+.B w
+All warnings.
+.SS Incompatibilities
+.LP
+Long names cause some incompatibilities.
+Unix troff will interpret
+.IP
+.B
+\&.dsabcd
+.LP
+as defining a string
+.B ab
+with contents
+.BR cd .
+Normally, GNU troff will interpret this as a call of a macro named
+.BR dsabcd .
+Also Unix troff will interpret
+.B \e*[
+or
+.B \en[
+as references to a string or number register called
+.BR [ .
+In GNU troff, however, this will normally be interpreted as the start
+of a long name.
+In
+.I compatibility mode
+GNU troff will interpret these things in the traditional way.
+In compatibility mode, however, long names are not recognised.
+Compatibility mode can be turned on with the
+.B \-C
+command line option, and turned on or off with the
+.B cp
+request.
+The number register
+.B \en(.C
+is 1 if compatibility mode is on, 0 otherwise.
+.LP
+GNU troff
+does not allow the use of the escape sequences
+.BR \\e\e|\e^\e&\e}\e{\e (space) \e'\e`\e-\e_\e!\e%\ec
+in names of strings, macros, diversions, number registers,
+fonts or environments; Unix troff does.
+The
+.B \eA
+escape sequence may be helpful in avoiding use of these
+escape sequences in names.
+.LP
+Fractional pointsizes cause one noteworthy incompatibility.
+In Unix troff the
+.B ps
+request ignores scale indicators and so
+.IP
+.B .ps\ 10u
+.LP
+will set the pointsize to 10 points, whereas in
+GNU troff it will set the pointsize to 10 scaled points.
+.LP
+In GNU troff there is a fundamental difference between unformatted,
+input characters, and formatted, output characters.
+Everything that affects how an output character
+will be output is stored with the character; once an output
+character has been constructed it is unaffected by any subsequent
+requests that are executed, including
+.BR bd ,
+.BR cs ,
+.BR tkf ,
+.BR tr ,
+or
+.B fp
+requests.
+Normally output characters are constructed from input
+characters at the moment immediately before the character
+is added to the current output line.
+Macros, diversions and strings are all, in fact, the same type
+of object; they contain lists of input characters and output
+characters in any combination.
+An output character does not behave like an input character
+for the purposes of macro processing; it does not inherit any
+of the special properties that the input character from which it
+was constructed might have had.
+For example,
+.IP
+.nf
+.ft B
+\&.di x
+\e\e\e\e
+\&.br
+\&.di
+\&.x
+.ft
+.fi
+.LP
+will print
+.B \e\e
+in GNU troff;
+each pair of input
+.BR \e s
+is turned into one output
+.B \e
+and the resulting output
+.BR \e s
+are not interpreted as escape characters when they are reread.
+Unix troff would interpret them as escape characters
+when they were reread and would end up printing one
+.BR \e .
+The correct way to obtain a printable
+.B \e
+is to use the
+.B \ee
+escape sequence: this will always print a single instance of the
+current escape character, regardless of whether or not it is used in a
+diversion; it will also work in both GNU troff and Unix troff.
+If you wish for some reason to store in a diversion an escape
+sequence that will be interpreted when the diversion is reread,
+you can either use the traditional
+.B \e!
+transparent output facility, or, if this is unsuitable, the new
+.B \e?
+escape sequence.
+.SH ENVIRONMENT
+.TP
+.SM
+.B GROFF_TMAC_PATH
+A colon separated list of directories in which to search for
+macro files.
+.TP
+.SM
+.B GROFF_TYPESETTER
+Default device.
+.TP
+.SM
+.B GROFF_FONT_PATH
+A colon separated list of directories in which to search for the
+.BI dev name
+directory.
+.B troff
+will search in directories given in the
+.B \-F
+option before these, and in standard directories
+.RB ( @FONTPATH@ )
+after these.
+.SH FILES
+.Tp \w'@FONTDIR@/devname/DESC'u+3n
+.B @MACRODIR@/troffrc
+Initialization file
+.TP
+.BI @MACRODIR@/tmac. name
+Macro files
+.TP
+.BI @FONTDIR@/dev name /DESC
+Device description file for device
+.IR name .
+.TP
+.BI @FONTDIR@/dev name / F
+Font file for font
+.I F
+of device
+.IR name .
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@)
+.BR @g@tbl (@MAN1EXT@),
+.BR @g@pic (@MAN1EXT@),
+.BR @g@eqn (@MAN1EXT@),
+.BR grops (@MAN1EXT@),
+.BR grodvi (@MAN1EXT@),
+.BR grotty (@MAN1EXT@),
+.BR grohtml (@MAN1EXT@),
+.BR groff_font (@MAN5EXT@),
+.BR groff_out (@MAN5EXT@),
+.BR groff_char (@MAN7EXT@)
diff --git a/src/utils/addftinfo/Makefile.sub b/src/utils/addftinfo/Makefile.sub
new file mode 100644
index 00000000..23848d54
--- /dev/null
+++ b/src/utils/addftinfo/Makefile.sub
@@ -0,0 +1,11 @@
+PROG=addftinfo
+MAN1=addftinfo.n
+XLIBS=$(LIBGROFF)
+OBJS=\
+ addftinfo.o \
+ guess.o
+CCSRCS=\
+ $(srcdir)/addftinfo.cc \
+ $(srcdir)/guess.cc
+HDRS=\
+ $(srcdir)/guess.h
diff --git a/src/utils/addftinfo/addftinfo.cc b/src/utils/addftinfo/addftinfo.cc
new file mode 100644
index 00000000..55b62427
--- /dev/null
+++ b/src/utils/addftinfo/addftinfo.cc
@@ -0,0 +1,196 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+#include "stringclass.h"
+#include "cset.h"
+#include "guess.h"
+
+static void usage();
+static void convert_font(const font_params &, FILE *, FILE *);
+
+typedef int font_params::*param_t;
+
+static struct {
+ const char *name;
+ param_t par;
+} param_table[] = {
+ { "x-height", &font_params::x_height },
+ { "fig-height", &font_params::fig_height },
+ { "asc-height", &font_params::asc_height },
+ { "body-height", &font_params::body_height },
+ { "cap-height", &font_params::cap_height },
+ { "comma-depth", &font_params::comma_depth },
+ { "desc-depth", &font_params::desc_depth },
+ { "body-depth", &font_params::body_depth },
+};
+
+// These are all in thousandths of an em.
+// These values are correct for PostScript Times Roman.
+
+#define DEFAULT_X_HEIGHT 448
+#define DEFAULT_FIG_HEIGHT 676
+#define DEFAULT_ASC_HEIGHT 682
+#define DEFAULT_BODY_HEIGHT 676
+#define DEFAULT_CAP_HEIGHT 662
+#define DEFAULT_COMMA_DEPTH 143
+#define DEFAULT_DESC_DEPTH 217
+#define DEFAULT_BODY_DEPTH 177
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ if (argc < 4)
+ usage();
+ int resolution;
+ if (sscanf(argv[argc-3], "%d", &resolution) != 1)
+ usage();
+ if (resolution <= 0)
+ fatal("resolution must be > 0");
+ int unitwidth;
+ if (sscanf(argv[argc-2], "%d", &unitwidth) != 1)
+ usage();
+ if (unitwidth <= 0)
+ fatal("unitwidth must be > 0");
+ font_params param;
+ const char *font = argv[argc-1];
+ param.italic = (font[0] != '\0' && strchr(font, '\0')[-1] == 'I');
+ param.em = (resolution*unitwidth)/72;
+ param.x_height = DEFAULT_X_HEIGHT;
+ param.fig_height = DEFAULT_FIG_HEIGHT;
+ param.asc_height = DEFAULT_ASC_HEIGHT;
+ param.body_height = DEFAULT_BODY_HEIGHT;
+ param.cap_height = DEFAULT_CAP_HEIGHT;
+ param.comma_depth = DEFAULT_COMMA_DEPTH;
+ param.desc_depth = DEFAULT_DESC_DEPTH;
+ param.body_depth = DEFAULT_BODY_DEPTH;
+ int i;
+ for (i = 1; i < argc && argv[i][0] == '-'; i++) {
+ if (argv[i][1] == '-' && argv[i][2] == '\0') {
+ i++;
+ break;
+ }
+ if (i + 1 >= argc)
+ usage();
+ int j;
+ for (j = 0;; j++) {
+ if (j >= sizeof(param_table)/sizeof(param_table[0]))
+ fatal("parameter `%1' not recognized", argv[i] + 1);
+ if (strcmp(param_table[j].name, argv[i] + 1) == 0)
+ break;
+ }
+ if (sscanf(argv[i+1], "%d", &(param.*(param_table[j].par))) != 1)
+ fatal("invalid argument `%1'", argv[i+1]);
+ i++;
+ }
+ if (argc - i != 3)
+ usage();
+ errno = 0;
+ FILE *infp = fopen(font, "r");
+ if (infp == 0)
+ fatal("can't open `%1': %2", font, strerror(errno));
+ convert_font(param, infp, stdout);
+ return 0;
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-param value] ... resolution unitwidth font\n",
+ program_name);
+ exit(1);
+}
+
+static int get_line(FILE *fp, string *p)
+{
+ int c;
+ p->clear();
+ while ((c = getc(fp)) != EOF) {
+ *p += char(c);
+ if (c == '\n')
+ break;
+ }
+ return p->length() > 0;
+}
+
+static void convert_font(const font_params &param, FILE *infp, FILE *outfp)
+{
+ string s;
+ while (get_line(infp, &s)) {
+ put_string(s, outfp);
+ if (s.length() >= 8
+ && strncmp(&s[0], "charset", 7))
+ break;
+ }
+ while (get_line(infp, &s)) {
+ s += '\0';
+ string name;
+ const char *p = s.contents();
+ while (csspace(*p))
+ p++;
+ while (*p != '\0' && !csspace(*p))
+ name += *p++;
+ while (csspace(*p))
+ p++;
+ for (const char *q = s.contents(); q < p; q++)
+ putc(*q, outfp);
+ char *next;
+ char_metric metric;
+ metric.width = (int)strtol(p, &next, 10);
+ if (next != p) {
+ printf("%d", metric.width);
+ p = next;
+ metric.type = (int)strtol(p, &next, 10);
+ if (next != p) {
+ name += '\0';
+ guess(name.contents(), param, &metric);
+ if (metric.sk == 0) {
+ if (metric.left_ic == 0) {
+ if (metric.ic == 0) {
+ if (metric.depth == 0) {
+ if (metric.height != 0)
+ printf(",%d", metric.height);
+ }
+ else
+ printf(",%d,%d", metric.height, metric.depth);
+ }
+ else
+ printf(",%d,%d,%d", metric.height, metric.depth, metric.ic);
+ }
+ else
+ printf(",%d,%d,%d,%d", metric.height, metric.depth, metric.ic,
+ metric.left_ic);
+ }
+ else
+ printf(",%d,%d,%d,%d,%d", metric.height, metric.depth, metric.ic,
+ metric.left_ic, metric.sk);
+ }
+ }
+ fputs(p, outfp);
+ }
+}
+
diff --git a/src/utils/addftinfo/addftinfo.man b/src/utils/addftinfo/addftinfo.man
new file mode 100644
index 00000000..6741c171
--- /dev/null
+++ b/src/utils/addftinfo/addftinfo.man
@@ -0,0 +1,102 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.TH ADDFTINFO @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+addftinfo \- add information to troff font files for use with groff
+.SH SYNOPSIS
+.B addftinfo
+[
+.BI \- param\ value\fR.\|.\|.
+]
+.I res
+.I unitwidth
+.I font
+.SH DESCRIPTION
+.B addftinfo
+reads a troff font file
+and adds some additional font-metric information
+that is used by the groff system.
+The font file with the information added is written on the
+standard output.
+The information added is guessed using
+some parametric information about the font
+and assumptions
+about the traditional troff names for characters.
+The main information added is the heights and depths of characters.
+The
+.I res
+and
+.I unitwidth
+arguments should be the same as the corresponding parameters
+in the DESC file;
+.I font
+is the name of the file describing the font;
+if
+.I font
+ends with
+.B I
+the font will be assumed to be italic.
+.SH OPTIONS
+Each of the options changes one of the parameters that is used
+to derive the heights and depths.
+Like the existing quantities in the font
+file, each
+.I value
+is in
+.RI inches/ res
+for a font whose point size is
+.IR unitwidth .
+.I param
+must be one of:
+.TP
+.B x-height
+The height of lowercase letters without ascenders such as x.
+.TP
+.B fig-height
+The height of figures (digits).
+.TP
+.B asc-height
+The height of characters with ascenders, such as b, d or l.
+.TP
+.B body-height
+The height of characters such as parentheses.
+.TP
+.B cap-height
+The height of uppercase letters such as A.
+.TP
+.B comma-depth
+The depth of a comma.
+.TP
+.B desc-depth
+The depth of characters with descenders, such as p,q, or y.
+.TP
+.B body-depth
+The depth of characters such as parentheses.
+.LP
+.B addftinfo
+makes no attempt to use the specified parameters to guess
+the unspecified parameters.
+If a parameter is not specified the default will be used.
+The defaults are chosen to have the reasonable values for
+a Times font.
+.SH "SEE ALSO"
+.BR font (5)
+.BR groff_font (@MAN5EXT@),
+.BR groff (@MAN1EXT@),
+.BR groff_char (@MAN7EXT@)
diff --git a/src/utils/addftinfo/guess.cc b/src/utils/addftinfo/guess.cc
new file mode 100644
index 00000000..dcfd4c92
--- /dev/null
+++ b/src/utils/addftinfo/guess.cc
@@ -0,0 +1,490 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "guess.h"
+
+void guess(const char *s, const font_params &param, char_metric *metric)
+{
+ int &height = metric->height;
+ int &depth = metric->depth;
+
+ metric->ic = 0;
+ metric->left_ic = 0;
+ metric->sk = 0;
+ height = 0;
+ depth = 0;
+ if (s[0] == '\0' || (s[1] != '\0' && s[2] != '\0'))
+ goto do_default;
+#define HASH(c1, c2) (((unsigned char)(c1) << 8) | (unsigned char)(c2))
+ switch (HASH(s[0], s[1])) {
+ default:
+ do_default:
+ if (metric->type & 01)
+ depth = param.desc_depth;
+ if (metric->type & 02)
+ height = param.asc_height;
+ else
+ height = param.x_height;
+ break;
+ case HASH('\\', '|'):
+ case HASH('\\', '^'):
+ case HASH('\\', '&'):
+ // these have zero height and depth
+ break;
+ case HASH('f', 0):
+ height = param.asc_height;
+ if (param.italic)
+ depth = param.desc_depth;
+ break;
+ case HASH('a', 0):
+ case HASH('c', 0):
+ case HASH('e', 0):
+ case HASH('m', 0):
+ case HASH('n', 0):
+ case HASH('o', 0):
+ case HASH('r', 0):
+ case HASH('s', 0):
+ case HASH('u', 0):
+ case HASH('v', 0):
+ case HASH('w', 0):
+ case HASH('x', 0):
+ case HASH('z', 0):
+ height = param.x_height;
+ break;
+ case HASH('i', 0):
+ height = param.x_height;
+ break;
+ case HASH('b', 0):
+ case HASH('d', 0):
+ case HASH('h', 0):
+ case HASH('k', 0):
+ case HASH('l', 0):
+ case HASH('F', 'i'):
+ case HASH('F', 'l'):
+ case HASH('f', 'f'):
+ case HASH('f', 'i'):
+ case HASH('f', 'l'):
+ height = param.asc_height;
+ break;
+ case HASH('t', 0):
+ height = param.asc_height;
+ break;
+ case HASH('g', 0):
+ case HASH('p', 0):
+ case HASH('q', 0):
+ case HASH('y', 0):
+ height = param.x_height;
+ depth = param.desc_depth;
+ break;
+ case HASH('j', 0):
+ height = param.x_height;
+ depth = param.desc_depth;
+ break;
+ case HASH('A', 0):
+ case HASH('B', 0):
+ case HASH('C', 0):
+ case HASH('D', 0):
+ case HASH('E', 0):
+ case HASH('F', 0):
+ case HASH('G', 0):
+ case HASH('H', 0):
+ case HASH('I', 0):
+ case HASH('J', 0):
+ case HASH('K', 0):
+ case HASH('L', 0):
+ case HASH('M', 0):
+ case HASH('N', 0):
+ case HASH('O', 0):
+ case HASH('P', 0):
+ case HASH('Q', 0):
+ case HASH('R', 0):
+ case HASH('S', 0):
+ case HASH('T', 0):
+ case HASH('U', 0):
+ case HASH('V', 0):
+ case HASH('W', 0):
+ case HASH('X', 0):
+ case HASH('Y', 0):
+ case HASH('Z', 0):
+ height = param.cap_height;
+ break;
+ case HASH('*', 'A'):
+ case HASH('*', 'B'):
+ case HASH('*', 'C'):
+ case HASH('*', 'D'):
+ case HASH('*', 'E'):
+ case HASH('*', 'F'):
+ case HASH('*', 'G'):
+ case HASH('*', 'H'):
+ case HASH('*', 'I'):
+ case HASH('*', 'K'):
+ case HASH('*', 'L'):
+ case HASH('*', 'M'):
+ case HASH('*', 'N'):
+ case HASH('*', 'O'):
+ case HASH('*', 'P'):
+ case HASH('*', 'Q'):
+ case HASH('*', 'R'):
+ case HASH('*', 'S'):
+ case HASH('*', 'T'):
+ case HASH('*', 'U'):
+ case HASH('*', 'W'):
+ case HASH('*', 'X'):
+ case HASH('*', 'Y'):
+ case HASH('*', 'Z'):
+ height = param.cap_height;
+ break;
+ case HASH('0', 0):
+ case HASH('1', 0):
+ case HASH('2', 0):
+ case HASH('3', 0):
+ case HASH('4', 0):
+ case HASH('5', 0):
+ case HASH('6', 0):
+ case HASH('7', 0):
+ case HASH('8', 0):
+ case HASH('9', 0):
+ case HASH('1', '2'):
+ case HASH('1', '4'):
+ case HASH('3', '4'):
+ height = param.fig_height;
+ break;
+ case HASH('(', 0):
+ case HASH(')', 0):
+ case HASH('[', 0):
+ case HASH(']', 0):
+ case HASH('{', 0):
+ case HASH('}', 0):
+ height = param.body_height;
+ depth = param.body_depth;
+ break;
+ case HASH('i', 's'):
+ height = (param.em*3)/4;
+ depth = param.em/4;
+ break;
+ case HASH('*', 'a'):
+ case HASH('*', 'e'):
+ case HASH('*', 'i'):
+ case HASH('*', 'k'):
+ case HASH('*', 'n'):
+ case HASH('*', 'o'):
+ case HASH('*', 'p'):
+ case HASH('*', 's'):
+ case HASH('*', 't'):
+ case HASH('*', 'u'):
+ case HASH('*', 'w'):
+ height = param.x_height;
+ break;
+ case HASH('*', 'd'):
+ case HASH('*', 'l'):
+ height = param.asc_height;
+ break;
+ case HASH('*', 'g'):
+ case HASH('*', 'h'):
+ case HASH('*', 'm'):
+ case HASH('*', 'r'):
+ case HASH('*', 'x'):
+ case HASH('*', 'y'):
+ height = param.x_height;
+ depth = param.desc_depth;
+ break;
+ case HASH('*', 'b'):
+ case HASH('*', 'c'):
+ case HASH('*', 'f'):
+ case HASH('*', 'q'):
+ case HASH('*', 'z'):
+ height = param.asc_height;
+ depth = param.desc_depth;
+ break;
+ case HASH('t', 's'):
+ height = param.x_height;
+ depth = param.desc_depth;
+ break;
+ case HASH('!', 0):
+ case HASH('?', 0):
+ case HASH('"', 0):
+ case HASH('#', 0):
+ case HASH('$', 0):
+ case HASH('%', 0):
+ case HASH('&', 0):
+ case HASH('*', 0):
+ case HASH('+', 0):
+ height = param.asc_height;
+ break;
+ case HASH('`', 0):
+ case HASH('\'', 0):
+ height = param.asc_height;
+ break;
+ case HASH('~', 0):
+ case HASH('^', 0):
+ case HASH('a', 'a'):
+ case HASH('g', 'a'):
+ height = param.asc_height;
+ break;
+ case HASH('r', 'u'):
+ case HASH('.', 0):
+ break;
+ case HASH(',', 0):
+ depth = param.comma_depth;
+ break;
+ case HASH('m', 'i'):
+ case HASH('-', 0):
+ case HASH('h', 'y'):
+ case HASH('e', 'm'):
+ height = param.x_height;
+ break;
+ case HASH(':', 0):
+ height = param.x_height;
+ break;
+ case HASH(';', 0):
+ height = param.x_height;
+ depth = param.comma_depth;
+ break;
+ case HASH('=', 0):
+ case HASH('e', 'q'):
+ height = param.x_height;
+ break;
+ case HASH('<', 0):
+ case HASH('>', 0):
+ case HASH('>', '='):
+ case HASH('<', '='):
+ case HASH('@', 0):
+ case HASH('/', 0):
+ case HASH('|', 0):
+ case HASH('\\', 0):
+ height = param.asc_height;
+ break;
+ case HASH('_', 0):
+ case HASH('u', 'l'):
+ case HASH('\\', '_'):
+ depth = param.em/4;
+ break;
+ case HASH('r', 'n'):
+ height = (param.em*3)/4;
+ break;
+ case HASH('s', 'r'):
+ height = (param.em*3)/4;
+ depth = param.em/4;
+ break;
+ case HASH('b', 'u'):
+ case HASH('s', 'q'):
+ case HASH('d', 'e'):
+ case HASH('d', 'g'):
+ case HASH('f', 'm'):
+ case HASH('c', 't'):
+ case HASH('r', 'g'):
+ case HASH('c', 'o'):
+ case HASH('p', 'l'):
+ case HASH('*', '*'):
+ case HASH('s', 'c'):
+ case HASH('s', 'l'):
+ case HASH('=', '='):
+ case HASH('~', '='):
+ case HASH('a', 'p'):
+ case HASH('!', '='):
+ case HASH('-', '>'):
+ case HASH('<', '-'):
+ case HASH('u', 'a'):
+ case HASH('d', 'a'):
+ case HASH('m', 'u'):
+ case HASH('d', 'i'):
+ case HASH('+', '-'):
+ case HASH('c', 'u'):
+ case HASH('c', 'a'):
+ case HASH('s', 'b'):
+ case HASH('s', 'p'):
+ case HASH('i', 'b'):
+ case HASH('i', 'p'):
+ case HASH('i', 'f'):
+ case HASH('p', 'd'):
+ case HASH('g', 'r'):
+ case HASH('n', 'o'):
+ case HASH('p', 't'):
+ case HASH('e', 's'):
+ case HASH('m', 'o'):
+ case HASH('b', 'r'):
+ case HASH('d', 'd'):
+ case HASH('r', 'h'):
+ case HASH('l', 'h'):
+ case HASH('o', 'r'):
+ case HASH('c', 'i'):
+ height = param.asc_height;
+ break;
+ case HASH('l', 't'):
+ case HASH('l', 'b'):
+ case HASH('r', 't'):
+ case HASH('r', 'b'):
+ case HASH('l', 'k'):
+ case HASH('r', 'k'):
+ case HASH('b', 'v'):
+ case HASH('l', 'f'):
+ case HASH('r', 'f'):
+ case HASH('l', 'c'):
+ case HASH('r', 'c'):
+ height = (param.em*3)/4;
+ depth = param.em/4;
+ break;
+#if 0
+ case HASH('%', '0'):
+ case HASH('-', '+'):
+ case HASH('-', 'D'):
+ case HASH('-', 'd'):
+ case HASH('-', 'd'):
+ case HASH('-', 'h'):
+ case HASH('.', 'i'):
+ case HASH('.', 'j'):
+ case HASH('/', 'L'):
+ case HASH('/', 'O'):
+ case HASH('/', 'l'):
+ case HASH('/', 'o'):
+ case HASH('=', '~'):
+ case HASH('A', 'E'):
+ case HASH('A', 'h'):
+ case HASH('A', 'N'):
+ case HASH('C', 's'):
+ case HASH('D', 'o'):
+ case HASH('F', 'c'):
+ case HASH('F', 'o'):
+ case HASH('I', 'J'):
+ case HASH('I', 'm'):
+ case HASH('O', 'E'):
+ case HASH('O', 'f'):
+ case HASH('O', 'K'):
+ case HASH('O', 'm'):
+ case HASH('O', 'R'):
+ case HASH('P', 'o'):
+ case HASH('R', 'e'):
+ case HASH('S', '1'):
+ case HASH('S', '2'):
+ case HASH('S', '3'):
+ case HASH('T', 'P'):
+ case HASH('T', 'p'):
+ case HASH('Y', 'e'):
+ case HASH('\\', '-'):
+ case HASH('a', '"'):
+ case HASH('a', '-'):
+ case HASH('a', '.'):
+ case HASH('a', '^'):
+ case HASH('a', 'b'):
+ case HASH('a', 'c'):
+ case HASH('a', 'd'):
+ case HASH('a', 'e'):
+ case HASH('a', 'h'):
+ case HASH('a', 'o'):
+ case HASH('a', 't'):
+ case HASH('a', '~'):
+ case HASH('b', 'a'):
+ case HASH('b', 'b'):
+ case HASH('b', 's'):
+ case HASH('c', '*'):
+ case HASH('c', '+'):
+ case HASH('f', '/'):
+ case HASH('f', 'a'):
+ case HASH('f', 'c'):
+ case HASH('f', 'o'):
+ case HASH('h', 'a'):
+ case HASH('h', 'o'):
+ case HASH('i', 'j'):
+ case HASH('l', 'A'):
+ case HASH('l', 'B'):
+ case HASH('l', 'C'):
+ case HASH('m', 'd'):
+ case HASH('n', 'c'):
+ case HASH('n', 'e'):
+ case HASH('n', 'm'):
+ case HASH('o', 'A'):
+ case HASH('o', 'a'):
+ case HASH('o', 'e'):
+ case HASH('o', 'q'):
+ case HASH('p', 'l'):
+ case HASH('p', 'p'):
+ case HASH('p', 's'):
+ case HASH('r', '!'):
+ case HASH('r', '?'):
+ case HASH('r', 'A'):
+ case HASH('r', 'B'):
+ case HASH('r', 'C'):
+ case HASH('r', 's'):
+ case HASH('s', 'h'):
+ case HASH('s', 's'):
+ case HASH('t', 'e'):
+ case HASH('t', 'f'):
+ case HASH('t', 'i'):
+ case HASH('t', 'm'):
+ case HASH('~', '~'):
+ case HASH('v', 'S'):
+ case HASH('v', 'Z'):
+ case HASH('v', 's'):
+ case HASH('v', 'z'):
+ case HASH('^', 'A'):
+ case HASH('^', 'E'):
+ case HASH('^', 'I'):
+ case HASH('^', 'O'):
+ case HASH('^', 'U'):
+ case HASH('^', 'a'):
+ case HASH('^', 'e'):
+ case HASH('^', 'i'):
+ case HASH('^', 'o'):
+ case HASH('^', 'u'):
+ case HASH('`', 'A'):
+ case HASH('`', 'E'):
+ case HASH('`', 'I'):
+ case HASH('`', 'O'):
+ case HASH('`', 'U'):
+ case HASH('`', 'a'):
+ case HASH('`', 'e'):
+ case HASH('`', 'i'):
+ case HASH('`', 'o'):
+ case HASH('`', 'u'):
+ case HASH('~', 'A'):
+ case HASH('~', 'N'):
+ case HASH('~', 'O'):
+ case HASH('~', 'a'):
+ case HASH('~', 'n'):
+ case HASH('~', 'o'):
+ case HASH('\'', 'A'):
+ case HASH('\'', 'C'):
+ case HASH('\'', 'E'):
+ case HASH('\'', 'I'):
+ case HASH('\'', 'O'):
+ case HASH('\'', 'U'):
+ case HASH('\'', 'a'):
+ case HASH('\'', 'c'):
+ case HASH('\'', 'e'):
+ case HASH('\'', 'i'):
+ case HASH('\'', 'o'):
+ case HASH('\'', 'u')
+ case HASH(':', 'A'):
+ case HASH(':', 'E'):
+ case HASH(':', 'I'):
+ case HASH(':', 'O'):
+ case HASH(':', 'U'):
+ case HASH(':', 'Y'):
+ case HASH(':', 'a'):
+ case HASH(':', 'e'):
+ case HASH(':', 'i'):
+ case HASH(':', 'o'):
+ case HASH(':', 'u'):
+ case HASH(':', 'y'):
+ case HASH(',', 'C'):
+ case HASH(',', 'c'):
+#endif
+ }
+}
diff --git a/src/utils/addftinfo/guess.h b/src/utils/addftinfo/guess.h
new file mode 100644
index 00000000..4471dda8
--- /dev/null
+++ b/src/utils/addftinfo/guess.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+struct font_params {
+ int italic;
+ int em;
+ int x_height;
+ int fig_height;
+ int cap_height;
+ int asc_height;
+ int body_height;
+ int comma_depth;
+ int desc_depth;
+ int body_depth;
+};
+
+struct char_metric {
+ int width;
+ int type;
+ int height;
+ int depth;
+ int ic;
+ int left_ic;
+ int sk;
+};
+
+void guess(const char *s, const font_params &param, char_metric *metric);
diff --git a/src/utils/afmtodit/Makefile.sub b/src/utils/afmtodit/Makefile.sub
new file mode 100644
index 00000000..c27b2b80
--- /dev/null
+++ b/src/utils/afmtodit/Makefile.sub
@@ -0,0 +1,21 @@
+MAN1=afmtodit.n
+CLEANADD=afmtodit
+
+all: afmtodit
+
+afmtodit: afmtodit.pl
+ if test -n "$(PERLPATH)"; then \
+ sed -e 's;/usr/bin/perl;$(PERLPATH);' \
+ $(srcdir)/afmtodit.pl >afmtodit; \
+ else \
+ cp $(srcdir)/afmtodit.pl afmtodit; \
+ fi
+ chmod +x afmtodit
+
+install_data: afmtodit
+ -test -d $(bindir) || $(mkinstalldirs) $(bindir)
+ -rm -f $(bindir)/afmtodit
+ $(INSTALL_PROGRAM) afmtodit $(bindir)/afmtodit
+
+uninstall_sub:
+ -rm -f $(bindir)/afmtodit
diff --git a/src/utils/afmtodit/afmtodit.man b/src/utils/afmtodit/afmtodit.man
new file mode 100644
index 00000000..84fe8f29
--- /dev/null
+++ b/src/utils/afmtodit/afmtodit.man
@@ -0,0 +1,221 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.TH AFMTODIT @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+afmtodit \- create font files for use with groff \-Tps
+.SH SYNOPSIS
+.B afmtodit
+[
+.B \-ns
+]
+[
+.BI \-d desc_file
+]
+[
+.BI \-e enc_file
+]
+[
+.BI \-i n
+]
+[
+.BI \-a n
+]
+.I afm_file
+.I map_file
+.I font
+.SH DESCRIPTION
+.B afmtodit
+creates a font file for use with groff and
+.BR grops .
+.B afmtodit
+is written in perl;
+you must have perl version 3 installed in order to run
+.BR afmtodit .
+.I afm_file
+is the AFM (Adobe Font Metric) file for the font.
+.I map_file
+is a file that says which groff character names map onto
+each PostScript character name;
+this file should contain a sequence of lines of the form
+.IP
+.I
+ps_char groff_char
+.LP
+where
+.I ps_char
+is the PostScript name of the character
+and
+.I groff_char
+is the groff name of the character (as used in the groff font file.)
+The same
+.I ps_char
+can occur multiple times in the file;
+each
+.I groff_char
+must occur at most once.
+.I font
+is the groff name of the font.
+If a PostScript character is in the encoding to be used for the font
+but is not mentioned in
+.I map_file
+then
+.B afmtodit
+will put it in the groff font file as an unnamed character,
+which can be accessed by the
+.B \eN
+escape sequence in
+.BR troff .
+The groff font file will be output to a file called
+.IR font .
+.LP
+If there is a downloadable font file for the font, it may be listed in
+the file
+.BR @FONTDIR@/devps/download ;
+see
+.BR grops (@MAN1EXT@).
+.LP
+If the
+.B \-i
+option is used,
+.B afmtodit
+will automatically generate an italic correction,
+a left italic correction and a subscript correction
+for each character
+(the significance of these parameters is explained in
+.BR groff_font (@MAN5EXT@));
+these parameters may be specified for individual characters by
+adding to the
+.I afm_file
+lines of the form:
+.IP
+.BI italicCorrection\ ps_char\ n
+.br
+.BI leftItalicCorrection\ ps_char\ n
+.br
+.BI subscriptCorrection\ ps_char\ n
+.LP
+where
+.I ps_char
+is the PostScript name of the character,
+and
+.I n
+is the desired value of the corresponding parameter in thousandths of an em.
+These parameters are normally needed only for italic (or oblique) fonts.
+.SH OPTIONS
+.TP
+.B \-n
+Don't output a
+.B ligatures
+command for this font.
+Use this with constant-width fonts.
+.TP
+.B \-s
+The font is special.
+The effect of this option is to add the
+.B special
+command to the font file.
+.TP
+.BI \-d desc_file
+The device description file is
+.I desc_file
+rather than the default
+.BR DESC .
+.TP
+.BI \-e enc_file
+The PostScript font should be reencoded to use the encoding described
+in enc_file.
+The format of
+.I enc_file
+is described in
+.BR grops (@MAN1EXT@).
+.TP
+.BI \-a n
+Use
+.I n
+as the slant parameter in the font file;
+this is used by groff in the positioning of accents.
+By default
+.B afmtodit
+uses the negative of the ItalicAngle specified in the afm file;
+with true italic fonts it is sometimes desirable to use
+a slant that is less than this.
+If you find that characters from an italic font have accents
+placed too far to the right over them,
+then use the
+.B \-a
+option to give the font a smaller slant.
+.TP
+.BI \-i n
+Generate an italic correction for each character so that
+the character's width plus the character's italic correction
+is equal to
+.I n
+thousandths of an em
+plus the amount by which the right edge of the character's bounding
+is to the right of the character's origin.
+If this would result in a negative italic correction, use a zero
+italic correction instead.
+.IP
+Also generate a subscript correction equal to the
+product of the tangent of the slant of the font and
+four fifths of the x-height of the font.
+If this would result in a subscript correction greater than the italic
+correction, use a subscript correction equal to the italic correction
+instead.
+.IP
+Also generate a left italic correction for each character
+equal to
+.I n
+thousandths of an em
+plus the amount by which the left edge of the character's bounding box
+is to the left of the character's origin.
+The left italic correction may be negative.
+.IP
+This option is normally needed only with italic (or oblique) fonts.
+The font files distributed with groff were created using an option of
+.B \-i50
+for italic fonts.
+.SH FILES
+.Tp \w'\fB@FONTDIR@/devps/download'u+2n
+.B @FONTDIR@/devps/DESC
+Device description file.
+.TP
+.BI @FONTDIR@/devps/ F
+Font description file for font
+.IR F .
+.TP
+.B @FONTDIR@/devps/download
+List of downloadable fonts.
+.TP
+.B @FONTDIR@/devps/text.enc
+Encoding used for text fonts.
+.TP
+.B @FONTDIR@/devps/generate/textmap
+Standard mapping.
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@),
+.BR grops (@MAN1EXT@),
+.BR groff_font (@MAN5EXT@),
+.BR perl (1)
diff --git a/src/utils/afmtodit/afmtodit.pl b/src/utils/afmtodit/afmtodit.pl
new file mode 100644
index 00000000..a44ae7a2
--- /dev/null
+++ b/src/utils/afmtodit/afmtodit.pl
@@ -0,0 +1,326 @@
+#! /usr/bin/perl -P-
+# -*- Perl -*-
+#Copyright (C) 1989-2000 Free Software Foundation, Inc.
+# Written by James Clark (jjc@jclark.com)
+#
+#This file is part of groff.
+#
+#groff 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.
+#
+#groff 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 groff; see the file COPYING. If not, write to the Free Software
+#Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+$prog = $0;
+$prog =~ s@.*/@@;
+
+do 'getopts.pl';
+do Getopts('e:sd:i:a:n');
+
+if ($#ARGV != 2) {
+ die "Usage: $prog [-ns] [-d DESC] [-e encoding] [-i n] [-a angle] afmfile mapfile font\n";
+}
+
+$afm = $ARGV[0];
+$map = $ARGV[1];
+$font = $ARGV[2];
+$desc = $opt_d || "DESC";
+
+# read the afm file
+
+open(AFM, $afm) || die "$prog: can't open \`$ARGV[0]': $!\n";
+
+while (<AFM>) {
+ chop;
+ @field = split(' ');
+ if ($field[0] eq "FontName") {
+ $psname = $field[1];
+ }
+ elsif($field[0] eq "ItalicAngle") {
+ $italic_angle = -$field[1];
+ }
+ elsif ($field[0] eq "KPX") {
+ if ($#field == 3) {
+ push(kern1, $field[1]);
+ push(kern2, $field[2]);
+ push(kernx, $field[3]);
+ }
+ }
+ elsif ($field[0] eq "italicCorrection") {
+ $italic_correction{$field[1]} = $field[2];
+ }
+ elsif ($field[0] eq "leftItalicCorrection") {
+ $left_italic_correction{$field[1]} = $field[2];
+ }
+ elsif ($field[0] eq "subscriptCorrection") {
+ $subscript_correction{$field[1]} = $field[2];
+ }
+ elsif ($field[0] eq "StartCharMetrics") {
+ while (<AFM>) {
+ @field = split(' ');
+ last if ($field[0] eq "EndCharMetrics");
+ if ($field[0] eq "C") {
+ $c = -1;
+ $wx = 0;
+ $n = "";
+ $lly = 0;
+ $ury = 0;
+ $llx = 0;
+ $urx = 0;
+ $c = $field[1];
+ $i = 2;
+ while ($i <= $#field) {
+ if ($field[$i] eq "WX") {
+ $w = $field[$i + 1];
+ $i += 2;
+ }
+ elsif ($field[$i] eq "N") {
+ $n = $field[$i + 1];
+ $i += 2;
+ }
+ elsif ($field[$i] eq "B") {
+ $llx = $field[$i + 1];
+ $lly = $field[$i + 2];
+ $urx = $field[$i + 3];
+ $ury = $field[$i + 4];
+ $i += 5;
+ }
+ elsif ($field[$i] eq "L") {
+ push(ligatures, $field[$i + 2]);
+ $i += 3;
+ }
+ else {
+ while ($i <= $#field && $field[$i] ne ";") {
+ $i++;
+ }
+ $i++;
+ }
+ }
+ if (!$opt_e && $c != -1) {
+ $encoding[$c] = $n;
+ $in_encoding{$n} = 1;
+ }
+ $width{$n} = $w;
+ $height{$n} = $ury;
+ $depth{$n} = -$lly;
+ $left_side_bearing{$n} = -$llx;
+ $right_side_bearing{$n} = $urx - $w;
+ }
+ }
+ }
+}
+close(AFM);
+
+# read the DESC file
+
+$sizescale = 1;
+
+open(DESC, $desc) || die "$prog: can't open \`$desc': $!\n";
+while (<DESC>) {
+ next if /^#/;
+ chop;
+ @field = split(' ');
+ last if $field[0] eq "charset";
+ if ($field[0] eq "res") { $resolution = $field[1]; }
+ if ($field[0] eq "unitwidth") { $unitwidth = $field[1]; }
+ if ($field[0] eq "sizescale") { $sizescale = $field[1]; }
+}
+close(DESC);
+
+if ($opt_e) {
+ # read the encoding file
+
+ open(ENCODING, $opt_e) || die "$prog: can't open \`$opt_e': $!\n";
+ while (<ENCODING>) {
+ chop;
+ @field = split(' ');
+ if ($#field == 1) {
+ if ($field[1] >= 0 && defined $width{$field[0]}) {
+ $encoding[$field[1]] = $field[0];
+ $in_encoding{$field[0]} = 1;
+ }
+ }
+ }
+ close(ENCODING);
+}
+
+# read the map file
+
+open(MAP, $map) || die "$prog: can't open \`$map': $!\n";
+while (<MAP>) {
+ next if /^#/;
+ chop;
+ @field = split(' ');
+ if ($#field == 1 && $in_encoding{$field[0]}) {
+ if (defined $mapped{$field[1]}) {
+ warn "Both $mapped{$field[1]} and $field[0] map to $field[1]";
+ }
+ elsif ($field[1] eq "space") {
+ # the PostScript character "space" is automatically mapped
+ # to the groff character "space"; this is for grops
+ warn "you are not allowed to map to the groff character `space'";
+ }
+ elsif ($field[0] eq "space") {
+ warn "you are not allowed to map the PostScript character `space'";
+ }
+ else {
+ $nmap{$field[0]} += 0;
+ $map{$field[0],$nmap{$field[0]}} = $field[1];
+ $nmap{$field[0]} += 1;
+ $mapped{$field[1]} = $field[0];
+ }
+ }
+}
+close(MAP);
+
+$italic_angle = $opt_a if $opt_a;
+
+# print it all out
+
+open(FONT, ">$font") || die "$prog: can't open \`$font' for output: $!\n";
+select(FONT);
+
+print("name $font\n");
+print("internalname $psname\n") if $psname;
+print("special\n") if $opt_s;
+printf("slant %g\n", $italic_angle) if $italic_angle != 0;
+printf("spacewidth %d\n", do conv($width{"space"})) if defined $width{"space"};
+
+if ($opt_e) {
+ $e = $opt_e;
+ $e =~ s@.*/@@;
+ print("encoding $e\n");
+}
+
+if (!$opt_n && $#ligatures >= 0) {
+ print("ligatures");
+ foreach $lig (@ligatures) {
+ print(" $lig");
+ }
+ print(" 0\n");
+}
+
+if ($#kern1 >= 0) {
+ print("kernpairs\n");
+
+ for ($i = 0; $i <= $#kern1; $i++) {
+ $c1 = $kern1[$i];
+ $c2 = $kern2[$i];
+ if ($in_encoding{$c1} == 1 && $nmap{$c1} != 0
+ && $in_encoding{$c2} == 1 && $nmap{$c2} != 0) {
+ for ($j = 0; $j < $nmap{$c1}; $j++) {
+ for ($k = 0; $k < $nmap{$c2}; $k++) {
+ if ($kernx[$i] != 0) {
+ printf("%s %s %d\n",
+ $map{$c1,$j},
+ $map{$c2,$k},
+ do conv($kernx[$i]));
+ }
+ }
+ }
+ }
+ }
+}
+
+# characters not shorter than asc_boundary are considered to have ascenders
+$asc_boundary = $height{"t"} - 1;
+
+# likewise for descenders
+$desc_boundary = $depth{"g"};
+$desc_boundary = $depth{"j"} if $depth{"j"} < $desc_boundary;
+$desc_boundary = $depth{"p"} if $depth{"p"} < $desc_boundary;
+$desc_boundary = $depth{"q"} if $depth{"q"} < $desc_boundary;
+$desc_boundary = $depth{"y"} if $depth{"y"} < $desc_boundary;
+$desc_boundary -= 1;
+
+if (defined $height{"x"}) {
+ $xheight = $height{"x"};
+}
+elsif (defined $height{"alpha"}) {
+ $xheight = $height{"alpha"};
+}
+else {
+ $xheight = 450;
+}
+
+$italic_angle = $italic_angle*3.14159265358979323846/180.0;
+$slant = sin($italic_angle)/cos($italic_angle);
+$slant = 0 if $slant < 0;
+
+print("charset\n");
+for ($i = 0; $i < 256; $i++) {
+ $ch = $encoding[$i];
+ if ($ch ne "" && $ch ne "space") {
+ $map{$ch,"0"} = "---" if $nmap{$ch} == 0;
+ $type = 0;
+ $h = $height{$ch};
+ $h = 0 if $h < 0;
+ $d = $depth{$ch};
+ $d = 0 if $d < 0;
+ $type = 1 if $d >= $desc_boundary;
+ $type += 2 if $h >= $asc_boundary;
+ printf("%s\t%d", $map{$ch,"0"}, do conv($width{$ch}));
+ $italic_correction = 0;
+ $left_math_fit = 0;
+ $subscript_correction = 0;
+ if (defined $opt_i) {
+ $italic_correction = $right_side_bearing{$ch} + $opt_i;
+ $italic_correction = 0 if $italic_correction < 0;
+ $subscript_correction = $slant * $xheight * .8;
+ $subscript_correction = $italic_correction if
+ $subscript_correction > $italic_correction;
+ $left_math_fit = $left_side_bearing{$ch} + $opt_i;
+ }
+ if (defined $italic_correction{$ch}) {
+ $italic_correction = $italic_correction{$ch};
+ }
+ if (defined $left_italic_correction{$ch}) {
+ $left_math_fit = $left_italic_correction{$ch};
+ }
+ if (defined $subscript_correction{$ch}) {
+ $subscript_correction = $subscript_correction{$ch};
+ }
+ if ($subscript_correction != 0) {
+ printf(",%d,%d", do conv($h), do conv($d));
+ printf(",%d,%d,%d", do conv($italic_correction),
+ do conv($left_math_fit),
+ do conv($subscript_correction));
+ }
+ elsif ($left_math_fit != 0) {
+ printf(",%d,%d", do conv($h), do conv($d));
+ printf(",%d,%d", do conv($italic_correction),
+ do conv($left_math_fit));
+ }
+ elsif ($italic_correction != 0) {
+ printf(",%d,%d", do conv($h), do conv($d));
+ printf(",%d", do conv($italic_correction));
+ }
+ elsif ($d != 0) {
+ printf(",%d,%d", do conv($h), do conv($d));
+ }
+ else {
+ # always put the height in to stop groff guessing
+ printf(",%d", do conv($h));
+ }
+ printf("\t%d", $type);
+ printf("\t0%03o\t-- %s\n", $i, $ch);
+ for ($j = 1; $j < $nmap{$ch}; $j++) {
+ printf("%s\t\"\n", $map{$ch,$j});
+ }
+ }
+ if ($ch eq "space" && defined $width{"space"}) {
+ printf("space\t%d\t0\t0%03o\n", do conv($width{"space"}), $i);
+ }
+}
+
+sub conv {
+ $_[0]*$unitwidth*$resolution/(72*1000*$sizescale) + ($_[0] < 0 ? -.5 : .5);
+}
diff --git a/src/utils/hpftodit/Makefile.sub b/src/utils/hpftodit/Makefile.sub
new file mode 100644
index 00000000..f5ff13e4
--- /dev/null
+++ b/src/utils/hpftodit/Makefile.sub
@@ -0,0 +1,6 @@
+PROG=hpftodit
+MAN1=hpftodit.n
+XLIBS=$(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=hpftodit.o
+CCSRCS=$(srcdir)/hpftodit.cc
diff --git a/src/utils/hpftodit/hpftodit.cc b/src/utils/hpftodit/hpftodit.cc
new file mode 100644
index 00000000..af0738c4
--- /dev/null
+++ b/src/utils/hpftodit/hpftodit.cc
@@ -0,0 +1,779 @@
+// -*- C++ -*-
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+TODO
+put human readable font name in device file
+devise new names for useful characters
+use --- for unnamed characters
+option to specify symbol sets to look in
+make it work with TrueType fonts
+put filename in error messages (or fix lib)
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <errno.h>
+#include "assert.h"
+#include "lib.h"
+#include "posix.h"
+#include "errarg.h"
+#include "error.h"
+#include "cset.h"
+
+#define SIZEOF(v) (sizeof(v)/sizeof(v[0]))
+
+const int MULTIPLIER = 3;
+
+inline
+int scale(int n)
+{
+ return n * MULTIPLIER;
+}
+
+// tags in TFM file
+
+enum tag_type {
+ min_tag = 400,
+ type_tag = 400,
+ symbol_set_tag = 404,
+ msl_tag = 403,
+ inches_per_point_tag = 406,
+ design_units_per_em_tag = 408,
+ posture_tag = 409,
+ stroke_weight_tag = 411,
+ spacing_tag = 412,
+ slant_tag = 413,
+ appearance_width_tag = 414,
+ word_spacing_tag = 421,
+ x_height_tag = 424,
+ lower_ascent_tag = 427,
+ lower_descent_tag = 428,
+ width_tag = 433,
+ left_extent_tag = 435,
+ right_extent_tag = 436,
+ ascent_tag = 437,
+ descent_tag = 438,
+ pair_kern_tag = 439,
+ typeface_tag = 442,
+ max_tag = 443
+ };
+
+// types in TFM file
+
+enum {
+ ENUM_TYPE = 1,
+ BYTE_TYPE = 2,
+ USHORT_TYPE = 3,
+ FLOAT_TYPE = 5,
+ SIGNED_SHORT_TYPE = 17
+ };
+
+
+typedef unsigned char byte;
+typedef unsigned short uint16;
+typedef short int16;
+typedef unsigned int uint32;
+
+class File {
+public:
+ File(const char *);
+ void skip(int n);
+ byte get_byte();
+ uint16 get_uint16();
+ uint32 get_uint32();
+ void seek(uint32 n);
+private:
+ unsigned char *buf_;
+ const unsigned char *ptr_;
+ const unsigned char *end_;
+};
+
+struct entry {
+ char present;
+ uint16 type;
+ uint32 count;
+ uint32 value;
+ entry() : present(0) { }
+};
+
+struct char_info {
+ uint16 msl;
+ uint16 width;
+ uint16 ascent;
+ int16 descent;
+ int16 left_extent;
+ uint16 right_extent;
+ uint16 symbol_set;
+ unsigned char code;
+};
+
+const uint16 NO_SYMBOL_SET = 0;
+
+struct name_list {
+ char *name;
+ name_list *next;
+ name_list(const char *s, name_list *p) : name(strsave(s)), next(p) { }
+ ~name_list() { a_delete name; }
+};
+
+struct symbol_set {
+ uint16 select;
+ uint16 index[256];
+};
+
+#define SYMBOL_SET(n, c) ((n) * 32 + ((c) - 64))
+
+uint16 text_symbol_sets[] = {
+ SYMBOL_SET(0, 'N'), // Latin 1
+ SYMBOL_SET(6, 'J'), // Microsoft Publishing
+ SYMBOL_SET(2, 'N'), // Latin 2
+ 0
+ };
+
+uint16 special_symbol_sets[] = {
+ SYMBOL_SET(8, 'M'),
+ SYMBOL_SET(5, 'M'),
+ SYMBOL_SET(15, 'U'),
+ 0
+ };
+
+entry tags[max_tag + 1 - min_tag];
+
+char_info *char_table;
+uint32 nchars;
+
+int msl_name_table_size = 0;
+name_list **msl_name_table = 0;
+
+int n_symbol_sets;
+symbol_set *symbol_set_table;
+
+static int special_flag = 0;
+static int italic_flag = 0;
+static int italic_sep;
+
+static void usage();
+static const char *xbasename(const char *);
+static void read_tags(File &);
+static void check_type();
+static void check_units(File &);
+static int read_map(const char *);
+static void require_tag(tag_type);
+static void dump_tags(File &f);
+static void output_spacewidth();
+static void output_pclweight();
+static void output_pclproportional();
+static void read_and_output_pcltypeface(File &);
+static void output_pclstyle();
+static void output_slant();
+static void output_ligatures();
+static void read_symbol_sets(File &);
+static void read_and_output_kernpairs(File &);
+static void output_charset();
+static void read_char_table(File &f);
+
+inline
+entry &tag_info(tag_type t)
+{
+ return tags[t - min_tag];
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+
+ int opt;
+ int debug_flag = 0;
+
+ while ((opt = getopt(argc, argv, "dsvi:")) != EOF) {
+ switch (opt) {
+ case 'd':
+ debug_flag = 1;
+ break;
+ case 's':
+ special_flag = 1;
+ break;
+ case 'i':
+ italic_flag = 1;
+ italic_sep = atoi(optarg);
+ break;
+ case 'v':
+ {
+ extern const char *Version_string;
+ fprintf(stderr, "hpftodit version %s\n", Version_string);
+ fflush(stderr);
+ break;
+ }
+ break;
+ case '?':
+ usage();
+ default:
+ assert(0);
+ }
+ }
+ if (argc - optind != 3)
+ usage();
+ File f(argv[optind]);
+ if (!read_map(argv[optind + 1]))
+ exit(1);
+ current_filename = 0;
+ current_lineno = -1; // no line numbers
+ if (freopen(argv[optind + 2], "w", stdout) == 0)
+ fatal("cannot open `%1': %2", argv[optind + 2], strerror(errno));
+ current_filename = argv[optind];
+ printf("name %s\n", xbasename(argv[optind + 2]));
+ if (special_flag)
+ printf("special\n");
+ read_tags(f);
+ check_type();
+ check_units(f);
+ if (debug_flag)
+ dump_tags(f);
+ read_char_table(f);
+ output_spacewidth();
+ output_slant();
+ read_and_output_pcltypeface(f);
+ output_pclproportional();
+ output_pclweight();
+ output_pclstyle();
+ read_symbol_sets(f);
+ output_ligatures();
+ read_and_output_kernpairs(f);
+ output_charset();
+ return 0;
+}
+
+static
+void usage()
+{
+ fprintf(stderr, "usage: %s [-s] [-i n] tfm_file map_file output_font\n",
+ program_name);
+ exit(1);
+}
+
+File::File(const char *s)
+{
+ int fd = open(s, O_RDONLY);
+ if (fd < 0)
+ fatal("cannot open `%1': %2", s, strerror(errno));
+ current_filename = s;
+ struct stat sb;
+ if (fstat(fd, &sb) < 0)
+ fatal("cannot stat: %1", strerror(errno));
+ if (!S_ISREG(sb.st_mode))
+ fatal("not a regular file");
+ buf_ = new unsigned char[sb.st_size];
+ long nread = read(fd, buf_, sb.st_size);
+ if (nread < 0)
+ fatal("read error: %1", strerror(errno));
+ if (nread != sb.st_size)
+ fatal("read unexpected number of bytes");
+ ptr_ = buf_;
+ end_ = buf_ + sb.st_size;
+}
+
+void File::skip(int n)
+{
+ if (end_ - ptr_ < n)
+ fatal("unexpected end of file");
+ ptr_ += n;
+}
+
+void File::seek(uint32 n)
+{
+ if (end_ - buf_ < n)
+ fatal("unexpected end of file");
+ ptr_ = buf_ + n;
+}
+
+byte File::get_byte()
+{
+ if (ptr_ >= end_)
+ fatal("unexpected end of file");
+ return *ptr_++;
+}
+
+uint16 File::get_uint16()
+{
+ if (end_ - ptr_ < 2)
+ fatal("unexpected end of file");
+ uint16 n = *ptr_++;
+ return n + (*ptr_++ << 8);
+}
+
+uint32 File::get_uint32()
+{
+ if (end_ - ptr_ < 4)
+ fatal("unexpected end of file");
+ uint32 n = *ptr_++;
+ for (int i = 0; i < 3; i++)
+ n += *ptr_++ << (i + 1)*8;
+ return n;
+}
+
+static
+void read_tags(File &f)
+{
+ if (f.get_byte() != 'I' || f.get_byte() != 'I')
+ fatal("not an Intel format TFM file");
+ f.skip(6);
+ uint16 ntags = f.get_uint16();
+ entry dummy;
+ for (uint16 i = 0; i < ntags; i++) {
+ uint16 tag = f.get_uint16();
+ entry *p;
+ if (min_tag <= tag && tag <= max_tag)
+ p = tags + (tag - min_tag);
+ else
+ p = &dummy;
+ p->present = 1;
+ p->type = f.get_uint16();
+ p->count = f.get_uint32();
+ p->value = f.get_uint32();
+ }
+}
+
+static
+void check_type()
+{
+ require_tag(type_tag);
+ if (tag_info(type_tag).value != 0) {
+ if (tag_info(type_tag).value == 2)
+ fatal("cannot handle TrueType tfm files");
+ fatal("unknown type tag %1", int(tag_info(type_tag).value));
+ }
+}
+
+static
+void check_units(File &f)
+{
+ require_tag(design_units_per_em_tag);
+ f.seek(tag_info(design_units_per_em_tag).value);
+ uint32 num = f.get_uint32();
+ uint32 den = f.get_uint32();
+ if (num != 8782 || den != 1)
+ fatal("design units per em != 8782/1");
+ require_tag(inches_per_point_tag);
+ f.seek(tag_info(inches_per_point_tag).value);
+ num = f.get_uint32();
+ den = f.get_uint32();
+ if (num != 100 || den != 7231)
+ fatal("inches per point not 100/7231");
+}
+
+static
+void require_tag(tag_type t)
+{
+ if (!tag_info(t).present)
+ fatal("tag %1 missing", int(t));
+}
+
+static
+void output_spacewidth()
+{
+ require_tag(word_spacing_tag);
+ printf("spacewidth %d\n", scale(tag_info(word_spacing_tag).value));
+}
+
+static
+void read_symbol_sets(File &f)
+{
+ uint32 symbol_set_dir_length = tag_info(symbol_set_tag).count;
+ n_symbol_sets = symbol_set_dir_length/14;
+ symbol_set_table = new symbol_set[n_symbol_sets];
+ int i;
+ for (i = 0; i < n_symbol_sets; i++) {
+ f.seek(tag_info(symbol_set_tag).value + i*14);
+ (void)f.get_uint32();
+ uint32 off1 = f.get_uint32();
+ uint32 off2 = f.get_uint32();
+ (void)f.get_uint16(); // what's this for?
+ f.seek(off1);
+ int j;
+ uint16 kind = 0;
+ for (j = 0; j < off2 - off1; j++) {
+ unsigned char c = f.get_byte();
+ if ('0' <= c && c <= '9')
+ kind = kind*10 + (c - '0');
+ else if ('A' <= c && c <= 'Z')
+ kind = kind*32 + (c - 64);
+ }
+ symbol_set_table[i].select = kind;
+ for (j = 0; j < 256; j++)
+ symbol_set_table[i].index[j] = f.get_uint16();
+ }
+ for (i = 0; i < nchars; i++)
+ char_table[i].symbol_set = NO_SYMBOL_SET;
+
+ uint16 *symbol_set_selectors = (special_flag
+ ? special_symbol_sets
+ : text_symbol_sets);
+ for (i = 0; symbol_set_selectors[i] != 0; i++) {
+ int j;
+ for (j = 0; j < n_symbol_sets; j++)
+ if (symbol_set_table[j].select == symbol_set_selectors[i])
+ break;
+ if (j < n_symbol_sets) {
+ for (int k = 0; k < 256; k++) {
+ uint16 index = symbol_set_table[j].index[k];
+ if (index != 0xffff
+ && char_table[index].symbol_set == NO_SYMBOL_SET) {
+ char_table[index].symbol_set = symbol_set_table[j].select;
+ char_table[index].code = k;
+ }
+ }
+ }
+ }
+}
+
+static
+void read_char_table(File &f)
+{
+ require_tag(msl_tag);
+ nchars = tag_info(msl_tag).count;
+ char_table = new char_info[nchars];
+
+ f.seek(tag_info(msl_tag).value);
+ uint32 i;
+ for (i = 0; i < nchars; i++)
+ char_table[i].msl = f.get_uint16();
+
+ require_tag(width_tag);
+ f.seek(tag_info(width_tag).value);
+ for (i = 0; i < nchars; i++)
+ char_table[i].width = f.get_uint16();
+
+ require_tag(ascent_tag);
+ f.seek(tag_info(ascent_tag).value);
+ for (i = 0; i < nchars; i++) {
+ char_table[i].ascent = f.get_uint16();
+ }
+
+ require_tag(descent_tag);
+ f.seek(tag_info(descent_tag).value);
+ for (i = 0; i < nchars; i++) {
+ char_table[i].descent = f.get_uint16();
+ if (char_table[i].descent > 0)
+ char_table[i].descent = 0;
+ }
+
+ require_tag(left_extent_tag);
+ f.seek(tag_info(left_extent_tag).value);
+ for (i = 0; i < nchars; i++)
+ char_table[i].left_extent = int16(f.get_uint16());
+
+ require_tag(right_extent_tag);
+ f.seek(tag_info(right_extent_tag).value);
+ for (i = 0; i < nchars; i++)
+ char_table[i].right_extent = f.get_uint16();
+}
+
+static
+void output_pclweight()
+{
+ require_tag(stroke_weight_tag);
+ int stroke_weight = tag_info(stroke_weight_tag).value;
+ int pcl_stroke_weight;
+ if (stroke_weight < 128)
+ pcl_stroke_weight = -3;
+ else if (stroke_weight == 128)
+ pcl_stroke_weight = 0;
+ else if (stroke_weight <= 145)
+ pcl_stroke_weight = 1;
+ else if (stroke_weight <= 179)
+ pcl_stroke_weight = 3;
+ else
+ pcl_stroke_weight = 4;
+ printf("pclweight %d\n", pcl_stroke_weight);
+}
+
+static
+void output_pclproportional()
+{
+ require_tag(spacing_tag);
+ printf("pclproportional %d\n", tag_info(spacing_tag).value == 0);
+}
+
+static
+void read_and_output_pcltypeface(File &f)
+{
+ printf("pcltypeface ");
+ require_tag(typeface_tag);
+ f.seek(tag_info(typeface_tag).value);
+ for (uint32 i = 0; i < tag_info(typeface_tag).count; i++) {
+ unsigned char c = f.get_byte();
+ if (c == '\0')
+ break;
+ putchar(c);
+ }
+ printf("\n");
+}
+
+static
+void output_pclstyle()
+{
+ unsigned pcl_style = 0;
+ // older tfms don't have the posture tag
+ if (tag_info(posture_tag).present) {
+ if (tag_info(posture_tag).value)
+ pcl_style |= 1;
+ }
+ else {
+ require_tag(slant_tag);
+ if (tag_info(slant_tag).value != 0)
+ pcl_style |= 1;
+ }
+ require_tag(appearance_width_tag);
+ if (tag_info(appearance_width_tag).value < 100) // guess
+ pcl_style |= 4;
+ printf("pclstyle %d\n", pcl_style);
+}
+
+static
+void output_slant()
+{
+ require_tag(slant_tag);
+ int slant = int16(tag_info(slant_tag).value);
+ if (slant != 0)
+ printf("slant %f\n", slant/100.0);
+}
+
+static
+void output_ligatures()
+{
+ // don't use ligatures for fixed space font
+ require_tag(spacing_tag);
+ if (tag_info(spacing_tag).value != 0)
+ return;
+ static const char *ligature_names[] = {
+ "fi", "fl", "ff", "ffi", "ffl"
+ };
+
+ static const char *ligature_chars[] = {
+ "fi", "fl", "ff", "Fi", "Fl"
+ };
+
+ unsigned ligature_mask = 0;
+ int i;
+ for (i = 0; i < nchars; i++) {
+ uint16 msl = char_table[i].msl;
+ if (msl < msl_name_table_size
+ && char_table[i].symbol_set != NO_SYMBOL_SET) {
+ for (name_list *p = msl_name_table[msl]; p; p = p->next)
+ for (int j = 0; j < SIZEOF(ligature_chars); j++)
+ if (strcmp(p->name, ligature_chars[j]) == 0) {
+ ligature_mask |= 1 << j;
+ break;
+ }
+ }
+ }
+ if (ligature_mask) {
+ printf("ligatures");
+ for (i = 0; i < SIZEOF(ligature_names); i++)
+ if (ligature_mask & (1 << i))
+ printf(" %s", ligature_names[i]);
+ printf(" 0\n");
+ }
+}
+
+static
+void read_and_output_kernpairs(File &f)
+{
+ if (tag_info(pair_kern_tag).present) {
+ printf("kernpairs\n");
+ f.seek(tag_info(pair_kern_tag).value);
+ uint16 n_pairs = f.get_uint16();
+ for (int i = 0; i < n_pairs; i++) {
+ uint16 i1 = f.get_uint16();
+ uint16 i2 = f.get_uint16();
+ int16 val = int16(f.get_uint16());
+ if (char_table[i1].symbol_set != NO_SYMBOL_SET
+ && char_table[i2].symbol_set != NO_SYMBOL_SET
+ && char_table[i1].msl < msl_name_table_size
+ && char_table[i2].msl < msl_name_table_size) {
+ for (name_list *p = msl_name_table[char_table[i1].msl];
+ p;
+ p = p->next)
+ for (name_list *q = msl_name_table[char_table[i2].msl];
+ q;
+ q = q->next)
+ printf("%s %s %d\n", p->name, q->name, scale(val));
+ }
+ }
+ }
+}
+
+static
+void output_charset()
+{
+ require_tag(slant_tag);
+ double slant_angle = int16(tag_info(slant_tag).value)*PI/18000.0;
+ double slant = sin(slant_angle)/cos(slant_angle);
+
+ require_tag(x_height_tag);
+ require_tag(lower_ascent_tag);
+ require_tag(lower_descent_tag);
+
+ printf("charset\n");
+ int i;
+ for (i = 0; i < nchars; i++) {
+ uint16 msl = char_table[i].msl;
+ if (msl < msl_name_table_size
+ && msl_name_table[msl]) {
+ if (char_table[i].symbol_set != NO_SYMBOL_SET) {
+ printf("%s\t%d,%d",
+ msl_name_table[msl]->name,
+ scale(char_table[i].width),
+ scale(char_table[i].ascent));
+ int depth = scale(- char_table[i].descent);
+ if (depth < 0)
+ depth = 0;
+ int italic_correction = 0;
+ int left_italic_correction = 0;
+ int subscript_correction = 0;
+ if (italic_flag) {
+ italic_correction = scale(char_table[i].right_extent
+ - char_table[i].width
+ + italic_sep);
+ if (italic_correction < 0)
+ italic_correction = 0;
+ subscript_correction = int((tag_info(x_height_tag).value
+ * slant * .8) + .5);
+ if (subscript_correction > italic_correction)
+ subscript_correction = italic_correction;
+ left_italic_correction = scale(italic_sep
+ - char_table[i].left_extent);
+ }
+ if (subscript_correction != 0)
+ printf(",%d,%d,%d,%d",
+ depth, italic_correction, left_italic_correction,
+ subscript_correction);
+ else if (left_italic_correction != 0)
+ printf(",%d,%d,%d", depth, italic_correction, left_italic_correction);
+ else if (italic_correction != 0)
+ printf(",%d,%d", depth, italic_correction);
+ else if (depth != 0)
+ printf(",%d", depth);
+ // This is fairly arbitrary. Fortunately it doesn't much matter.
+ unsigned type = 0;
+ if (char_table[i].ascent > (tag_info(lower_ascent_tag).value*9)/10)
+ type |= 2;
+ if (char_table[i].descent < (int16(tag_info(lower_descent_tag).value)*9)/10)
+ type |= 1;
+ printf("\t%d\t%d\n",
+ type,
+ char_table[i].symbol_set*256 + char_table[i].code);
+ for (name_list *p = msl_name_table[msl]->next; p; p = p->next)
+ printf("%s\t\"\n", p->name);
+ }
+ else
+ warning("MSL %1 not in any of the searched symbol sets", msl);
+ }
+ }
+}
+
+static
+void dump_tags(File &f)
+{
+ int i;
+ for (i = min_tag; i <= max_tag; i++) {
+ enum tag_type t = tag_type(i);
+ if (tag_info(t).present) {
+ fprintf(stderr,
+ "%d %d %d %d\n", i, tag_info(t).type, tag_info(t).count,
+ tag_info(t).value);
+ if (tag_info(t).type == FLOAT_TYPE
+ && tag_info(t).count == 1) {
+ f.seek(tag_info(t).value);
+ uint32 num = f.get_uint32();
+ uint32 den = f.get_uint32();
+ fprintf(stderr, "(%u/%u = %g)\n", num, den, (double)num/den);
+ }
+ }
+ }
+}
+
+static
+int read_map(const char *file)
+{
+ errno = 0;
+ FILE *fp = fopen(file, "r");
+ if (!fp) {
+ error("can't open `%1': %2", file, strerror(errno));
+ return 0;
+ }
+ current_filename = file;
+ char buf[512];
+ current_lineno = 0;
+ while (fgets(buf, int(sizeof(buf)), fp)) {
+ current_lineno++;
+ char *ptr = buf;
+ while (csspace(*ptr))
+ ptr++;
+ if (*ptr == '\0' || *ptr == '#')
+ continue;
+ ptr = strtok(ptr, " \n\t");
+ if (!ptr)
+ continue;
+ int n;
+ if (sscanf(ptr, "%d", &n) != 1) {
+ error("bad map file");
+ fclose(fp);
+ return 0;
+ }
+ if (n < 0) {
+ error("negative code");
+ fclose(fp);
+ return 0;
+ }
+ if (n >= msl_name_table_size) {
+ size_t old_size = msl_name_table_size;
+ name_list **old_table = msl_name_table;
+ msl_name_table_size = n + 256;
+ msl_name_table = new name_list *[msl_name_table_size];
+ if (old_table) {
+ memcpy(msl_name_table, old_table, old_size*sizeof(name_list *));
+ a_delete old_table;
+ }
+ for (size_t i = old_size; i < msl_name_table_size; i++)
+ msl_name_table[i] = 0;
+ }
+ ptr = strtok(0, " \n\t");
+ if (!ptr) {
+ error("missing names");
+ fclose(fp);
+ return 0;
+ }
+ for (; ptr; ptr = strtok(0, " \n\t"))
+ msl_name_table[n] = new name_list(ptr, msl_name_table[n]);
+ }
+ fclose(fp);
+ return 1;
+}
+
+static
+const char *xbasename(const char *s)
+{
+ const char *b = strrchr(s, '/');
+ return b ? b + 1 : s;
+}
diff --git a/src/utils/hpftodit/hpftodit.man b/src/utils/hpftodit/hpftodit.man
new file mode 100644
index 00000000..75af154e
--- /dev/null
+++ b/src/utils/hpftodit/hpftodit.man
@@ -0,0 +1,151 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.TH HPFTODIT @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+hpftodit \- create font description files for use with groff \-Tlj4
+.SH SYNOPSIS
+.B hpftodit
+[
+.B \-sv
+]
+[
+.BI \-i n
+]
+.I tfm_file
+.I map_file
+.I font
+.SH DESCRIPTION
+.B hpftodit
+creates a font file for use with
+.B
+groff \-Tlj4\fR
+from an HP tagged font metric file.
+.I tfm_file
+is the name of the tagged font metric file for the font.
+.I map_file
+is a file giving the groff names for characters in the font;
+this file should consist of a sequence of lines of the form:
+.IP
+.I
+n c1 c2 \fR.\|.\|.
+.LP
+where
+.I n
+is a decimal integer giving the MSL number of the character,
+and
+.IR c1 ,
+.IR c2 ,.\|.\|.
+are the groff names of the character.
+.I font
+is the name of the groff font file.
+The groff font file is written to
+.IR font .
+.LP
+The
+.B \-s
+option should be given if the font is special
+(a font is
+.I special
+if
+.B troff
+should search it whenever
+a character is not found in the current font.)
+If the font is special,
+it should be listed in the
+.B fonts
+command in the DESC file;
+if it is not special, there is no need to list it, since
+.B troff
+can automatically mount it when it's first used.
+.LP
+If the
+.B \-i
+option is used,
+.B hpftodit
+will automatically generate an italic correction,
+a left italic correction and a subscript correction
+for each character
+(the significance of these parameters is explained in
+.BR groff_font (@MAN5EXT@)).
+.SH OPTIONS
+.TP
+.B \-v
+Print the version number.
+.TP
+.B \-s
+The font is special.
+The effect of this option is to add the
+.B special
+command to the font file.
+.TP
+.BI \-i n
+Generate an italic correction for each character so that
+the character's width plus the character's italic correction
+is equal to
+.I n
+design units
+plus the amount by which the right edge of the character's bounding
+is to the right of the character's origin.
+If this would result in a negative italic correction, use a zero
+italic correction instead.
+There are 8782 design units per em for Intellifont fonts.
+.IP
+Also generate a subscript correction equal to the
+product of the tangent of the slant of the font and
+four fifths of the x-height of the font.
+If this would result in a subscript correction greater than the italic
+correction, use a subscript correction equal to the italic correction
+instead.
+.IP
+Also generate a left italic correction for each character
+equal to
+.I n
+design units
+plus the amount by which the left edge of the character's bounding box
+is to the left of the character's origin.
+The left italic correction may be negative.
+.IP
+This option is normally needed only with italic (or oblique) fonts.
+.SH FILES
+.Tp \w'\fB@FONTDIR@/devlj4/DESC'u+2n
+.B @FONTDIR@/devlj4/DESC
+Device description file.
+.TP
+.BI @FONTDIR@/devlj4/ F
+Font description file for font
+.IR F .
+.SH BUGS
+.LP
+This program was written without the benefit of complete, official
+documentation on the tagged font metric format.
+It is therefore likely that it will fail to work on tfm files that are
+dissimilar to those for the internal fonts on the Laserjet 4,
+with which it was tested:
+.LP
+TrueType tfm files are not supported.
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@),
+.BR grolj4 (@MAN1EXT@),
+.BR groff_font (@MAN5EXT@)
diff --git a/src/utils/indxbib/Makefile.sub b/src/utils/indxbib/Makefile.sub
new file mode 100644
index 00000000..2c50e659
--- /dev/null
+++ b/src/utils/indxbib/Makefile.sub
@@ -0,0 +1,30 @@
+PROG=indxbib
+MAN1=indxbib.n
+XLIBS=$(LIBBIB) $(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=\
+ indxbib.o \
+ dirnamemax.o \
+ signal.o
+CCSRCS=\
+ $(srcdir)/indxbib.cc
+CSRCS=\
+ $(srcdir)/dirnamemax.c \
+ $(srcdir)/signal.c
+NAMEPREFIX=$(g)
+
+install_data: eign
+ -test -d $(datadir) || $(mkinstalldirs) $(datadir)
+ -test -d $(datasubdir) || $(mkinstalldirs) $(datasubdir)
+ if test -f /usr/lib/eign; then \
+ rm -f $(common_words_file); \
+ ln -s /usr/lib/eign $(common_words_file) 2>/dev/null \
+ || ln /usr/lib/eign $(common_words_file) 2>/dev/null \
+ || cp /usr/lib/eign $(common_words_file); \
+ else \
+ rm -f $(common_words_file); \
+ $(INSTALL_DATA) $(srcdir)/eign $(common_words_file); \
+ fi
+
+uninstall_sub:
+ -rm -f $(common_words_file)
diff --git a/src/utils/indxbib/dirnamemax.c b/src/utils/indxbib/dirnamemax.c
new file mode 100755
index 00000000..a8cd9923
--- /dev/null
+++ b/src/utils/indxbib/dirnamemax.c
@@ -0,0 +1,49 @@
+/* dir_name_max(dir) does the same as pathconf(dir, _PC_NAME_MAX) */
+
+#include <sys/types.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#ifdef _POSIX_VERSION
+
+long dir_name_max(dir)
+ char *dir;
+{
+ return pathconf(dir, _PC_NAME_MAX);
+}
+
+#else /* not _POSIX_VERSION */
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif /* HAVE_LIMITS_H */
+
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#else /* not HAVE_DIRENT_H */
+#ifdef HAVE_SYS_DIR_H
+#include <sys/dir.h>
+#endif /* HAVE_SYS_DIR_H */
+#endif /* not HAVE_DIRENT_H */
+
+#ifndef NAME_MAX
+#ifdef MAXNAMLEN
+#define NAME_MAX MAXNAMLEN
+#else /* !MAXNAMLEN */
+#ifdef MAXNAMELEN
+#define NAME_MAX MAXNAMELEN
+#else /* !MAXNAMELEN */
+#define NAME_MAX 14
+#endif /* !MAXNAMELEN */
+#endif /* !MAXNAMLEN */
+#endif /* !NAME_MAX */
+
+long dir_name_max(dir)
+ char *dir;
+{
+ return NAME_MAX;
+}
+
+#endif /* not _POSIX_VERSION */
diff --git a/src/utils/indxbib/eign b/src/utils/indxbib/eign
new file mode 100644
index 00000000..7718c8b1
--- /dev/null
+++ b/src/utils/indxbib/eign
@@ -0,0 +1,133 @@
+a
+i
+the
+to
+of
+and
+in
+is
+it
+for
+that
+if
+you
+this
+be
+on
+with
+not
+have
+are
+or
+as
+from
+can
+but
+by
+at
+an
+will
+no
+all
+was
+do
+there
+my
+one
+so
+we
+they
+what
+would
+any
+which
+about
+get
+your
+use
+some
+me
+then
+name
+like
+out
+when
+up
+time
+other
+more
+only
+just
+end
+also
+know
+how
+new
+should
+been
+than
+them
+he
+who
+make
+may
+people
+these
+now
+their
+here
+into
+first
+could
+way
+had
+see
+work
+well
+were
+two
+very
+where
+while
+us
+because
+good
+same
+even
+much
+most
+many
+such
+long
+his
+over
+last
+since
+right
+before
+our
+without
+too
+those
+why
+must
+part
+being
+current
+back
+still
+go
+point
+value
+each
+did
+both
+true
+off
+say
+another
+state
+might
+under
+start
+try
diff --git a/src/utils/indxbib/indxbib.cc b/src/utils/indxbib/indxbib.cc
new file mode 100644
index 00000000..c22190f5
--- /dev/null
+++ b/src/utils/indxbib/indxbib.cc
@@ -0,0 +1,744 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "posix.h"
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+#include "stringclass.h"
+#include "cset.h"
+#include "cmap.h"
+
+#include "defs.h"
+#include "index.h"
+
+extern "C" {
+ // Sun's stdlib.h fails to declare this.
+ char *mktemp(char *);
+}
+
+#define DEFAULT_HASH_TABLE_SIZE 997
+#define TEMP_INDEX_TEMPLATE "indxbibXXXXXX"
+
+// (2^n - MALLOC_OVERHEAD) should be a good argument for malloc().
+
+#define MALLOC_OVERHEAD 16
+
+#ifdef BLOCK_SIZE
+#undef BLOCK_SIZE
+#endif
+
+const int BLOCK_SIZE = ((1024 - MALLOC_OVERHEAD - sizeof(struct block *)
+ - sizeof(int)) / sizeof(int));
+struct block {
+ block *next;
+ int used;
+ int v[BLOCK_SIZE];
+
+ block(block *p = 0) : next(p), used(0) { }
+};
+
+struct block;
+
+union table_entry {
+ block *ptr;
+ int count;
+};
+
+struct word_list {
+ word_list *next;
+ char *str;
+ int len;
+ word_list(const char *, int, word_list *);
+};
+
+table_entry *hash_table;
+int hash_table_size = DEFAULT_HASH_TABLE_SIZE;
+// We make this the same size as hash_table so we only have to do one
+// mod per key.
+static word_list **common_words_table = 0;
+char *key_buffer;
+
+FILE *indxfp;
+int ntags = 0;
+string filenames;
+char *temp_index_file = 0;
+
+const char *ignore_fields = "XYZ";
+const char *common_words_file = COMMON_WORDS_FILE;
+int n_ignore_words = 100;
+int truncate_len = 6;
+int shortest_len = 3;
+int max_keys_per_item = 100;
+
+static void usage();
+static void write_hash_table();
+static void init_hash_table();
+static void read_common_words_file();
+static int store_key(char *s, int len);
+static void possibly_store_key(char *s, int len);
+static int do_whole_file(const char *filename);
+static int do_file(const char *filename);
+static void store_reference(int filename_index, int pos, int len);
+static void check_integer_arg(char opt, const char *arg, int min, int *res);
+static void store_filename(const char *);
+static void fwrite_or_die(const void *ptr, int size, int nitems, FILE *fp);
+static char *get_cwd();
+
+extern "C" {
+ void cleanup();
+ long dir_name_max(const char *);
+ void catch_fatal_signals();
+ void ignore_fatal_signals();
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+
+ const char *basename = 0;
+ typedef int (*parser_t)(const char *);
+ parser_t parser = do_file;
+ const char *directory = 0;
+ const char *foption = 0;
+ int opt;
+ while ((opt = getopt(argc, argv, "c:o:h:i:k:l:t:n:c:d:f:vw")) != EOF)
+ switch (opt) {
+ case 'c':
+ common_words_file = optarg;
+ break;
+ case 'd':
+ directory = optarg;
+ break;
+ case 'f':
+ foption = optarg;
+ break;
+ case 'h':
+ check_integer_arg('h', optarg, 1, &hash_table_size);
+ if (!is_prime(hash_table_size)) {
+ while (!is_prime(++hash_table_size))
+ ;
+ warning("%1 not prime: using %2 instead", optarg, hash_table_size);
+ }
+ break;
+ case 'i':
+ ignore_fields = optarg;
+ break;
+ case 'k':
+ check_integer_arg('k', optarg, 1, &max_keys_per_item);
+ break;
+ case 'l':
+ check_integer_arg('l', optarg, 0, &shortest_len);
+ break;
+ case 'n':
+ check_integer_arg('n', optarg, 0, &n_ignore_words);
+ break;
+ case 'o':
+ basename = optarg;
+ break;
+ case 't':
+ check_integer_arg('t', optarg, 1, &truncate_len);
+ break;
+ case 'w':
+ parser = do_whole_file;
+ break;
+ case 'v':
+ {
+ extern const char *Version_string;
+ fprintf(stderr, "GNU indxbib version %s\n", Version_string);
+ fflush(stderr);
+ break;
+ }
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ if (optind >= argc && foption == 0)
+ fatal("no files and no -f option");
+ if (!directory) {
+ char *path = get_cwd();
+ store_filename(path);
+ a_delete path;
+ }
+ else
+ store_filename(directory);
+ init_hash_table();
+ store_filename(common_words_file);
+ store_filename(ignore_fields);
+ key_buffer = new char[truncate_len];
+ read_common_words_file();
+ if (!basename)
+ basename = optind < argc ? argv[optind] : DEFAULT_INDEX_NAME;
+ const char *p = strrchr(basename, '/');
+ long name_max;
+ if (p) {
+ char *dir = strsave(basename);
+ dir[p - basename] = '\0';
+ name_max = dir_name_max(dir);
+ a_delete dir;
+ }
+ else
+ name_max = dir_name_max(".");
+ const char *filename = p ? p + 1 : basename;
+ if (name_max >= 0 && strlen(filename) + sizeof(INDEX_SUFFIX) - 1 > name_max)
+ fatal("`%1.%2' is too long for a filename", filename, INDEX_SUFFIX);
+ if (p) {
+ p++;
+ temp_index_file = new char[p - basename + sizeof(TEMP_INDEX_TEMPLATE)];
+ memcpy(temp_index_file, basename, p - basename);
+ strcpy(temp_index_file + (p - basename), TEMP_INDEX_TEMPLATE);
+ }
+ else {
+ temp_index_file = strsave(TEMP_INDEX_TEMPLATE);
+ }
+ if (!mktemp(temp_index_file) || !temp_index_file[0])
+ fatal("cannot create file name for temporary file");
+ catch_fatal_signals();
+ int fd = creat(temp_index_file, S_IRUSR|S_IRGRP|S_IROTH);
+ if (fd < 0)
+ fatal("can't create temporary index file: %1", strerror(errno));
+ indxfp = fdopen(fd, "w");
+ if (indxfp == 0)
+ fatal("fdopen failed");
+ if (fseek(indxfp, sizeof(index_header), 0) < 0)
+ fatal("can't seek past index header: %1", strerror(errno));
+ int failed = 0;
+ if (foption) {
+ FILE *fp = stdin;
+ if (strcmp(foption, "-") != 0) {
+ errno = 0;
+ fp = fopen(foption, "r");
+ if (!fp)
+ fatal("can't open `%1': %2", foption, strerror(errno));
+ }
+ string path;
+ int lineno = 1;
+ for (;;) {
+ int c;
+ for (c = getc(fp); c != '\n' && c != EOF; c = getc(fp)) {
+ if (c == '\0')
+ error_with_file_and_line(foption, lineno,
+ "nul character in pathname ignored");
+ else
+ path += c;
+ }
+ if (path.length() > 0) {
+ path += '\0';
+ if (!(*parser)(path.contents()))
+ failed = 1;
+ path.clear();
+ }
+ if (c == EOF)
+ break;
+ lineno++;
+ }
+ if (fp != stdin)
+ fclose(fp);
+ }
+ for (int i = optind; i < argc; i++)
+ if (!(*parser)(argv[i]))
+ failed = 1;
+ write_hash_table();
+ if (fclose(indxfp) < 0)
+ fatal("error closing temporary index file: %1", strerror(errno));
+ char *index_file = new char[strlen(basename) + sizeof(INDEX_SUFFIX)];
+ strcpy(index_file, basename);
+ strcat(index_file, INDEX_SUFFIX);
+#ifdef HAVE_RENAME
+ if (rename(temp_index_file, index_file) < 0)
+ fatal("can't rename temporary index file: %1", strerror(errno));
+#else /* not HAVE_RENAME */
+ ignore_fatal_signals();
+ if (unlink(index_file) < 0) {
+ if (errno != ENOENT)
+ fatal("can't unlink `%1': %2", index_file, strerror(errno));
+ }
+ if (link(temp_index_file, index_file) < 0)
+ fatal("can't link temporary index file: %1", strerror(errno));
+ if (unlink(temp_index_file) < 0)
+ fatal("can't unlink temporary index file: %1", strerror(errno));
+#endif /* not HAVE_RENAME */
+ temp_index_file = 0;
+ return failed;
+}
+
+static void usage()
+{
+ fprintf(stderr,
+"usage: %s [-vw] [-c file] [-d dir] [-f file] [-h n] [-i XYZ] [-k n]\n"
+" [-l n] [-n n] [-o base] [-t n] [files...]\n",
+ program_name);
+ exit(1);
+}
+
+static void check_integer_arg(char opt, const char *arg, int min, int *res)
+{
+ char *ptr;
+ long n = strtol(arg, &ptr, 10);
+ if (n == 0 && ptr == arg)
+ error("argument to -%1 not an integer", opt);
+ else if (n < min)
+ error("argument to -%1 must not be less than %2", opt, min);
+ else {
+ if (n > INT_MAX)
+ error("argument to -%1 greater than maximum integer", opt);
+ else if (*ptr != '\0')
+ error("junk after integer argument to -%1", opt);
+ *res = int(n);
+ }
+}
+
+static char *get_cwd()
+{
+ char *buf;
+ int size = 12;
+
+ for (;;) {
+ buf = new char[size];
+ if (getcwd(buf, size))
+ break;
+ if (errno != ERANGE)
+ fatal("cannot get current working directory: %1", strerror(errno));
+ a_delete buf;
+ if (size == INT_MAX)
+ fatal("current working directory longer than INT_MAX");
+ if (size > INT_MAX/2)
+ size = INT_MAX;
+ else
+ size *= 2;
+ }
+ return buf;
+}
+
+word_list::word_list(const char *s, int n, word_list *p)
+: next(p), len(n)
+{
+ str = new char[n];
+ memcpy(str, s, n);
+}
+
+static void read_common_words_file()
+{
+ if (n_ignore_words <= 0)
+ return;
+ errno = 0;
+ FILE *fp = fopen(common_words_file, "r");
+ if (!fp)
+ fatal("can't open `%1': %2", common_words_file, strerror(errno));
+ common_words_table = new word_list * [hash_table_size];
+ for (int i = 0; i < hash_table_size; i++)
+ common_words_table[i] = 0;
+ int count = 0;
+ int key_len = 0;
+ for (;;) {
+ int c = getc(fp);
+ while (c != EOF && !csalnum(c))
+ c = getc(fp);
+ if (c == EOF)
+ break;
+ do {
+ if (key_len < truncate_len)
+ key_buffer[key_len++] = cmlower(c);
+ c = getc(fp);
+ } while (c != EOF && csalnum(c));
+ if (key_len >= shortest_len) {
+ int h = hash(key_buffer, key_len) % hash_table_size;
+ common_words_table[h] = new word_list(key_buffer, key_len,
+ common_words_table[h]);
+ }
+ if (++count >= n_ignore_words)
+ break;
+ key_len = 0;
+ if (c == EOF)
+ break;
+ }
+ n_ignore_words = count;
+ fclose(fp);
+}
+
+static int do_whole_file(const char *filename)
+{
+ errno = 0;
+ FILE *fp = fopen(filename, "r");
+ if (!fp) {
+ error("can't open `%1': %2", filename, strerror(errno));
+ return 0;
+ }
+ int count = 0;
+ int key_len = 0;
+ int c;
+ while ((c = getc(fp)) != EOF) {
+ if (csalnum(c)) {
+ key_len = 1;
+ key_buffer[0] = c;
+ while ((c = getc(fp)) != EOF) {
+ if (!csalnum(c))
+ break;
+ if (key_len < truncate_len)
+ key_buffer[key_len++] = c;
+ }
+ if (store_key(key_buffer, key_len)) {
+ if (++count >= max_keys_per_item)
+ break;
+ }
+ if (c == EOF)
+ break;
+ }
+ }
+ store_reference(filenames.length(), 0, 0);
+ store_filename(filename);
+ fclose(fp);
+ return 1;
+}
+
+static int do_file(const char *filename)
+{
+ errno = 0;
+ FILE *fp = fopen(filename, "r");
+ if (fp == 0) {
+ error("can't open `%1': %2", filename, strerror(errno));
+ return 0;
+ }
+ int filename_index = filenames.length();
+ store_filename(filename);
+
+ enum {
+ START, // at the start of the file; also in between references
+ BOL, // in the middle of a reference, at the beginning of the line
+ PERCENT, // seen a percent at the beginning of the line
+ IGNORE, // ignoring a field
+ IGNORE_BOL, // at the beginning of a line ignoring a field
+ KEY, // in the middle of a key
+ DISCARD, // after truncate_len bytes of a key
+ MIDDLE // in between keys
+ } state = START;
+
+ // In states START, BOL, IGNORE_BOL, space_count how many spaces at
+ // the beginning have been seen. In states PERCENT, IGNORE, KEY,
+ // MIDDLE space_count must be 0.
+ int space_count = 0;
+ int byte_count = 0; // bytes read
+ int key_len = 0;
+ int ref_start = -1; // position of start of current reference
+ for (;;) {
+ int c = getc(fp);
+ if (c == EOF)
+ break;
+ byte_count++;
+ switch (state) {
+ case START:
+ if (c == ' ' || c == '\t') {
+ space_count++;
+ break;
+ }
+ if (c == '\n') {
+ space_count = 0;
+ break;
+ }
+ ref_start = byte_count - space_count - 1;
+ space_count = 0;
+ if (c == '%')
+ state = PERCENT;
+ else if (csalnum(c)) {
+ state = KEY;
+ key_buffer[0] = c;
+ key_len = 1;
+ }
+ else
+ state = MIDDLE;
+ break;
+ case BOL:
+ switch (c) {
+ case '%':
+ if (space_count > 0) {
+ space_count = 0;
+ state = MIDDLE;
+ }
+ else
+ state = PERCENT;
+ break;
+ case ' ':
+ case '\t':
+ space_count++;
+ break;
+ case '\n':
+ store_reference(filename_index, ref_start,
+ byte_count - 1 - space_count - ref_start);
+ state = START;
+ space_count = 0;
+ break;
+ default:
+ space_count = 0;
+ if (csalnum(c)) {
+ state = KEY;
+ key_buffer[0] = c;
+ key_len = 1;
+ }
+ else
+ state = MIDDLE;
+ }
+ break;
+ case PERCENT:
+ if (strchr(ignore_fields, c) != 0)
+ state = IGNORE;
+ else if (c == '\n')
+ state = BOL;
+ else
+ state = MIDDLE;
+ break;
+ case IGNORE:
+ if (c == '\n')
+ state = IGNORE_BOL;
+ break;
+ case IGNORE_BOL:
+ switch (c) {
+ case '%':
+ if (space_count > 0) {
+ state = IGNORE;
+ space_count = 0;
+ }
+ else
+ state = PERCENT;
+ break;
+ case ' ':
+ case '\t':
+ space_count++;
+ break;
+ case '\n':
+ store_reference(filename_index, ref_start,
+ byte_count - 1 - space_count - ref_start);
+ state = START;
+ space_count = 0;
+ break;
+ default:
+ space_count = 0;
+ state = IGNORE;
+ }
+ break;
+ case KEY:
+ if (csalnum(c)) {
+ if (key_len < truncate_len)
+ key_buffer[key_len++] = c;
+ else
+ state = DISCARD;
+ }
+ else {
+ possibly_store_key(key_buffer, key_len);
+ key_len = 0;
+ if (c == '\n')
+ state = BOL;
+ else
+ state = MIDDLE;
+ }
+ break;
+ case DISCARD:
+ if (!csalnum(c)) {
+ possibly_store_key(key_buffer, key_len);
+ key_len = 0;
+ if (c == '\n')
+ state = BOL;
+ else
+ state = MIDDLE;
+ }
+ break;
+ case MIDDLE:
+ if (csalnum(c)) {
+ state = KEY;
+ key_buffer[0] = c;
+ key_len = 1;
+ }
+ else if (c == '\n')
+ state = BOL;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ switch (state) {
+ case START:
+ break;
+ case DISCARD:
+ case KEY:
+ possibly_store_key(key_buffer, key_len);
+ // fall through
+ case BOL:
+ case PERCENT:
+ case IGNORE_BOL:
+ case IGNORE:
+ case MIDDLE:
+ store_reference(filename_index, ref_start,
+ byte_count - ref_start - space_count);
+ break;
+ default:
+ assert(0);
+ }
+ fclose(fp);
+ return 1;
+}
+
+static void store_reference(int filename_index, int pos, int len)
+{
+ tag t;
+ t.filename_index = filename_index;
+ t.start = pos;
+ t.length = len;
+ fwrite_or_die(&t, sizeof(t), 1, indxfp);
+ ntags++;
+}
+
+static void store_filename(const char *fn)
+{
+ filenames += fn;
+ filenames += '\0';
+}
+
+static void init_hash_table()
+{
+ hash_table = new table_entry[hash_table_size];
+ for (int i = 0; i < hash_table_size; i++)
+ hash_table[i].ptr = 0;
+}
+
+static void possibly_store_key(char *s, int len)
+{
+ static int last_tagno = -1;
+ static int key_count;
+ if (last_tagno != ntags) {
+ last_tagno = ntags;
+ key_count = 0;
+ }
+ if (key_count < max_keys_per_item) {
+ if (store_key(s, len))
+ key_count++;
+ }
+}
+
+static int store_key(char *s, int len)
+{
+ if (len < shortest_len)
+ return 0;
+ int is_number = 1;
+ for (int i = 0; i < len; i++)
+ if (!csdigit(s[i])) {
+ is_number = 0;
+ s[i] = cmlower(s[i]);
+ }
+ if (is_number && !(len == 4 && s[0] == '1' && s[1] == '9'))
+ return 0;
+ int h = hash(s, len) % hash_table_size;
+ if (common_words_table) {
+ for (word_list *ptr = common_words_table[h]; ptr; ptr = ptr->next)
+ if (len == ptr->len && memcmp(s, ptr->str, len) == 0)
+ return 0;
+ }
+ table_entry *pp = hash_table + h;
+ if (!pp->ptr)
+ pp->ptr = new block;
+ else if (pp->ptr->v[pp->ptr->used - 1] == ntags)
+ return 1;
+ else if (pp->ptr->used >= BLOCK_SIZE)
+ pp->ptr = new block(pp->ptr);
+ pp->ptr->v[(pp->ptr->used)++] = ntags;
+ return 1;
+}
+
+static void write_hash_table()
+{
+ const int minus_one = -1;
+ int li = 0;
+ for (int i = 0; i < hash_table_size; i++) {
+ block *ptr = hash_table[i].ptr;
+ if (!ptr)
+ hash_table[i].count = -1;
+ else {
+ hash_table[i].count = li;
+ block *rev = 0;
+ while (ptr) {
+ block *tem = ptr;
+ ptr = ptr->next;
+ tem->next = rev;
+ rev = tem;
+ }
+ while (rev) {
+ fwrite_or_die(rev->v, sizeof(int), rev->used, indxfp);
+ li += rev->used;
+ block *tem = rev;
+ rev = rev->next;
+ delete tem;
+ }
+ fwrite_or_die(&minus_one, sizeof(int), 1, indxfp);
+ li += 1;
+ }
+ }
+ if (sizeof(table_entry) == sizeof(int))
+ fwrite_or_die(hash_table, sizeof(int), hash_table_size, indxfp);
+ else {
+ // write it out word by word
+ for (int i = 0; i < hash_table_size; i++)
+ fwrite_or_die(&hash_table[i].count, sizeof(int), 1, indxfp);
+ }
+ fwrite_or_die(filenames.contents(), 1, filenames.length(), indxfp);
+ if (fseek(indxfp, 0, 0) < 0)
+ fatal("error seeking on index file: %1", strerror(errno));
+ index_header h;
+ h.magic = INDEX_MAGIC;
+ h.version = INDEX_VERSION;
+ h.tags_size = ntags;
+ h.lists_size = li;
+ h.table_size = hash_table_size;
+ h.strings_size = filenames.length();
+ h.truncate = truncate_len;
+ h.shortest = shortest_len;
+ h.common = n_ignore_words;
+ fwrite_or_die(&h, sizeof(h), 1, indxfp);
+}
+
+static void fwrite_or_die(const void *ptr, int size, int nitems, FILE *fp)
+{
+ if (fwrite(ptr, size, nitems, fp) != nitems)
+ fatal("fwrite failed: %1", strerror(errno));
+}
+
+void fatal_error_exit()
+{
+ cleanup();
+ exit(3);
+}
+
+extern "C" {
+
+void cleanup()
+{
+ if (temp_index_file)
+ unlink(temp_index_file);
+}
+
+}
diff --git a/src/utils/indxbib/indxbib.man b/src/utils/indxbib/indxbib.man
new file mode 100644
index 00000000..914cb698
--- /dev/null
+++ b/src/utils/indxbib/indxbib.man
@@ -0,0 +1,204 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.TH @G@INDXBIB @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+@g@indxbib \- make inverted index for bibliographic databases
+.SH SYNOPSIS
+.nr a \n(.j
+.ad l
+.nr i \n(.i
+.in +\w'\fB@g@indxbib 'u
+.ti \niu
+.B @g@indxbib
+.de OP
+.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
+.el .RB "[\ " "\\$1" "\ ]"
+..
+.OP \-vw
+.OP \-c file
+.OP \-d dir
+.OP \-f file
+.OP \-h n
+.OP \-i string
+.OP \-k n
+.OP \-l n
+.OP \-n n
+.OP \-o file
+.OP \-t n
+.RI [\ filename \|.\|.\|.\ ]
+.ad \na
+.SH DESCRIPTION
+.B @g@indxbib
+makes an inverted index for the bibliographic databases in
+.IR filename \|.\|.\|.
+for use with
+.BR @g@refer (@MAN1EXT@),
+.BR @g@lookbib (@MAN1EXT@),
+and
+.BR lkbib (@MAN1EXT@).
+The index will be named
+.IB filename @INDEX_SUFFIX@\fR;
+the index is written to a temporary file which is then renamed to this.
+If no filenames are given on the command line because the
+.B \-f
+option has been used, and no
+.B \-o
+option is given, the index will be named
+.BR @DEFAULT_INDEX_NAME@@INDEX_SUFFIX@ .
+.LP
+Bibliographic databases are divided into records by blank lines.
+Within a record, each fields starts with a
+.B %
+character at the beginning of a line.
+Fields have a one letter name which follows the
+.B %
+character.
+.LP
+The values set by the
+.BR \-c ,
+.BR \-n ,
+.BR \-l
+and
+.B \-t
+options are stored in the index;
+when the index is searched, keys will be discarded and truncated in a
+manner appropriate to these options;
+the original keys will be used for verifying that any record
+found using the index actually contains the keys.
+This means that a user of an index need not know whether these
+options were used in the creation of the index,
+provided that not all the keys to be searched for
+would have been discarded during indexing
+and that the user supplies at least the part of each key
+that would have remained after being truncated during indexing.
+The value set by the
+.B \-i
+option is also stored in the index
+and will be used in verifying records found using the index.
+.SH OPTIONS
+.TP
+.B \-v
+Print the version number.
+.TP
+.B \-w
+Index whole files.
+Each file is a separate record.
+.TP
+.BI \-c file
+Read the list of common words from
+.I file
+instead of
+.BR @COMMON_WORDS_FILE@ .
+.TP
+.BI \-d dir
+Use
+.I dir
+as the pathname of the current working directory to store in the index,
+instead of the path printed by
+.BR pwd (1).
+Usually
+.I dir
+will be a symbolic link that points to the directory printed by
+.BR pwd (1).
+.TP
+.BI \-f file
+Read the files to be indexed from
+.IR file .
+If
+.I file
+is
+.BR \- ,
+files will be read from the standard input.
+The
+.B \-f
+option can be given at most once.
+.TP
+.BI \-i string
+Don't index the contents of fields whose names are in
+.IR string .
+Initially
+.I string
+is
+.BR XYZ .
+.TP
+.BI \-h n
+Use the first prime greater than or equal to
+.I n
+for the size of the hash table.
+Larger values of
+.I n
+will usually make searching faster,
+but will make the index larger
+and
+.B @g@indxbib
+use more memory.
+Initially
+.I n
+is 997.
+.TP
+.BI \-k n
+Use at most
+.I n
+keys per input record.
+Initially
+.I n
+is 100.
+.TP
+.BI \-l n
+Discard keys that are shorter than
+.IR n .
+Initially
+.I n
+is 3.
+.TP
+.BI \-n n
+Discard the
+.I n
+most common words.
+Initially
+.I n
+is 100.
+.TP
+.BI \-o basename
+The index should be named
+.IB basename @INDEX_SUFFIX@\fR.
+.TP
+.BI \-t n
+Truncate keys to
+.IR n .
+Initially
+.I n
+is 6.
+.SH FILES
+.TP \w'\fBindxbib\fIXXXXXX'u+2n
+.IB filename @INDEX_SUFFIX@
+Index.
+.TP
+.B @DEFAULT_INDEX_NAME@@INDEX_SUFFIX@
+Default index name.
+.TP
+.B @COMMON_WORDS_FILE@
+List of common words.
+.TP
+.BI indxbib XXXXXX
+Temporary file.
+.SH "SEE ALSO"
+.BR @g@refer (@MAN1EXT@),
+.BR lkbib (@MAN1EXT@),
+.BR @g@lookbib (@MAN1EXT@)
diff --git a/src/utils/indxbib/signal.c b/src/utils/indxbib/signal.c
new file mode 100644
index 00000000..8078472f
--- /dev/null
+++ b/src/utils/indxbib/signal.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Unfortunately vendors seem to have problems writing a <signal.h>
+that is correct for C++, so we implement all signal handling in C. */
+
+#include <sys/types.h>
+#include <signal.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifndef RETSIGTYPE
+#define RETSIGTYPE void
+#endif
+
+extern void cleanup();
+
+static RETSIGTYPE handle_fatal_signal(signum)
+ int signum;
+{
+ signal(signum, SIG_DFL);
+ cleanup();
+ kill(getpid(), signum);
+}
+
+void catch_fatal_signals()
+{
+#ifdef SIGHUP
+ signal(SIGHUP, handle_fatal_signal);
+#endif
+ signal(SIGINT, handle_fatal_signal);
+ signal(SIGTERM, handle_fatal_signal);
+}
+
+#ifndef HAVE_RENAME
+
+void ignore_fatal_signals()
+{
+#ifdef SIGHUP
+ signal(SIGHUP, SIG_IGN);
+#endif
+ signal(SIGINT, SIG_IGN);
+ signal(SIGTERM, SIG_IGN);
+}
+
+#endif /* not HAVE_RENAME */
diff --git a/src/utils/lkbib/Makefile.sub b/src/utils/lkbib/Makefile.sub
new file mode 100644
index 00000000..8f31e10f
--- /dev/null
+++ b/src/utils/lkbib/Makefile.sub
@@ -0,0 +1,6 @@
+PROG=lkbib
+MAN1=lkbib.n
+XLIBS=$(LIBBIB) $(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=lkbib.o
+CCSRCS=$(srcdir)/lkbib.cc
diff --git a/src/utils/lkbib/lkbib.cc b/src/utils/lkbib/lkbib.cc
new file mode 100644
index 00000000..cfd099a5
--- /dev/null
+++ b/src/utils/lkbib/lkbib.cc
@@ -0,0 +1,124 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+
+#include "defs.h"
+#include "refid.h"
+#include "search.h"
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-nv] [-p database] [-i XYZ] [-t N] keys ...\n",
+ program_name);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int search_default = 1;
+ search_list list;
+ int opt;
+ while ((opt = getopt(argc, argv, "nvVi:t:p:")) != EOF)
+ switch (opt) {
+ case 'V':
+ verify_flag = 1;
+ break;
+ case 'n':
+ search_default = 0;
+ break;
+ case 'i':
+ linear_ignore_fields = optarg;
+ break;
+ case 't':
+ {
+ char *ptr;
+ long n = strtol(optarg, &ptr, 10);
+ if (n == 0 && ptr == optarg) {
+ error("bad integer `%1' in `t' option", optarg);
+ break;
+ }
+ if (n < 1)
+ n = 1;
+ linear_truncate_len = int(n);
+ break;
+ }
+ case 'v':
+ {
+ extern const char *Version_string;
+ fprintf(stderr, "GNU lkbib version %s\n", Version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'p':
+ list.add_file(optarg);
+ break;
+ case '?':
+ usage();
+ default:
+ assert(0);
+ }
+ if (optind >= argc)
+ usage();
+ char *filename = getenv("REFER");
+ if (filename)
+ list.add_file(filename);
+ else if (search_default)
+ list.add_file(DEFAULT_INDEX, 1);
+ if (list.nfiles() == 0)
+ fatal("no databases");
+ int total_len = 0;
+ int i;
+ for (i = optind; i < argc; i++)
+ total_len += strlen(argv[i]);
+ total_len += argc - optind - 1 + 1; // for spaces and '\0'
+ char *buffer = new char[total_len];
+ char *ptr = buffer;
+ for (i = optind; i < argc; i++) {
+ if (i > optind)
+ *ptr++ = ' ';
+ strcpy(ptr, argv[i]);
+ ptr = strchr(ptr, '\0');
+ }
+ search_list_iterator iter(&list, buffer);
+ const char *start;
+ int len;
+ int count;
+ for (count = 0; iter.next(&start, &len); count++) {
+ if (fwrite(start, 1, len, stdout) != len)
+ fatal("write error on stdout: %1", strerror(errno));
+ // Can happen for last reference in file.
+ if (start[len - 1] != '\n')
+ putchar('\n');
+ putchar('\n');
+ }
+ return !count;
+}
diff --git a/src/utils/lkbib/lkbib.man b/src/utils/lkbib/lkbib.man
new file mode 100644
index 00000000..f16a77ec
--- /dev/null
+++ b/src/utils/lkbib/lkbib.man
@@ -0,0 +1,107 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.ds g \" empty
+.ds G \" empty
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.TH LKBIB @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+lkbib \- search bibliographic databases
+.SH SYNOPSIS
+.B lkbib
+[
+.B \-v
+]
+[
+.BI \-i fields
+]
+[
+.BI \-p filename
+]
+[
+.BI \-t n
+]
+.IR key \|.\|.\|.
+.SH DESCRIPTION
+.B lkbib
+searches bibliographic databases for references that contain the keys
+.IR key \|.\|.\|.
+and prints any references found on the standard output.
+.B lkbib
+will search any databases given by
+.B \-p
+options, and then a default database.
+The default database is taken from the
+.SB REFER
+environment variable if it is set,
+otherwise it is
+.BR @DEFAULT_INDEX@ .
+For each database
+.I filename
+to be searched,
+if an index
+.IB filename @INDEX_SUFFIX@
+created by
+.BR @g@indxbib (@MAN1EXT@)
+exists, then it will be searched instead;
+each index can cover multiple databases.
+.SH OPTIONS
+.TP
+.B \-v
+Print the version number.
+.TP
+.BI \-p filename
+Search
+.IR filename .
+Multiple
+.B \-p
+options can be used.
+.TP
+.BI \-i string
+When searching files for which no index exists,
+ignore the contents of fields whose names are in
+.IR string .
+.TP
+.BI \-t n
+Only require the first
+.I n
+characters of keys to be given.
+Initially
+.I n
+is 6.
+.SH ENVIRONMENT
+.TP \w'\fBREFER'u+2n
+.SB REFER
+Default database.
+.SH FILES
+.Tp \w'\fB@DEFAULT_INDEX@'u+2n
+.B @DEFAULT_INDEX@
+Default database to be used if the
+.SB REFER
+environment variable is not set.
+.IB filename @INDEX_SUFFIX@
+Index files.
+.SH "SEE ALSO"
+.BR @g@refer (@MAN1EXT@),
+.BR @g@lookbib (@MAN1EXT@),
+.BR @g@indxbib (@MAN1EXT@)
diff --git a/src/utils/lookbib/Makefile.sub b/src/utils/lookbib/Makefile.sub
new file mode 100644
index 00000000..91b14045
--- /dev/null
+++ b/src/utils/lookbib/Makefile.sub
@@ -0,0 +1,7 @@
+PROG=lookbib
+MAN1=lookbib.n
+XLIBS=$(LIBBIB) $(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=lookbib.o
+CCSRCS=$(srcdir)/lookbib.cc
+NAMEPREFIX=$(g)
diff --git a/src/utils/lookbib/lookbib.cc b/src/utils/lookbib/lookbib.cc
new file mode 100644
index 00000000..4240a47f
--- /dev/null
+++ b/src/utils/lookbib/lookbib.cc
@@ -0,0 +1,128 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "errarg.h"
+#include "error.h"
+#include "lib.h"
+#include "cset.h"
+
+#include "refid.h"
+#include "search.h"
+
+extern "C" {
+ int isatty(int);
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-v] [-i XYZ] [-t N] database ...\n",
+ program_name);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int opt;
+ while ((opt = getopt(argc, argv, "vVi:t:")) != EOF)
+ switch (opt) {
+ case 'V':
+ verify_flag = 1;
+ break;
+ case 'i':
+ linear_ignore_fields = optarg;
+ break;
+ case 't':
+ {
+ char *ptr;
+ long n = strtol(optarg, &ptr, 10);
+ if (n == 0 && ptr == optarg) {
+ error("bad integer `%1' in `t' option", optarg);
+ break;
+ }
+ if (n < 1)
+ n = 1;
+ linear_truncate_len = int(n);
+ break;
+ }
+ case 'v':
+ {
+ extern const char *Version_string;
+ fprintf(stderr, "GNU lookbib version %s\n", Version_string);
+ fflush(stderr);
+ break;
+ }
+ case '?':
+ usage();
+ default:
+ assert(0);
+ }
+ if (optind >= argc)
+ usage();
+ search_list list;
+ for (int i = optind; i < argc; i++)
+ list.add_file(argv[i]);
+ if (list.nfiles() == 0)
+ fatal("no databases");
+ char line[1024];
+ int interactive = isatty(fileno(stdin));
+ for (;;) {
+ if (interactive) {
+ fputs("> ", stderr);
+ fflush(stderr);
+ }
+ if (!fgets(line, sizeof(line), stdin))
+ break;
+ char *ptr = line;
+ while (csspace(*ptr))
+ ptr++;
+ if (*ptr == '\0')
+ continue;
+ search_list_iterator iter(&list, line);
+ const char *start;
+ int len;
+ int count;
+ for (count = 0; iter.next(&start, &len); count++) {
+ if (fwrite(start, 1, len, stdout) != len)
+ fatal("write error on stdout: %1", strerror(errno));
+ // Can happen for last reference in file.
+ if (start[len - 1] != '\n')
+ putchar('\n');
+ putchar('\n');
+ }
+ fflush(stdout);
+ if (interactive) {
+ fprintf(stderr, "%d found\n", count);
+ fflush(stderr);
+ }
+ }
+ if (interactive)
+ putc('\n', stderr);
+ return 0;
+}
+
diff --git a/src/utils/lookbib/lookbib.man b/src/utils/lookbib/lookbib.man
new file mode 100644
index 00000000..465990ba
--- /dev/null
+++ b/src/utils/lookbib/lookbib.man
@@ -0,0 +1,75 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.TH @G@LOOKBIB @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+@g@lookbib \- search bibliographic databases
+.SH SYNOPSIS
+.B @g@lookbib
+[
+.B \-v
+]
+[
+.BI \-i string
+]
+[
+.BI \-t n
+]
+.IR filename \|.\|.\|.
+.SH DESCRIPTION
+@g@lookbib prints a prompt on the standard error (unless the standard input is not a terminal),
+reads from the standard input a line containing a set of keywords,
+searches the bibliographic databases
+.IR filename \|.\|.\|.
+for references containing those keywords,
+prints any references found on the standard output,
+and repeats this process until the end of input.
+For each database
+.I filename
+to be searched,
+if an index
+.IB filename @INDEX_SUFFIX@
+created by
+.BR @g@indxbib (@MAN1EXT@)
+exists, then it will be searched instead;
+each index can cover multiple databases.
+.SH OPTIONS
+.TP
+.B \-v
+Print the version number.
+.TP
+.BI \-i string
+When searching files for which no index exists,
+ignore the contents of fields whose names are in
+.IR string .
+.TP
+.BI \-t n
+Only require the first
+.I n
+characters of keys to be given.
+Initially
+.I n
+is 6.
+.SH FILES
+.TP \w'\fIfilename\fB@INDEX_SUFFIX@'u+2n
+.IB filename @INDEX_SUFFIX@
+Index files.
+.SH "SEE ALSO"
+.BR @g@refer (@MAN1EXT@),
+.BR lkbib (@MAN1EXT@),
+.BR @g@indxbib (@MAN1EXT@)
diff --git a/src/utils/pfbtops/Makefile.sub b/src/utils/pfbtops/Makefile.sub
new file mode 100644
index 00000000..f731ff57
--- /dev/null
+++ b/src/utils/pfbtops/Makefile.sub
@@ -0,0 +1,6 @@
+PROG=pfbtops
+MAN1=pfbtops.n
+OBJS=pfbtops.o
+CSRCS=$(srcdir)/pfbtops.c
+XLIBS=$(LIBGROFF)
+MLIB=$(LIBM)
diff --git a/src/utils/pfbtops/pfbtops.c b/src/utils/pfbtops/pfbtops.c
new file mode 100644
index 00000000..46b882f5
--- /dev/null
+++ b/src/utils/pfbtops/pfbtops.c
@@ -0,0 +1,112 @@
+/* This translates ps fonts in .pfb format to ASCII ps files. */
+
+#include <stdio.h>
+
+/* Binary bytes per output line. */
+#define BYTES_PER_LINE (64/2)
+#define HEX_DIGITS "0123456789abcdef"
+
+static char *program_name;
+
+static void error(s)
+ char *s;
+{
+ fprintf(stderr, "%s: %s\n", program_name, s);
+ exit(2);
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-v] [pfb_file]\n", program_name);
+ exit(1);
+}
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int opt;
+ extern int optind;
+
+ program_name = argv[0];
+
+ while ((opt = getopt(argc, argv, "v")) != EOF) {
+ switch (opt) {
+ case 'v':
+ {
+ extern char *Version_string;
+ fprintf(stderr, "pfbtops groff version %s\n", Version_string);
+ fflush(stderr);
+ break;
+ }
+ case '?':
+ usage();
+ }
+ }
+
+ if (argc - optind > 1)
+ usage();
+ if (argc > optind && !freopen(argv[optind], "r", stdin))
+ {
+ perror(argv[optind]);
+ exit(1);
+ }
+ for (;;)
+ {
+ int type, c, i;
+ long n;
+
+ c = getchar();
+ if (c != 0x80)
+ error("first byte of packet not 0x80");
+ type = getchar();
+ if (type == 3)
+ break;
+ if (type != 1 && type != 2)
+ error("bad packet type");
+ n = 0;
+ for (i = 0; i < 4; i++)
+ {
+ c = getchar();
+ if (c == EOF)
+ error("end of file in packet header");
+ n |= (long)c << (i << 3);
+ }
+ if (n < 0)
+ error("negative packet length");
+ if (type == 1)
+ {
+ while (--n >= 0)
+ {
+ c = getchar();
+ if (c == EOF)
+ error("end of file in text packet");
+ if (c == '\r')
+ c = '\n';
+ putchar(c);
+ }
+ if (c != '\n')
+ putchar('\n');
+ }
+ else
+ {
+ int count = 0;
+ while (--n >= 0)
+ {
+ c = getchar();
+ if (c == EOF)
+ error("end of file in binary packet");
+ if (count >= BYTES_PER_LINE)
+ {
+ putchar('\n');
+ count = 0;
+ }
+ count++;
+ putchar(HEX_DIGITS[(c >> 4) & 0xf]);
+ putchar(HEX_DIGITS[c & 0xf]);
+ }
+ putchar('\n');
+ }
+ }
+ exit(0);
+}
diff --git a/src/utils/pfbtops/pfbtops.man b/src/utils/pfbtops/pfbtops.man
new file mode 100644
index 00000000..cfef3e0a
--- /dev/null
+++ b/src/utils/pfbtops/pfbtops.man
@@ -0,0 +1,44 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.TH PFBTOPS @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+pfbtops \- translate a PostScript font in .pfb format to ASCII
+.SH SYNOPSIS
+.B pfbtops
+[
+.I pfb_file
+]
+.SH DESCRIPTION
+.B pfbtops
+translates a PostScript font in
+.B .pfb
+format to ASCII.
+If
+.I pfb_file
+is omitted the pfb file will be read from the standard input.
+The ASCII format PostScript font will be written on the standard output.
+PostScript fonts for MS-DOS are normally supplied in
+.B .pfb
+format.
+.LP
+The resulting ASCII format PostScript font can be used with groff.
+It must first be listed in
+.BR @FONTDIR@/devps/download .
+.SH "SEE ALSO"
+.BR grops (@MAN1EXT@)
diff --git a/src/utils/tfmtodit/Makefile.sub b/src/utils/tfmtodit/Makefile.sub
new file mode 100644
index 00000000..057bb3e6
--- /dev/null
+++ b/src/utils/tfmtodit/Makefile.sub
@@ -0,0 +1,6 @@
+PROG=tfmtodit
+MAN1=tfmtodit.n
+XLIBS=$(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=tfmtodit.o
+CCSRCS=$(srcdir)/tfmtodit.cc
diff --git a/src/utils/tfmtodit/tfmtodit.cc b/src/utils/tfmtodit/tfmtodit.cc
new file mode 100644
index 00000000..16752742
--- /dev/null
+++ b/src/utils/tfmtodit/tfmtodit.cc
@@ -0,0 +1,851 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* I have tried to incorporate the changes needed for TeX 3.0 tfm files,
+but I haven't tested them. */
+
+/* Groff requires more font metric information than TeX. The reason
+for this is that TeX has separate Math Italic fonts, whereas groff
+uses normal italic fonts for math. The two additional pieces of
+information required by groff correspond to the two arguments to the
+math_fit() macro in the Metafont programs for the CM fonts. In the
+case of a font for which math_fitting is false, these two arguments
+are normally ignored by Metafont. We need to get hold of these two
+parameters and put them in the groff font file.
+
+We do this by loading this definition after cmbase when creating cm.base.
+
+def ignore_math_fit(expr left_adjustment,right_adjustment) =
+ special "adjustment";
+ numspecial left_adjustment*16/designsize;
+ numspecial right_adjustment*16/designsize;
+ enddef;
+
+This puts the two arguments to the math_fit macro into the gf file.
+(They will appear in the gf file immediately before the character to
+which they apply.) We then create a gf file using this cm.base. Then
+we run tfmtodit and specify this gf file with the -g option.
+
+This need only be done for a font for which math_fitting is false;
+When it's true, the left_correction and subscript_correction should
+both be zero. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <errno.h>
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+#include "assert.h"
+#include "cset.h"
+
+/* Values in the tfm file should be multiplied by this. */
+
+#define MULTIPLIER 1
+
+struct char_info_word {
+ unsigned char width_index;
+ char height_index;
+ char depth_index;
+ char italic_index;
+ char tag;
+ unsigned char remainder;
+};
+
+struct lig_kern_command {
+ unsigned char skip_byte;
+ unsigned char next_char;
+ unsigned char op_byte;
+ unsigned char remainder;
+};
+
+class tfm {
+ int bc;
+ int ec;
+ int nw;
+ int nh;
+ int nd;
+ int ni;
+ int nl;
+ int nk;
+ int np;
+ int cs;
+ int ds;
+ char_info_word *char_info;
+ int *width;
+ int *height;
+ int *depth;
+ int *italic;
+ lig_kern_command *lig_kern;
+ int *kern;
+ int *param;
+public:
+ tfm();
+ ~tfm();
+ int load(const char *);
+ int contains(int);
+ int get_width(int);
+ int get_height(int);
+ int get_depth(int);
+ int get_italic(int);
+ int get_param(int, int *);
+ int get_checksum();
+ int get_design_size();
+ int get_lig(unsigned char, unsigned char, unsigned char *);
+ friend class kern_iterator;
+};
+
+class kern_iterator {
+ tfm *t;
+ int c;
+ int i;
+public:
+ kern_iterator(tfm *);
+ int next(unsigned char *c1, unsigned char *c2, int *k);
+};
+
+
+kern_iterator::kern_iterator(tfm *p)
+: t(p), c(t->bc), i(-1)
+{
+}
+
+int kern_iterator::next(unsigned char *c1, unsigned char *c2, int *k)
+{
+ for (; c <= t->ec; c++)
+ if (t->char_info[c - t->bc].tag == 1) {
+ if (i < 0) {
+ i = t->char_info[c - t->bc].remainder;
+ if (t->lig_kern[i].skip_byte > 128)
+ i = (256*t->lig_kern[i].op_byte
+ + t->lig_kern[i].remainder);
+ }
+ for (;;) {
+ int skip = t->lig_kern[i].skip_byte;
+ if (skip <= 128 && t->lig_kern[i].op_byte >= 128) {
+ *c1 = c;
+ *c2 = t->lig_kern[i].next_char;
+ *k = t->kern[256*(t->lig_kern[i].op_byte - 128)
+ + t->lig_kern[i].remainder];
+ if (skip == 128) {
+ c++;
+ i = -1;
+ }
+ else
+ i += skip + 1;
+ return 1;
+ }
+ if (skip >= 128)
+ break;
+ i += skip + 1;
+ }
+ i = -1;
+ }
+ return 0;
+}
+
+tfm::tfm()
+: char_info(0), width(0), height(0), depth(0), italic(0), lig_kern(0),
+ kern(0), param(0)
+{
+}
+
+int tfm::get_lig(unsigned char c1, unsigned char c2, unsigned char *cp)
+{
+ if (contains(c1) && char_info[c1 - bc].tag == 1) {
+ int i = char_info[c1 - bc].remainder;
+ if (lig_kern[i].skip_byte > 128)
+ i = 256*lig_kern[i].op_byte + lig_kern[i].remainder;
+ for (;;) {
+ int skip = lig_kern[i].skip_byte;
+ if (skip > 128)
+ break;
+ // We are only interested in normal ligatures, for which
+ // op_byte == 0.
+ if (lig_kern[i].op_byte == 0
+ && lig_kern[i].next_char == c2) {
+ *cp = lig_kern[i].remainder;
+ return 1;
+ }
+ if (skip == 128)
+ break;
+ i += skip + 1;
+ }
+ }
+ return 0;
+}
+
+int tfm::contains(int i)
+{
+ return i >= bc && i <= ec && char_info[i - bc].width_index != 0;
+}
+
+int tfm::get_width(int i)
+{
+ return width[char_info[i - bc].width_index];
+}
+
+int tfm::get_height(int i)
+{
+ return height[char_info[i - bc].height_index];
+}
+
+int tfm::get_depth(int i)
+{
+ return depth[char_info[i - bc].depth_index];
+}
+
+int tfm::get_italic(int i)
+{
+ return italic[char_info[i - bc].italic_index];
+}
+
+int tfm::get_param(int i, int *p)
+{
+ if (i <= 0 || i > np)
+ return 0;
+ else {
+ *p = param[i - 1];
+ return 1;
+ }
+}
+
+int tfm::get_checksum()
+{
+ return cs;
+}
+
+int tfm::get_design_size()
+{
+ return ds;
+}
+
+tfm::~tfm()
+{
+ a_delete char_info;
+ a_delete width;
+ a_delete height;
+ a_delete depth;
+ a_delete italic;
+ a_delete lig_kern;
+ a_delete kern;
+ a_delete param;
+}
+
+int read2(unsigned char *&s)
+{
+ int n;
+ n = *s++ << 8;
+ n |= *s++;
+ return n;
+}
+
+int read4(unsigned char *&s)
+{
+ int n;
+ n = *s++ << 24;
+ n |= *s++ << 16;
+ n |= *s++ << 8;
+ n |= *s++;
+ return n;
+}
+
+
+int tfm::load(const char *file)
+{
+ errno = 0;
+ FILE *fp = fopen(file, "r");
+ if (!fp) {
+ error("can't open `%1': %2", file, strerror(errno));
+ return 0;
+ }
+ int c1 = getc(fp);
+ int c2 = getc(fp);
+ if (c1 == EOF || c2 == EOF) {
+ fclose(fp);
+ error("unexpected end of file on `%1'", file);
+ return 0;
+ }
+ int lf = (c1 << 8) + c2;
+ int toread = lf*4 - 2;
+ unsigned char *buf = new unsigned char[toread];
+ if (fread(buf, 1, toread, fp) != toread) {
+ if (feof(fp))
+ error("unexpected end of file on `%1'", file);
+ else
+ error("error on file `%1'", file);
+ a_delete buf;
+ fclose(fp);
+ return 0;
+ }
+ fclose(fp);
+ if (lf < 6) {
+ error("bad tfm file `%1': impossibly short", file);
+ a_delete buf;
+ return 0;
+ }
+ unsigned char *ptr = buf;
+ int lh = read2(ptr);
+ bc = read2(ptr);
+ ec = read2(ptr);
+ nw = read2(ptr);
+ nh = read2(ptr);
+ nd = read2(ptr);
+ ni = read2(ptr);
+ nl = read2(ptr);
+ nk = read2(ptr);
+ int ne = read2(ptr);
+ np = read2(ptr);
+ if (6 + lh + (ec - bc + 1) + nw + nh + nd + ni + nl + nk + ne + np != lf) {
+ error("bad tfm file `%1': lengths do not sum", file);
+ a_delete buf;
+ return 0;
+ }
+ if (lh < 2) {
+ error("bad tfm file `%1': header too short", file);
+ a_delete buf;
+ return 0;
+ }
+ char_info = new char_info_word[ec - bc + 1];
+ width = new int[nw];
+ height = new int[nh];
+ depth = new int[nd];
+ italic = new int[ni];
+ lig_kern = new lig_kern_command[nl];
+ kern = new int[nk];
+ param = new int[np];
+ int i;
+ cs = read4(ptr);
+ ds = read4(ptr);
+ ptr += (lh-2)*4;
+ for (i = 0; i < ec - bc + 1; i++) {
+ char_info[i].width_index = *ptr++;
+ unsigned char tem = *ptr++;
+ char_info[i].depth_index = tem & 0xf;
+ char_info[i].height_index = tem >> 4;
+ tem = *ptr++;
+ char_info[i].italic_index = tem >> 2;
+ char_info[i].tag = tem & 3;
+ char_info[i].remainder = *ptr++;
+ }
+ for (i = 0; i < nw; i++)
+ width[i] = read4(ptr);
+ for (i = 0; i < nh; i++)
+ height[i] = read4(ptr);
+ for (i = 0; i < nd; i++)
+ depth[i] = read4(ptr);
+ for (i = 0; i < ni; i++)
+ italic[i] = read4(ptr);
+ for (i = 0; i < nl; i++) {
+ lig_kern[i].skip_byte = *ptr++;
+ lig_kern[i].next_char = *ptr++;
+ lig_kern[i].op_byte = *ptr++;
+ lig_kern[i].remainder = *ptr++;
+ }
+ for (i = 0; i < nk; i++)
+ kern[i] = read4(ptr);
+ ptr += ne*4;
+ for (i = 0; i < np; i++)
+ param[i] = read4(ptr);
+ assert(ptr == buf + lf*4 - 2);
+ a_delete buf;
+ return 1;
+}
+
+class gf {
+ int left[256];
+ int right[256];
+ static int sread4(int *p, FILE *fp);
+ static int uread3(int *p, FILE *fp);
+ static int uread2(int *p, FILE *fp);
+ static int skip(int n, FILE *fp);
+public:
+ gf();
+ int load(const char *file);
+ int get_left_adjustment(int i) { return left[i]; }
+ int get_right_adjustment(int i) { return right[i]; }
+};
+
+gf::gf()
+{
+ for (int i = 0; i < 256; i++)
+ left[i] = right[i] = 0;
+}
+
+int gf::load(const char *file)
+{
+ enum {
+ paint_0 = 0,
+ paint1 = 64,
+ boc = 67,
+ boc1 = 68,
+ eoc = 69,
+ skip0 = 70,
+ skip1 = 71,
+ new_row_0 = 74,
+ xxx1 = 239,
+ yyy = 243,
+ no_op = 244,
+ pre = 247,
+ post = 248
+ };
+ int got_an_adjustment = 0;
+ int pending_adjustment = 0;
+ int left_adj, right_adj;
+ const int gf_id_byte = 131;
+ errno = 0;
+ FILE *fp = fopen(file, "r");
+ if (!fp) {
+ error("can't open `%1': %2", file, strerror(errno));
+ return 0;
+ }
+ if (getc(fp) != pre || getc(fp) != gf_id_byte) {
+ error("bad gf file");
+ return 0;
+ }
+ int n = getc(fp);
+ if (n == EOF)
+ goto eof;
+ if (!skip(n, fp))
+ goto eof;
+ for (;;) {
+ int op = getc(fp);
+ if (op == EOF)
+ goto eof;
+ if (op == post)
+ break;
+ if ((op >= paint_0 && op <= paint_0 + 63)
+ || (op >= new_row_0 && op <= new_row_0 + 164))
+ continue;
+ switch (op) {
+ case no_op:
+ case eoc:
+ case skip0:
+ break;
+ case paint1:
+ case skip1:
+ if (!skip(1, fp))
+ goto eof;
+ break;
+ case paint1 + 1:
+ case skip1 + 1:
+ if (!skip(2, fp))
+ goto eof;
+ break;
+ case paint1 + 2:
+ case skip1 + 2:
+ if (!skip(3, fp))
+ goto eof;
+ break;
+ case boc:
+ {
+ int code;
+ if (!sread4(&code, fp))
+ goto eof;
+ if (pending_adjustment) {
+ pending_adjustment = 0;
+ left[code & 0377] = left_adj;
+ right[code & 0377] = right_adj;
+ }
+ if (!skip(20, fp))
+ goto eof;
+ break;
+ }
+ case boc1:
+ {
+ int code = getc(fp);
+ if (code == EOF)
+ goto eof;
+ if (pending_adjustment) {
+ pending_adjustment = 0;
+ left[code] = left_adj;
+ right[code] = right_adj;
+ }
+ if (!skip(4, fp))
+ goto eof;
+ break;
+ }
+ case xxx1:
+ {
+ int len = getc(fp);
+ if (len == EOF)
+ goto eof;
+ char buf[256];
+ if (fread(buf, 1, len, fp) != len)
+ goto eof;
+ if (len == 10 /* strlen("adjustment") */
+ && memcmp(buf, "adjustment", len) == 0) {
+ int c = getc(fp);
+ if (c != yyy) {
+ if (c != EOF)
+ ungetc(c, fp);
+ break;
+ }
+ if (!sread4(&left_adj, fp))
+ goto eof;
+ c = getc(fp);
+ if (c != yyy) {
+ if (c != EOF)
+ ungetc(c, fp);
+ break;
+ }
+ if (!sread4(&right_adj, fp))
+ goto eof;
+ got_an_adjustment = 1;
+ pending_adjustment = 1;
+ }
+ break;
+ }
+ case xxx1 + 1:
+ if (!uread2(&n, fp) || !skip(n, fp))
+ goto eof;
+ break;
+ case xxx1 + 2:
+ if (!uread3(&n, fp) || !skip(n, fp))
+ goto eof;
+ break;
+ case xxx1 + 3:
+ if (!sread4(&n, fp) || !skip(n, fp))
+ goto eof;
+ break;
+ case yyy:
+ if (!skip(4, fp))
+ goto eof;
+ break;
+ default:
+ fatal("unrecognized opcode `%1'", op);
+ break;
+ }
+ }
+ if (!got_an_adjustment)
+ warning("no adjustment specials found in gf file");
+ return 1;
+ eof:
+ error("unexpected end of file");
+ return 0;
+}
+
+int gf::sread4(int *p, FILE *fp)
+{
+ *p = getc(fp);
+ if (*p >= 128)
+ *p -= 256;
+ *p <<= 8;
+ *p |= getc(fp);
+ *p <<= 8;
+ *p |= getc(fp);
+ *p <<= 8;
+ *p |= getc(fp);
+ return !ferror(fp) && !feof(fp);
+}
+
+int gf::uread3(int *p, FILE *fp)
+{
+ *p = getc(fp);
+ *p <<= 8;
+ *p |= getc(fp);
+ *p <<= 8;
+ *p |= getc(fp);
+ return !ferror(fp) && !feof(fp);
+}
+
+int gf::uread2(int *p, FILE *fp)
+{
+ *p = getc(fp);
+ *p <<= 8;
+ *p |= getc(fp);
+ return !ferror(fp) && !feof(fp);
+}
+
+int gf::skip(int n, FILE *fp)
+{
+ while (--n >= 0)
+ if (getc(fp) == EOF)
+ return 0;
+ return 1;
+}
+
+
+struct char_list {
+ char *ch;
+ char_list *next;
+ char_list(const char *, char_list * = 0);
+};
+
+char_list::char_list(const char *s, char_list *p) : ch(strsave(s)), next(p)
+{
+}
+
+
+int read_map(const char *file, char_list **table)
+{
+ errno = 0;
+ FILE *fp = fopen(file, "r");
+ if (!fp) {
+ error("can't open `%1': %2", file, strerror(errno));
+ return 0;
+ }
+ for (int i = 0; i < 256; i++)
+ table[i] = 0;
+ char buf[512];
+ int lineno = 0;
+ while (fgets(buf, int(sizeof(buf)), fp)) {
+ lineno++;
+ char *ptr = buf;
+ while (csspace(*ptr))
+ ptr++;
+ if (*ptr == '\0' || *ptr == '#')
+ continue;
+ ptr = strtok(ptr, " \n\t");
+ if (!ptr)
+ continue;
+ int n;
+ if (sscanf(ptr, "%d", &n) != 1) {
+ error("%1:%2: bad map file", file, lineno);
+ fclose(fp);
+ return 0;
+ }
+ if (n < 0 || n > 255) {
+ error("%1:%2: code out of range", file, lineno);
+ fclose(fp);
+ return 0;
+ }
+ ptr = strtok(0, " \n\t");
+ if (!ptr) {
+ error("%1:%2: missing names", file, lineno);
+ fclose(fp);
+ return 0;
+ }
+ for (; ptr; ptr = strtok(0, " \n\t"))
+ table[n] = new char_list(ptr, table[n]);
+ }
+ fclose(fp);
+ return 1;
+}
+
+
+/* Every character that can participate in a ligature appears in the
+lig_chars table. `ch' gives the full-name of the character, `name'
+gives the groff name of the character, `i' gives its index in
+the encoding, which is filled in later (-1 if it does not appear). */
+
+struct {
+ const char *ch;
+ int i;
+} lig_chars[] = {
+ { "f", -1 },
+ { "i", -1 },
+ { "l", -1 },
+ { "ff", -1 },
+ { "fi", -1 },
+ { "fl", -1 },
+ { "Fi", -1 },
+ { "Fl", -1 },
+};
+
+// Indices into lig_chars[].
+
+enum { CH_f, CH_i, CH_l, CH_ff, CH_fi, CH_fl, CH_ffi, CH_ffl };
+
+// Each possible ligature appears in this table.
+
+struct {
+ unsigned char c1, c2, res;
+ const char *ch;
+} lig_table[] = {
+ { CH_f, CH_f, CH_ff, "ff" },
+ { CH_f, CH_i, CH_fi, "fi" },
+ { CH_f, CH_l, CH_fl, "fl" },
+ { CH_ff, CH_i, CH_ffi, "ffi" },
+ { CH_ff, CH_l, CH_ffl, "ffl" },
+ };
+
+static void usage();
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ int special_flag = 0;
+ int skewchar = -1;
+ int opt;
+ const char *gf_file = 0;
+ while ((opt = getopt(argc, argv, "svg:k:")) != EOF)
+ switch (opt) {
+ case 'g':
+ gf_file = optarg;
+ break;
+ case 's':
+ special_flag = 1;
+ break;
+ case 'k':
+ {
+ char *ptr;
+ long n = strtol(optarg, &ptr, 0);
+ if ((n == 0 && ptr == optarg)
+ || *ptr != '\0'
+ || n < 0
+ || n > UCHAR_MAX)
+ error("invalid skewchar");
+ else
+ skewchar = (int)n;
+ break;
+ }
+ case 'v':
+ {
+ extern const char *Version_string;
+ fprintf(stderr, "tfmtodit version %s\n", Version_string);
+ fflush(stderr);
+ break;
+ }
+ case '?':
+ usage();
+ break;
+ case EOF:
+ assert(0);
+ }
+ if (argc - optind != 3)
+ usage();
+ gf g;
+ if (gf_file) {
+ if (!g.load(gf_file))
+ return 1;
+ }
+ const char *tfm_file = argv[optind];
+ const char *map_file = argv[optind + 1];
+ const char *font_file = argv[optind + 2];
+ tfm t;
+ if (!t.load(tfm_file))
+ return 1;
+ char_list *table[256];
+ if (!read_map(map_file, table))
+ return 1;
+ errno = 0;
+ if (!freopen(font_file, "w", stdout)) {
+ error("can't open `%1' for writing: %2", font_file, strerror(errno));
+ return 1;
+ }
+ printf("name %s\n", font_file);
+ if (special_flag)
+ fputs("special\n", stdout);
+ char *internal_name = strsave(argv[optind]);
+ int len = strlen(internal_name);
+ if (len > 4 && strcmp(internal_name + len - 4, ".tfm") == 0)
+ internal_name[len - 4] = '\0';
+ char *s = strrchr(internal_name, '/');
+ printf("internalname %s\n", s ? s + 1 : internal_name);
+ int n;
+ if (t.get_param(2, &n)) {
+ if (n > 0)
+ printf("spacewidth %d\n", n*MULTIPLIER);
+ }
+ if (t.get_param(1, &n) && n != 0)
+ printf("slant %f\n", atan2(n/double(1<<20), 1.0)*180.0/PI);
+ int xheight;
+ if (!t.get_param(5, &xheight))
+ xheight = 0;
+ int i;
+ // Print the list of ligatures.
+ // First find the indices of each character that can participate in
+ // a ligature.
+ for (i = 0; i < 256; i++)
+ for (int j = 0; j < sizeof(lig_chars)/sizeof(lig_chars[0]); j++)
+ for (char_list *p = table[i]; p; p = p->next)
+ if (strcmp(lig_chars[j].ch, p->ch) == 0)
+ lig_chars[j].i = i;
+ // For each possible ligature, if its participants all exist,
+ // and it appears as a ligature in the tfm file, include in
+ // the list of ligatures.
+ int started = 0;
+ for (i = 0; i < sizeof(lig_table)/sizeof(lig_table[0]); i++) {
+ int i1 = lig_chars[lig_table[i].c1].i;
+ int i2 = lig_chars[lig_table[i].c2].i;
+ int r = lig_chars[lig_table[i].res].i;
+ if (i1 >= 0 && i2 >= 0 && r >= 0) {
+ unsigned char c;
+ if (t.get_lig(i1, i2, &c) && c == r) {
+ if (!started) {
+ started = 1;
+ fputs("ligatures", stdout);
+ }
+ printf(" %s", lig_table[i].ch);
+ }
+ }
+ }
+ if (started)
+ fputs(" 0\n", stdout);
+ printf("checksum %d\n", t.get_checksum());
+ printf("designsize %d\n", t.get_design_size());
+ // Now print out the kerning information.
+ int had_kern = 0;
+ kern_iterator iter(&t);
+ unsigned char c1, c2;
+ int k;
+ while (iter.next(&c1, &c2, &k))
+ if (c2 != skewchar) {
+ k *= MULTIPLIER;
+ char_list *q = table[c2];
+ for (char_list *p1 = table[c1]; p1; p1 = p1->next)
+ for (char_list *p2 = q; p2; p2 = p2->next) {
+ if (!had_kern) {
+ printf("kernpairs\n");
+ had_kern = 1;
+ }
+ printf("%s %s %d\n", p1->ch, p2->ch, k);
+ }
+ }
+ printf("charset\n");
+ char_list unnamed("---");
+ for (i = 0; i < 256; i++)
+ if (t.contains(i)) {
+ char_list *p = table[i] ? table[i] : &unnamed;
+ int m[6];
+ m[0] = t.get_width(i);
+ m[1] = t.get_height(i);
+ m[2] = t.get_depth(i);
+ m[3] = t.get_italic(i);
+ m[4] = g.get_left_adjustment(i);
+ m[5] = g.get_right_adjustment(i);
+ printf("%s\t%d", p->ch, m[0]*MULTIPLIER);
+ int j;
+ for (j = int(sizeof(m)/sizeof(m[0])) - 1; j > 0; j--)
+ if (m[j] != 0)
+ break;
+ for (k = 1; k <= j; k++)
+ printf(",%d", m[k]*MULTIPLIER);
+ int type = 0;
+ if (m[2] > 0)
+ type = 1;
+ if (m[1] > xheight)
+ type += 2;
+ printf("\t%d\t%04o\n", type, i);
+ for (p = p->next; p; p = p->next)
+ printf("%s\t\"\n", p->ch);
+ }
+ return 0;
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-sv] [-g gf_file] [-k skewchar] tfm_file map_file font\n",
+ program_name);
+ exit(1);
+}
diff --git a/src/utils/tfmtodit/tfmtodit.man b/src/utils/tfmtodit/tfmtodit.man
new file mode 100644
index 00000000..f17c4414
--- /dev/null
+++ b/src/utils/tfmtodit/tfmtodit.man
@@ -0,0 +1,167 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X
+.el .ds tx TeX
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.TH TFMTODIT @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+tfmtodit \- create font files for use with groff \-Tdvi
+.SH SYNOPSIS
+.B tfmtodit
+[
+.B \-sv
+]
+[
+.BI \-g gf_file
+]
+[
+.BI \-k skewchar
+]
+.I tfm_file
+.I map_file
+.I font
+.SH DESCRIPTION
+.B tfmtodit
+creates a font file for use with
+.B
+groff \-Tdvi\fR.
+.I tfm_file
+is the name of the \*(tx font metric file for the font.
+.I map_file
+is a file giving the groff names for characters in the font;
+this file should consist of a sequence of lines of the form:
+.IP
+.I
+n c1 c2 \fR.\|.\|.
+.LP
+where
+.I n
+is a decimal integer giving the position of the character in the font,
+and
+.IR c1 ,
+.IR c2 ,.\|.\|.
+are the groff names of the character.
+If a character has no groff names but exists in the tfm file,
+then it will be put in the groff font file as an unnamed character.
+.I font
+is the name of the groff font file.
+The groff font file is written to
+.IR font .
+.LP
+The
+.B \-s
+option should be given if the font is special
+(a font is
+.I special
+if
+.B troff
+should search it whenever
+a character is not found in the current font.)
+If the font is special,
+it should be listed in the
+.B fonts
+command in the DESC file;
+if it is not special, there is no need to list it, since
+.B troff
+can automatically mount it when it's first used.
+.LP
+To do a good job of math typesetting, groff requires
+font metric information not present in the tfm file.
+The reason for this is that \*(tx has separate math italic fonts
+whereas groff uses normal italic fonts for math.
+The additional information required by groff is given by the
+two arguments to the
+.B math_fit
+macro in the Metafont programs for the Computer Modern fonts.
+In a text font (a font for which
+.B math_fitting
+is false), Metafont normally ignores these two arguments.
+Metafont can be made to put this information in the gf file
+by loading the following definition after
+.B cmbase
+when creating
+.BR cm.base :
+.IP
+.nf
+.ft B
+def ignore_math_fit(expr left_adjustment,right_adjustment) =
+ special "adjustment";
+ numspecial left_adjustment*16/designsize;
+ numspecial right_adjustment*16/designsize;
+ enddef;
+.fi
+.ft R
+.LP
+The gf file created using this modified
+.B cm.base
+should be specified with the
+.B \-g
+option.
+The
+.B \-g
+option should not be given for a font for which
+.B math_fitting
+is true.
+.SH OPTIONS
+.TP
+.B \-v
+Print the version number.
+.TP
+.B \-s
+The font is special.
+The effect of this option is to add the
+.B special
+command to the font file.
+.TP
+.BI \-k n
+The skewchar of this font is at position
+.IR n .
+.I n
+should be an integer;
+it may be given in decimal,
+or with a leading
+.B 0
+in octal,
+or with a leading
+.B 0x
+in hexadecimal.
+The effect of this option is to ignore any kerns whose second component
+is the specified character.
+.TP
+.BI \-g gf_file
+.I gf_file
+is a gf file produced by Metafont containing special and numspecial
+commands giving additional font metric information.
+.SH FILES
+.Tp \w'\fB@FONTDIR@/devdvi/DESC'u+2n
+.B @FONTDIR@/devdvi/DESC
+Device description file.
+.TP
+.BI @FONTDIR@/devdvi/ F
+Font description file for font
+.IR F .
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@),
+.BR grodvi (@MAN1EXT@),
+.BR groff_font (@MAN5EXT@)
diff --git a/src/xditview/ChangeLog b/src/xditview/ChangeLog
new file mode 100644
index 00000000..435e1869
--- /dev/null
+++ b/src/xditview/ChangeLog
@@ -0,0 +1,353 @@
+2000-02-06 Werner LEMBERG <wl@gnu.org>
+
+ * Imakefile: Adapted to new directory structure.
+
+ * README: Updated.
+
+Version 1.15 released
+=====================
+
+1999-12-21 Werner LEMBERG <wl@gnu.org>
+
+ * README: Fixed ftp GNU address.
+
+1999-12-13 Werner LEMBERG <wl@gnu.org>
+
+ * device.c: Use extern declarations of strtok(), strchr(), and
+ getenv() only if not defined as macros.
+
+1999-11-18 Larry Jones <larry.jones@sdrc.com>
+
+ * xditview.c: Add fallback_resources to allow running without
+ access to the app-defaults file.
+
+ * Imakefile: Added rule to create app-defaults to a C header file.
+
+ * GXditview-ad.h: New file containing fallback default resources.
+
+ * ad2c: New file to do the app-defaults -> C header file
+ conversion.
+
+1999-10-27 Larry Jones <larry.jones@sdrc.com>
+
+ * font.c (DisposeFontSizes): If there's a problem loading a font,
+ xditview will fall-back and use the default font, but it hasn't
+ checked before unloading fonts which could result in unloading the
+ default font (possibly multiple times) and then X errors.
+
+1999-09-13 Werner LEMBERG <wl@gnu.org>
+
+ * Imakefile (extraclean): Added Makefile.
+
+ * xditview.c (main, MakePrompt): Fixing compilation warnings.
+
+ * TODO: Imakefile should be replaced with a configure script.
+
+1999-09-12 Werner LEMBERG <wl@gnu.org>
+
+ * Imakefile (GROFF_FONTPATH): Another addition.
+
+ * device.c (FONTPATH): Update to match current groff version.
+
+1999-09-11 Larry Jones <larry.jones@sdrc.com>
+
+ * Imakefile (GROFF_LIBDIR, GROFF_FONTPATH): Update to match
+ current groff version.
+
+ * Dvi.c (Realize, Destroy), DviP.h, draw.c (setFillGC), gray*.bm:
+ Allow 8 levels of gray rather than just 1.
+
+ * draw.c (DrawFilledCircle, DrawFilledEllipse, DrawFilledPolygon):
+ Draw outlines to prevent gaps between abutting figures.
+
+1999-05-27 Werner LEMBERG <wl@gnu.org>
+
+ * xtotroff.c (usage): Fixed typo.
+
+Mon Sep 11 10:40:33 1995 James Clark <jjc@jclark.com>
+
+ * device.c (INT_MIN, INT_MAX): Don't define if already defined.
+
+Mon Aug 8 11:14:11 1994 James Clark (jjc@jclark.com)
+
+ * DviChar.c (Adobe_Symbol_map): Use \(nb for notsubset.
+
+Tue Apr 19 04:41:16 1994 James Clark (jjc@jclark.com)
+
+ * Dvi.c (resources): Change default for background and foreground
+ to "XtDefaultBackground" and "XtDefaultForeground".
+
+Sat Feb 12 10:38:47 1994 James Clark (jjc@jclark.com)
+
+ * DviChar.c (Adobe_Symbol_map): Rename radicalex to rn.
+
+Thu May 27 20:30:12 1993 James Clark (jjc@jclark.com)
+
+ * device.c (isascii): Define if necessary.
+ (canonicalize_name): Cast argument to isdigit() to unsigned char.
+
+Thu Apr 29 18:36:57 1993 James Clark (jjc at jclark.com)
+
+ * xditview.c: Include <X11/Xos.h>.
+ (NewFile): Don't declare rindex(). Use strrchr() rather than
+ rindex().
+
+Tue Mar 30 15:12:09 1993 James Clark (jjc at jclark)
+
+ * draw.c (charExists): Check that fi->per_char is not NULL.
+
+Sat Dec 12 17:42:40 1992 James Clark (jjc at jclark)
+
+ * Dvi.c (SetGeometry): Cast XtMakeGeometryRequest arguments.
+
+ * draw.c (DrawPolygon, DrawFilledPolygon): Cast Xtfree argument.
+
+ * font.c (DisposeFontSizes): Add declaration.
+
+ * draw.c (FakeCharacter): Add declaration.
+
+Wed Oct 28 13:24:00 1992 James Clark (jjc at jclark)
+
+ * Imakefile (install.dev): Deleted.
+ (fonts): New target.
+
+Mon Oct 12 10:50:44 1992 James Clark (jjc at jclark)
+
+ * Imakefile (install.dev): Say when we're installing devX*-12.
+
+ * Imakefile (install.dev): Depends on DESC and FontMap.
+
+Thu Oct 1 20:03:45 1992 James Clark (jjc at jclark)
+
+ * xditview.c (Syntax): Mention -filename option.
+
+Sat Aug 15 12:56:39 1992 James Clark (jjc at jclark)
+
+ * GXditview.ad: Bind space and return to NextPage. Bind backspace
+ and delete to previous page.
+
+ * DviChar.c (Adobe_Symbol_map): Add `an'.
+
+ * DviChar.c (Adobe_Symbol_map): Add arrowvertex, arrowverttp, and
+ arrowvertbt.
+
+Mon Aug 10 11:54:27 1992 James Clark (jjc at jclark)
+
+ * FontMap: Add m/p fields to the fonts names.
+
+Sat Aug 8 12:00:28 1992 James Clark (jjc at jclark)
+
+ * DESC: Leave font positions 5-9 blank.
+
+Tue Jul 28 11:37:05 1992 James Clark (jjc at jclark)
+
+ * Imakefile: Don't use gendef. Pass definition of FONTPATH using
+ DEFINES.
+ (path.h): Deleted.
+ (device.c): Don't include path.h. Provide default definition of
+ FONTPATH.
+
+Mon Jul 6 14:06:53 1992 James Clark (jjc at jclark)
+
+ * Imakefile: Don't install tmac.X and tmac.Xps.
+ * tmac.X, tmac.Xps: Moved to ../macros.
+
+ * Imakefile: Don't install eqnchar.
+ * eqnchar: Deleted.
+
+Sun Jun 14 12:55:02 1992 James Clark (jjc@jclark)
+
+ * tmac.Xps: Handle OE, oe, lq, rq.
+ * draw.c (FakeCharacter): Don't handle these.
+
+ * draw.c (FakeCharacter): Don't handle f/.
+
+Mon Jun 8 11:46:37 1992 James Clark (jjc@jclark)
+
+ * tmac.X: Translate char160 to space.
+
+Sun Jun 7 14:39:53 1992 James Clark (jjc@jclark)
+
+ * tmac.X: Do `mso tmac.psic' before restoring compatibility mode.
+
+ * tmac.X: Add \(OE, \(oe, \(ah, \(ao, \(ho.
+
+ * tmac.Xps: Make it work in compatibility mode.
+ Redo existing character definitions with .Xps-char.
+ Add more character definitions.
+ (Xps-char): New macro.
+
+Sat Jun 6 21:46:03 1992 James Clark (jjc@jclark)
+
+ * DviChar.c (Adobe_Symbol_map): Add +h, +f, +p, Fn, lz.
+ * tmac.X: Add \(bq, \(Bq, \(aq.
+ * tmac.Xps: Handle \(aq, \(bq, \(Bq, \(Fn.
+
+Wed Jun 3 11:11:15 1992 James Clark (jjc@jclark)
+
+ * DviChar.c (Adobe_Symbol_map): Add wp.
+
+Tue Apr 21 09:21:59 1992 James Clark (jjc at jclark)
+
+ * GXditview.ad: Bind n, p, q keys to NextPage, PreviousPage and
+ Quit actions.
+
+ * xditview.c (RerasterizeAction): New function.
+ (xditview_actions): Add RerasterizeAction.
+ * GXditview.ad: Bind r key to Rerasterize action.
+
+Fri Apr 17 08:25:36 1992 James Clark (jjc at jclark)
+
+ * xditview.c: Add -filename option.
+ (main): Copy any -filename argument into current_file_name.
+
+Mon Mar 16 10:21:58 1992 James Clark (jjc at jclark)
+
+ * tmac.X: Load tmac.pspic.
+
+Sun Mar 8 11:27:19 1992 James Clark (jjc at jclark)
+
+ * Lex.c (GetLine, GetWord, GetNumber): Rewrite.
+
+Sat Oct 12 22:58:52 1991 James Clark (jjc at jclark)
+
+ * Dvi.c (SetDevice): If the size change request is refused but a
+ larger geometry is offered, request that.
+
+Wed Oct 9 12:27:48 1991 James Clark (jjc at jclark)
+
+ * font.c (InstallFontSizes): Ignore FontNameAverageWidth component.
+
+ * Dvi.c (default_font_map): Add `adobe' to font names to avoid
+ ambiguity.
+
+ * FontMap: New file.
+ * FontMap.X100, FontMap.X75: Deleted.
+ * xtotroff.c (main, usage): Add -s and -r options.
+ (MapFont): Change the font pattern to have the selected resolution and
+ size.
+ * Imakefile (install.dev): Use FontMap and supply appropriate -s
+ and -r options.
+
+ * xtotroff.c (MapFont): Check for ambiguity by comparing canonicalized
+ font names.
+
+ * DviP.h (DviFontList): Add initialized and scalable members.
+ (font.c): Add support for scalable fonts based on R5 xditview.
+
+ * DviChar.c: Use xmalloc rather than malloc.
+ * xditview.c (xmalloc): New function.
+ * xtotroff.c (xmalloc): New function.
+ * other files: Use XtMalloc and XtFree instead of malloc and free.
+
+Thu Aug 29 20:15:31 1991 James Clark (jjc at jclark)
+
+ * draw.c (setGC): Do multiplication in floating point to avoid
+ overflow.
+
+Tue Aug 13 12:04:41 1991 James Clark (jjc at jclark)
+
+ * draw.c (FakeCharacter): Remove casts in defintion of pack2.
+
+Tue Jul 30 11:42:39 1991 James Clark (jjc at jclark)
+
+ * tmac.Xps: New file.
+ * Imakefile (install): Install tmac.Xps.
+
+Tue Jul 2 09:31:37 1991 James Clark (jjc at jclark)
+
+ * xtotroff.c (main): Pass argv[0] to usage().
+
+Sun Jun 30 12:34:06 1991 James Clark (jjc at jclark)
+
+ * xtotroff.c (MapFont): Handle the case where XLoadQueryFont
+ returns NULL.
+
+Sat Jun 29 12:32:52 1991 James Clark (jjc at jclark)
+
+ * Imakefile: Use ../gendef to generate path.h.
+
+Sun Jun 16 13:26:34 1991 James Clark (jjc at jclark)
+
+ * Imakefile (depend.o): Change to device.o.
+
+Sun Jun 2 12:17:56 1991 James Clark (jjc at jclark)
+
+ * Imakefile: Remove spaces from the beginning of variable
+ assignment lines.
+
+Sun May 26 14:14:01 1991 James Clark (jjc at jclark)
+
+ * xditview.c (Syntax): Update.
+
+ * Dvi.c (DviSaveToFile, SaveToFile): New functions.
+ (FindPage): Check that we're not readingTmp before checking for
+ end of file of normal input file.
+ (ClassPartInitialize): New function.
+ * Dvi.h: Add declaration of DviSaveToFile.
+ * DviP.h: Add save method to DviClassPart. Declare
+ InheritSaveToFile.
+ * xditview.c (DoPrint, Print, PrintAction): New functions.
+ * xditview.c: Add print menu entry.
+ * xditview.c: Provide printCommand application resource.
+ * lex.c: Don't output EOF to temporary file.
+
+ * Dvi.c (QueryGeometry): Check request->request_mode.
+
+ * Dvi.c (SetDevice): New function.
+ (SetDeviceResolution): Deleted.
+
+ * Dvi.c: Add resolution resource.
+ * DviP.h: Add definitions of XtNResolution and XtCResolution.
+ * xditview.c: Add -resolution argument.
+ * GXditview.ad: Add default for GXditview.height.
+ * Dvi.c (Initialize, SetDevice): Use default_resolution.
+
+ * Dvi.c: Make MY_HEIGHT and MY_WIDTH use the paperlength and
+ paperwidth commands in the DESC file.
+
+ * Dvi.c: Add SS font to default font map.
+
+ * draw.c: Rewritten so as not to assume device and display
+ resolution is the same.
+ * DviP.h: Include device.h. Add device_font member to DviFontList.
+ Add adjustable arrary to DviCharCache. Add text_x_width,
+ text_device_width, word_flag, device_font, device_font_number,
+ device, native, device_resolution, display_resolution,
+ paperlength, paperwidth, scale_factor, sizescale members.
+ * Dvi.c (Initialize): Initialize new variable used by draw.c
+ (Destroy): Call device_destroy.
+ * font.c (MaxFontPosition): New function.
+ (LookupFontSizeBySize): Handle sizescale.
+ (InstallFont): Load the device font.
+ (ForgetFonts): New function.
+ (QueryDeviceFont): New function.
+ * parse.c (ParseInput): Handle t and u commands. Split off
+ character output into draw.c.
+ (ParseDeviceControl): Ignore res command. Use the device argument
+ to the T command.
+
+ * font.c (MapXNameToDviName): Ifdefed out.
+
+ * path.h: New file.
+ * device.c, device.h: New files.
+
+ * DviChar.c: Add entries for lB, rB, oq, lC, rC, md.
+
+ * INSTALL: New file.
+
+ * libxdvi: Merged into main directory.
+ * xtotroff.c, xditview.c: Change includes accordingly.
+
+ * devX75, devX100: Merged into main directory.
+ * xditview.man: Renamed to gxditview.man.
+
+ * Xditview.ad: Renamed to GXditview.ad.
+ * xditview.c (main): Use class of GXditview rather than xditview.
+
+ * Imakefile: New file.
+ * Makefile: Deleted.
+
+ * xtotroff.c (MapFont): Unlink output file before opening it.
+
+ * Started separate ChangeLog.
diff --git a/src/xditview/DESC b/src/xditview/DESC
new file mode 100644
index 00000000..172170c9
--- /dev/null
+++ b/src/xditview/DESC
@@ -0,0 +1,9 @@
+styles R I B BI
+fonts 6 0 0 0 0 0 S
+sizes 8 10 12 14 18 24 0
+res 75
+X11
+hor 1
+vert 1
+unitwidth 10
+postpro gxditview
diff --git a/src/xditview/Dvi.c b/src/xditview/Dvi.c
new file mode 100644
index 00000000..5eae76d8
--- /dev/null
+++ b/src/xditview/Dvi.c
@@ -0,0 +1,579 @@
+#ifndef SABER
+#ifndef lint
+static char Xrcsid[] = "$XConsortium: Dvi.c,v 1.9 89/12/10 16:12:25 rws Exp $";
+#endif /* lint */
+#endif /* SABER */
+
+/*
+ * Dvi.c - Dvi display widget
+ *
+ */
+
+#define XtStrlen(s) ((s) ? strlen(s) : 0)
+
+ /* The following are defined for the reader's convenience. Any
+ Xt..Field macro in this code just refers to some field in
+ one of the substructures of the WidgetRec. */
+
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/Xmu/Converters.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "DviP.h"
+
+/****************************************************************
+ *
+ * Full class record constant
+ *
+ ****************************************************************/
+
+/* Private Data */
+
+static char default_font_map[] = "\
+TR -adobe-times-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
+TI -adobe-times-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\
+TB -adobe-times-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
+TBI -adobe-times-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\
+CR -adobe-courier-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
+CI -adobe-courier-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\
+CB -adobe-courier-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
+CBI -adobe-courier-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\
+HR -adobe-helvetica-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
+HI -adobe-helvetica-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\
+HB -adobe-helvetica-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
+HBI -adobe-helvetica-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\
+NR -adobe-new century schoolbook-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
+NI -adobe-new century schoolbook-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\
+NB -adobe-new century schoolbook-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
+NBI -adobe-new century schoolbook-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\
+S -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
+SS -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
+";
+
+#define offset(field) XtOffset(DviWidget, field)
+
+#define MY_WIDTH(dw) ((int)(dw->dvi.paperwidth * dw->dvi.scale_factor + .5))
+#define MY_HEIGHT(dw) ((int)(dw->dvi.paperlength * dw->dvi.scale_factor + .5))
+
+static XtResource resources[] = {
+ {XtNfontMap, XtCFontMap, XtRString, sizeof (char *),
+ offset(dvi.font_map_string), XtRString, default_font_map},
+ {XtNforeground, XtCForeground, XtRPixel, sizeof (unsigned long),
+ offset(dvi.foreground), XtRString, "XtDefaultForeground"},
+ {XtNbackground, XtCBackground, XtRPixel, sizeof (unsigned long),
+ offset(dvi.background), XtRString, "XtDefaultBackground"},
+ {XtNpageNumber, XtCPageNumber, XtRInt, sizeof (int),
+ offset(dvi.requested_page), XtRString, "1"},
+ {XtNlastPageNumber, XtCLastPageNumber, XtRInt, sizeof (int),
+ offset (dvi.last_page), XtRString, "0"},
+ {XtNfile, XtCFile, XtRFile, sizeof (FILE *),
+ offset (dvi.file), XtRFile, (char *) 0},
+ {XtNseek, XtCSeek, XtRBoolean, sizeof (Boolean),
+ offset(dvi.seek), XtRString, "false"},
+ {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
+ offset(dvi.default_font), XtRString, "xtdefaultfont"},
+ {XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof (int),
+ offset(dvi.backing_store), XtRString, "default"},
+ {XtNnoPolyText, XtCNoPolyText, XtRBoolean, sizeof (Boolean),
+ offset(dvi.noPolyText), XtRString, "false"},
+ {XtNresolution, XtCResolution, XtRInt, sizeof(int),
+ offset(dvi.default_resolution), XtRString, "75"},
+};
+
+#undef offset
+
+static void ClassInitialize ();
+static void ClassPartInitialize();
+static void Initialize(), Realize (), Destroy (), Redisplay ();
+static Boolean SetValues (), SetValuesHook ();
+static XtGeometryResult QueryGeometry ();
+static void ShowDvi ();
+static void CloseFile (), OpenFile ();
+static void FindPage ();
+
+static void SaveToFile ();
+
+DviClassRec dviClassRec = {
+{
+ &widgetClassRec, /* superclass */
+ "Dvi", /* class_name */
+ sizeof(DviRec), /* size */
+ ClassInitialize, /* class_initialize */
+ ClassPartInitialize, /* class_part_initialize */
+ FALSE, /* class_inited */
+ Initialize, /* initialize */
+ NULL, /* initialize_hook */
+ Realize, /* realize */
+ NULL, /* actions */
+ 0, /* num_actions */
+ resources, /* resources */
+ XtNumber(resources), /* resource_count */
+ NULLQUARK, /* xrm_class */
+ FALSE, /* compress_motion */
+ TRUE, /* compress_exposure */
+ TRUE, /* compress_enterleave */
+ FALSE, /* visible_interest */
+ Destroy, /* destroy */
+ NULL, /* resize */
+ Redisplay, /* expose */
+ SetValues, /* set_values */
+ SetValuesHook, /* set_values_hook */
+ NULL, /* set_values_almost */
+ NULL, /* get_values_hook */
+ NULL, /* accept_focus */
+ XtVersion, /* version */
+ NULL, /* callback_private */
+ 0, /* tm_table */
+ QueryGeometry, /* query_geometry */
+ NULL, /* display_accelerator */
+ NULL /* extension */
+},{
+ SaveToFile, /* save */
+},
+};
+
+WidgetClass dviWidgetClass = (WidgetClass) &dviClassRec;
+
+static void ClassInitialize ()
+{
+ XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
+ NULL, 0 );
+}
+
+/****************************************************************
+ *
+ * Private Procedures
+ *
+ ****************************************************************/
+
+/* ARGSUSED */
+static void Initialize(request, new)
+ Widget request, new;
+{
+ DviWidget dw = (DviWidget) new;
+
+ dw->dvi.current_page = 0;
+ dw->dvi.font_map = 0;
+ dw->dvi.cache.index = 0;
+ dw->dvi.text_x_width = 0;
+ dw->dvi.text_device_width = 0;
+ dw->dvi.word_flag = 0;
+ dw->dvi.file = 0;
+ dw->dvi.tmpFile = 0;
+ dw->dvi.state = 0;
+ dw->dvi.readingTmp = 0;
+ dw->dvi.cache.char_index = 0;
+ dw->dvi.cache.font_size = -1;
+ dw->dvi.cache.font_number = -1;
+ dw->dvi.cache.adjustable[0] = 0;
+ dw->dvi.file_map = 0;
+ dw->dvi.fonts = 0;
+ dw->dvi.seek = False;
+ dw->dvi.device_resolution = dw->dvi.default_resolution;
+ dw->dvi.display_resolution = dw->dvi.default_resolution;
+ dw->dvi.paperlength = dw->dvi.default_resolution*11;
+ dw->dvi.paperwidth = (dw->dvi.default_resolution*8
+ + dw->dvi.default_resolution/2);
+ dw->dvi.scale_factor = 1.0;
+ dw->dvi.sizescale = 1;
+ dw->dvi.line_thickness = -1;
+ dw->dvi.line_width = 1;
+ dw->dvi.fill = DVI_FILL_MAX;
+ dw->dvi.device_font = 0;
+ dw->dvi.device_font_number = -1;
+ dw->dvi.device = 0;
+ dw->dvi.native = 0;
+}
+
+#include "gray1.bm"
+#include "gray2.bm"
+#include "gray3.bm"
+#include "gray4.bm"
+#include "gray5.bm"
+#include "gray6.bm"
+#include "gray7.bm"
+#include "gray8.bm"
+
+static void
+Realize (w, valueMask, attrs)
+ Widget w;
+ XtValueMask *valueMask;
+ XSetWindowAttributes *attrs;
+{
+ DviWidget dw = (DviWidget) w;
+ XGCValues values;
+
+ if (dw->dvi.backing_store != Always + WhenMapped + NotUseful) {
+ attrs->backing_store = dw->dvi.backing_store;
+ *valueMask |= CWBackingStore;
+ }
+ XtCreateWindow (w, (unsigned)InputOutput, (Visual *) CopyFromParent,
+ *valueMask, attrs);
+ values.foreground = dw->dvi.foreground;
+ values.cap_style = CapRound;
+ values.join_style = JoinRound;
+ values.line_width = dw->dvi.line_width;
+ dw->dvi.normal_GC = XCreateGC (XtDisplay (w), XtWindow (w),
+ GCForeground|GCCapStyle|GCJoinStyle
+ |GCLineWidth,
+ &values);
+ dw->dvi.gray[0] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
+ gray1_bits,
+ gray1_width, gray1_height);
+ dw->dvi.gray[1] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
+ gray2_bits,
+ gray2_width, gray2_height);
+ dw->dvi.gray[2] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
+ gray3_bits,
+ gray3_width, gray3_height);
+ dw->dvi.gray[3] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
+ gray4_bits,
+ gray4_width, gray4_height);
+ dw->dvi.gray[4] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
+ gray5_bits,
+ gray5_width, gray5_height);
+ dw->dvi.gray[5] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
+ gray6_bits,
+ gray6_width, gray6_height);
+ dw->dvi.gray[6] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
+ gray7_bits,
+ gray7_width, gray7_height);
+ dw->dvi.gray[7] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
+ gray8_bits,
+ gray8_width, gray8_height);
+ values.background = dw->dvi.background;
+ values.stipple = dw->dvi.gray[5];
+ dw->dvi.fill_GC = XCreateGC (XtDisplay (w), XtWindow (w),
+ GCForeground|GCBackground|GCStipple,
+ &values);
+
+ dw->dvi.fill_type = 9;
+
+ if (dw->dvi.file)
+ OpenFile (dw);
+ ParseFontMap (dw);
+}
+
+static void
+Destroy(w)
+ Widget w;
+{
+ DviWidget dw = (DviWidget) w;
+
+ XFreeGC (XtDisplay (w), dw->dvi.normal_GC);
+ XFreeGC (XtDisplay (w), dw->dvi.fill_GC);
+ XFreePixmap (XtDisplay (w), dw->dvi.gray[0]);
+ XFreePixmap (XtDisplay (w), dw->dvi.gray[1]);
+ XFreePixmap (XtDisplay (w), dw->dvi.gray[2]);
+ XFreePixmap (XtDisplay (w), dw->dvi.gray[3]);
+ XFreePixmap (XtDisplay (w), dw->dvi.gray[4]);
+ XFreePixmap (XtDisplay (w), dw->dvi.gray[5]);
+ XFreePixmap (XtDisplay (w), dw->dvi.gray[6]);
+ XFreePixmap (XtDisplay (w), dw->dvi.gray[7]);
+ DestroyFontMap (dw->dvi.font_map);
+ DestroyFileMap (dw->dvi.file_map);
+ device_destroy (dw->dvi.device);
+}
+
+/*
+ * Repaint the widget window
+ */
+
+/* ARGSUSED */
+static void
+Redisplay(w, event, region)
+ Widget w;
+ XEvent *event;
+ Region region;
+{
+ DviWidget dw = (DviWidget) w;
+ XRectangle extents;
+
+ XClipBox (region, &extents);
+ dw->dvi.extents.x1 = extents.x;
+ dw->dvi.extents.y1 = extents.y;
+ dw->dvi.extents.x2 = extents.x + extents.width;
+ dw->dvi.extents.y2 = extents.y + extents.height;
+ ShowDvi (dw);
+}
+
+/*
+ * Set specified arguments into widget
+ */
+/* ARGSUSED */
+static Boolean
+SetValues (current, request, new)
+ DviWidget current, request, new;
+{
+ Boolean redisplay = FALSE;
+ char *new_map;
+ int cur, req;
+
+ if (current->dvi.font_map_string != request->dvi.font_map_string) {
+ new_map = XtMalloc (strlen (request->dvi.font_map_string) + 1);
+ if (new_map) {
+ redisplay = TRUE;
+ strcpy (new_map, request->dvi.font_map_string);
+ new->dvi.font_map_string = new_map;
+ if (current->dvi.font_map_string)
+ XtFree (current->dvi.font_map_string);
+ current->dvi.font_map_string = 0;
+ ParseFontMap (new);
+ }
+ }
+
+ req = request->dvi.requested_page;
+ cur = current->dvi.requested_page;
+ if (cur != req) {
+ if (!request->dvi.file)
+ req = 0;
+ else {
+ if (req < 1)
+ req = 1;
+ if (current->dvi.last_page != 0 &&
+ req > current->dvi.last_page)
+ req = current->dvi.last_page;
+ }
+ if (cur != req)
+ redisplay = TRUE;
+ new->dvi.requested_page = req;
+ if (current->dvi.last_page == 0 && req > cur)
+ FindPage (new);
+ }
+
+ return redisplay;
+}
+
+/*
+ * use the set_values_hook entry to check when
+ * the file is set
+ */
+
+static Boolean
+SetValuesHook (dw, args, num_argsp)
+ DviWidget dw;
+ ArgList args;
+ Cardinal *num_argsp;
+{
+ Cardinal i;
+
+ for (i = 0; i < *num_argsp; i++) {
+ if (!strcmp (args[i].name, XtNfile)) {
+ CloseFile (dw);
+ OpenFile (dw);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void CloseFile (dw)
+ DviWidget dw;
+{
+ if (dw->dvi.tmpFile)
+ fclose (dw->dvi.tmpFile);
+ ForgetPagePositions (dw);
+}
+
+static void OpenFile (dw)
+ DviWidget dw;
+{
+ char tmpName[sizeof ("/tmp/dviXXXXXX")];
+
+ dw->dvi.tmpFile = 0;
+ if (!dw->dvi.seek) {
+ strcpy (tmpName, "/tmp/dviXXXXXX");
+ mktemp (tmpName);
+ dw->dvi.tmpFile = fopen (tmpName, "w+");
+ unlink (tmpName);
+ }
+ dw->dvi.requested_page = 1;
+ dw->dvi.last_page = 0;
+}
+
+static XtGeometryResult
+QueryGeometry (w, request, geometry_return)
+ Widget w;
+ XtWidgetGeometry *request, *geometry_return;
+{
+ XtGeometryResult ret;
+ DviWidget dw = (DviWidget) w;
+
+ ret = XtGeometryYes;
+ if (((request->request_mode & CWWidth)
+ && request->width < MY_WIDTH(dw))
+ || ((request->request_mode & CWHeight)
+ && request->height < MY_HEIGHT(dw)))
+ ret = XtGeometryAlmost;
+ geometry_return->width = MY_WIDTH(dw);
+ geometry_return->height = MY_HEIGHT(dw);
+ geometry_return->request_mode = CWWidth|CWHeight;
+ return ret;
+}
+
+SetDevice (dw, name)
+ DviWidget dw;
+ char *name;
+{
+ XtWidgetGeometry request, reply;
+ XtGeometryResult ret;
+
+ ForgetFonts (dw);
+ dw->dvi.device = device_load (name);
+ if (!dw->dvi.device)
+ return;
+ dw->dvi.sizescale = dw->dvi.device->sizescale;
+ dw->dvi.device_resolution = dw->dvi.device->res;
+ dw->dvi.native = dw->dvi.device->X11;
+ dw->dvi.paperlength = dw->dvi.device->paperlength;
+ dw->dvi.paperwidth = dw->dvi.device->paperwidth;
+ if (dw->dvi.native) {
+ dw->dvi.display_resolution = dw->dvi.device_resolution;
+ dw->dvi.scale_factor = 1.0;
+ }
+ else {
+ dw->dvi.display_resolution = dw->dvi.default_resolution;
+ dw->dvi.scale_factor = ((double)dw->dvi.display_resolution
+ / dw->dvi.device_resolution);
+ }
+ request.request_mode = CWWidth|CWHeight;
+ request.width = MY_WIDTH(dw);
+ request.height = MY_HEIGHT(dw);
+ ret = XtMakeGeometryRequest ((Widget)dw, &request, &reply);
+ if (ret == XtGeometryAlmost
+ && reply.height >= request.height
+ && reply.width >= request.width) {
+ request.width = reply.width;
+ request.height = reply.height;
+ XtMakeGeometryRequest ((Widget)dw, &request, &reply);
+ }
+}
+
+static void
+ShowDvi (dw)
+ DviWidget dw;
+{
+ if (!dw->dvi.file) {
+ static char Error[] = "No file selected";
+
+ XSetFont (XtDisplay(dw), dw->dvi.normal_GC,
+ dw->dvi.default_font->fid);
+ XDrawString (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ 20, 20, Error, strlen (Error));
+ return;
+ }
+
+ FindPage (dw);
+
+ dw->dvi.display_enable = 1;
+ ParseInput (dw);
+ if (dw->dvi.last_page && dw->dvi.requested_page > dw->dvi.last_page)
+ dw->dvi.requested_page = dw->dvi.last_page;
+}
+
+static void
+FindPage (dw)
+ DviWidget dw;
+{
+ int i;
+ long file_position;
+
+ if (dw->dvi.requested_page < 1)
+ dw->dvi.requested_page = 1;
+
+ if (dw->dvi.last_page != 0 && dw->dvi.requested_page > dw->dvi.last_page)
+ dw->dvi.requested_page = dw->dvi.last_page;
+
+ file_position = SearchPagePosition (dw, dw->dvi.requested_page);
+ if (file_position != -1) {
+ FileSeek(dw, file_position);
+ dw->dvi.current_page = dw->dvi.requested_page;
+ } else {
+ for (i=dw->dvi.requested_page; i > 0; i--) {
+ file_position = SearchPagePosition (dw, i);
+ if (file_position != -1)
+ break;
+ }
+ if (file_position == -1)
+ file_position = 0;
+ FileSeek (dw, file_position);
+
+ dw->dvi.current_page = i;
+
+ dw->dvi.display_enable = 0;
+ while (dw->dvi.current_page != dw->dvi.requested_page) {
+ dw->dvi.current_page = ParseInput (dw);
+ /*
+ * at EOF, seek back to the beginning of this page.
+ */
+ if (!dw->dvi.readingTmp && feof (dw->dvi.file)) {
+ file_position = SearchPagePosition (dw,
+ dw->dvi.current_page);
+ if (file_position != -1)
+ FileSeek (dw, file_position);
+ dw->dvi.requested_page = dw->dvi.current_page;
+ break;
+ }
+ }
+ }
+}
+
+void DviSaveToFile(w, fp)
+ Widget w;
+ FILE *fp;
+{
+ XtCheckSubclass(w, dviWidgetClass, NULL);
+ (*((DviWidgetClass) XtClass(w))->command_class.save)(w, fp);
+}
+
+static
+void SaveToFile(w, fp)
+ Widget w;
+ FILE *fp;
+{
+ DviWidget dw = (DviWidget)w;
+ long pos;
+ int c;
+
+ if (dw->dvi.tmpFile) {
+ pos = ftell(dw->dvi.tmpFile);
+ if (dw->dvi.ungot) {
+ pos--;
+ dw->dvi.ungot = 0;
+ /* The ungot character is in the tmpFile, so we don't
+ want to read it from file. */
+ (void)getc(dw->dvi.file);
+ }
+ }
+ else
+ pos = ftell(dw->dvi.file);
+ FileSeek(dw, 0L);
+ while (DviGetC(dw, &c) != EOF)
+ if (putc(c, fp) == EOF) {
+ /* XXX print error message */
+ break;
+ }
+ FileSeek(dw, pos);
+}
+
+static
+void ClassPartInitialize(widget_class)
+ WidgetClass widget_class;
+{
+ DviWidgetClass wc = (DviWidgetClass)widget_class;
+ DviWidgetClass super = (DviWidgetClass) wc->core_class.superclass;
+ if (wc->command_class.save == InheritSaveToFile)
+ wc->command_class.save = super->command_class.save;
+}
+
+/*
+Local Variables:
+c-indent-level: 8
+c-continued-statement-offset: 8
+c-brace-offset: -8
+c-argdecl-indent: 8
+c-label-offset: -8
+c-tab-always-indent: nil
+End:
+*/
diff --git a/src/xditview/Dvi.h b/src/xditview/Dvi.h
new file mode 100644
index 00000000..5aab7d8c
--- /dev/null
+++ b/src/xditview/Dvi.h
@@ -0,0 +1,46 @@
+/*
+* $XConsortium: Dvi.h,v 1.4 89/07/21 14:22:06 jim Exp $
+*/
+
+#ifndef _XtDvi_h
+#define _XtDvi_h
+
+/***********************************************************************
+ *
+ * Dvi Widget
+ *
+ ***********************************************************************/
+
+/* Parameters:
+
+ Name Class RepType Default Value
+ ---- ----- ------- -------------
+ background Background pixel White
+ foreground Foreground Pixel Black
+ fontMap FontMap char * ...
+ pageNumber PageNumber int 1
+*/
+
+#define XtNfontMap "fontMap"
+#define XtNpageNumber "pageNumber"
+#define XtNlastPageNumber "lastPageNumber"
+#define XtNnoPolyText "noPolyText"
+#define XtNseek "seek"
+#define XtNresolution "resolution"
+
+#define XtCFontMap "FontMap"
+#define XtCPageNumber "PageNumber"
+#define XtCLastPageNumber "LastPageNumber"
+#define XtCNoPolyText "NoPolyText"
+#define XtCSeek "Seek"
+#define XtCResolution "Resolution"
+
+typedef struct _DviRec *DviWidget; /* completely defined in DviPrivate.h */
+typedef struct _DviClassRec *DviWidgetClass; /* completely defined in DviPrivate.h */
+
+extern WidgetClass dviWidgetClass;
+
+extern void DviSaveToFile();
+
+#endif /* _XtDvi_h */
+/* DON'T ADD STUFF AFTER THIS #endif */
diff --git a/src/xditview/DviChar.c b/src/xditview/DviChar.c
new file mode 100644
index 00000000..90c63698
--- /dev/null
+++ b/src/xditview/DviChar.c
@@ -0,0 +1,664 @@
+/*
+ * DviChar.c
+ *
+ * Map DVI (ditroff output) character names to
+ * font indexes and back
+ */
+
+#include "DviChar.h"
+
+extern char *xmalloc();
+
+#define allocHash() ((DviCharNameHash *) xmalloc (sizeof (DviCharNameHash)))
+
+struct map_list {
+ struct map_list *next;
+ DviCharNameMap *map;
+};
+
+static struct map_list *world;
+
+static int standard_maps_loaded = 0;
+static void load_standard_maps ();
+static int hash_name ();
+static dispose_hash(), compute_hash();
+
+DviCharNameMap *
+DviFindMap (encoding)
+ char *encoding;
+{
+ struct map_list *m;
+
+ if (!standard_maps_loaded)
+ load_standard_maps ();
+ for (m = world; m; m=m->next)
+ if (!strcmp (m->map->encoding, encoding))
+ return m->map;
+ return 0;
+}
+
+void
+DviRegisterMap (map)
+ DviCharNameMap *map;
+{
+ struct map_list *m;
+
+ if (!standard_maps_loaded)
+ load_standard_maps ();
+ for (m = world; m; m = m->next)
+ if (!strcmp (m->map->encoding, map->encoding))
+ break;
+ if (!m) {
+ m = (struct map_list *) xmalloc (sizeof *m);
+ m->next = world;
+ world = m;
+ }
+ dispose_hash (map);
+ m->map = map;
+ compute_hash (map);
+}
+
+static
+dispose_hash (map)
+ DviCharNameMap *map;
+{
+ DviCharNameHash **buckets;
+ DviCharNameHash *h, *next;
+ int i;
+
+ buckets = map->buckets;
+ for (i = 0; i < DVI_HASH_SIZE; i++) {
+ for (h = buckets[i]; h; h=next) {
+ next = h->next;
+ free (h);
+ }
+ }
+}
+
+static int
+hash_name (name)
+ char *name;
+{
+ int i = 0;
+
+ while (*name)
+ i = (i << 1) ^ *name++;
+ if (i < 0)
+ i = -i;
+ return i;
+}
+
+static
+compute_hash (map)
+ DviCharNameMap *map;
+{
+ DviCharNameHash **buckets;
+ int c, s, i;
+ DviCharNameHash *h;
+
+ buckets = map->buckets;
+ for (i = 0; i < DVI_HASH_SIZE; i++)
+ buckets[i] = 0;
+ for (c = 0; c < DVI_MAP_SIZE; c++)
+ for (s = 0; s < DVI_MAX_SYNONYMS; s++) {
+ if (!map->dvi_names[c][s])
+ break;
+ i = hash_name (map->dvi_names[c][s]) % DVI_HASH_SIZE;
+ h = allocHash ();
+ h->next = buckets[i];
+ buckets[i] = h;
+ h->name = map->dvi_names[c][s];
+ h->position = c;
+ }
+
+}
+
+int
+DviCharIndex (map, name)
+ DviCharNameMap *map;
+ char *name;
+{
+ int i;
+ DviCharNameHash *h;
+
+ i = hash_name (name) % DVI_HASH_SIZE;
+ for (h = map->buckets[i]; h; h=h->next)
+ if (!strcmp (h->name, name))
+ return h->position;
+ return -1;
+}
+
+static DviCharNameMap ISO8859_1_map = {
+ "iso8859-1",
+ 0,
+{
+{ 0, /* 0 */},
+{ 0, /* 1 */},
+{ 0, /* 2 */},
+{ 0, /* 3 */},
+{ 0, /* 4 */},
+{ 0, /* 5 */},
+{ 0, /* 6 */},
+{ 0, /* 7 */},
+{ 0, /* 8 */},
+{ 0, /* 9 */},
+{ 0, /* 10 */},
+{ 0, /* 11 */},
+{ 0, /* 12 */},
+{ 0, /* 13 */},
+{ 0, /* 14 */},
+{ 0, /* 15 */},
+{ 0, /* 16 */},
+{ 0, /* 17 */},
+{ 0, /* 18 */},
+{ 0, /* 19 */},
+{ 0, /* 20 */},
+{ 0, /* 21 */},
+{ 0, /* 22 */},
+{ 0, /* 23 */},
+{ 0, /* 24 */},
+{ 0, /* 25 */},
+{ 0, /* 26 */},
+{ 0, /* 27 */},
+{ 0, /* 28 */},
+{ 0, /* 29 */},
+{ 0, /* 30 */},
+{ 0, /* 31 */},
+{ 0, /* 32 */},
+{ "!", /* 33 */},
+{ "\"", /* 34 */},
+{ "#","sh", /* 35 */},
+{ "$","Do", /* 36 */},
+{ "%", /* 37 */},
+{ "&", /* 38 */},
+{ "'", /* 39 */},
+{ "(", /* 40 */},
+{ ")", /* 41 */},
+{ "*", /* 42 */},
+{ "+", /* 43 */},
+{ ",", /* 44 */},
+{ "\\-", /* 45 */},
+{ ".", /* 46 */},
+{ "/","sl", /* 47 */},
+{ "0", /* 48 */},
+{ "1", /* 49 */},
+{ "2", /* 50 */},
+{ "3", /* 51 */},
+{ "4", /* 52 */},
+{ "5", /* 53 */},
+{ "6", /* 54 */},
+{ "7", /* 55 */},
+{ "8", /* 56 */},
+{ "9", /* 57 */},
+{ ":", /* 58 */},
+{ ";", /* 59 */},
+{ "<", /* 60 */},
+{ "=","eq", /* 61 */},
+{ ">", /* 62 */},
+{ "?", /* 63 */},
+{ "@","at", /* 64 */},
+{ "A", /* 65 */},
+{ "B", /* 66 */},
+{ "C", /* 67 */},
+{ "D", /* 68 */},
+{ "E", /* 69 */},
+{ "F", /* 70 */},
+{ "G", /* 71 */},
+{ "H", /* 72 */},
+{ "I", /* 73 */},
+{ "J", /* 74 */},
+{ "K", /* 75 */},
+{ "L", /* 76 */},
+{ "M", /* 77 */},
+{ "N", /* 78 */},
+{ "O", /* 79 */},
+{ "P", /* 80 */},
+{ "Q", /* 81 */},
+{ "R", /* 82 */},
+{ "S", /* 83 */},
+{ "T", /* 84 */},
+{ "U", /* 85 */},
+{ "V", /* 86 */},
+{ "W", /* 87 */},
+{ "X", /* 88 */},
+{ "Y", /* 89 */},
+{ "Z", /* 90 */},
+{ "[","lB", /* 91 */},
+{ "\\","rs", /* 92 */},
+{ "]","rB", /* 93 */},
+{ "^","a^","ha" /* 94 */},
+{ "_", /* 95 */},
+{ "`","oq", /* 96 */},
+{ "a", /* 97 */},
+{ "b", /* 98 */},
+{ "c", /* 99 */},
+{ "d", /* 100 */},
+{ "e", /* 101 */},
+{ "f", /* 102 */},
+{ "g", /* 103 */},
+{ "h", /* 104 */},
+{ "i", /* 105 */},
+{ "j", /* 106 */},
+{ "k", /* 107 */},
+{ "l", /* 108 */},
+{ "m", /* 109 */},
+{ "n", /* 110 */},
+{ "o", /* 111 */},
+{ "p", /* 112 */},
+{ "q", /* 113 */},
+{ "r", /* 114 */},
+{ "s", /* 115 */},
+{ "t", /* 116 */},
+{ "u", /* 117 */},
+{ "v", /* 118 */},
+{ "w", /* 119 */},
+{ "x", /* 120 */},
+{ "y", /* 121 */},
+{ "z", /* 122 */},
+{ "{","lC", /* 123 */},
+{ "|","or","ba" /* 124 */},
+{ "}","rC", /* 125 */},
+{ "~","a~","ap","ti" /* 126 */},
+{ 0, /* 127 */},
+{ 0, /* 128 */},
+{ 0, /* 129 */},
+{ 0, /* 130 */},
+{ 0, /* 131 */},
+{ 0, /* 132 */},
+{ 0, /* 133 */},
+{ 0, /* 134 */},
+{ 0, /* 135 */},
+{ 0, /* 136 */},
+{ 0, /* 137 */},
+{ 0, /* 138 */},
+{ 0, /* 139 */},
+{ 0, /* 140 */},
+{ 0, /* 141 */},
+{ 0, /* 142 */},
+{ 0, /* 143 */},
+{ 0, /* 144 */},
+{ 0, /* 145 */},
+{ 0, /* 146 */},
+{ 0, /* 147 */},
+{ 0, /* 148 */},
+{ 0, /* 149 */},
+{ 0, /* 150 */},
+{ 0, /* 151 */},
+{ 0, /* 152 */},
+{ 0, /* 153 */},
+{ 0, /* 154 */},
+{ 0, /* 155 */},
+{ 0, /* 156 */},
+{ 0, /* 157 */},
+{ 0, /* 158 */},
+{ 0, /* 159 */},
+{ 0, /* 160 */},
+{ "r!", "\241", /* 161 */},
+{ "ct", "\242", /* 162 */},
+{ "Po", "\243", /* 163 */},
+{ "Cs", "\244", /* 164 */},
+{ "Ye", "\245", /* 165 */},
+{ "bb", "\246", /* 166 */},
+{ "sc", "\247", /* 167 */},
+{ "ad", "\250", /* 168 */},
+{ "co", "\251", /* 169 */},
+{ "Of", "\252", /* 170 */},
+{ "Fo", "\253", /* 171 */},
+{ "no", "\254", /* 172 */},
+{ "-", "hy", "\255" /* 173 */},
+{ "rg", "\256", /* 174 */},
+{ "a-", "\257", /* 175 */},
+{ "de", "\260", /* 176 */},
+{ "+-", "\261", /* 177 */},
+{ "S2", "\262", /* 178 */},
+{ "S3", "\263", /* 179 */},
+{ "aa", "\264", /* 180 */},
+/* Omit *m here; we want *m to match the other greek letters in the
+ symbol font. */
+{ "\265", /* 181 */},
+{ "ps", "\266", /* 182 */},
+{ "md", "\267", /* 183 */},
+{ "ac", "\270", /* 184 */},
+{ "S1", "\271", /* 185 */},
+{ "Om", "\272", /* 186 */},
+{ "Fc", "\273", /* 187 */},
+{ "14", "\274", /* 188 */},
+{ "12", "\275", /* 189 */},
+{ "34", "\276", /* 190 */},
+{ "r?", "\277", /* 191 */},
+{ "`A", "\300", /* 192 */},
+{ "'A", "\301", /* 193 */},
+{ "^A", "\302", /* 194 */},
+{ "~A", "\303", /* 195 */},
+{ ":A", "\304", /* 196 */},
+{ "oA", "\305", /* 197 */},
+{ "AE", "\306", /* 198 */},
+{ ",C", "\307", /* 199 */},
+{ "`E", "\310", /* 200 */},
+{ "'E", "\311", /* 201 */},
+{ "^E", "\312", /* 202 */},
+{ ":E", "\313", /* 203 */},
+{ "`I", "\314", /* 204 */},
+{ "'I", "\315", /* 205 */},
+{ "^I", "\316", /* 206 */},
+{ ":I", "\317", /* 207 */},
+{ "-D", "\320", /* 208 */},
+{ "~N", "\321", /* 209 */},
+{ "`O", "\322", /* 210 */},
+{ "'O", "\323", /* 211 */},
+{ "^O", "\324", /* 212 */},
+{ "~O", "\325", /* 213 */},
+{ ":O", "\326", /* 214 */},
+{ "mu", "\327", /* 215 */},
+{ "/O", "\330", /* 216 */},
+{ "`U", "\331", /* 217 */},
+{ "'U", "\332", /* 218 */},
+{ "^U", "\333", /* 219 */},
+{ ":U", "\334", /* 220 */},
+{ "'Y", "\335", /* 221 */},
+{ "TP", "\336", /* 222 */},
+{ "ss", "\337", /* 223 */},
+{ "`a", "\340", /* 224 */},
+{ "'a", "\341", /* 225 */},
+{ "^a", "\342", /* 226 */},
+{ "~a", "\343", /* 227 */},
+{ ":a", "\344", /* 228 */},
+{ "oa", "\345", /* 229 */},
+{ "ae", "\346", /* 230 */},
+{ ",c", "\347", /* 231 */},
+{ "`e", "\350", /* 232 */},
+{ "'e", "\351", /* 233 */},
+{ "^e", "\352", /* 234 */},
+{ ":e", "\353", /* 235 */},
+{ "`i", "\354", /* 236 */},
+{ "'i", "\355", /* 237 */},
+{ "^i", "\356", /* 238 */},
+{ ":i", "\357", /* 239 */},
+{ "Sd", "\360", /* 240 */},
+{ "~n", "\361", /* 241 */},
+{ "`o", "\362", /* 242 */},
+{ "'o", "\363", /* 243 */},
+{ "^o", "\364", /* 244 */},
+{ "~o", "\365", /* 245 */},
+{ ":o", "\366", /* 246 */},
+{ "di", "\367", /* 247 */},
+{ "/o", "\370", /* 248 */},
+{ "`u", "\371", /* 249 */},
+{ "'u", "\372", /* 250 */},
+{ "^u", "\373", /* 251 */},
+{ ":u", "\374", /* 252 */},
+{ "'y", "\375", /* 253 */},
+{ "Tp", "\376", /* 254 */},
+{ ":y", "\377", /* 255 */},
+}};
+
+static DviCharNameMap Adobe_Symbol_map = {
+ "adobe-fontspecific",
+ 1,
+{
+{ 0, /* 0 */},
+{ 0, /* 1 */},
+{ 0, /* 2 */},
+{ 0, /* 3 */},
+{ 0, /* 4 */},
+{ 0, /* 5 */},
+{ 0, /* 6 */},
+{ 0, /* 7 */},
+{ 0, /* 8 */},
+{ 0, /* 9 */},
+{ 0, /* 10 */},
+{ 0, /* 11 */},
+{ 0, /* 12 */},
+{ 0, /* 13 */},
+{ 0, /* 14 */},
+{ 0, /* 15 */},
+{ 0, /* 16 */},
+{ 0, /* 17 */},
+{ 0, /* 18 */},
+{ 0, /* 19 */},
+{ 0, /* 20 */},
+{ 0, /* 21 */},
+{ 0, /* 22 */},
+{ 0, /* 23 */},
+{ 0, /* 24 */},
+{ 0, /* 25 */},
+{ 0, /* 26 */},
+{ 0, /* 27 */},
+{ 0, /* 28 */},
+{ 0, /* 29 */},
+{ 0, /* 30 */},
+{ 0, /* 31 */},
+{ 0, /* 32 */},
+{ "!", /* 33 */},
+{ "fa", /* 34 */},
+{ "#", "sh", /* 35 */},
+{ "te", /* 36 */},
+{ "%", /* 37 */},
+{ "&", /* 38 */},
+{ "st", /* 39 */},
+{ "(", /* 40 */},
+{ ")", /* 41 */},
+{ "**", /* 42 */},
+{ "+", "pl", /* 43 */},
+{ ",", /* 44 */},
+{ "\\-", "mi", /* 45 */},
+{ ".", /* 46 */},
+{ "/", "sl", /* 47 */},
+{ "0", /* 48 */},
+{ "1", /* 49 */},
+{ "2", /* 50 */},
+{ "3", /* 51 */},
+{ "4", /* 52 */},
+{ "5", /* 53 */},
+{ "6", /* 54 */},
+{ "7", /* 55 */},
+{ "8", /* 56 */},
+{ "9", /* 57 */},
+{ ":", /* 58 */},
+{ ";", /* 59 */},
+{ "<", /* 60 */},
+{ "=", "eq", /* 61 */},
+{ ">", /* 62 */},
+{ "?", /* 63 */},
+{ "=~", /* 64 */},
+{ "*A", /* 65 */},
+{ "*B", /* 66 */},
+{ "*X", /* 67 */},
+{ "*D", /* 68 */},
+{ "*E", /* 69 */},
+{ "*F", /* 70 */},
+{ "*G", /* 71 */},
+{ "*Y", /* 72 */},
+{ "*I", /* 73 */},
+{ "+h", /* 74 */},
+{ "*K", /* 75 */},
+{ "*L", /* 76 */},
+{ "*M", /* 77 */},
+{ "*N", /* 78 */},
+{ "*O", /* 79 */},
+{ "*P", /* 80 */},
+{ "*H", /* 81 */},
+{ "*R", /* 82 */},
+{ "*S", /* 83 */},
+{ "*T", /* 84 */},
+{ 0, /* 85 */},
+{ "ts", /* 86 */},
+{ "*W", /* 87 */},
+{ "*C", /* 88 */},
+{ "*Q", /* 89 */},
+{ "*Z", /* 90 */},
+{ "[", "lB", /* 91 */},
+{ "tf", "3d", /* 92 */},
+{ "]", "rB", /* 93 */},
+{ "pp", /* 94 */},
+{ "_", /* 95 */},
+{ "radicalex", /* 96 */},
+{ "*a", /* 97 */},
+{ "*b", /* 98 */},
+{ "*x", /* 99 */},
+{ "*d", /* 100 */},
+{ "*e", /* 101 */},
+{ "*f", /* 102 */},
+{ "*g", /* 103 */},
+{ "*y", /* 104 */},
+{ "*i", /* 105 */},
+{ "+f", /* 106 */},
+{ "*k", /* 107 */},
+{ "*l", /* 108 */},
+{ "*m", "\265", /* 109 */},
+{ "*n", /* 110 */},
+{ "*o", /* 111 */},
+{ "*p", /* 112 */},
+{ "*h", /* 113 */},
+{ "*r", /* 114 */},
+{ "*s", /* 115 */},
+{ "*t", /* 116 */},
+{ "*u", /* 117 */},
+{ "+p", /* 118 */},
+{ "*w", /* 119 */},
+{ "*c", /* 120 */},
+{ "*q", /* 121 */},
+{ "*z", /* 122 */},
+{ "lC", "{", /* 123 */},
+{ "ba", "or", "|", /* 124 */},
+{ "rC", "}", /* 125 */},
+{ "ap", /* 126 */},
+{ 0, /* 127 */},
+{ 0, /* 128 */},
+{ 0, /* 129 */},
+{ 0, /* 130 */},
+{ 0, /* 131 */},
+{ 0, /* 132 */},
+{ 0, /* 133 */},
+{ 0, /* 134 */},
+{ 0, /* 135 */},
+{ 0, /* 136 */},
+{ 0, /* 137 */},
+{ 0, /* 138 */},
+{ 0, /* 139 */},
+{ 0, /* 140 */},
+{ 0, /* 141 */},
+{ 0, /* 142 */},
+{ 0, /* 143 */},
+{ 0, /* 144 */},
+{ 0, /* 145 */},
+{ 0, /* 146 */},
+{ 0, /* 147 */},
+{ 0, /* 148 */},
+{ 0, /* 149 */},
+{ 0, /* 150 */},
+{ 0, /* 151 */},
+{ 0, /* 152 */},
+{ 0, /* 153 */},
+{ 0, /* 154 */},
+{ 0, /* 155 */},
+{ 0, /* 156 */},
+{ 0, /* 157 */},
+{ 0, /* 158 */},
+{ 0, /* 159 */},
+{ 0, /* 160 */},
+{ "*U", /* 161 */},
+{ "fm", /* 162 */},
+{ "<=", /* 163 */},
+{ "f/", /* 164 */},
+{ "if", /* 165 */},
+{ "Fn", /* 166 */},
+{ "CL", /* 167 */},
+{ "DI", /* 168 */},
+{ "HE", /* 169 */},
+{ "SP", /* 170 */},
+{ "<>", /* 171 */},
+{ "<-", /* 172 */},
+{ "ua", "arrowverttp" /* 173 */},
+{ "->", /* 174 */},
+{ "da", "arrowvertbt" /* 175 */},
+{ "de", "\260", /* 176 */},
+{ "+-", "\261", /* 177 */},
+{ "sd", /* 178 */},
+{ ">=", /* 179 */},
+{ "mu", "\327", /* 180 */},
+{ "pt", /* 181 */},
+{ "pd", /* 182 */},
+{ "bu", /* 183 */},
+{ "di", "\367", /* 184 */},
+{ "!=", /* 185 */},
+{ "==", /* 186 */},
+{ "~=", "~~", /* 187 */},
+{ 0, /* 188 */},
+{ "arrowvertex", /* 189 */},
+{ "an", /* 190 */},
+{ "CR", /* 191 */},
+{ "Ah", /* 192 */},
+{ "Im", /* 193 */},
+{ "Re", /* 194 */},
+{ "wp", /* 195 */},
+{ "c*", /* 196 */},
+{ "c+", /* 197 */},
+{ "es", /* 198 */},
+{ "ca", /* 199 */},
+{ "cu", /* 200 */},
+{ "sp", /* 201 */},
+{ "ip", /* 202 */},
+{ "nb", /* 203 */},
+{ "sb", /* 204 */},
+{ "ib", /* 205 */},
+{ "mo", /* 206 */},
+{ "nm", /* 207 */},
+{ "/_", /* 208 */},
+{ "gr", /* 209 */},
+{ "rg", /* 210 */},
+{ "co", /* 211 */},
+{ "tm", /* 212 */},
+{ 0, /* 213 */},
+{ "sr", /* 214 */},
+{ "md", /* 215 */},
+{ "no", "\254", /* 216 */},
+{ "AN", /* 217 */},
+{ "OR", /* 218 */},
+{ "hA", /* 219 */},
+{ "lA", /* 220 */},
+{ "uA", /* 221 */},
+{ "rA", /* 222 */},
+{ "dA", /* 223 */},
+{ "lz", /* 224 */},
+{ "la", /* 225 */},
+{ 0, /* 226 */},
+{ 0, /* 227 */},
+{ 0, /* 228 */},
+{ 0, /* 229 */},
+{ "parenlefttp", /* 230 */},
+{ "parenleftex", /* 231 */},
+{ "parenleftbt", /* 232 */},
+{ "bracketlefttp", "lc", /* 233 */},
+{ "bracketleftex", /* 234 */},
+{ "bracketleftbt", "lf", /* 235 */},
+{ "bracelefttp", "lt", /* 236 */},
+{ "braceleftmid", "lk", /* 237 */},
+{ "braceleftbt", "lb", /* 238 */},
+{ "bracerightex", "braceleftex", "bv", /* 239 */},
+{ 0, /* 240 */},
+{ "ra", /* 241 */},
+{ "is", /* 242 */},
+{ 0, /* 243 */},
+{ 0, /* 244 */},
+{ 0, /* 245 */},
+{ "parenrighttp", /* 246 */},
+{ "parenrightex", /* 247 */},
+{ "parenrightbt", /* 248 */},
+{ "bracketrighttp", "rc", /* 249 */},
+{ "bracketrightex", /* 250 */},
+{ "bracketrightbt", "rf", /* 251 */},
+{ "bracerighttp", "rt" /* 252 */},
+{ "bracerightmid", "rk" /* 253 */},
+{ "bracerightbt", "rb" /* 254 */},
+{ 0, /* 255 */},
+}};
+
+
+static void
+load_standard_maps ()
+{
+ standard_maps_loaded = 1;
+ DviRegisterMap (&ISO8859_1_map);
+ DviRegisterMap (&Adobe_Symbol_map);
+}
diff --git a/src/xditview/DviChar.h b/src/xditview/DviChar.h
new file mode 100644
index 00000000..b075240d
--- /dev/null
+++ b/src/xditview/DviChar.h
@@ -0,0 +1,37 @@
+/*
+ * DviChar.h
+ *
+ * descriptions for mapping dvi names to
+ * font indexes and back. Dvi fonts are all
+ * 256 elements (actually only 256-32 are usable).
+ *
+ * The encoding names are taken from X -
+ * case insensitive, a dash separating the
+ * CharSetRegistry from the CharSetEncoding
+ */
+
+# define DVI_MAX_SYNONYMS 10
+# define DVI_MAP_SIZE 256
+# define DVI_HASH_SIZE 256
+
+typedef struct _dviCharNameHash {
+ struct _dviCharNameHash *next;
+ char *name;
+ int position;
+} DviCharNameHash;
+
+typedef struct _dviCharNameMap {
+ char *encoding;
+ int special;
+ char *dvi_names[DVI_MAP_SIZE][DVI_MAX_SYNONYMS];
+ DviCharNameHash *buckets[DVI_HASH_SIZE];
+} DviCharNameMap;
+
+extern DviCharNameMap *DviFindMap ( /* char *encoding */ );
+extern void DviRegisterMap ( /* DviCharNameMap *map */ );
+#ifdef NOTDEF
+extern char *DviCharName ( /* DviCharNameMap *map, int index, int synonym */ );
+#else
+#define DviCharName(map,index,synonym) ((map)->dvi_names[index][synonym])
+#endif
+extern int DviCharIndex ( /* DviCharNameMap *map, char *name */ );
diff --git a/src/xditview/DviP.h b/src/xditview/DviP.h
new file mode 100644
index 00000000..851fdfee
--- /dev/null
+++ b/src/xditview/DviP.h
@@ -0,0 +1,233 @@
+/*
+ * $XConsortium: DviP.h,v 1.5 89/07/22 19:44:08 keith Exp $
+ */
+
+/*
+ * DviP.h - Private definitions for Dvi widget
+ */
+
+#ifndef _XtDviP_h
+#define _XtDviP_h
+
+#include "Dvi.h"
+#include "DviChar.h"
+#include "device.h"
+
+/***********************************************************************
+ *
+ * Dvi Widget Private Data
+ *
+ ***********************************************************************/
+
+/************************************
+ *
+ * Class structure
+ *
+ ***********************************/
+
+/* Type for save method. */
+
+typedef void (*DviSaveProc)();
+
+/*
+ * New fields for the Dvi widget class record
+ */
+
+
+typedef struct _DviClass {
+ DviSaveProc save;
+} DviClassPart;
+
+/*
+ * Full class record declaration
+ */
+
+typedef struct _DviClassRec {
+ CoreClassPart core_class;
+ DviClassPart command_class;
+} DviClassRec;
+
+extern DviClassRec dviClassRec;
+
+/***************************************
+ *
+ * Instance (widget) structure
+ *
+ **************************************/
+
+/*
+ * a list of fonts we've used for this widget
+ */
+
+typedef struct _dviFontSizeList {
+ struct _dviFontSizeList *next;
+ int size;
+ char *x_name;
+ XFontStruct *font;
+ int doesnt_exist;
+} DviFontSizeList;
+
+typedef struct _dviFontList {
+ struct _dviFontList *next;
+ char *dvi_name;
+ char *x_name;
+ int dvi_number;
+ Boolean initialized;
+ Boolean scalable;
+ DviFontSizeList *sizes;
+ DviCharNameMap *char_map;
+ DeviceFont *device_font;
+} DviFontList;
+
+typedef struct _dviFontMap {
+ struct _dviFontMap *next;
+ char *dvi_name;
+ char *x_name;
+} DviFontMap;
+
+#define DVI_TEXT_CACHE_SIZE 256
+#define DVI_CHAR_CACHE_SIZE 1024
+
+typedef struct _dviCharCache {
+ XTextItem cache[DVI_TEXT_CACHE_SIZE];
+ char adjustable[DVI_TEXT_CACHE_SIZE];
+ char char_cache[DVI_CHAR_CACHE_SIZE];
+ int index;
+ int max;
+ int char_index;
+ int font_size;
+ int font_number;
+ XFontStruct *font;
+ int start_x, start_y;
+ int x, y;
+} DviCharCache;
+
+typedef struct _dviState {
+ struct _dviState *next;
+ int font_size;
+ int font_number;
+ int x;
+ int y;
+} DviState;
+
+typedef struct _dviFileMap {
+ struct _dviFileMap *next;
+ long position;
+ int page_number;
+} DviFileMap;
+
+/*
+ * New fields for the Dvi widget record
+ */
+
+typedef struct {
+ /*
+ * resource specifiable items
+ */
+ char *font_map_string;
+ unsigned long foreground;
+ unsigned long background;
+ int requested_page;
+ int last_page;
+ XFontStruct *default_font;
+ FILE *file;
+ Boolean noPolyText;
+ Boolean seek; /* file is "seekable" */
+ int default_resolution;
+ /*
+ * private state
+ */
+ FILE *tmpFile; /* used when reading stdin */
+ char readingTmp; /* reading now from tmp */
+ char ungot; /* have ungetc'd a char */
+ GC normal_GC;
+ GC fill_GC;
+ DviFileMap *file_map;
+ DviFontList *fonts;
+ DviFontMap *font_map;
+ int current_page;
+ int font_size;
+ int font_number;
+ DeviceFont *device_font;
+ int device_font_number;
+ Device *device;
+ int native;
+ int device_resolution;
+ int display_resolution;
+ int paperlength;
+ int paperwidth;
+ double scale_factor; /* display res / device res */
+ int sizescale;
+ int line_thickness;
+ int line_width;
+
+#define DVI_FILL_MAX 1000
+
+ int fill;
+#define DVI_FILL_WHITE 0
+#define DVI_FILL_GRAY 1
+#define DVI_FILL_BLACK 2
+ int fill_type;
+ Pixmap gray[8];
+ int backing_store;
+ XFontStruct *font;
+ int display_enable;
+ struct ExposedExtents {
+ int x1, y1, x2, y2;
+ } extents;
+ DviState *state;
+ DviCharCache cache;
+ int text_x_width;
+ int text_device_width;
+ int word_flag;
+} DviPart;
+
+#define DviGetIn(dw,cp)\
+ (dw->dvi.tmpFile ? (\
+ DviGetAndPut (dw, cp) \
+ ) :\
+ (*cp = getc (dw->dvi.file))\
+)
+
+#define DviGetC(dw, cp)\
+ (dw->dvi.readingTmp ? (\
+ ((*cp = getc (dw->dvi.tmpFile)) == EOF) ? (\
+ fseek (dw->dvi.tmpFile, 0l, 2),\
+ (dw->dvi.readingTmp = 0),\
+ DviGetIn (dw,cp)\
+ ) : (\
+ *cp\
+ )\
+ ) : (\
+ DviGetIn(dw,cp)\
+ )\
+)
+
+#define DviUngetC(dw, c)\
+ (dw->dvi.readingTmp ? (\
+ ungetc (c, dw->dvi.tmpFile)\
+ ) : ( \
+ (dw->dvi.ungot = 1),\
+ ungetc (c, dw->dvi.file)))
+
+/*
+ * Full widget declaration
+ */
+
+typedef struct _DviRec {
+ CorePart core;
+ DviPart dvi;
+} DviRec;
+
+#define InheritSaveToFile ((DviSaveProc)_XtInherit)
+
+extern XFontStruct *QueryFont ();
+
+extern DviCharNameMap *QueryFontMap ();
+
+extern DeviceFont *QueryDeviceFont ();
+
+extern char *GetWord(), *GetLine();
+#endif /* _XtDviP_h */
+
+
diff --git a/src/xditview/FontMap b/src/xditview/FontMap
new file mode 100644
index 00000000..90911f04
--- /dev/null
+++ b/src/xditview/FontMap
@@ -0,0 +1,17 @@
+TR -adobe-times-medium-r-normal--*-*-*-*-p-*-iso8859-1
+TI -adobe-times-medium-i-normal--*-*-*-*-p-*-iso8859-1
+TB -adobe-times-bold-r-normal--*-*-*-*-p-*-iso8859-1
+TBI -adobe-times-bold-i-normal--*-*-*-*-p-*-iso8859-1
+CR -adobe-courier-medium-r-normal--*-*-*-*-m-*-iso8859-1
+CI -adobe-courier-medium-o-normal--*-*-*-*-m-*-iso8859-1
+CB -adobe-courier-bold-r-normal--*-*-*-*-m-*-iso8859-1
+CBI -adobe-courier-bold-o-normal--*-*-*-*-m-*-iso8859-1
+HR -adobe-helvetica-medium-r-normal--*-*-*-*-p-*-iso8859-1
+HI -adobe-helvetica-medium-o-normal--*-*-*-*-p-*-iso8859-1
+HB -adobe-helvetica-bold-r-normal--*-*-*-*-p-*-iso8859-1
+HBI -adobe-helvetica-bold-o-normal--*-*-*-*-p-*-iso8859-1
+NR -adobe-new century schoolbook-medium-r-normal--*-*-*-*-p-*-iso8859-1
+NI -adobe-new century schoolbook-medium-i-normal--*-*-*-*-p-*-iso8859-1
+NB -adobe-new century schoolbook-bold-r-normal--*-*-*-*-p-*-iso8859-1
+NBI -adobe-new century schoolbook-bold-i-normal--*-*-*-*-p-*-iso8859-1
+S -adobe-symbol-medium-r-normal--*-*-*-*-p-*-adobe-fontspecific
diff --git a/src/xditview/GXditview-ad.h b/src/xditview/GXditview-ad.h
new file mode 100644
index 00000000..d9be3da2
--- /dev/null
+++ b/src/xditview/GXditview-ad.h
@@ -0,0 +1,52 @@
+"GXditview.height: 840",
+"GXditview.paned.allowResize: true",
+"GXditview.paned.viewport.allowVert: true",
+"GXditview.paned.viewport.allowHoriz: true",
+"GXditview.paned.viewport.skipAdjust: false",
+"GXditview.paned.viewport.width: 600",
+"GXditview.paned.viewport.height: 800",
+"GXditview.paned.viewport.showGrip: false",
+"GXditview.paned.label.skipAdjust: true",
+"GXditview.paned.viewport.dvi.translations: #augment \
+ <Btn1Down>: XawPositionSimpleMenu(menu) MenuPopup(menu)\\n\
+ <Key>Next: NextPage()\\n\
+ <Key>n: NextPage()\\n\
+ <Key>space: NextPage()\\n\
+ <Key>Return: NextPage()\\n\
+ <Key>Prior: PreviousPage()\\n\
+ <Key>p: PreviousPage()\\n\
+ <Key>BackSpace: PreviousPage()\\n\
+ <Key>Delete: PreviousPage()\\n\
+ <Key>Select: SelectPage()\\n\
+ <Key>Find: OpenFile()\\n\
+ <Key>r: Rerasterize()\\n\
+ <Key>q: Quit()",
+"GXditview.paned.label.translations: #augment \
+ <Btn1Down>: XawPositionSimpleMenu(menu) MenuPopup(menu)\\n\
+ <Key>Next: NextPage()\\n\
+ <Key>n: NextPage()\\n\
+ <Key>space: NextPage()\\n\
+ <Key>Return: NextPage()\\n\
+ <Key>Prior: PreviousPage()\\n\
+ <Key>p: PreviousPage()\\n\
+ <Key>BackSpace: PreviousPage()\\n\
+ <Key>Delete: PreviousPage()\\n\
+ <Key>Select: SelectPage()\\n\
+ <Key>Find: OpenFile()\\n\
+ <Key>r: Rerasterize()\\n\
+ <Key>q: Quit()",
+"GXditview.menu.nextPage.label: Next Page",
+"GXditview.menu.previousPage.label: Previous Page",
+"GXditview.menu.selectPage.label: Select Page",
+"GXditview.menu.print.label: Print",
+"GXditview.menu.openFile.label: Open",
+"GXditview.menu.quit.label: Quit",
+"GXditview.promptShell.allowShellResize: true",
+"GXditview.promptShell.promptDialog.value.translations: #override \
+ <Key>Return: Accept()",
+"GXditview.promptShell.promptDialog.accept.label: Accept",
+"GXditview.promptShell.promptDialog.accept.translations: #override \
+ <BtnUp>: Accept() unset()",
+"GXditview.promptShell.promptDialog.cancel.label: Cancel",
+"GXditview.promptShell.promptDialog.cancel.translations: #override \
+ <BtnUp>: Cancel() unset()",
diff --git a/src/xditview/GXditview.ad b/src/xditview/GXditview.ad
new file mode 100644
index 00000000..e99ff5e1
--- /dev/null
+++ b/src/xditview/GXditview.ad
@@ -0,0 +1,57 @@
+GXditview.height: 840
+
+GXditview.paned.allowResize: true
+GXditview.paned.viewport.allowVert: true
+GXditview.paned.viewport.allowHoriz: true
+GXditview.paned.viewport.skipAdjust: false
+GXditview.paned.viewport.width: 600
+GXditview.paned.viewport.height: 800
+GXditview.paned.viewport.showGrip: false
+GXditview.paned.label.skipAdjust: true
+
+GXditview.paned.viewport.dvi.translations: #augment \
+ <Btn1Down>: XawPositionSimpleMenu(menu) MenuPopup(menu)\n\
+ <Key>Next: NextPage()\n\
+ <Key>n: NextPage()\n\
+ <Key>space: NextPage()\n\
+ <Key>Return: NextPage()\n\
+ <Key>Prior: PreviousPage()\n\
+ <Key>p: PreviousPage()\n\
+ <Key>BackSpace: PreviousPage()\n\
+ <Key>Delete: PreviousPage()\n\
+ <Key>Select: SelectPage()\n\
+ <Key>Find: OpenFile()\n\
+ <Key>r: Rerasterize()\n\
+ <Key>q: Quit()
+GXditview.paned.label.translations: #augment \
+ <Btn1Down>: XawPositionSimpleMenu(menu) MenuPopup(menu)\n\
+ <Key>Next: NextPage()\n\
+ <Key>n: NextPage()\n\
+ <Key>space: NextPage()\n\
+ <Key>Return: NextPage()\n\
+ <Key>Prior: PreviousPage()\n\
+ <Key>p: PreviousPage()\n\
+ <Key>BackSpace: PreviousPage()\n\
+ <Key>Delete: PreviousPage()\n\
+ <Key>Select: SelectPage()\n\
+ <Key>Find: OpenFile()\n\
+ <Key>r: Rerasterize()\n\
+ <Key>q: Quit()
+GXditview.menu.nextPage.label: Next Page
+GXditview.menu.previousPage.label: Previous Page
+GXditview.menu.selectPage.label: Select Page
+GXditview.menu.print.label: Print
+GXditview.menu.openFile.label: Open
+GXditview.menu.quit.label: Quit
+
+GXditview.promptShell.allowShellResize: true
+GXditview.promptShell.promptDialog.value.translations: #override \
+ <Key>Return: Accept()
+
+GXditview.promptShell.promptDialog.accept.label: Accept
+GXditview.promptShell.promptDialog.accept.translations: #override \
+ <BtnUp>: Accept() unset()
+
+GXditview.promptShell.promptDialog.cancel.label: Cancel
+GXditview.promptShell.promptDialog.cancel.translations: #override \
+ <BtnUp>: Cancel() unset()
diff --git a/src/xditview/INSTALL b/src/xditview/INSTALL
new file mode 100644
index 00000000..144118fd
--- /dev/null
+++ b/src/xditview/INSTALL
@@ -0,0 +1,20 @@
+This version of gxditview uses imake.
+
+Here are the steps needed to install gxditview:
+
+- edit the Imakefile if necessary
+
+- xmkmf
+
+- make depend
+
+- make
+
+- make install
+
+- make install.man (installs the man page)
+
+The gxditview binary will be installed in the usual place for X
+binaries (eg /usr/bin/X11). Previous versions of gxditview were
+installed along with the other groff binaries (eg in /usr/local/bin);
+you will need to remove these by hand.
diff --git a/src/xditview/Imakefile b/src/xditview/Imakefile
new file mode 100755
index 00000000..ad94a07b
--- /dev/null
+++ b/src/xditview/Imakefile
@@ -0,0 +1,60 @@
+GROFF_LIBDIR = /usr/local/share/groff
+GROFF_FONTDIR = $(GROFF_LIBDIR)/font
+GROFF_FONTPATH = .:$(GROFF_FONTDIR):/usr/local/lib/font:/usr/lib/font
+DPIS = 75 100
+
+PROGRAMS = gxditview xtotroff
+DEPLIBS = XawClientDepLibs
+LOCAL_LIBRARIES = XawClientLibs
+SRCS1 = xditview.c Dvi.c draw.c font.c lex.c page.c \
+ parse.c XFontName.c DviChar.c device.c
+OBJS1 = xditview.o Dvi.o draw.o font.o lex.o page.o \
+ parse.o XFontName.o DviChar.o device.o
+SRCS2 = xtotroff.c XFontName.c DviChar.c
+OBJS2 = xtotroff.o XFontName.o DviChar.o
+INCLUDES = -I$(TOOLKITSRC) -I$(TOP)
+MATHLIB = -lm
+DEFINES = $(SIGNAL_DEFINES) -DFONTPATH=\"$(GROFF_FONTPATH)\" # -DX_NOT_STDC_ENV
+
+DEVDIR = ../../font
+MKINSTALLDIRS = ../../mkinstalldirs
+
+ComplexProgramTarget_1(gxditview,$(LOCAL_LIBRARIES),$(MATHLIB))
+NormalProgramTarget(xtotroff,$(OBJS2),$(DEPXLIB),$(XLIB), /**/)
+
+InstallAppDefaults(GXditview)
+
+fonts: xtotroff DESC FontMap
+ @dir=`pwd`; \
+ fonts=`sed -e 's/[ ].*//' FontMap`; \
+ for dpi in $(DPIS); do \
+ echo Making devX$$dpi; \
+ test -d $(DEVDIR)/devX$$dpi || \
+ $(MKINSTALLDIRS) $(DEVDIR)/devX$$dpi; \
+ rm -f $(DEVDIR)/devX$$dpi/DESC; \
+ sed -e "s/res 75/res $$dpi/" DESC >$(DEVDIR)/devX$$dpi/DESC; \
+ (cd $(DEVDIR)/devX$$dpi; \
+ rm -f Makefile.sub; \
+ echo DEV=X$$dpi >Makefile.sub; \
+ echo DEVFILES=DESC $$fonts >>Makefile.sub; \
+ $$dir/xtotroff -g -r $$dpi -s 10 $$dir/FontMap); \
+ echo Making devX$$dpi-12; \
+ test -d $(DEVDIR)/devX$$dpi-12 || \
+ $(MKINSTALLDIRS) $(DEVDIR)/devX$$dpi-12; \
+ rm -f $(DEVDIR)/devX$$dpi-12/DESC; \
+ sed -e "s/res 75/res $$dpi/" -e 's/unitwidth 10/unitwidth 12/' DESC \
+ >$(DEVDIR)/devX$$dpi-12/DESC; \
+ (cd $(DEVDIR)/devX$$dpi-12; \
+ rm -f Makefile.sub; \
+ echo DEV=X$$dpi-12 >Makefile.sub; \
+ echo DEVFILES=DESC $$fonts >>Makefile.sub; \
+ $$dir/xtotroff -g -r $$dpi -s 12 $$dir/FontMap); \
+ done
+
+GXditview-ad.h: GXditview.ad
+ /bin/sh ad2c GXditview.ad >GXditview-ad.h
+
+extraclean: clean
+ -rm -f junk tmp grot old Makefile
+
+FORCE:
diff --git a/src/xditview/Menu.h b/src/xditview/Menu.h
new file mode 100644
index 00000000..c306b274
--- /dev/null
+++ b/src/xditview/Menu.h
@@ -0,0 +1,46 @@
+/*
+ * $XConsortium: Menu.h,v 1.2 89/07/21 14:22:10 jim Exp $
+ */
+
+#ifndef _XtMenu_h
+#define _XtMenu_h
+
+/***********************************************************************
+ *
+ * Menu Widget
+ *
+ ***********************************************************************/
+
+/* Parameters:
+
+ Name Class RepType Default Value
+ ---- ----- ------- -------------
+ background Background pixel White
+ border BorderColor pixel Black
+ borderWidth BorderWidth int 1
+ height Height int 120
+ mappedWhenManaged MappedWhenManaged Boolean True
+ reverseVideo ReverseVideo Boolean False
+ width Width int 120
+ x Position int 0
+ y Position int 0
+
+*/
+
+#define XtNmenuEntries "menuEntries"
+#define XtNhorizontalPadding "horizontalPadding"
+#define XtNverticalPadding "verticalPadding"
+#define XtNselection "Selection"
+
+#define XtCMenuEntries "MenuEntries"
+#define XtCPadding "Padding"
+#define XtCSelection "Selection"
+
+typedef struct _MenuRec *MenuWidget; /* completely defined in MenuPrivate.h */
+typedef struct _MenuClassRec *MenuWidgetClass; /* completely defined in MenuPrivate.h */
+
+extern WidgetClass menuWidgetClass;
+
+extern Widget XawMenuCreate ();
+#endif /* _XtMenu_h */
+/* DON'T ADD STUFF AFTER THIS #endif */
diff --git a/src/xditview/README b/src/xditview/README
new file mode 100644
index 00000000..b18f64a7
--- /dev/null
+++ b/src/xditview/README
@@ -0,0 +1,14 @@
+This is gxditview, a X11 previewer for groff based on MIT's xditview.
+This version can be used with the output of gtroff -Tps as well as
+with -TX75 and -TX100. You will need X11R5 or newer to install it (it
+might work on X11R4, but I haven't tested it.)
+
+See the file INSTALL in this directory for installation instructions.
+
+xditview is copyrighted by MIT under the usual X terms (see
+gxditview.man); my changes to it are in the public domain.
+
+Please report bugs to bug-groff@gnu.org.
+
+James Clark
+jjc@jclark.com
diff --git a/src/xditview/TODO b/src/xditview/TODO
new file mode 100644
index 00000000..161a7cf1
--- /dev/null
+++ b/src/xditview/TODO
@@ -0,0 +1,17 @@
+Replace Imakefile with a configure script.
+
+Better error handling.
+
+Resource and command-line option to specify font path.
+
+Resource to specify name of environment variable from which to get the
+font path.
+
+Have character substitutions (currently done in draw.c:FakeCharacter)
+specified in a resource (similar format to FontMap).
+
+The initial width of the dialog box should expand to accommodate the
+default value.
+
+Option in Print dialog to specify that only the current page should be
+printed.
diff --git a/src/xditview/XFontName.c b/src/xditview/XFontName.c
new file mode 100644
index 00000000..5ca9bb81
--- /dev/null
+++ b/src/xditview/XFontName.c
@@ -0,0 +1,256 @@
+/*
+ * XFontName.c
+ *
+ * build/parse X Font name strings
+ */
+
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+#include "XFontName.h"
+#include <ctype.h>
+
+static char *
+extractStringField (name, buffer, size, attrp, bit)
+ char *name;
+ char *buffer;
+ int size;
+ unsigned int *attrp;
+ unsigned int bit;
+{
+ char *buf = buffer;
+
+ if (!*name)
+ return 0;
+ while (*name && *name != '-' && size > 0) {
+ *buf++ = *name++;
+ --size;
+ }
+ if (size <= 0)
+ return 0;
+ *buf = '\0';
+ if (buffer[0] != '*' || buffer[1] != '\0')
+ *attrp |= bit;
+ if (*name == '-')
+ return name+1;
+ return name;
+}
+
+static char *
+extractUnsignedField (name, result, attrp, bit)
+ char *name;
+ unsigned int *result;
+ unsigned int *attrp;
+ unsigned int bit;
+{
+ char buf[256];
+ char *c;
+ unsigned int i;
+
+ name = extractStringField (name, buf, sizeof (buf), attrp, bit);
+ if (!name)
+ return 0;
+ if (!(*attrp & bit))
+ return name;
+ i = 0;
+ for (c = buf; *c; c++) {
+ if (!isdigit (*c))
+ return 0;
+ i = i * 10 + (*c - '0');
+ }
+ *result = i;
+ return name;
+}
+
+Bool
+XParseFontName (fontNameString, fontName, fontNameAttributes)
+ XFontNameString fontNameString;
+ XFontName *fontName;
+ unsigned int *fontNameAttributes;
+{
+ char *name = fontNameString;
+ XFontName temp;
+ unsigned int attributes = 0;
+
+#define GetString(field,bit)\
+ if (!(name = extractStringField \
+ (name, temp.field, sizeof (temp.field),\
+ &attributes, bit))) \
+ return False;
+
+#define GetUnsigned(field,bit)\
+ if (!(name = extractUnsignedField \
+ (name, &temp.field, \
+ &attributes, bit))) \
+ return False;
+
+ GetString (Registry, FontNameRegistry)
+ GetString (Foundry, FontNameFoundry)
+ GetString (FamilyName, FontNameFamilyName)
+ GetString (WeightName, FontNameWeightName)
+ GetString (Slant, FontNameSlant)
+ GetString (SetwidthName, FontNameSetwidthName)
+ GetString (AddStyleName, FontNameAddStyleName)
+ GetUnsigned (PixelSize, FontNamePixelSize)
+ GetUnsigned (PointSize, FontNamePointSize)
+ GetUnsigned (ResolutionX, FontNameResolutionX)
+ GetUnsigned (ResolutionY, FontNameResolutionY)
+ GetString (Spacing, FontNameSpacing)
+ GetUnsigned (AverageWidth, FontNameAverageWidth)
+ GetString (CharSetRegistry, FontNameCharSetRegistry)
+ if (!*name) {
+ temp.CharSetEncoding[0] = '\0';
+ attributes |= FontNameCharSetEncoding;
+ } else {
+ GetString (CharSetEncoding, FontNameCharSetEncoding)
+ }
+ *fontName = temp;
+ *fontNameAttributes = attributes;
+ return True;
+}
+
+static char *
+utoa (u, s, size)
+ unsigned int u;
+ char *s;
+ int size;
+{
+ char *t;
+
+ t = s + size;
+ *--t = '\0';
+ do
+ *--t = (u % 10) + '0';
+ while (u /= 10);
+ return t;
+}
+
+Bool
+XFormatFontName (fontName, fontNameAttributes, fontNameString)
+ XFontName *fontName;
+ unsigned int fontNameAttributes;
+ XFontNameString fontNameString;
+{
+ XFontNameString tmp;
+ char *name = tmp, *f;
+ int left = sizeof (tmp) - 1;
+ char number[32];
+
+#define PutString(field, bit)\
+ f = (fontNameAttributes & bit) ? \
+ fontName->field \
+ : "*"; \
+ if ((left -= strlen (f)) < 0) \
+ return False; \
+ while (*f) \
+ if ((*name++ = *f++) == '-') \
+ return False;
+#define PutHyphen()\
+ if (--left < 0) \
+ return False; \
+ *name++ = '-';
+
+#define PutUnsigned(field, bit) \
+ f = (fontNameAttributes & bit) ? \
+ utoa (fontName->field, number, sizeof (number)) \
+ : "*"; \
+ if ((left -= strlen (f)) < 0) \
+ return False; \
+ while (*f) \
+ *name++ = *f++;
+
+ PutString (Registry, FontNameRegistry)
+ PutHyphen ();
+ PutString (Foundry, FontNameFoundry)
+ PutHyphen ();
+ PutString (FamilyName, FontNameFamilyName)
+ PutHyphen ();
+ PutString (WeightName, FontNameWeightName)
+ PutHyphen ();
+ PutString (Slant, FontNameSlant)
+ PutHyphen ();
+ PutString (SetwidthName, FontNameSetwidthName)
+ PutHyphen ();
+ PutString (AddStyleName, FontNameAddStyleName)
+ PutHyphen ();
+ PutUnsigned (PixelSize, FontNamePixelSize)
+ PutHyphen ();
+ PutUnsigned (PointSize, FontNamePointSize)
+ PutHyphen ();
+ PutUnsigned (ResolutionX, FontNameResolutionX)
+ PutHyphen ();
+ PutUnsigned (ResolutionY, FontNameResolutionY)
+ PutHyphen ();
+ PutString (Spacing, FontNameSpacing)
+ PutHyphen ();
+ PutUnsigned (AverageWidth, FontNameAverageWidth)
+ PutHyphen ();
+ PutString (CharSetRegistry, FontNameCharSetRegistry)
+ PutHyphen ();
+ PutString (CharSetEncoding, FontNameCharSetEncoding)
+ *name = '\0';
+ strcpy (fontNameString, tmp);
+ return True;
+}
+
+Bool
+XCompareFontName (name1, name2, fontNameAttributes)
+ XFontName *name1, *name2;
+ unsigned int fontNameAttributes;
+{
+#define CompareString(field,bit) \
+ if (fontNameAttributes & bit) \
+ if (strcmp (name1->field, name2->field)) \
+ return False;
+
+#define CompareUnsigned(field,bit) \
+ if (fontNameAttributes & bit) \
+ if (name1->field != name2->field) \
+ return False;
+
+ CompareString (Registry, FontNameRegistry)
+ CompareString (Foundry, FontNameFoundry)
+ CompareString (FamilyName, FontNameFamilyName)
+ CompareString (WeightName, FontNameWeightName)
+ CompareString (Slant, FontNameSlant)
+ CompareString (SetwidthName, FontNameSetwidthName)
+ CompareString (AddStyleName, FontNameAddStyleName)
+ CompareUnsigned (PixelSize, FontNamePixelSize)
+ CompareUnsigned (PointSize, FontNamePointSize)
+ CompareUnsigned (ResolutionX, FontNameResolutionX)
+ CompareUnsigned (ResolutionY, FontNameResolutionY)
+ CompareString (Spacing, FontNameSpacing)
+ CompareUnsigned (AverageWidth, FontNameAverageWidth)
+ CompareString (CharSetRegistry, FontNameCharSetRegistry)
+ CompareString (CharSetEncoding, FontNameCharSetEncoding)
+ return True;
+}
+
+XCopyFontName (name1, name2, fontNameAttributes)
+ XFontName *name1, *name2;
+ unsigned int fontNameAttributes;
+{
+#define CopyString(field,bit) \
+ if (fontNameAttributes & bit) \
+ strcpy (name2->field, name1->field);
+
+#define CopyUnsigned(field,bit) \
+ if (fontNameAttributes & bit) \
+ name2->field = name1->field;
+
+ CopyString (Registry, FontNameRegistry)
+ CopyString (Foundry, FontNameFoundry)
+ CopyString (FamilyName, FontNameFamilyName)
+ CopyString (WeightName, FontNameWeightName)
+ CopyString (Slant, FontNameSlant)
+ CopyString (SetwidthName, FontNameSetwidthName)
+ CopyString (AddStyleName, FontNameAddStyleName)
+ CopyUnsigned (PixelSize, FontNamePixelSize)
+ CopyUnsigned (PointSize, FontNamePointSize)
+ CopyUnsigned (ResolutionX, FontNameResolutionX)
+ CopyUnsigned (ResolutionY, FontNameResolutionY)
+ CopyString (Spacing, FontNameSpacing)
+ CopyUnsigned (AverageWidth, FontNameAverageWidth)
+ CopyString (CharSetRegistry, FontNameCharSetRegistry)
+ CopyString (CharSetEncoding, FontNameCharSetEncoding)
+ return True;
+}
diff --git a/src/xditview/XFontName.h b/src/xditview/XFontName.h
new file mode 100644
index 00000000..efe9eb16
--- /dev/null
+++ b/src/xditview/XFontName.h
@@ -0,0 +1,45 @@
+typedef struct _xFontName {
+ char Registry[256];
+ char Foundry[256];
+ char FamilyName[256];
+ char WeightName[256];
+ char Slant[3];
+ char SetwidthName[256];
+ char AddStyleName[256];
+ unsigned int PixelSize;
+ unsigned int PointSize;
+ unsigned int ResolutionX;
+ unsigned int ResolutionY;
+ char Spacing[2];
+ unsigned int AverageWidth;
+ char CharSetRegistry[256];
+ char CharSetEncoding[256];
+} XFontName;
+
+#define FontNameRegistry (1<<0)
+#define FontNameFoundry (1<<1)
+#define FontNameFamilyName (1<<2)
+#define FontNameWeightName (1<<3)
+#define FontNameSlant (1<<4)
+#define FontNameSetwidthName (1<<5)
+#define FontNameAddStyleName (1<<6)
+#define FontNamePixelSize (1<<7)
+#define FontNamePointSize (1<<8)
+#define FontNameResolutionX (1<<9)
+#define FontNameResolutionY (1<<10)
+#define FontNameSpacing (1<<11)
+#define FontNameAverageWidth (1<<12)
+#define FontNameCharSetRegistry (1<<13)
+#define FontNameCharSetEncoding (1<<14)
+
+#define SlantRoman "R"
+#define SlantItalic "I"
+#define SlantOblique "O"
+#define SlantReverseItalic "RI"
+#define SlantReverseOblique "RO"
+
+#define SpacingMonoSpaced "M"
+#define SpacingProportional "P"
+#define SpacingCharacterCell "C"
+
+typedef char XFontNameString[256];
diff --git a/src/xditview/ad2c b/src/xditview/ad2c
new file mode 100644
index 00000000..651ab8c4
--- /dev/null
+++ b/src/xditview/ad2c
@@ -0,0 +1,62 @@
+#!/bin/sh
+#
+# ad2c : Convert app-defaults file to C strings decls.
+#
+# George Ferguson, ferguson@cs.rcohester.edu, 12 Nov 1990.
+# 19 Mar 1991: gf
+# Made it self-contained.
+# 6 Jan 1992: mycroft@gnu.ai.mit.edu (Charles Hannum)
+# Removed use of "-n" and ":read" label since Gnu and
+# IBM sed print pattern space on "n" command. Still works
+# with Sun sed, of course.
+# 7 Jan 1992: matthew@sunpix.East.Sun.COM (Matthew Stier)
+# Escape quotes after escaping backslashes.
+# 8 Jul 1992: Version 1.6
+# Manpage fixes.
+# 19 Apr 1993: Version 1.7
+# Remove comments that were inside the sed command since
+# some versions of sed don't like them. The comments are
+# now given here in the header.
+#
+# Comments on the script by line:
+# /^!/d Remove comments
+# /^$/d Remove blanks
+# s/\\/\\\\/g Escape backslashes...
+# s/\\$//g ...except the line continuation ones
+# s/"/\\"/g Escape quotes
+# s/^/"/ Add leading quote
+# : test Establish label for later branch
+# /\\$/b slash Branch to label "slash" if line ends in backslash
+# s/$/",/ Otherwise add closing quote and comma...
+# p ...output the line...
+# d ...and clear the pattern space so it's not printed again
+# : slash Branch comes here if line ends in backslash
+# n Read next line, append to pattern space
+# [...] The "d" and "s" commands that follow just delete
+# comments and blank lines and escape control sequences
+# b test Branch up to see if the line ends in backslash or not
+#
+
+sed '
+/^!/d
+/^$/d
+s/\\/\\\\/g
+s/\\$//g
+s/"/\\"/g
+s/^/"/
+: test
+/\\$/b slash
+s/$/",/
+p
+d
+: slash
+n
+/^!/d
+/^$/d
+s/"/\\"/g
+s/\\\\/\\/g
+s/\\n/\\\\n/g
+s/\\t/\\\\t/g
+s/\\f/\\\\f/g
+s/\\b/\\\\b/g
+b test' "$@"
diff --git a/src/xditview/device.c b/src/xditview/device.c
new file mode 100644
index 00000000..f1e51dea
--- /dev/null
+++ b/src/xditview/device.c
@@ -0,0 +1,594 @@
+/* device.c */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include <X11/Xos.h>
+#include <X11/Intrinsic.h>
+
+#include "device.h"
+
+#ifndef FONTPATH
+#define FONTPATH "/usr/local/share/groff/font:/usr/local/lib/font:/usr/lib/font"
+#endif
+
+#ifndef isascii
+#define isascii(c) (1)
+#endif
+
+extern void exit();
+#ifndef strtok
+extern char *strtok();
+#endif
+#ifndef strchr
+extern char *strchr();
+#endif
+#ifndef getenv
+extern char *getenv();
+#endif
+
+/* Name of environment variable containing path to be used for
+searching for device and font description files. */
+#define FONTPATH_ENV_VAR "GROFF_FONT_PATH"
+
+#define WS " \t\r\n"
+
+#ifndef INT_MIN
+/* Minimum and maximum values a `signed int' can hold. */
+#define INT_MIN (-INT_MAX-1)
+#define INT_MAX 2147483647
+#endif
+
+#define CHAR_TABLE_SIZE 307
+
+struct _DeviceFont {
+ char *name;
+ int special;
+ DeviceFont *next;
+ Device *dev;
+ struct charinfo *char_table[CHAR_TABLE_SIZE];
+ struct charinfo *code_table[256];
+};
+
+struct charinfo {
+ int width;
+ int code;
+ struct charinfo *next;
+ struct charinfo *code_next;
+ char name[1];
+};
+
+static char *current_filename = 0;
+static int current_lineno = -1;
+
+static void error();
+static FILE *open_device_file();
+static DeviceFont *load_font();
+static Device *new_device();
+static DeviceFont *new_font();
+static void delete_font();
+static unsigned hash_name();
+static struct charinfo *add_char();
+static int read_charset_section();
+static char *canonicalize_name();
+
+static
+Device *new_device(name)
+ char *name;
+{
+ Device *dev;
+
+ dev = XtNew(Device);
+ dev->sizescale = 1;
+ dev->res = 0;
+ dev->unitwidth = 0;
+ dev->fonts = 0;
+ dev->X11 = 0;
+ dev->paperlength = 0;
+ dev->paperwidth = 0;
+ dev->name = XtNewString(name);
+ return dev;
+}
+
+void device_destroy(dev)
+ Device *dev;
+{
+ DeviceFont *f;
+
+ if (!dev)
+ return;
+ f = dev->fonts;
+ while (f) {
+ DeviceFont *tem = f;
+ f = f->next;
+ delete_font(tem);
+ }
+
+ XtFree(dev->name);
+ XtFree((char *)dev);
+}
+
+Device *device_load(name)
+ char *name;
+{
+ Device *dev;
+ FILE *fp;
+ int err = 0;
+ char buf[256];
+
+ fp = open_device_file(name, "DESC", &current_filename);
+ if (!fp)
+ return 0;
+ dev = new_device(name);
+ current_lineno = 0;
+ while (fgets(buf, sizeof(buf), fp)) {
+ char *p;
+ current_lineno++;
+ p = strtok(buf, WS);
+ if (p) {
+ int *np = 0;
+ char *q;
+
+ if (strcmp(p, "charset") == 0)
+ break;
+ if (strcmp(p, "X11") == 0)
+ dev->X11 = 1;
+ else if (strcmp(p, "sizescale") == 0)
+ np = &dev->sizescale;
+ else if (strcmp(p, "res") == 0)
+ np = &dev->res;
+ else if (strcmp(p, "unitwidth") == 0)
+ np = &dev->unitwidth;
+ else if (strcmp(p, "paperwidth") == 0)
+ np = &dev->paperwidth;
+ else if (strcmp(p, "paperlength") == 0)
+ np = &dev->paperlength;
+
+ if (np) {
+ q = strtok((char *)0, WS);
+ if (!q || sscanf(q, "%d", np) != 1 || *np <= 0) {
+ error("bad argument");
+ err = 1;
+ break;
+ }
+ }
+ }
+ }
+ fclose(fp);
+ current_lineno = -1;
+ if (!err) {
+ if (dev->res == 0) {
+ error("missing res line");
+ err = 1;
+ }
+ else if (dev->unitwidth == 0) {
+ error("missing unitwidth line");
+ err = 1;
+ }
+ }
+ if (dev->paperlength == 0)
+ dev->paperlength = dev->res*11;
+ if (dev->paperwidth == 0)
+ dev->paperwidth = dev->res*8 + dev->res/2;
+ if (err) {
+ device_destroy(dev);
+ dev = 0;
+ }
+ XtFree(current_filename);
+ current_filename = 0;
+ return dev;
+}
+
+
+DeviceFont *device_find_font(dev, name)
+ Device *dev;
+ char *name;
+{
+ DeviceFont *f;
+
+ if (!dev)
+ return 0;
+ for (f = dev->fonts; f; f = f->next)
+ if (strcmp(f->name, name) == 0)
+ return f;
+ return load_font(dev, name);
+}
+
+static
+DeviceFont *load_font(dev, name)
+ Device *dev;
+ char *name;
+{
+ FILE *fp;
+ char buf[256];
+ DeviceFont *f;
+ int special = 0;
+
+ fp = open_device_file(dev->name, name, &current_filename);
+ if (!fp)
+ return 0;
+ current_lineno = 0;
+ for (;;) {
+ char *p;
+
+ if (!fgets(buf, sizeof(buf), fp)) {
+ error("no charset line");
+ return 0;
+ }
+ current_lineno++;
+ p = strtok(buf, WS);
+ /* charset must be on a line by itself */
+ if (p && strcmp(p, "charset") == 0 && strtok((char *)0, WS) == 0)
+ break;
+ if (p && strcmp(p, "special") == 0)
+ special = 1;
+ }
+ f = new_font(name, dev);
+ f->special = special;
+ if (!read_charset_section(f, fp)) {
+ delete_font(f);
+ f = 0;
+ }
+ else {
+ f->next = dev->fonts;
+ dev->fonts = f;
+ }
+ fclose(fp);
+ XtFree(current_filename);
+ current_filename = 0;
+ return f;
+}
+
+static
+DeviceFont *new_font(name, dev)
+ char *name;
+ Device *dev;
+{
+ int i;
+ DeviceFont *f;
+
+ f = XtNew(DeviceFont);
+ f->name = XtNewString(name);
+ f->dev = dev;
+ f->special = 0;
+ f->next = 0;
+ for (i = 0; i < CHAR_TABLE_SIZE; i++)
+ f->char_table[i] = 0;
+ for (i = 0; i < 256; i++)
+ f->code_table[i] = 0;
+ return f;
+}
+
+static
+void delete_font(f)
+ DeviceFont *f;
+{
+ int i;
+
+ if (!f)
+ return;
+ XtFree(f->name);
+ for (i = 0; i < CHAR_TABLE_SIZE; i++) {
+ struct charinfo *ptr = f->char_table[i];
+ while (ptr) {
+ struct charinfo *tem = ptr;
+ ptr = ptr->next;
+ XtFree((char *)tem);
+ }
+ }
+ XtFree((char *)f);
+}
+
+
+static
+unsigned hash_name(name)
+ char *name;
+{
+ unsigned n = 0;
+ /* XXX do better than this */
+ while (*name)
+ n = (n << 1) ^ *name++;
+
+ return n;
+}
+
+static
+int scale_round(n, x, y)
+ int n, x, y;
+{
+ int y2;
+
+ if (x == 0)
+ return 0;
+ y2 = y/2;
+ if (n >= 0) {
+ if (n <= (INT_MAX - y2)/x)
+ return (n*x + y2)/y;
+ }
+ else if (-(unsigned)n <= (-(unsigned)INT_MIN - y2)/x)
+ return (n*x - y2)/y;
+ return (int)(n*(double)x/(double)y + .5);
+}
+
+static
+char *canonicalize_name(s)
+ char *s;
+{
+ static char ch[2];
+ if (s[0] == 'c' && s[1] == 'h' && s[2] == 'a' && s[3] == 'r') {
+ char *p;
+ int n;
+
+ for (p = s + 4; *p; p++)
+ if (!isascii(*p) || !isdigit((unsigned char)*p))
+ return s;
+ n = atoi(s + 4);
+ if (n >= 0 && n <= 0xff) {
+ ch[0] = (char)n;
+ return ch;
+ }
+ }
+ return s;
+}
+
+/* Return 1 if the character is present in the font; widthp gets the
+width if non-null. */
+
+int device_char_width(f, ps, name, widthp)
+ DeviceFont *f;
+ int ps;
+ char *name;
+ int *widthp;
+{
+ struct charinfo *p;
+
+ name = canonicalize_name(name);
+ for (p = f->char_table[hash_name(name) % CHAR_TABLE_SIZE];; p = p->next) {
+ if (!p)
+ return 0;
+ if (strcmp(p->name, name) == 0)
+ break;
+ }
+ *widthp = scale_round(p->width, ps, f->dev->unitwidth);
+ return 1;
+}
+
+int device_code_width(f, ps, code, widthp)
+ DeviceFont *f;
+ int ps;
+ int code;
+ int *widthp;
+{
+ struct charinfo *p;
+
+ for (p = f->code_table[code & 0xff];; p = p->code_next) {
+ if (!p)
+ return 0;
+ if (p->code == code)
+ break;
+ }
+ *widthp = scale_round(p->width, ps, f->dev->unitwidth);
+ return 1;
+}
+
+char *device_name_for_code(f, code)
+ DeviceFont *f;
+ int code;
+{
+ static struct charinfo *state = 0;
+ if (f)
+ state = f->code_table[code & 0xff];
+ for (; state; state = state->code_next)
+ if (state->code == code && state->name[0] != '\0') {
+ char *name = state->name;
+ state = state->code_next;
+ return name;
+ }
+ return 0;
+}
+
+int device_font_special(f)
+ DeviceFont *f;
+{
+ return f->special;
+}
+
+static
+struct charinfo *add_char(f, name, width, code)
+ DeviceFont *f;
+ char *name;
+ int width, code;
+{
+ struct charinfo **pp;
+ struct charinfo *ci;
+
+ name = canonicalize_name(name);
+ if (strcmp(name, "---") == 0)
+ name = "";
+
+ ci = (struct charinfo *)XtMalloc(XtOffsetOf(struct charinfo, name[0])
+ + strlen(name) + 1);
+
+ strcpy(ci->name, name);
+ ci->width = width;
+ ci->code = code;
+
+ if (*name != '\0') {
+ pp = &f->char_table[hash_name(name) % CHAR_TABLE_SIZE];
+ ci->next = *pp;
+ *pp = ci;
+ }
+ pp = &f->code_table[code & 0xff];
+ ci->code_next = *pp;
+ *pp = ci;
+ return ci;
+}
+
+/* Return non-zero for success. */
+
+static
+int read_charset_section(f, fp)
+ DeviceFont *f;
+ FILE *fp;
+{
+ struct charinfo *last_charinfo = 0;
+ char buf[256];
+
+ while (fgets(buf, sizeof(buf), fp)) {
+ char *name;
+ int width;
+ int code;
+ char *p;
+
+ current_lineno++;
+ name = strtok(buf, WS);
+ if (!name)
+ continue; /* ignore blank lines */
+ p = strtok((char *)0, WS);
+ if (!p) /* end of charset section */
+ break;
+ if (strcmp(p, "\"") == 0) {
+ if (!last_charinfo) {
+ error("first line of charset section cannot use `\"'");
+ return 0;
+ }
+ else
+ (void)add_char(f, name,
+ last_charinfo->width, last_charinfo->code);
+ }
+ else {
+ char *q;
+ if (sscanf(p, "%d", &width) != 1) {
+ error("bad width field");
+ return 0;
+ }
+ p = strtok((char *)0, WS);
+ if (!p) {
+ error("missing type field");
+ return 0;
+ }
+ p = strtok((char *)0, WS);
+ if (!p) {
+ error("missing code field");
+ return 0;
+ }
+ code = (int)strtol(p, &q, 0);
+ if (q == p) {
+ error("bad code field");
+ return 0;
+ }
+ last_charinfo = add_char(f, name, width, code);
+ }
+ }
+ return 1;
+}
+
+static
+FILE *find_file(file, path, result)
+ char *file, *path, **result;
+{
+ char *buf = NULL;
+ int bufsiz = 0;
+ int flen;
+ FILE *fp;
+
+ *result = NULL;
+
+ if (file == NULL)
+ return NULL;
+ if (*file == '\0')
+ return NULL;
+
+ if (*file == '/') {
+ fp = fopen(file, "r");
+ if (fp)
+ *result = XtNewString(file);
+ return fp;
+ }
+
+ flen = strlen(file);
+
+ if (!path)
+ return NULL;
+
+ while (*path) {
+ int len;
+ char *start, *end;
+
+ start = path;
+ end = strchr(path, ':');
+ if (end)
+ path = end + 1;
+ else
+ path = end = strchr(path, '\0');
+ if (start >= end)
+ continue;
+ if (end[-1] == '/')
+ --end;
+ len = (end - start) + 1 + flen + 1;
+ if (len > bufsiz) {
+ if (buf)
+ buf = XtRealloc(buf, len);
+ else
+ buf = XtMalloc(len);
+ bufsiz = len;
+ }
+ memcpy(buf, start, end - start);
+ buf[end - start] = '/';
+ strcpy(buf + (end - start) + 1, file);
+ fp = fopen(buf, "r");
+ if (fp) {
+ *result = buf;
+ return fp;
+ }
+ }
+ XtFree(buf);
+ return NULL;
+}
+
+static
+FILE *open_device_file(device_name, file_name, result)
+ char *device_name, *file_name, **result;
+{
+ char *buf, *path;
+ FILE *fp;
+
+ buf = XtMalloc(3 + strlen(device_name) + 1 + strlen(file_name) + 1);
+ sprintf(buf, "dev%s/%s", device_name, file_name);
+ path = getenv(FONTPATH_ENV_VAR);
+ if (!path)
+ path = FONTPATH;
+ fp = find_file(buf, path, result);
+ if (!fp) {
+ fprintf(stderr, "can't find device file `%s'\n", file_name);
+ fflush(stderr);
+ }
+ XtFree(buf);
+ return fp;
+}
+
+static
+void error(s)
+ char *s;
+{
+ if (current_filename) {
+ fprintf(stderr, "%s:", current_filename);
+ if (current_lineno > 0)
+ fprintf(stderr, "%d:", current_lineno);
+ putc(' ', stderr);
+ }
+ fputs(s, stderr);
+ putc('\n', stderr);
+ fflush(stderr);
+}
+
+/*
+Local Variables:
+c-indent-level: 4
+c-continued-statement-offset: 4
+c-brace-offset: -4
+c-argdecl-indent: 4
+c-label-offset: -4
+c-tab-always-indent: nil
+End:
+*/
diff --git a/src/xditview/device.h b/src/xditview/device.h
new file mode 100644
index 00000000..2b9a64ba
--- /dev/null
+++ b/src/xditview/device.h
@@ -0,0 +1,21 @@
+
+typedef struct _DeviceFont DeviceFont;
+
+typedef struct _Device {
+ char *name;
+ int sizescale;
+ int res;
+ int unitwidth;
+ int paperlength;
+ int paperwidth;
+ int X11;
+ DeviceFont *fonts;
+} Device;
+
+extern void device_destroy();
+extern Device *device_load();
+extern DeviceFont *device_find_font();
+extern int device_char_width();
+extern char *device_name_for_code();
+extern int device_code_width();
+extern int device_font_special();
diff --git a/src/xditview/draw.c b/src/xditview/draw.c
new file mode 100644
index 00000000..69e86cd6
--- /dev/null
+++ b/src/xditview/draw.c
@@ -0,0 +1,721 @@
+/*
+ * draw.c
+ *
+ * accept dvi function calls and translate to X
+ */
+
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+
+/* math.h on a Sequent doesn't define M_PI, apparently */
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#include "DviP.h"
+
+#define DeviceToX(dw, n) ((int)((n) * (dw)->dvi.scale_factor + .5))
+#define XPos(dw) (DeviceToX((dw), (dw)->dvi.state->x - \
+ (dw)->dvi.text_device_width) + (dw)->dvi.text_x_width)
+#define YPos(dw) (DeviceToX((dw), (dw)->dvi.state->y))
+
+static int FakeCharacter();
+
+HorizontalMove(dw, delta)
+ DviWidget dw;
+ int delta;
+{
+ dw->dvi.state->x += delta;
+}
+
+HorizontalGoto(dw, NewPosition)
+ DviWidget dw;
+ int NewPosition;
+{
+ dw->dvi.state->x = NewPosition;
+}
+
+VerticalMove(dw, delta)
+ DviWidget dw;
+ int delta;
+{
+ dw->dvi.state->y += delta;
+}
+
+VerticalGoto(dw, NewPosition)
+ DviWidget dw;
+ int NewPosition;
+{
+ dw->dvi.state->y = NewPosition;
+}
+
+AdjustCacheDeltas (dw)
+ DviWidget dw;
+{
+ int extra;
+ int nadj;
+ int i;
+
+ nadj = 0;
+ extra = DeviceToX(dw, dw->dvi.text_device_width)
+ - dw->dvi.text_x_width;
+ if (extra == 0)
+ return;
+ for (i = 0; i <= dw->dvi.cache.index; i++)
+ if (dw->dvi.cache.adjustable[i])
+ ++nadj;
+ if (nadj == 0)
+ return;
+ dw->dvi.text_x_width += extra;
+ for (i = 0; i <= dw->dvi.cache.index; i++)
+ if (dw->dvi.cache.adjustable[i]) {
+ int x;
+ int *deltap;
+
+ x = extra/nadj;
+ deltap = &dw->dvi.cache.cache[i].delta;
+#define MIN_DELTA 2
+ if (*deltap > 0 && x + *deltap < MIN_DELTA) {
+ x = MIN_DELTA - *deltap;
+ if (x <= 0)
+ *deltap = MIN_DELTA;
+ else
+ x = 0;
+ }
+ else
+ *deltap += x;
+ extra -= x;
+ --nadj;
+ dw->dvi.cache.adjustable[i] = 0;
+ }
+}
+
+FlushCharCache (dw)
+ DviWidget dw;
+{
+ if (dw->dvi.cache.char_index != 0) {
+ AdjustCacheDeltas (dw);
+ XDrawText (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ dw->dvi.cache.start_x, dw->dvi.cache.start_y,
+ dw->dvi.cache.cache, dw->dvi.cache.index + 1);
+ }
+ dw->dvi.cache.index = 0;
+ dw->dvi.cache.max = DVI_TEXT_CACHE_SIZE;
+#if 0
+ if (dw->dvi.noPolyText)
+ dw->dvi.cache.max = 1;
+#endif
+ dw->dvi.cache.char_index = 0;
+ dw->dvi.cache.cache[0].nchars = 0;
+ dw->dvi.cache.start_x = dw->dvi.cache.x = XPos (dw);
+ dw->dvi.cache.start_y = dw->dvi.cache.y = YPos (dw);
+}
+
+Newline (dw)
+ DviWidget dw;
+{
+ FlushCharCache (dw);
+ dw->dvi.text_x_width = dw->dvi.text_device_width = 0;
+ dw->dvi.word_flag = 0;
+}
+
+Word (dw)
+ DviWidget dw;
+{
+ dw->dvi.word_flag = 1;
+}
+
+#define charWidth(fi,c) (\
+ (fi)->per_char ?\
+ (fi)->per_char[(c) - (fi)->min_char_or_byte2].width\
+ :\
+ (fi)->max_bounds.width\
+)
+
+
+static
+int charExists (fi, c)
+ XFontStruct *fi;
+ int c;
+{
+ XCharStruct *p;
+
+ if (fi->per_char == NULL ||
+ c < fi->min_char_or_byte2 || c > fi->max_char_or_byte2)
+ return 0;
+ p = fi->per_char + (c - fi->min_char_or_byte2);
+ return (p->lbearing != 0 || p->rbearing != 0 || p->width != 0
+ || p->ascent != 0 || p->descent != 0 || p->attributes != 0);
+}
+
+static
+DoCharacter (dw, c, wid)
+ DviWidget dw;
+ int c;
+ int wid; /* width in device units */
+{
+ register XFontStruct *font;
+ register XTextItem *text;
+ int x, y;
+
+ x = XPos(dw);
+ y = YPos(dw);
+
+ /*
+ * quick and dirty extents calculation:
+ */
+ if (!(y + 24 >= dw->dvi.extents.y1
+ && y - 24 <= dw->dvi.extents.y2
+#if 0
+ && x + 24 >= dw->dvi.extents.x1
+ && x - 24 <= dw->dvi.extents.x2
+#endif
+ ))
+ return;
+
+ if (y != dw->dvi.cache.y
+ || dw->dvi.cache.char_index >= DVI_CHAR_CACHE_SIZE) {
+ FlushCharCache (dw);
+ x = dw->dvi.cache.x;
+ }
+ /*
+ * load a new font, if the current block is not empty,
+ * step to the next.
+ */
+ if (dw->dvi.cache.font_size != dw->dvi.state->font_size ||
+ dw->dvi.cache.font_number != dw->dvi.state->font_number)
+ {
+ dw->dvi.cache.font_size = dw->dvi.state->font_size;
+ dw->dvi.cache.font_number = dw->dvi.state->font_number;
+ dw->dvi.cache.font = QueryFont (dw,
+ dw->dvi.cache.font_number,
+ dw->dvi.cache.font_size);
+ if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
+ ++dw->dvi.cache.index;
+ if (dw->dvi.cache.index >= dw->dvi.cache.max)
+ FlushCharCache (dw);
+ dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
+ dw->dvi.cache.adjustable[dw->dvi.cache.index] = 0;
+ }
+ }
+ if (x != dw->dvi.cache.x || dw->dvi.word_flag) {
+ if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
+ ++dw->dvi.cache.index;
+ if (dw->dvi.cache.index >= dw->dvi.cache.max)
+ FlushCharCache (dw);
+ dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
+ }
+ dw->dvi.cache.adjustable[dw->dvi.cache.index]
+ = dw->dvi.word_flag;
+ dw->dvi.word_flag = 0;
+ }
+ font = dw->dvi.cache.font;
+ text = &dw->dvi.cache.cache[dw->dvi.cache.index];
+ if (text->nchars == 0) {
+ text->chars = &dw->dvi.cache.char_cache[dw->dvi.cache.char_index];
+ text->delta = x - dw->dvi.cache.x;
+ if (font != dw->dvi.font) {
+ text->font = font->fid;
+ dw->dvi.font = font;
+ } else
+ text->font = None;
+ dw->dvi.cache.x += text->delta;
+ }
+ if (charExists(font, c)) {
+ int w;
+ dw->dvi.cache.char_cache[dw->dvi.cache.char_index++] = (char) c;
+ ++text->nchars;
+ w = charWidth(font, c);
+ dw->dvi.cache.x += w;
+ if (wid != 0) {
+ dw->dvi.text_x_width += w;
+ dw->dvi.text_device_width += wid;
+ }
+ }
+}
+
+static
+int FindCharWidth (dw, buf, widp)
+ DviWidget dw;
+ char *buf;
+ int *widp;
+{
+ int maxpos;
+ int i;
+
+ if (dw->dvi.device_font == 0
+ || dw->dvi.state->font_number != dw->dvi.device_font_number) {
+ dw->dvi.device_font_number = dw->dvi.state->font_number;
+ dw->dvi.device_font
+ = QueryDeviceFont (dw, dw->dvi.device_font_number);
+ }
+ if (dw->dvi.device_font
+ && device_char_width (dw->dvi.device_font,
+ dw->dvi.state->font_size, buf, widp))
+ return 1;
+
+ maxpos = MaxFontPosition (dw);
+ for (i = 1; i <= maxpos; i++) {
+ DeviceFont *f = QueryDeviceFont (dw, i);
+ if (f && device_font_special (f)
+ && device_char_width (f, dw->dvi.state->font_size,
+ buf, widp)) {
+ dw->dvi.state->font_number = i;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Return the width of the character in device units. */
+
+int PutCharacter (dw, buf)
+ DviWidget dw;
+ char *buf;
+{
+ int prevFont;
+ int c = -1;
+ int wid = 0;
+ DviCharNameMap *map;
+
+ if (!dw->dvi.display_enable)
+ return 0; /* The width doesn't matter in this case. */
+ prevFont = dw->dvi.state->font_number;
+ if (!FindCharWidth (dw, buf, &wid))
+ return 0;
+ map = QueryFontMap (dw, dw->dvi.state->font_number);
+ if (map)
+ c = DviCharIndex (map, buf);
+ if (c >= 0)
+ DoCharacter (dw, c, wid);
+ else
+ (void) FakeCharacter (dw, buf, wid);
+ dw->dvi.state->font_number = prevFont;
+ return wid;
+}
+
+/* Return 1 if we can fake it; 0 otherwise. */
+
+static
+int FakeCharacter (dw, buf, wid)
+ DviWidget dw;
+ char *buf;
+ int wid;
+{
+ int oldx, oldw;
+ char ch[2];
+ char *chars = 0;
+
+ if (buf[0] == '\0' || buf[1] == '\0' || buf[2] != '\0')
+ return 0;
+#define pack2(c1, c2) (((c1) << 8) | (c2))
+
+ switch (pack2(buf[0], buf[1])) {
+ case pack2('f', 'i'):
+ chars = "fi";
+ break;
+ case pack2('f', 'l'):
+ chars = "fl";
+ break;
+ case pack2('f', 'f'):
+ chars = "ff";
+ break;
+ case pack2('F', 'i'):
+ chars = "ffi";
+ break;
+ case pack2('F', 'l'):
+ chars = "ffl";
+ break;
+ }
+ if (!chars)
+ return 0;
+ oldx = dw->dvi.state->x;
+ oldw = dw->dvi.text_device_width;
+ ch[1] = '\0';
+ for (; *chars; chars++) {
+ ch[0] = *chars;
+ dw->dvi.state->x += PutCharacter (dw, ch);
+ }
+ dw->dvi.state->x = oldx;
+ dw->dvi.text_device_width = oldw + wid;
+ return 1;
+}
+
+PutNumberedCharacter (dw, c)
+ DviWidget dw;
+ int c;
+{
+ char *name;
+ int wid;
+ DviCharNameMap *map;
+
+ if (!dw->dvi.display_enable)
+ return;
+
+ if (dw->dvi.device_font == 0
+ || dw->dvi.state->font_number != dw->dvi.device_font_number) {
+ dw->dvi.device_font_number = dw->dvi.state->font_number;
+ dw->dvi.device_font
+ = QueryDeviceFont (dw, dw->dvi.device_font_number);
+ }
+
+ if (dw->dvi.device_font == 0
+ || !device_code_width (dw->dvi.device_font,
+ dw->dvi.state->font_size, c, &wid))
+ return;
+ if (dw->dvi.native) {
+ DoCharacter (dw, c, wid);
+ return;
+ }
+ map = QueryFontMap (dw, dw->dvi.state->font_number);
+ if (!map)
+ return;
+ for (name = device_name_for_code (dw->dvi.device_font, c);
+ name;
+ name = device_name_for_code ((DeviceFont *)0, c)) {
+ int code = DviCharIndex (map, name);
+ if (code >= 0) {
+ DoCharacter (dw, code, wid);
+ break;
+ }
+ if (FakeCharacter (dw, name, wid))
+ break;
+ }
+}
+
+ClearPage (dw)
+ DviWidget dw;
+{
+ XClearWindow (XtDisplay (dw), XtWindow (dw));
+}
+
+static
+setGC (dw)
+ DviWidget dw;
+{
+ int desired_line_width;
+
+ if (dw->dvi.line_thickness < 0)
+ desired_line_width = (int)(((double)dw->dvi.device_resolution
+ * dw->dvi.state->font_size)
+ / (10.0*72.0*dw->dvi.sizescale));
+ else
+ desired_line_width = dw->dvi.line_thickness;
+
+ if (desired_line_width != dw->dvi.line_width) {
+ XGCValues values;
+ values.line_width = DeviceToX(dw, desired_line_width);
+ if (values.line_width == 0)
+ values.line_width = 1;
+ XChangeGC(XtDisplay (dw), dw->dvi.normal_GC,
+ GCLineWidth, &values);
+ dw->dvi.line_width = desired_line_width;
+ }
+}
+
+static
+setFillGC (dw)
+ DviWidget dw;
+{
+ int fill_type;
+ unsigned long mask = GCFillStyle | GCForeground;
+
+ fill_type = (dw->dvi.fill * 10) / (DVI_FILL_MAX + 1);
+ if (dw->dvi.fill_type != fill_type) {
+ XGCValues values;
+ if (fill_type <= 0) {
+ values.foreground = dw->dvi.background;
+ values.fill_style = FillSolid;
+ } else if (fill_type >= 9) {
+ values.foreground = dw->dvi.foreground;
+ values.fill_style = FillSolid;
+ } else {
+ values.foreground = dw->dvi.foreground;
+ values.fill_style = FillOpaqueStippled;
+ values.stipple = dw->dvi.gray[fill_type - 1];
+ mask |= GCStipple;
+ }
+ XChangeGC(XtDisplay (dw), dw->dvi.fill_GC, mask, &values);
+ dw->dvi.fill_type = fill_type;
+ }
+}
+
+DrawLine (dw, x, y)
+ DviWidget dw;
+ int x, y;
+{
+ int xp, yp;
+
+ AdjustCacheDeltas (dw);
+ setGC (dw);
+ xp = XPos (dw);
+ yp = YPos (dw);
+ XDrawLine (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ xp, yp,
+ xp + DeviceToX (dw, x), yp + DeviceToX (dw, y));
+}
+
+DrawCircle (dw, diam)
+ DviWidget dw;
+ int diam;
+{
+ int d;
+
+ AdjustCacheDeltas (dw);
+ setGC (dw);
+ d = DeviceToX (dw, diam);
+ XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ XPos (dw), YPos (dw) - d/2,
+ d, d, 0, 64*360);
+}
+
+DrawFilledCircle (dw, diam)
+ DviWidget dw;
+ int diam;
+{
+ int d;
+
+ AdjustCacheDeltas (dw);
+ setFillGC (dw);
+ d = DeviceToX (dw, diam);
+ XFillArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
+ XPos (dw), YPos (dw) - d/2,
+ d, d, 0, 64*360);
+ XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
+ XPos (dw), YPos (dw) - d/2,
+ d, d, 0, 64*360);
+}
+
+DrawEllipse (dw, a, b)
+ DviWidget dw;
+ int a, b;
+{
+ AdjustCacheDeltas (dw);
+ setGC (dw);
+ XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ XPos (dw), YPos (dw) - DeviceToX (dw, b/2),
+ DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
+}
+
+DrawFilledEllipse (dw, a, b)
+ DviWidget dw;
+ int a, b;
+{
+ AdjustCacheDeltas (dw);
+ setFillGC (dw);
+ XFillArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
+ XPos (dw), YPos (dw) - DeviceToX (dw, b/2),
+ DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
+ XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
+ XPos (dw), YPos (dw) - DeviceToX (dw, b/2),
+ DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
+}
+
+DrawArc (dw, x0, y0, x1, y1)
+ DviWidget dw;
+ int x0, y0, x1, y1;
+{
+ int angle1, angle2;
+ int rad = (int)((sqrt ((double)x0*x0 + (double)y0*y0)
+ + sqrt ((double)x1*x1 + (double)y1*y1) + 1.0)/2.0);
+ if ((x0 == 0 && y0 == 0) || (x1 == 0 && y1 == 0))
+ return;
+ angle1 = (int)(atan2 ((double)y0, (double)-x0)*180.0*64.0/M_PI);
+ angle2 = (int)(atan2 ((double)-y1, (double)x1)*180.0*64.0/M_PI);
+
+ angle2 -= angle1;
+ if (angle2 < 0)
+ angle2 += 64*360;
+
+ AdjustCacheDeltas (dw);
+ setGC (dw);
+
+ rad = DeviceToX (dw, rad);
+ XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ XPos (dw) + DeviceToX (dw, x0) - rad,
+ YPos (dw) + DeviceToX (dw, y0) - rad,
+ rad*2, rad*2, angle1, angle2);
+}
+
+DrawPolygon (dw, v, n)
+ DviWidget dw;
+ int *v;
+ int n;
+{
+ XPoint *p;
+ int i;
+ int dx, dy;
+
+ n /= 2;
+
+ AdjustCacheDeltas (dw);
+ setGC (dw);
+ p = (XPoint *)XtMalloc((n + 2)*sizeof(XPoint));
+ p[0].x = XPos (dw);
+ p[0].y = YPos (dw);
+ dx = 0;
+ dy = 0;
+ for (i = 0; i < n; i++) {
+ dx += v[2*i];
+ p[i + 1].x = DeviceToX (dw, dx) + p[0].x;
+ dy += v[2*i + 1];
+ p[i + 1].y = DeviceToX (dw, dy) + p[0].y;
+ }
+ p[n+1].x = p[0].x;
+ p[n+1].y = p[0].y;
+ XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ p, n + 2, CoordModeOrigin);
+ XtFree((char *)p);
+}
+
+
+DrawFilledPolygon (dw, v, n)
+ DviWidget dw;
+ int *v;
+ int n;
+{
+ XPoint *p;
+ int i;
+ int dx, dy;
+
+ n /= 2;
+ if (n < 2)
+ return;
+
+ AdjustCacheDeltas (dw);
+ setFillGC (dw);
+ p = (XPoint *)XtMalloc((n + 2)*sizeof(XPoint));
+ p[0].x = p[n+1].x = XPos (dw);
+ p[0].y = p[n+1].y = YPos (dw);
+ dx = 0;
+ dy = 0;
+ for (i = 0; i < n; i++) {
+ dx += v[2*i];
+ p[i + 1].x = DeviceToX (dw, dx) + p[0].x;
+ dy += v[2*i + 1];
+ p[i + 1].y = DeviceToX (dw, dy) + p[0].y;
+ }
+ XFillPolygon (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
+ p, n + 1, Complex, CoordModeOrigin);
+ XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
+ p, n + 2, CoordModeOrigin);
+ XtFree((char *)p);
+}
+
+#define POINTS_MAX 10000
+
+static
+appendPoint(points, pointi, x, y)
+ XPoint *points;
+ int *pointi;
+ int x, y;
+{
+ if (*pointi < POINTS_MAX) {
+ points[*pointi].x = x;
+ points[*pointi].y = y;
+ *pointi += 1;
+ }
+}
+
+#define FLATNESS 1
+
+static
+flattenCurve(points, pointi, x2, y2, x3, y3, x4, y4)
+ XPoint *points;
+ int *pointi;
+ int x2, y2, x3, y3, x4, y4;
+{
+ int x1, y1, dx, dy, n1, n2, n;
+
+ x1 = points[*pointi - 1].x;
+ y1 = points[*pointi - 1].y;
+
+ dx = x4 - x1;
+ dy = y4 - y1;
+
+ n1 = dy*(x2 - x1) - dx*(y2 - y1);
+ n2 = dy*(x3 - x1) - dx*(y3 - y1);
+ if (n1 < 0)
+ n1 = -n1;
+ if (n2 < 0)
+ n2 = -n2;
+ n = n1 > n2 ? n1 : n2;
+
+ if (n*n / (dy*dy + dx*dx) <= FLATNESS*FLATNESS)
+ appendPoint (points, pointi, x4, y4);
+ else {
+ flattenCurve (points, pointi,
+ (x1 + x2)/2, (y1 + y2)/2,
+ (x1 + x2*2 + x3)/4, (y1 + y2*2 + y3)/4,
+ (x1 +3*x2 + 3*x3 + x4)/8, (y1 +3*y2 + 3*y3 + y4)/8);
+ flattenCurve (points, pointi,
+ (x2 + x3*2 + x4)/4, (y2 + y3*2 + y4)/4,
+ (x3 + x4)/2, (y3 + y4)/2,
+ x4, y4);
+ }
+}
+
+
+DrawSpline (dw, v, n)
+ DviWidget dw;
+ int *v;
+ int n;
+{
+ int sx, sy, tx, ty;
+ int ox, oy, dx, dy;
+ int i;
+ int pointi;
+ XPoint points[POINTS_MAX];
+
+ if (n == 0 || (n & 1) != 0)
+ return;
+ AdjustCacheDeltas (dw);
+ setGC (dw);
+ ox = XPos (dw);
+ oy = YPos (dw);
+ dx = v[0];
+ dy = v[1];
+ sx = ox;
+ sy = oy;
+ tx = sx + DeviceToX (dw, dx);
+ ty = sy + DeviceToX (dw, dy);
+
+ pointi = 0;
+
+ appendPoint (points, &pointi, sx, sy);
+ appendPoint (points, &pointi, (sx + tx)/2, (sy + ty)/2);
+
+ for (i = 2; i < n; i += 2) {
+ int ux = ox + DeviceToX (dw, dx += v[i]);
+ int uy = oy + DeviceToX (dw, dy += v[i+1]);
+ flattenCurve (points, &pointi,
+ (sx + tx*5)/6, (sy + ty*5)/6,
+ (tx*5 + ux)/6, (ty*5 + uy)/6,
+ (tx + ux)/2, (ty + uy)/2);
+ sx = tx;
+ sy = ty;
+ tx = ux;
+ ty = uy;
+ }
+
+ appendPoint (points, &pointi, tx, ty);
+
+ XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ points, pointi, CoordModeOrigin);
+}
+
+
+/*
+Local Variables:
+c-indent-level: 8
+c-continued-statement-offset: 8
+c-brace-offset: -8
+c-argdecl-indent: 8
+c-label-offset: -8
+c-tab-always-indent: nil
+End:
+*/
diff --git a/src/xditview/font.c b/src/xditview/font.c
new file mode 100644
index 00000000..2e028aa6
--- /dev/null
+++ b/src/xditview/font.c
@@ -0,0 +1,471 @@
+/*
+ * font.c
+ *
+ * map dvi fonts to X fonts
+ */
+
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "DviP.h"
+#include "XFontName.h"
+
+static DisposeFontSizes();
+
+static char *
+savestr (s)
+ char *s;
+{
+ char *n;
+
+ if (!s)
+ return 0;
+ n = XtMalloc (strlen (s) + 1);
+ if (n)
+ strcpy (n, s);
+ return n;
+}
+
+static DviFontList *
+LookupFontByPosition (dw, position)
+ DviWidget dw;
+ int position;
+{
+ DviFontList *f;
+
+ for (f = dw->dvi.fonts; f; f = f->next)
+ if (f->dvi_number == position)
+ break;
+ return f;
+}
+
+int
+MaxFontPosition (dw)
+ DviWidget dw;
+{
+ DviFontList *f;
+ int n = -1;
+
+ for (f = dw->dvi.fonts; f; f = f->next)
+ if (f->dvi_number > n)
+ n = f->dvi_number;
+ return n;
+}
+
+static DviFontSizeList *
+LookupFontSizeBySize (dw, f, size)
+ DviWidget dw;
+ DviFontList *f;
+ int size;
+{
+ DviFontSizeList *fs, *best = 0, *smallest = 0;
+ int bestsize = 0;
+ XFontName fontName;
+ unsigned int fontNameAttributes;
+ char fontNameString[2048];
+ int decipointsize;
+
+ if (f->scalable) {
+ decipointsize = (10*size)/dw->dvi.sizescale;
+ for (best = f->sizes; best; best = best->next)
+ if (best->size == decipointsize)
+ return best;
+ best = (DviFontSizeList *) XtMalloc(sizeof *best);
+ best->next = f->sizes;
+ best->size = decipointsize;
+ f->sizes = best;
+ XParseFontName (f->x_name, &fontName, &fontNameAttributes);
+ fontNameAttributes &= ~(FontNamePixelSize|FontNameAverageWidth);
+ fontNameAttributes |= FontNameResolutionX;
+ fontNameAttributes |= FontNameResolutionY;
+ fontNameAttributes |= FontNamePointSize;
+ fontName.ResolutionX = dw->dvi.display_resolution;
+ fontName.ResolutionY = dw->dvi.display_resolution;
+ fontName.PointSize = decipointsize;
+ XFormatFontName (&fontName, fontNameAttributes, fontNameString);
+ best->x_name = savestr (fontNameString);
+ best->doesnt_exist = 0;
+ best->font = 0;
+ return best;
+ }
+ for (fs = f->sizes; fs; fs=fs->next) {
+ if (dw->dvi.sizescale*fs->size <= 10*size
+ && fs->size >= bestsize) {
+ best = fs;
+ bestsize = fs->size;
+ }
+ if (smallest == 0 || fs->size < smallest->size)
+ smallest = fs;
+ }
+ return best ? best : smallest;
+}
+
+static char *
+SkipFontNameElement (n)
+ char *n;
+{
+ while (*n != '-')
+ if (!*++n)
+ return 0;
+ return n+1;
+}
+
+# define SizePosition 8
+# define EncodingPosition 13
+
+static
+ConvertFontNameToSize (n)
+ char *n;
+{
+ int i, size;
+
+ for (i = 0; i < SizePosition; i++) {
+ n = SkipFontNameElement (n);
+ if (!n)
+ return -1;
+ }
+ size = atoi (n);
+ return size;
+}
+
+static char *
+ConvertFontNameToEncoding (n)
+ char *n;
+{
+ int i;
+ for (i = 0; i < EncodingPosition; i++) {
+ n = SkipFontNameElement (n);
+ if (!n)
+ return 0;
+ }
+ return n;
+}
+
+DviFontSizeList *
+InstallFontSizes (dw, x_name, scalablep)
+ DviWidget dw;
+ char *x_name;
+ Boolean *scalablep;
+{
+ char fontNameString[2048];
+ char **fonts;
+ int i, count;
+ int size;
+ DviFontSizeList *sizes, *new;
+ XFontName fontName;
+ unsigned int fontNameAttributes;
+
+ *scalablep = FALSE;
+ if (!XParseFontName (x_name, &fontName, &fontNameAttributes))
+ return 0;
+ fontNameAttributes &= ~(FontNamePixelSize|FontNamePointSize
+ |FontNameAverageWidth);
+ fontNameAttributes |= FontNameResolutionX;
+ fontNameAttributes |= FontNameResolutionY;
+ fontName.ResolutionX = dw->dvi.display_resolution;
+ fontName.ResolutionY = dw->dvi.display_resolution;
+ XFormatFontName (&fontName, fontNameAttributes, fontNameString);
+ fonts = XListFonts (XtDisplay (dw), fontNameString, 10000000, &count);
+ sizes = 0;
+ for (i = 0; i < count; i++) {
+ size = ConvertFontNameToSize (fonts[i]);
+ if (size == 0) {
+ DisposeFontSizes (dw, sizes);
+ sizes = 0;
+ *scalablep = TRUE;
+ break;
+ }
+ if (size != -1) {
+ new = (DviFontSizeList *) XtMalloc (sizeof *new);
+ new->next = sizes;
+ new->size = size;
+ new->x_name = savestr (fonts[i]);
+ new->doesnt_exist = 0;
+ new->font = 0;
+ sizes = new;
+ }
+ }
+ XFreeFontNames (fonts);
+ return sizes;
+}
+
+static
+DisposeFontSizes (dw, fs)
+ DviWidget dw;
+ DviFontSizeList *fs;
+{
+ DviFontSizeList *next;
+
+ for (; fs; fs=next) {
+ next = fs->next;
+ if (fs->x_name)
+ XtFree (fs->x_name);
+ if (fs->font && fs->font != dw->dvi.default_font) {
+ XUnloadFont (XtDisplay (dw), fs->font->fid);
+ XFree ((char *)fs->font);
+ }
+ XtFree ((char *) fs);
+ }
+}
+
+static DviFontList *
+InstallFont (dw, position, dvi_name, x_name)
+ DviWidget dw;
+ int position;
+ char *dvi_name;
+ char *x_name;
+{
+ DviFontList *f;
+ char *encoding;
+
+ if ((f = LookupFontByPosition (dw, position)) != NULL) {
+ /*
+ * ignore gratuitous font loading
+ */
+ if (!strcmp (f->dvi_name, dvi_name) &&
+ !strcmp (f->x_name, x_name))
+ return f;
+
+ DisposeFontSizes (dw, f->sizes);
+ if (f->dvi_name)
+ XtFree (f->dvi_name);
+ if (f->x_name)
+ XtFree (f->x_name);
+ f->device_font = 0;
+ } else {
+ f = (DviFontList *) XtMalloc (sizeof (*f));
+ f->next = dw->dvi.fonts;
+ dw->dvi.fonts = f;
+ }
+ f->initialized = FALSE;
+ f->dvi_name = savestr (dvi_name);
+ f->device_font = device_find_font (dw->dvi.device, dvi_name);
+ f->x_name = savestr (x_name);
+ f->dvi_number = position;
+ f->sizes = 0;
+ f->scalable = FALSE;
+ if (f->x_name) {
+ encoding = ConvertFontNameToEncoding (f->x_name);
+ f->char_map = DviFindMap (encoding);
+ } else
+ f->char_map = 0;
+ /*
+ * force requery of fonts
+ */
+ dw->dvi.font = 0;
+ dw->dvi.font_number = -1;
+ dw->dvi.cache.font = 0;
+ dw->dvi.cache.font_number = -1;
+ dw->dvi.device_font = 0;
+ dw->dvi.device_font_number = -1;
+ return f;
+}
+
+ForgetFonts (dw)
+ DviWidget dw;
+{
+ DviFontList *f = dw->dvi.fonts;
+
+ while (f) {
+ DviFontList *tem = f;
+
+ if (f->sizes)
+ DisposeFontSizes (dw, f->sizes);
+ if (f->dvi_name)
+ XtFree (f->dvi_name);
+ if (f->x_name)
+ XtFree (f->x_name);
+ f = f->next;
+ XtFree ((char *) tem);
+ }
+
+ /*
+ * force requery of fonts
+ */
+ dw->dvi.font = 0;
+ dw->dvi.font_number = -1;
+ dw->dvi.cache.font = 0;
+ dw->dvi.cache.font_number = -1;
+ dw->dvi.device_font = 0;
+ dw->dvi.device_font_number = -1;
+ dw->dvi.fonts = 0;
+}
+
+
+static char *
+MapDviNameToXName (dw, dvi_name)
+ DviWidget dw;
+ char *dvi_name;
+{
+ DviFontMap *fm;
+
+ for (fm = dw->dvi.font_map; fm; fm=fm->next)
+ if (!strcmp (fm->dvi_name, dvi_name))
+ return fm->x_name;
+ return 0;
+}
+
+#if 0
+static char *
+MapXNameToDviName (dw, x_name)
+ DviWidget dw;
+ char *x_name;
+{
+ DviFontMap *fm;
+
+ for (fm = dw->dvi.font_map; fm; fm=fm->next)
+ if (!strcmp (fm->x_name, x_name))
+ return fm->dvi_name;
+ return 0;
+}
+#endif
+
+ParseFontMap (dw)
+ DviWidget dw;
+{
+ char dvi_name[1024];
+ char x_name[2048];
+ char *m, *s;
+ DviFontMap *fm, *new;
+
+ if (dw->dvi.font_map)
+ DestroyFontMap (dw->dvi.font_map);
+ fm = 0;
+ m = dw->dvi.font_map_string;
+ while (*m) {
+ s = m;
+ while (*m && !isspace (*m))
+ ++m;
+ strncpy (dvi_name, s, m-s);
+ dvi_name[m-s] = '\0';
+ while (isspace (*m))
+ ++m;
+ s = m;
+ while (*m && *m != '\n')
+ ++m;
+ strncpy (x_name, s, m-s);
+ x_name[m-s] = '\0';
+ new = (DviFontMap *) XtMalloc (sizeof *new);
+ new->x_name = savestr (x_name);
+ new->dvi_name = savestr (dvi_name);
+ new->next = fm;
+ fm = new;
+ ++m;
+ }
+ dw->dvi.font_map = fm;
+}
+
+DestroyFontMap (font_map)
+ DviFontMap *font_map;
+{
+ DviFontMap *next;
+
+ for (; font_map; font_map = next) {
+ next = font_map->next;
+ if (font_map->x_name)
+ XtFree (font_map->x_name);
+ if (font_map->dvi_name)
+ XtFree (font_map->dvi_name);
+ XtFree ((char *) font_map);
+ }
+}
+
+/* ARGSUSED */
+
+SetFontPosition (dw, position, dvi_name, extra)
+ DviWidget dw;
+ int position;
+ char *dvi_name;
+ char *extra; /* unused */
+{
+ char *x_name;
+
+ x_name = MapDviNameToXName (dw, dvi_name);
+ if (x_name)
+ (void) InstallFont (dw, position, dvi_name, x_name);
+}
+
+XFontStruct *
+QueryFont (dw, position, size)
+ DviWidget dw;
+ int position;
+ int size;
+{
+ DviFontList *f;
+ DviFontSizeList *fs;
+
+ f = LookupFontByPosition (dw, position);
+ if (!f)
+ return dw->dvi.default_font;
+ if (!f->initialized) {
+ f->sizes = InstallFontSizes (dw, f->x_name, &f->scalable);
+ f->initialized = TRUE;
+ }
+ fs = LookupFontSizeBySize (dw, f, size);
+ if (!fs)
+ return dw->dvi.default_font;
+ if (!fs->font) {
+ if (fs->x_name)
+ fs->font = XLoadQueryFont (XtDisplay (dw), fs->x_name);
+ if (!fs->font)
+ fs->font = dw->dvi.default_font;
+ }
+ return fs->font;
+}
+
+DeviceFont *
+QueryDeviceFont (dw, position)
+ DviWidget dw;
+ int position;
+{
+ DviFontList *f;
+
+ f = LookupFontByPosition (dw, position);
+ if (!f)
+ return 0;
+ return f->device_font;
+}
+
+DviCharNameMap *
+QueryFontMap (dw, position)
+ DviWidget dw;
+ int position;
+{
+ DviFontList *f;
+
+ f = LookupFontByPosition (dw, position);
+ if (f)
+ return f->char_map;
+ else
+ return 0;
+}
+
+#if 0
+LoadFont (dw, position, size)
+ DviWidget dw;
+ int position;
+ int size;
+{
+ XFontStruct *font;
+
+ font = QueryFont (dw, position, size);
+ dw->dvi.font_number = position;
+ dw->dvi.font_size = size;
+ dw->dvi.font = font;
+ XSetFont (XtDisplay (dw), dw->dvi.normal_GC, font->fid);
+ return;
+}
+#endif
+
+/*
+Local Variables:
+c-indent-level: 8
+c-continued-statement-offset: 8
+c-brace-offset: -8
+c-argdecl-indent: 8
+c-label-offset: -8
+c-tab-always-indent: nil
+End:
+*/
diff --git a/src/xditview/gray1.bm b/src/xditview/gray1.bm
new file mode 100644
index 00000000..c40a95e6
--- /dev/null
+++ b/src/xditview/gray1.bm
@@ -0,0 +1,4 @@
+#define gray1_width 3
+#define gray1_height 3
+static char gray1_bits[] = {
+ 0x00, 0x02, 0x00};
diff --git a/src/xditview/gray2.bm b/src/xditview/gray2.bm
new file mode 100644
index 00000000..e87a1bcc
--- /dev/null
+++ b/src/xditview/gray2.bm
@@ -0,0 +1,4 @@
+#define gray2_width 3
+#define gray2_height 3
+static char gray2_bits[] = {
+ 0x00, 0x03, 0x00};
diff --git a/src/xditview/gray3.bm b/src/xditview/gray3.bm
new file mode 100644
index 00000000..d9313ebd
--- /dev/null
+++ b/src/xditview/gray3.bm
@@ -0,0 +1,4 @@
+#define gray3_width 3
+#define gray3_height 3
+static char gray3_bits[] = {
+ 0x00, 0x03, 0x02};
diff --git a/src/xditview/gray4.bm b/src/xditview/gray4.bm
new file mode 100644
index 00000000..dad142a9
--- /dev/null
+++ b/src/xditview/gray4.bm
@@ -0,0 +1,4 @@
+#define gray4_width 3
+#define gray4_height 3
+static char gray4_bits[] = {
+ 0x00, 0x07, 0x02};
diff --git a/src/xditview/gray5.bm b/src/xditview/gray5.bm
new file mode 100644
index 00000000..5f576184
--- /dev/null
+++ b/src/xditview/gray5.bm
@@ -0,0 +1,4 @@
+#define gray5_width 3
+#define gray5_height 3
+static char gray5_bits[] = {
+ 0x04, 0x07, 0x02};
diff --git a/src/xditview/gray6.bm b/src/xditview/gray6.bm
new file mode 100644
index 00000000..b76701db
--- /dev/null
+++ b/src/xditview/gray6.bm
@@ -0,0 +1,4 @@
+#define gray6_width 3
+#define gray6_height 3
+static char gray6_bits[] = {
+ 0x04, 0x07, 0x03};
diff --git a/src/xditview/gray7.bm b/src/xditview/gray7.bm
new file mode 100644
index 00000000..ef47bc69
--- /dev/null
+++ b/src/xditview/gray7.bm
@@ -0,0 +1,4 @@
+#define gray7_width 3
+#define gray7_height 3
+static char gray7_bits[] = {
+ 0x05, 0x07, 0x03};
diff --git a/src/xditview/gray8.bm b/src/xditview/gray8.bm
new file mode 100644
index 00000000..12de7cb6
--- /dev/null
+++ b/src/xditview/gray8.bm
@@ -0,0 +1,4 @@
+#define gray8_width 3
+#define gray8_height 3
+static char gray8_bits[] = {
+ 0x05, 0x07, 0x07};
diff --git a/src/xditview/gxditview.man b/src/xditview/gxditview.man
new file mode 100644
index 00000000..04cd446d
--- /dev/null
+++ b/src/xditview/gxditview.man
@@ -0,0 +1,246 @@
+.\" -*- nroff -*-
+.TH GXDITVIEW 1 "Release 5" "X Version 11"
+.SH NAME
+gxditview \- display gtroff output files
+.SH SYNOPSIS
+.B gxditview
+.RI [\fB\- toolkitoption\ .\|.\|.\|]
+.RI [\fB\- option\ .\|.\|.\|]
+.RI [ filename ]
+.SH DESCRIPTION
+The
+.I gxditview
+program displays gtroff output on an X display.
+It uses the standard X11 fonts,
+so it does not require access to the server machine for font loading.
+.PP
+If
+.I filename
+is
+.BR \- ,
+.I gxditview
+will read the standard input.
+.PP
+The left mouse button brings up a menu with the following entries:
+.TP 8
+.B "Next Page"
+Display the next page.
+.TP
+.B "Previous Page"
+Display the previous page.
+.TP
+.B "Select Page"
+Select a particular numbered page specified by a dialog box.
+.TP
+.B Print
+Print the gtroff output using a command specified by a dialog box.
+The default command initially displayed is controlled by the
+.B printCommand
+application resource, and by the
+.B \-printCommand
+option.
+.TP
+.B Open
+Open for display a new file specified by a dialog box.
+The file should contain gtroff output.
+If the filename starts with
+.B |
+it will be taken to be a command to read from.
+.TP
+.B Quit
+Exit from
+.IR gxditview .
+.PP
+The
+.BR n ,
+Space
+and Return keys are bound to the
+.B Next\ Page
+action.
+The
+.BR p ,
+BackSpace
+and
+Delete
+keys are bound to the
+.B Previous\ Page
+action.
+The
+.B q
+key is bound to the
+.B Quit
+action.
+The
+.B r
+key is bound to the
+.B Rerasterize
+action which rereads the current file, and redisplays the current page;
+if the current file is a command, the command will be reexecuted.
+.PP
+The
+.B paperlength
+and
+.B paperwidth
+commands in the DESC file specify the length and width in machine units
+of the virtual page displayed by
+.IR gxditview .
+.SH OPTIONS
+.I Gxditview
+accepts all of the standard X Toolkit command line options along with the
+additional options listed below:
+.TP 8
+.B \-help
+This option indicates that a brief summary of the allowed options should be
+printed.
+.TP
+.B \-page
+This option specifies the page number of the document to be displayed.
+.TP
+.BI \-backingStore\ backing-store-type
+Redisplay of the gtroff output window can take upto a second or so,
+this option causes the server to save the window contents so that when
+it is scrolled around the viewport, the window is painted from
+contents saved in backing store.
+.I backing-store-type
+can be one of
+.BR Always ,
+.B WhenMapped
+or
+.BR NotUseful .
+.TP
+.BI \-printCommand\ command
+The default command displayed in the dialog box for the
+.B Print
+menu entry will be
+.IR command .
+.TP
+.BI \-resolution\ res
+The gtroff output file will be displayed at a resolution of
+.I res
+dpi,
+unless the DESC file contains the
+.B X11
+command, in which case the device resolution will be used.
+This corresponds the
+.I Dvi
+widget's
+.B resolution
+resource.
+The default is 75.
+.TP
+.BI \-filename\ string
+The default filename displayed in the dialog box for the
+.B Open
+menu entry will be
+.IR string .
+This can be either a filename, or a command starting with
+.BR | .
+.PP
+The following standard X Toolkit command line arguments are commonly used with
+.IR gxditview :
+.TP 8
+.BI \-bg\ color
+This option specifies the color to use for the background of the window.
+The default is \fIwhite\fP.
+.TP
+.BI \-bd\ color
+This option specifies the color to use for the border of the window.
+The default is \fIblack\fP.
+.TP
+.BI \-bw\ number
+This option specifies the width in pixels of the border surrounding the window.
+.TP
+.BI \-fg\ color
+This option specifies the color to use for displaying text. The default is
+\fIblack\fP.
+.TP
+.BI \-fn\ font
+This option specifies the font to be used for displaying widget text. The
+default is \fIfixed\fP.
+.TP
+.B \-rv
+This option indicates that reverse video should be simulated by swapping
+the foreground and background colors.
+.TP
+.BI \-geometry\ geometry
+This option specifies the preferred size and position of the window.
+.TP
+.BI \-display\ host : display
+This option specifies the X server to contact.
+.TP
+.BI \-xrm\ resourcestring
+This option specifies a resource string to be used.
+.SH X DEFAULTS
+This program uses the
+.I Dvi
+widget in the X Toolkit. It understands all of the core resource names and
+classes as well as:
+.PP
+.TP 8
+.BR width\ (class\ Width )
+Specifies the width of the window.
+.TP
+.BR height\ (class\ Height )
+Specifies the height of the window.
+.TP
+.BR foreground\ (class\ Foreground )
+Specifies the default foreground color.
+.TP
+.BR font\ (class\ Font )
+Specifies the font to be used for error messages.
+.TP
+.BR fontMap\ (class\ FontMap )
+Specifies the mapping from groff font names to X font names. This
+must be a string containing a sequence of lines. Each line contains
+two whitespace separated fields: first the groff font name, and
+secondly the X font name. The default is
+.nf
+"\e
+TR -adobe-times-medium-r-normal--*-100-*-*-*-*-iso8859-1\en\e
+TI -adobe-times-medium-i-normal--*-100-*-*-*-*-iso8859-1\en\e
+TB -adobe-times-bold-r-normal--*-100-*-*-*-*-iso8859-1\en\e
+TBI -adobe-times-bold-i-normal--*-100-*-*-*-*-iso8859-1\en\e
+CR -adobe-courier-medium-r-normal--*-100-*-*-*-*-iso8859-1\en\e
+CI -adobe-courier-medium-o-normal--*-100-*-*-*-*-iso8859-1\en\e
+CB -adobe-courier-bold-r-normal--*-100-*-*-*-*-iso8859-1\en\e
+CBI -adobe-courier-bold-o-normal--*-100-*-*-*-*-iso8859-1\en\e
+HR -adobe-helvetica-medium-r-normal--*-100-*-*-*-*-iso8859-1\en\e
+HI -adobe-helvetica-medium-o-normal--*-100-*-*-*-*-iso8859-1\en\e
+HB -adobe-helvetica-bold-r-normal--*-100-*-*-*-*-iso8859-1\en\e
+HBI -adobe-helvetica-bold-o-normal--*-100-*-*-*-*-iso8859-1\en\e
+NR -adobe-new century schoolbook-medium-r-normal--*-100-*-*-*-*-iso8859-1\en\e
+NI -adobe-new century schoolbook-medium-i-normal--*-100-*-*-*-*-iso8859-1\en\e
+NB -adobe-new century schoolbook-bold-r-normal--*-100-*-*-*-*-iso8859-1\en\e
+NBI -adobe-new century schoolbook-bold-i-normal--*-100-*-*-*-*-iso8859-1\en\e
+S -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\en\e
+SS -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\en\e
+"
+.fi
+
+.SH "SEE ALSO"
+.IR X (1),
+.IR xrdb (1),
+.IR gtroff (1),
+.IR groff (1)
+.SH ORIGIN
+This program is derived from xditview;
+portions of xditview originated in xtroff which was derived
+from suntroff.
+.SH COPYRIGHT
+Copyright 1989, Massachusetts Institute of Technology.
+.br
+See
+.IR X (1)
+for a full statement of rights and permissions.
+.SH AUTHORS
+Keith Packard (MIT X Consortium)
+.br
+Richard L. Hyde (Purdue)
+.br
+David Slattengren (Berkeley)
+.br
+Malcolm Slaney (Schlumberger Palo Alto Research)
+.br
+Mark Moraes (University of Toronto)
+.br
+James Clark
diff --git a/src/xditview/lex.c b/src/xditview/lex.c
new file mode 100644
index 00000000..32831bda
--- /dev/null
+++ b/src/xditview/lex.c
@@ -0,0 +1,103 @@
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <stdio.h>
+#include "DviP.h"
+
+DviGetAndPut(dw, cp)
+ DviWidget dw;
+ int *cp;
+{
+ if (dw->dvi.ungot) {
+ dw->dvi.ungot = 0;
+ *cp = getc (dw->dvi.file);
+ }
+ else {
+ *cp = getc (dw->dvi.file);
+ if (*cp != EOF)
+ putc (*cp, dw->dvi.tmpFile);
+ }
+ return *cp;
+}
+
+char *
+GetLine(dw, Buffer, Length)
+ DviWidget dw;
+ char *Buffer;
+ int Length;
+{
+ int i = 0, c;
+
+ Length--; /* Save room for final '\0' */
+
+ while (DviGetC (dw, &c) != EOF) {
+ if (Buffer && i < Length)
+ Buffer[i++] = c;
+ if (c == '\n') {
+ DviUngetC(dw, c);
+ break;
+ }
+ }
+ if (Buffer)
+ Buffer[i] = '\0';
+ return Buffer;
+}
+
+char *
+GetWord(dw, Buffer, Length)
+ DviWidget dw;
+ char *Buffer;
+ int Length;
+{
+ int i = 0, c;
+
+ Length--; /* Save room for final '\0' */
+ while (DviGetC(dw, &c) == ' ' || c == '\n')
+ ;
+ while (c != EOF) {
+ if (Buffer && i < Length)
+ Buffer[i++] = c;
+ if (DviGetC(dw, &c) == ' ' || c == '\n') {
+ DviUngetC(dw, c);
+ break;
+ }
+ }
+ if (Buffer)
+ Buffer[i] = '\0';
+ return Buffer;
+}
+
+GetNumber(dw)
+ DviWidget dw;
+{
+ int i = 0, c;
+ int negative = 0;
+
+ while (DviGetC(dw, &c) == ' ' || c == '\n')
+ ;
+ if (c == '-') {
+ negative = 1;
+ DviGetC(dw, &c);
+ }
+
+ for (; c >= '0' && c <= '9'; DviGetC(dw, &c)) {
+ if (negative)
+ i = i*10 - (c - '0');
+ else
+ i = i*10 + c - '0';
+ }
+ if (c != EOF)
+ DviUngetC(dw, c);
+ return i;
+}
+
+/*
+Local Variables:
+c-indent-level: 8
+c-continued-statement-offset: 8
+c-brace-offset: -8
+c-argdecl-indent: 8
+c-label-offset: -8
+c-tab-always-indent: nil
+End:
+*/
diff --git a/src/xditview/page.c b/src/xditview/page.c
new file mode 100644
index 00000000..9284199c
--- /dev/null
+++ b/src/xditview/page.c
@@ -0,0 +1,88 @@
+/*
+ * page.c
+ *
+ * map page numbers to file position
+ */
+
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "DviP.h"
+
+#ifdef X_NOT_STDC_ENV
+extern long ftell();
+#endif
+
+static DviFileMap *
+MapPageNumberToFileMap (dw, number)
+ DviWidget dw;
+ int number;
+{
+ DviFileMap *m;
+
+ for (m = dw->dvi.file_map; m; m=m->next)
+ if (m->page_number == number)
+ break;
+ return m;
+}
+
+DestroyFileMap (m)
+ DviFileMap *m;
+{
+ DviFileMap *next;
+
+ for (; m; m = next) {
+ next = m->next;
+ XtFree ((char *) m);
+ }
+}
+
+ForgetPagePositions (dw)
+ DviWidget dw;
+{
+ DestroyFileMap (dw->dvi.file_map);
+ dw->dvi.file_map = 0;
+}
+
+RememberPagePosition(dw, number)
+ DviWidget dw;
+ int number;
+{
+ DviFileMap *m;
+
+ if (!(m = MapPageNumberToFileMap (dw, number))) {
+ m = (DviFileMap *) XtMalloc (sizeof *m);
+ m->page_number = number;
+ m->next = dw->dvi.file_map;
+ dw->dvi.file_map = m;
+ }
+ if (dw->dvi.tmpFile)
+ m->position = ftell (dw->dvi.tmpFile);
+ else
+ m->position = ftell (dw->dvi.file);
+}
+
+SearchPagePosition (dw, number)
+ DviWidget dw;
+ int number;
+{
+ DviFileMap *m;
+
+ if (!(m = MapPageNumberToFileMap (dw, number)))
+ return -1;
+ return m->position;
+}
+
+FileSeek(dw, position)
+DviWidget dw;
+long position;
+{
+ if (dw->dvi.tmpFile) {
+ dw->dvi.readingTmp = 1;
+ fseek (dw->dvi.tmpFile, position, 0);
+ } else
+ fseek (dw->dvi.file, position, 0);
+}
+
diff --git a/src/xditview/parse.c b/src/xditview/parse.c
new file mode 100644
index 00000000..8367c17b
--- /dev/null
+++ b/src/xditview/parse.c
@@ -0,0 +1,334 @@
+/*
+ * parse.c
+ *
+ * parse dvi input
+ */
+
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "DviP.h"
+
+static int StopSeen = 0;
+static ParseDrawFunction(), ParseDeviceControl();
+static push_env(), pop_env();
+
+#define HorizontalMove(dw, delta) ((dw)->dvi.state->x += (delta))
+
+
+ParseInput(dw)
+ register DviWidget dw;
+{
+ int n, k;
+ int c;
+ char Buffer[BUFSIZ];
+ int NextPage;
+ int otherc;
+
+ StopSeen = 0;
+
+ /*
+ * make sure some state exists
+ */
+
+ if (!dw->dvi.state)
+ push_env (dw);
+ for (;;) {
+ switch (DviGetC(dw, &c)) {
+ case '\n':
+ break;
+ case ' ': /* when input is text */
+ case 0: /* occasional noise creeps in */
+ break;
+ case '{': /* push down current environment */
+ push_env(dw);
+ break;
+ case '}':
+ pop_env(dw);
+ break;
+ /*
+ * two motion digits plus a character
+ */
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ HorizontalMove(dw, (c-'0')*10 +
+ DviGetC(dw,&otherc)-'0');
+ /* fall through */
+ case 'c': /* single ascii character */
+ DviGetC(dw,&c);
+ if (c == ' ')
+ break;
+ Buffer[0] = c;
+ Buffer[1] = '\0';
+ (void) PutCharacter (dw, Buffer);
+ break;
+ case 'C':
+ GetWord (dw, Buffer, BUFSIZ);
+ (void) PutCharacter (dw, Buffer);
+ break;
+ case 't':
+ Buffer[1] = '\0';
+ while (DviGetC (dw, &c) != EOF
+ && c != ' ' && c != '\n') {
+ Buffer[0] = c;
+ HorizontalMove (dw, PutCharacter (dw, Buffer));
+ }
+ break;
+ case 'u':
+ n = GetNumber(dw);
+ Buffer[1] = '\0';
+ while (DviGetC (dw, &c) == ' ')
+ ;
+ while (c != EOF && c != ' ' && c != '\n') {
+ Buffer[0] = c;
+ HorizontalMove (dw,
+ PutCharacter (dw, Buffer) + n);
+ DviGetC (dw, &c);
+ }
+ break;
+
+ case 'D': /* draw function */
+ (void) GetLine(dw, Buffer, BUFSIZ);
+ if (dw->dvi.display_enable)
+ ParseDrawFunction(dw, Buffer);
+ break;
+ case 's': /* ignore fractional sizes */
+ n = GetNumber(dw);
+ dw->dvi.state->font_size = n;
+ break;
+ case 'f':
+ n = GetNumber(dw);
+ dw->dvi.state->font_number = n;
+ break;
+ case 'H': /* absolute horizontal motion */
+ k = GetNumber(dw);
+ HorizontalGoto(dw, k);
+ break;
+ case 'h': /* relative horizontal motion */
+ k = GetNumber(dw);
+ HorizontalMove(dw, k);
+ break;
+ case 'w': /* word space */
+ Word (dw);
+ break;
+ case 'V':
+ n = GetNumber(dw);
+ VerticalGoto(dw, n);
+ break;
+ case 'v':
+ n = GetNumber(dw);
+ VerticalMove(dw, n);
+ break;
+ case 'P': /* new spread */
+ break;
+ case 'p': /* new page */
+ (void) GetNumber(dw);
+ NextPage = dw->dvi.current_page + 1;
+ RememberPagePosition(dw, NextPage);
+ FlushCharCache (dw);
+ return(NextPage);
+ case 'N':
+ n = GetNumber(dw);
+ PutNumberedCharacter (dw, n);
+ break;
+ case 'n': /* end of line */
+ GetNumber(dw);
+ GetNumber(dw);
+ Newline (dw);
+ HorizontalGoto(dw, 0);
+ break;
+ case '+': /* continuation of X device control */
+ case '#': /* comment */
+ GetLine(dw, NULL, 0);
+ break;
+ case 'x': /* device control */
+ ParseDeviceControl(dw);
+ break;
+ case EOF:
+ dw->dvi.last_page = dw->dvi.current_page;
+ FlushCharCache (dw);
+ return dw->dvi.current_page;
+ default:
+ break;
+ }
+ }
+}
+
+static
+push_env(dw)
+ DviWidget dw;
+{
+ DviState *new;
+
+ new = (DviState *) XtMalloc (sizeof (*new));
+ if (dw->dvi.state)
+ *new = *(dw->dvi.state);
+ else {
+ new->font_size = 10;
+ new->font_number = 1;
+ new->x = 0;
+ new->y = 0;
+ }
+ new->next = dw->dvi.state;
+ dw->dvi.state = new;
+}
+
+static
+pop_env(dw)
+ DviWidget dw;
+{
+ DviState *old;
+
+ old = dw->dvi.state;
+ dw->dvi.state = old->next;
+ XtFree ((char *) old);
+}
+
+static
+InitTypesetter (dw)
+ DviWidget dw;
+{
+ while (dw->dvi.state)
+ pop_env (dw);
+ push_env (dw);
+ FlushCharCache (dw);
+}
+
+#define DRAW_ARGS_MAX 128
+
+static
+ParseDrawFunction(dw, buf)
+DviWidget dw;
+char *buf;
+{
+ int v[DRAW_ARGS_MAX];
+ int i;
+ char *ptr;
+
+ v[0] = v[1] = v[2] = v[3] = 0;
+
+ if (buf[0] == '\0')
+ return;
+ ptr = buf+1;
+
+ for (i = 0; i < DRAW_ARGS_MAX; i++) {
+ if (sscanf(ptr, "%d", v + i) != 1)
+ break;
+ while (*ptr == ' ')
+ ptr++;
+ while (*ptr != '\0' && *ptr != ' ')
+ ptr++;
+ }
+
+ switch (buf[0]) {
+ case 'l': /* draw a line */
+ DrawLine(dw, v[0], v[1]);
+ break;
+ case 'c': /* circle */
+ DrawCircle(dw, v[0]);
+ break;
+ case 'C':
+ DrawFilledCircle(dw, v[0]);
+ break;
+ case 'e': /* ellipse */
+ DrawEllipse(dw, v[0], v[1]);
+ break;
+ case 'E':
+ DrawFilledEllipse(dw, v[0], v[1]);
+ break;
+ case 'a': /* arc */
+ DrawArc(dw, v[0], v[1], v[2], v[3]);
+ break;
+ case 'p':
+ DrawPolygon(dw, v, i);
+ break;
+ case 'P':
+ DrawFilledPolygon(dw, v, i);
+ break;
+ case '~': /* wiggly line */
+ DrawSpline(dw, v, i);
+ break;
+ case 't':
+ dw->dvi.line_thickness = v[0];
+ break;
+ case 'f':
+ if (i > 0 && v[0] >= 0 && v[0] <= DVI_FILL_MAX)
+ dw->dvi.fill = v[0];
+ break;
+ default:
+#if 0
+ warning("unknown drawing function %s", buf);
+#endif
+ break;
+ }
+
+ if (buf[0] == 'e') {
+ if (i > 0)
+ dw->dvi.state->x += v[0];
+ }
+ else {
+ while (--i >= 0) {
+ if (i & 1)
+ dw->dvi.state->y += v[i];
+ else
+ dw->dvi.state->x += v[i];
+ }
+ }
+}
+
+static
+ParseDeviceControl(dw) /* Parse the x commands */
+ DviWidget dw;
+{
+ char str[20], str1[50];
+ int c, n;
+ extern int LastPage, CurrentPage;
+
+ GetWord (dw, str, 20);
+ switch (str[0]) { /* crude for now */
+ case 'T': /* output device */
+ GetWord (dw, str, 20);
+ SetDevice (dw, str);
+ break;
+ case 'i': /* initialize */
+ InitTypesetter (dw);
+ break;
+ case 't': /* trailer */
+ break;
+ case 'p': /* pause -- can restart */
+ break;
+ case 's': /* stop */
+ StopSeen = 1;
+ return;
+ case 'r': /* resolution when prepared */
+ break;
+ case 'f': /* font used */
+ n = GetNumber (dw);
+ GetWord (dw, str, 20);
+ GetLine (dw, str1, 50);
+ SetFontPosition (dw, n, str, str1);
+ break;
+ case 'H': /* char height */
+ break;
+ case 'S': /* slant */
+ break;
+ }
+ while (DviGetC (dw, &c) != '\n') /* skip rest of input line */
+ if (c == EOF)
+ return;
+ return;
+}
+
+
+/*
+Local Variables:
+c-indent-level: 8
+c-continued-statement-offset: 8
+c-brace-offset: -8
+c-argdecl-indent: 8
+c-label-offset: -8
+c-tab-always-indent: nil
+End:
+*/
diff --git a/src/xditview/xdit.bm b/src/xditview/xdit.bm
new file mode 100644
index 00000000..67b9c8ab
--- /dev/null
+++ b/src/xditview/xdit.bm
@@ -0,0 +1,14 @@
+#define xdit_width 32
+#define xdit_height 32
+static char xdit_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x03, 0x02, 0x00, 0x00, 0x02,
+ 0x8a, 0xa2, 0xfc, 0x03, 0x52, 0x14, 0x03, 0x04, 0x02, 0x80, 0x00, 0x08,
+ 0x52, 0x54, 0x00, 0x10, 0x8a, 0x22, 0x8f, 0x23, 0x02, 0x20, 0x06, 0x21,
+ 0x8a, 0x12, 0x8c, 0x40, 0x52, 0x14, 0x8c, 0x40, 0x02, 0x10, 0x58, 0x40,
+ 0x52, 0x14, 0x30, 0x40, 0x8a, 0x12, 0x30, 0x40, 0x02, 0x10, 0x70, 0x40,
+ 0x8a, 0x12, 0xc8, 0x40, 0x52, 0x24, 0xc4, 0xe0, 0x02, 0x20, 0x84, 0xe1,
+ 0x52, 0x54, 0xce, 0xf3, 0x8a, 0xa2, 0x00, 0xf8, 0x02, 0x00, 0x03, 0xfc,
+ 0x8a, 0x22, 0xfc, 0xf3, 0x52, 0x14, 0x00, 0xc2, 0x02, 0x00, 0x00, 0x02,
+ 0x52, 0x14, 0x45, 0x02, 0x8a, 0xa2, 0x28, 0x02, 0x02, 0x00, 0x00, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0xfe, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/src/xditview/xdit_mask.bm b/src/xditview/xdit_mask.bm
new file mode 100644
index 00000000..f34a4f86
--- /dev/null
+++ b/src/xditview/xdit_mask.bm
@@ -0,0 +1,14 @@
+#define xdit_mask_width 32
+#define xdit_mask_height 32
+static char xdit_mask_bits[] = {
+ 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07,
+ 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x1f,
+ 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xc7,
+ 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07,
+ 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/src/xditview/xditview.c b/src/xditview/xditview.c
new file mode 100644
index 00000000..e836cf50
--- /dev/null
+++ b/src/xditview/xditview.c
@@ -0,0 +1,594 @@
+/*
+ * Copyright 1991 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.
+ *
+ * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
+ * 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.
+ *
+ */
+/*
+ * xditview --
+ *
+ * Display ditroff output in an X window
+ */
+
+#ifndef SABER
+#ifndef lint
+static char rcsid[] = "$XConsortium: xditview.c,v 1.17 89/12/10 17:05:08 rws Exp $";
+#endif /* lint */
+#endif /* SABER */
+
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Shell.h>
+#include <X11/Xaw/Paned.h>
+#include <X11/Xaw/Viewport.h>
+#include <X11/Xaw/Box.h>
+#include <X11/Xaw/Command.h>
+#include <X11/Xaw/Dialog.h>
+#include <X11/Xaw/Label.h>
+#include <X11/Xaw/SimpleMenu.h>
+#include <X11/Xaw/SmeBSB.h>
+
+#include <signal.h>
+
+#include "Dvi.h"
+
+#include "xdit.bm"
+#include "xdit_mask.bm"
+#include "stdio.h"
+
+extern FILE *popen();
+extern void exit();
+
+static String fallback_resources[] = {
+#include "GXditview-ad.h"
+ NULL
+};
+
+static struct app_resources {
+ char *print_command;
+ char *filename;
+} app_resources;
+
+#define offset(field) XtOffset(struct app_resources *, field)
+
+/* Application resources. */
+
+static XtResource resources[] = {
+ {"printCommand", "PrintCommand", XtRString, sizeof(char*),
+ offset(print_command), XtRString, NULL},
+ {"filename", "Filename", XtRString, sizeof(char*),
+ offset(filename), XtRString, NULL},
+};
+
+#undef offset
+
+/* Command line options table. Only resources are entered here...there is a
+ pass over the remaining options after XtParseCommand is let loose. */
+
+static XrmOptionDescRec options[] = {
+{"-page", "*dvi.pageNumber", XrmoptionSepArg, NULL},
+{"-backingStore", "*dvi.backingStore", XrmoptionSepArg, NULL},
+{"-resolution", "*dvi.resolution", XrmoptionSepArg, NULL},
+{"-printCommand", ".printCommand", XrmoptionSepArg, NULL},
+{"-filename", ".filename", XrmoptionSepArg, NULL},
+{"-noPolyText", "*dvi.noPolyText", XrmoptionNoArg, "TRUE"},
+};
+
+static char current_print_command[1024];
+
+static char current_file_name[1024];
+static FILE *current_file;
+
+/*
+ * Report the syntax for calling xditview.
+ */
+
+static
+Syntax(call)
+ char *call;
+{
+ (void) printf ("Usage: %s [-fg <color>] [-bg <color>]\n", call);
+ (void) printf (" [-bd <color>] [-bw <pixels>] [-help]\n");
+ (void) printf (" [-display displayname] [-geometry geom]\n");
+ (void) printf (" [-page <page-number>] [-backing <backing-store>]\n");
+ (void) printf (" [-resolution <res>] [-print <command>]\n");
+ (void) printf (" [-filename <file>] [filename]\n\n");
+ exit(1);
+}
+
+static void NewFile (), SetPageNumber ();
+static Widget toplevel, paned, viewport, dvi;
+static Widget page;
+static Widget simpleMenu;
+
+static void NextPage(), PreviousPage(), SelectPage(), OpenFile(), Quit();
+static void Print();
+
+static struct menuEntry {
+ char *name;
+ void (*function)();
+} menuEntries[] = {
+ "nextPage", NextPage,
+ "previousPage", PreviousPage,
+ "selectPage", SelectPage,
+ "print", Print,
+ "openFile", OpenFile,
+ "quit", Quit,
+};
+
+static void NextPageAction(), PreviousPageAction(), SelectPageAction();
+static void OpenFileAction(), QuitAction();
+static void AcceptAction(), CancelAction();
+static void PrintAction();
+static void RerasterizeAction();
+
+XtActionsRec xditview_actions[] = {
+ "NextPage", NextPageAction,
+ "PreviousPage", PreviousPageAction,
+ "SelectPage", SelectPageAction,
+ "Print", PrintAction,
+ "OpenFile", OpenFileAction,
+ "Rerasterize", RerasterizeAction,
+ "Quit", QuitAction,
+ "Accept", AcceptAction,
+ "Cancel", CancelAction,
+};
+
+#define MenuNextPage 0
+#define MenuPreviousPage 1
+#define MenuSelectPage 2
+#define MenuPrint 3
+#define MenuOpenFile 4
+#define MenuQuit 5
+
+static char pageLabel[256] = "Page <none>";
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+ char *file_name = 0;
+ int i;
+ static Arg labelArgs[] = {
+ {XtNlabel, (XtArgVal) pageLabel},
+ };
+ XtAppContext xtcontext;
+ Arg topLevelArgs[2];
+ Widget entry;
+ Arg pageNumberArgs[1];
+ int page_number;
+
+ toplevel = XtAppInitialize(&xtcontext, "GXditview",
+ options, XtNumber (options),
+ &argc, argv, fallback_resources, NULL, 0);
+ if (argc > 2)
+ Syntax(argv[0]);
+
+ XtGetApplicationResources(toplevel, (XtPointer)&app_resources,
+ resources, XtNumber(resources),
+ NULL, (Cardinal) 0);
+ if (app_resources.print_command)
+ strcpy(current_print_command, app_resources.print_command);
+
+ XtAppAddActions(xtcontext, xditview_actions, XtNumber (xditview_actions));
+
+ XtSetArg (topLevelArgs[0], XtNiconPixmap,
+ XCreateBitmapFromData (XtDisplay (toplevel),
+ XtScreen(toplevel)->root,
+ xdit_bits, xdit_width, xdit_height));
+
+ XtSetArg (topLevelArgs[1], XtNiconMask,
+ XCreateBitmapFromData (XtDisplay (toplevel),
+ XtScreen(toplevel)->root,
+ xdit_mask_bits,
+ xdit_mask_width, xdit_mask_height));
+ XtSetValues (toplevel, topLevelArgs, 2);
+ if (argc > 1)
+ file_name = argv[1];
+
+ /*
+ * create the menu and insert the entries
+ */
+ simpleMenu = XtCreatePopupShell ("menu", simpleMenuWidgetClass, toplevel,
+ NULL, 0);
+ for (i = 0; i < XtNumber (menuEntries); i++) {
+ entry = XtCreateManagedWidget(menuEntries[i].name,
+ smeBSBObjectClass, simpleMenu,
+ NULL, (Cardinal) 0);
+ XtAddCallback(entry, XtNcallback, menuEntries[i].function, NULL);
+ }
+
+ paned = XtCreateManagedWidget("paned", panedWidgetClass, toplevel,
+ NULL, (Cardinal) 0);
+ viewport = XtCreateManagedWidget("viewport", viewportWidgetClass, paned,
+ NULL, (Cardinal) 0);
+ dvi = XtCreateManagedWidget ("dvi", dviWidgetClass, viewport, NULL, 0);
+ page = XtCreateManagedWidget ("label", labelWidgetClass, paned,
+ labelArgs, XtNumber (labelArgs));
+ XtSetArg (pageNumberArgs[0], XtNpageNumber, &page_number);
+ XtGetValues (dvi, pageNumberArgs, 1);
+ if (file_name)
+ NewFile (file_name);
+ /* NewFile modifies current_file_name, so do this here. */
+ if (app_resources.filename)
+ strcpy(current_file_name, app_resources.filename);
+ XtRealizeWidget (toplevel);
+ if (file_name)
+ SetPageNumber (page_number);
+ XtAppMainLoop(xtcontext);
+ return 0;
+}
+
+static void
+SetPageNumber (number)
+{
+ Arg arg[2];
+ int actual_number, last_page;
+
+ XtSetArg (arg[0], XtNpageNumber, number);
+ XtSetValues (dvi, arg, 1);
+ XtSetArg (arg[0], XtNpageNumber, &actual_number);
+ XtSetArg (arg[1], XtNlastPageNumber, &last_page);
+ XtGetValues (dvi, arg, 2);
+ if (actual_number == 0)
+ sprintf (pageLabel, "Page <none>");
+ else if (last_page > 0)
+ sprintf (pageLabel, "Page %d of %d", actual_number, last_page);
+ else
+ sprintf (pageLabel, "Page %d", actual_number);
+ XtSetArg (arg[0], XtNlabel, pageLabel);
+ XtSetValues (page, arg, 1);
+}
+
+static void
+SelectPageNumber (number_string)
+char *number_string;
+{
+ SetPageNumber (atoi(number_string));
+}
+
+static int hadFile = 0;
+
+static void
+NewFile (name)
+char *name;
+{
+ Arg arg[2];
+ char *n;
+ FILE *new_file;
+ Boolean seek = 0;
+
+ if (current_file) {
+ if (!strcmp (current_file_name, "-"))
+ ;
+ else if (current_file_name[0] == '|')
+ pclose (current_file);
+ else
+ fclose (current_file);
+ }
+ if (!strcmp (name, "-"))
+ new_file = stdin;
+ else if (name[0] == '|')
+ new_file = popen (name+1, "r");
+ else {
+ new_file = fopen (name, "r");
+ seek = 1;
+ }
+ if (!new_file) {
+ /* XXX display error message */
+ return;
+ }
+ XtSetArg (arg[0], XtNfile, new_file);
+ XtSetArg (arg[1], XtNseek, seek);
+ XtSetValues (dvi, arg, 2);
+ if (hadFile || name[0] != '-' || name[1] != '\0') {
+ XtSetArg (arg[0], XtNtitle, name);
+ if (name[0] != '/' && (n = strrchr (name, '/')))
+ n = n + 1;
+ else
+ n = name;
+ XtSetArg (arg[1], XtNiconName, n);
+ XtSetValues (toplevel, arg, 2);
+ }
+ hadFile = 1;
+ SelectPageNumber ("1");
+ strcpy (current_file_name, name);
+ current_file = new_file;
+}
+
+static char fileBuf[1024];
+
+ResetMenuEntry (entry)
+ Widget entry;
+{
+ Arg arg[1];
+
+ XtSetArg (arg[0], XtNpopupOnEntry, entry);
+ XtSetValues (XtParent(entry) , arg, (Cardinal) 1);
+}
+
+/*ARGSUSED*/
+
+static void
+NextPage (entry, name, data)
+ Widget entry;
+ caddr_t name, data;
+{
+ NextPageAction();
+ ResetMenuEntry (entry);
+}
+
+static void
+NextPageAction ()
+{
+ Arg args[1];
+ int number;
+
+ XtSetArg (args[0], XtNpageNumber, &number);
+ XtGetValues (dvi, args, 1);
+ SetPageNumber (number+1);
+}
+
+/*ARGSUSED*/
+
+static void
+PreviousPage (entry, name, data)
+ Widget entry;
+ caddr_t name, data;
+{
+ PreviousPageAction ();
+ ResetMenuEntry (entry);
+}
+
+static void
+PreviousPageAction ()
+{
+ Arg args[1];
+ int number;
+
+ XtSetArg (args[0], XtNpageNumber, &number);
+ XtGetValues (dvi, args, 1);
+ SetPageNumber (number-1);
+}
+
+/* ARGSUSED */
+
+static void
+SelectPage (entry, name, data)
+ Widget entry;
+ caddr_t name, data;
+{
+ SelectPageAction ();
+ ResetMenuEntry (entry);
+}
+
+static void
+SelectPageAction ()
+{
+ MakePrompt (toplevel, "Page number", SelectPageNumber, "");
+}
+
+
+static void
+DoPrint (name)
+ char *name;
+{
+ FILE *print_file;
+#ifdef SIGNALRETURNSINT
+ int (*handler)();
+#else
+ void (*handler)();
+#endif
+ /* Avoid dieing because of an invalid command. */
+ handler = signal(SIGPIPE, SIG_IGN);
+
+ print_file = popen(name, "w");
+ if (!print_file)
+ /* XXX print error message */
+ return;
+ DviSaveToFile(dvi, print_file);
+ pclose(print_file);
+ signal(SIGPIPE, handler);
+ strcpy(current_print_command, name);
+}
+
+static void
+RerasterizeAction()
+{
+ Arg args[1];
+ int number;
+
+ if (current_file_name[0] == 0) {
+ /* XXX display an error message */
+ return;
+ }
+ XtSetArg (args[0], XtNpageNumber, &number);
+ XtGetValues (dvi, args, 1);
+ NewFile(current_file_name);
+ SetPageNumber (number);
+}
+
+/* ARGSUSED */
+
+static void
+Print (entry, name, data)
+ Widget entry;
+ caddr_t name, data;
+{
+ PrintAction ();
+ ResetMenuEntry (entry);
+}
+
+static void
+PrintAction ()
+{
+ if (current_print_command[0])
+ strcpy (fileBuf, current_print_command);
+ else
+ fileBuf[0] = '\0';
+ MakePrompt (toplevel, "Print command:", DoPrint, fileBuf);
+}
+
+
+/* ARGSUSED */
+
+static void
+OpenFile (entry, name, data)
+ Widget entry;
+ caddr_t name, data;
+{
+ OpenFileAction ();
+ ResetMenuEntry (entry);
+}
+
+static void
+OpenFileAction ()
+{
+ if (current_file_name[0])
+ strcpy (fileBuf, current_file_name);
+ else
+ fileBuf[0] = '\0';
+ MakePrompt (toplevel, "File to open:", NewFile, fileBuf);
+}
+
+/* ARGSUSED */
+
+static void
+Quit (entry, closure, data)
+ Widget entry;
+ caddr_t closure, data;
+{
+ QuitAction ();
+}
+
+static void
+QuitAction ()
+{
+ exit (0);
+}
+
+Widget promptShell, promptDialog;
+void (*promptfunction)();
+
+/* ARGSUSED */
+static
+void CancelAction (widget, event, params, num_params)
+ Widget widget;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ if (promptShell) {
+ XtSetKeyboardFocus(toplevel, (Widget) None);
+ XtDestroyWidget(promptShell);
+ promptShell = (Widget) 0;
+ }
+}
+
+static
+void AcceptAction (widget, event, params, num_params)
+ Widget widget;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ (*promptfunction)(XawDialogGetValueString(promptDialog));
+ CancelAction (widget, event, params, num_params);
+}
+
+MakePrompt(centerw, prompt, func, def)
+Widget centerw;
+char *prompt;
+void (*func)();
+char *def;
+{
+ static Arg dialogArgs[] = {
+ {XtNlabel, 0},
+ {XtNvalue, 0},
+ };
+ Arg valueArgs[1];
+ Arg centerArgs[2];
+ Position source_x, source_y;
+ Position dest_x, dest_y;
+ Dimension center_width, center_height;
+ Dimension prompt_width, prompt_height;
+ Widget valueWidget;
+
+ CancelAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0);
+ promptShell = XtCreatePopupShell ("promptShell", transientShellWidgetClass,
+ toplevel, NULL, (Cardinal) 0);
+ dialogArgs[0].value = (XtArgVal)prompt;
+ dialogArgs[1].value = (XtArgVal)def;
+ promptDialog = XtCreateManagedWidget( "promptDialog", dialogWidgetClass,
+ promptShell, dialogArgs, XtNumber (dialogArgs));
+ XawDialogAddButton(promptDialog, "accept", NULL, (caddr_t) 0);
+ XawDialogAddButton(promptDialog, "cancel", NULL, (caddr_t) 0);
+ valueWidget = XtNameToWidget (promptDialog, "value");
+ if (valueWidget) {
+ XtSetArg (valueArgs[0], XtNresizable, TRUE);
+ XtSetValues (valueWidget, valueArgs, 1);
+ /*
+ * as resizable isn't set until just above, the
+ * default value will be displayed incorrectly.
+ * rectify the situation by resetting the values
+ */
+ XtSetValues (promptDialog, dialogArgs, XtNumber (dialogArgs));
+ }
+ XtSetKeyboardFocus (promptDialog, valueWidget);
+ XtSetKeyboardFocus (toplevel, valueWidget);
+ XtRealizeWidget (promptShell);
+ /*
+ * place the widget in the center of the "parent"
+ */
+ XtSetArg (centerArgs[0], XtNwidth, &center_width);
+ XtSetArg (centerArgs[1], XtNheight, &center_height);
+ XtGetValues (centerw, centerArgs, 2);
+ XtSetArg (centerArgs[0], XtNwidth, &prompt_width);
+ XtSetArg (centerArgs[1], XtNheight, &prompt_height);
+ XtGetValues (promptShell, centerArgs, 2);
+ source_x = (center_width - prompt_width) / 2;
+ source_y = (center_height - prompt_height) / 3;
+ XtTranslateCoords (centerw, source_x, source_y, &dest_x, &dest_y);
+ XtSetArg (centerArgs[0], XtNx, dest_x);
+ XtSetArg (centerArgs[1], XtNy, dest_y);
+ XtSetValues (promptShell, centerArgs, 2);
+ XtMapWidget(promptShell);
+ promptfunction = func;
+}
+
+/* For DviChar.c */
+
+char *xmalloc(n)
+ int n;
+{
+ return XtMalloc(n);
+}
+
+/*
+Local Variables:
+c-indent-level: 4
+c-continued-statement-offset: 4
+c-brace-offset: -4
+c-argdecl-indent: 4
+c-label-offset: -4
+c-tab-always-indent: nil
+End:
+*/
diff --git a/src/xditview/xtotroff.c b/src/xditview/xtotroff.c
new file mode 100644
index 00000000..3e4e78bc
--- /dev/null
+++ b/src/xditview/xtotroff.c
@@ -0,0 +1,303 @@
+/*
+ * xtotroff
+ *
+ * convert X font metrics into troff font metrics
+ */
+
+#include <X11/Xlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "XFontName.h"
+#include "DviChar.h"
+
+#ifdef X_NOT_STDC_ENV
+char *malloc();
+#else
+#include <stdlib.h>
+#endif
+
+#define charWidth(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].width)
+#define charHeight(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].ascent)
+#define charDepth(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].descent)
+#define charLBearing(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].lbearing)
+#define charRBearing(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].rbearing)
+
+Display *dpy;
+int groff_flag = 0;
+unsigned resolution = 75;
+unsigned point_size = 10;
+
+int charExists (fi, c)
+ XFontStruct *fi;
+ int c;
+{
+ XCharStruct *p;
+
+ if (c < fi->min_char_or_byte2 || c > fi->max_char_or_byte2)
+ return 0;
+ p = fi->per_char + (c - fi->min_char_or_byte2);
+ return (p->lbearing != 0 || p->rbearing != 0 || p->width != 0
+ || p->ascent != 0 || p->descent != 0 || p->attributes != 0);
+}
+
+/* Canonicalize the font name by replacing scalable parts by *s. */
+
+CanonicalizeFontName (font_name, canon_font_name)
+ char *font_name, *canon_font_name;
+{
+ unsigned int attributes;
+ XFontName parsed;
+
+ if (!XParseFontName(font_name, &parsed, &attributes)) {
+ fprintf (stderr, "not a standard name: %s\n", font_name);
+ return 0;
+ }
+
+ attributes &= ~(FontNamePixelSize|FontNameAverageWidth
+ |FontNamePointSize
+ |FontNameResolutionX|FontNameResolutionY);
+ XFormatFontName(&parsed, attributes, canon_font_name);
+ return 1;
+}
+
+int FontNamesAmbiguous(font_name, names, count)
+char *font_name;
+char **names;
+int count;
+{
+ char name1[2048], name2[2048];
+ int i;
+
+ if (count == 1)
+ return 0;
+
+ for (i = 0; i < count; i++) {
+ if (!CanonicalizeFontName(names[i], i == 0 ? name1 : name2)) {
+ fprintf(stderr, "bad font name: %s\n", names[i]);
+ return 1;
+ }
+ if (i > 0 && strcmp(name1, name2) != 0) {
+ fprintf(stderr, "ambiguous font name: %s\n", font_name);
+ fprintf(stderr, " matches %s\n", names[0]);
+ fprintf(stderr, " and %s\n", names[i]);
+ return 1;
+ }
+
+ }
+ return 0;
+}
+
+MapFont (font_name, troff_name)
+ char *font_name;
+ char *troff_name;
+{
+ XFontStruct *fi;
+ int count;
+ char **names;
+ FILE *out;
+ int c;
+ unsigned int attributes;
+ XFontName parsed;
+ int j, k;
+ DviCharNameMap *char_map;
+ char encoding[256];
+ char *s;
+ int wid;
+ char name_string[2048];
+
+ if (!XParseFontName(font_name, &parsed, &attributes)) {
+ fprintf (stderr, "not a standard name: %s\n", font_name);
+ return 0;
+ }
+
+ attributes &= ~(FontNamePixelSize|FontNameAverageWidth);
+ attributes |= FontNameResolutionX;
+ attributes |= FontNameResolutionY;
+ attributes |= FontNamePointSize;
+ parsed.ResolutionX = resolution;
+ parsed.ResolutionY = resolution;
+ parsed.PointSize = point_size*10;
+ XFormatFontName(&parsed, attributes, name_string);
+
+ names = XListFonts (dpy, name_string, 100000, &count);
+ if (count < 1) {
+ fprintf (stderr, "bad font name: %s\n", font_name);
+ return 0;
+ }
+
+ if (FontNamesAmbiguous(font_name, names, count))
+ return 0;
+
+ XParseFontName(names[0], &parsed, &attributes);
+ sprintf (encoding, "%s-%s", parsed.CharSetRegistry,
+ parsed.CharSetEncoding);
+ for (s = encoding; *s; s++)
+ if (isupper (*s))
+ *s = tolower (*s);
+ char_map = DviFindMap (encoding);
+ if (!char_map) {
+ fprintf (stderr, "not a standard encoding: %s\n", encoding);
+ return 0;
+ }
+
+ fi = XLoadQueryFont (dpy, names[0]);
+ if (!fi) {
+ fprintf (stderr, "font does not exist: %s\n", names[0]);
+ return 0;
+ }
+
+ printf ("%s -> %s\n", names[0], troff_name);
+
+ (void) unlink (troff_name);
+ out = fopen (troff_name, "w");
+ if (!out) {
+ perror (troff_name);
+ return 0;
+ }
+ fprintf (out, "name %s\n", troff_name);
+ if (!strcmp (char_map->encoding, "adobe-fontspecific"))
+ fprintf (out, "special\n");
+ if (charExists (fi, ' ')) {
+ int w = charWidth (fi, ' ');
+ if (w > 0)
+ fprintf (out, "spacewidth %d\n", w);
+ }
+ fprintf (out, "charset\n");
+ for (c = fi->min_char_or_byte2; c <= fi->max_char_or_byte2; c++) {
+ char *name = DviCharName (char_map,c,0);
+ if (charExists (fi, c) && (groff_flag || name)) {
+
+ wid = charWidth (fi, c);
+
+ fprintf (out, "%s\t%d",
+ name ? name : "---",
+ wid);
+ if (groff_flag) {
+ int param[5];
+ param[0] = charHeight (fi, c);
+ param[1] = charDepth (fi, c);
+ param[2] = 0 /* charRBearing (fi, c) - wid */;
+ param[3] = 0 /* charLBearing (fi, c) */;
+ param[4] = 0; /* XXX */
+ for (j = 0; j < 5; j++)
+ if (param[j] < 0)
+ param[j] = 0;
+ for (j = 4; j >= 0; j--)
+ if (param[j] != 0)
+ break;
+ for (k = 0; k <= j; k++)
+ fprintf (out, ",%d", param[k]);
+ }
+ fprintf (out, "\t0\t0%o\n", c);
+
+ if (name) {
+ for (k = 1; DviCharName(char_map,c,k); k++) {
+ fprintf (out, "%s\t\"\n",
+ DviCharName (char_map,c,k));
+ }
+ }
+ }
+ }
+ XUnloadFont (dpy, fi->fid);
+ fclose (out);
+ return 1;
+}
+
+static usage(prog)
+ char *prog;
+{
+ fprintf (stderr,
+ "usage: %s [-g] [-r resolution] [-s pointsize] FontMap\n",
+ prog);
+ exit (1);
+}
+
+
+/* For use by DviChar.c */
+
+char *xmalloc(n)
+int n;
+{
+ char *p = malloc(n);
+ if (!p) {
+ fprintf(stderr, "Out of memory\n");
+ exit(1);
+ }
+ return p;
+}
+
+main (argc, argv)
+ char **argv;
+{
+ char troff_name[1024];
+ char font_name[1024];
+ char line[1024];
+ char *a, *b, c;
+ int position;
+ FILE *map;
+ int opt;
+ extern int optind;
+ extern char *optarg;
+
+ while ((opt = getopt(argc, argv, "gr:s:")) != EOF) {
+ switch (opt) {
+ case 'g':
+ groff_flag = 1;
+ break;
+ case 'r':
+ sscanf(optarg, "%u", &resolution);
+ break;
+ case 's':
+ sscanf(optarg, "%u", &point_size);
+ break;
+ default:
+ usage(argv[0]);
+ }
+ }
+ if (argc - optind != 1)
+ usage(argv[0]);
+
+ dpy = XOpenDisplay (0);
+ if (!dpy) {
+ fprintf (stderr, "Can't connect to the X server.\n");
+ fprintf (stderr, "Make sure the DISPLAY environment variable is set correctly.\n");
+ exit (1);
+ }
+ position = 1;
+
+ map = fopen (argv[optind], "r");
+ if (map == NULL) {
+ perror (argv[optind]);
+ exit (1);
+ }
+
+ while (fgets (line, sizeof (line), map)) {
+ for (a=line,b=troff_name; *a; a++,b++) {
+ c = (*b = *a);
+ if (c == ' ' || c == '\t')
+ break;
+ }
+ *b = '\0';
+ while (*a && (*a == ' ' || *a == '\t'))
+ ++a;
+ for (b=font_name; *a; a++,b++)
+ if ((*b = *a) == '\n')
+ break;
+ *b = '\0';
+ if (!MapFont (font_name, troff_name))
+ exit (1);
+ ++position;
+ }
+ exit (0);
+}
+
+/*
+Local Variables:
+c-indent-level: 8
+c-continued-statement-offset: 8
+c-brace-offset: -8
+c-argdecl-indent: 8
+c-label-offset: -8
+c-tab-always-indent: nil
+End:
+*/
diff --git a/test-groff b/test-groff
new file mode 100644
index 00000000..e78ba302
--- /dev/null
+++ b/test-groff
@@ -0,0 +1,39 @@
+#! /bin/sh
+# This script runs groff without requiring that it be installed.
+# The current directory must be the build directory.
+
+builddir=./src
+srcdir=`echo $0 | sed -e 's;/[^/]*$;;'`
+
+if test ! -d $builddir/roff/groff || test ! -r $builddir/roff/groff/groff
+then
+ echo $0 must be run with the build directory as the current directory 2>&1
+ exit 1
+fi
+
+PATH=\
+$builddir/roff/troff:\
+$builddir/preproc/pic:\
+$builddir/preproc/eqn:\
+$builddir/preproc/tbl:\
+$builddir/preproc/refer:\
+$builddir/preproc/soelim:\
+$builddir/devices/grops:\
+$builddir/devices/grodvi:\
+$builddir/devices/grotty:\
+$builddir/devices/grolj4:\
+$builddir/devices/grohtml:\
+$srcdir/$builddir/xditview:\
+$PATH
+
+test -n "$srcdir" || srcdir=.
+
+XENVIRONMENT=`cd $srcdir; pwd`/src/xditview/GXditview.ad
+export XENVIRONMENT
+
+GROFF_COMMAND_PREFIX=
+GROFF_FONT_PATH=$builddir:$srcdir/font
+GROFF_TMAC_PATH=$srcdir/tmac:$srcdir/src/roff/troff
+export PATH GROFF_COMMAND_PREFIX GROFF_FONT_PATH GROFF_TMAC_PATH
+
+exec $builddir/roff/groff/groff ${1+"$@"}
diff --git a/tmac/Makefile.sub b/tmac/Makefile.sub
new file mode 100644
index 00000000..48db39c0
--- /dev/null
+++ b/tmac/Makefile.sub
@@ -0,0 +1,87 @@
+MAN7=\
+ groff_ms.n \
+ groff_man.n \
+ groff_me.n \
+ groff_msafer.n \
+ groff_mdoc.n \
+ groff_mdoc.samples.n \
+ groff_markup.n
+
+NORMALFILES=\
+ tmac.andoc tmac.pic tmac.ps tmac.psnew tmac.psold tmac.pspic \
+ tmac.psatk tmac.dvi tmac.tty tmac.tty-char tmac.X tmac.Xps tmac.latin1 \
+ tmac.lj4 eqnrc troffrc troffrc-end tmac.safer tmac.html tmac.arkup \
+ tmac.a4 tmac.trace
+SPECIALFILES=tmac.an tmac.s
+STRIPFILES=tmac.e tmac.doc tmac.doc.old
+MDOCFILES=doc-common doc-ditroff doc-nroff doc-syms
+mdocdir=$(tmacdir)/mdoc
+CLEANADD=\
+ stamp-strip stamp-wrap tmac.e-s tmac.doc-s tmac.doc.old-s \
+ doc-common-s doc-ditroff-s doc-nroff-s doc-syms-s *-wrap
+tmac_s_prefix=
+tmac_an_prefix=
+tmac_wrap=
+sys_tmac_prefix=
+
+all: stamp-strip stamp-wrap
+
+install_data: $(NORMALFILES) $(SPECIALFILES) stamp-wrap stamp-strip man.local
+ -test -d $(tmacdir) || $(mkinstalldirs) $(tmacdir)
+ if test -n "$(tmac_wrap)"; then \
+ for m in ""$(tmac_wrap); do \
+ $(INSTALL_DATA) $$m-wrap $(tmacdir)/tmac.$$m; \
+ done; \
+ fi
+ for f in $(NORMALFILES); do \
+ rm -f $(tmacdir)/$$f; \
+ $(INSTALL_DATA) $(srcdir)/$$f $(tmacdir)/$$f; \
+ done
+ -rm -f $(tmacdir)/tmac.$(tmac_s_prefix)s
+ $(INSTALL_DATA) $(srcdir)/tmac.s $(tmacdir)/tmac.$(tmac_s_prefix)s
+ -rm -f $(tmacdir)/tmac.$(tmac_an_prefix)an
+ $(INSTALL_DATA) $(srcdir)/tmac.an $(tmacdir)/tmac.$(tmac_an_prefix)an
+ for f in $(STRIPFILES); do \
+ rm -f $(tmacdir)/$$f; \
+ $(INSTALL_DATA) $$f-s $(tmacdir)/$$f; \
+ done
+ -test -d $(mdocdir) || $(mkinstalldirs) $(mdocdir)
+ for f in $(MDOCFILES); do \
+ rm -f $(mdocdir)/$$f; \
+ $(INSTALL_DATA) $$f-s $(mdocdir)/$$f; \
+ done
+ -test -f $(tmacdir)/man.local || \
+ $(INSTALL_DATA) $(srcdir)/man.local $(tmacdir)/man.local
+ -rm -f temp
+
+stamp-strip: $(STRIPFILES) $(MDOCFILES)
+ for f in $(STRIPFILES) $(MDOCFILES); do \
+ rm -f $$f-s; \
+ sed -f $(srcdir)/strip.sed $(srcdir)/$$f >$$f-s; \
+ done
+ touch $@
+
+stamp-wrap:
+ if test -n "$(tmac_wrap)"; then \
+ for m in ""$(tmac_wrap); do \
+ rm -f $$m-wrap; \
+ echo .cp 1 >$$m-wrap; \
+ echo .so $(sys_tmac_prefix)$$m >>$$m-wrap; \
+ done; \
+ fi
+ touch $@
+
+uninstall_sub:
+ -if test -n "$(tmac_wrap)"; then \
+ for m in ""$(tmac_wrap); do \
+ rm -f $(tmacdir)/tmac.$$m; \
+ done; \
+ fi
+ -for f in $(NORMALFILES) $(STRIPFILES); do rm -f $(tmacdir)/$$f; done
+ -rm -f $(tmacdir)/tmac.$(tmac_s_prefix)s
+ -rm -f $(tmacdir)/tmac.$(tmac_an_prefix)an
+ -if cmp -s $(tmacdir)/man.local $(srcdir)/man.local; then \
+ rm -f $(tmacdir)/man.local; \
+ fi
+ -for f in $(MDOCFILES); do rm -f $(mdocdir)/$$f; done
+ -rmdir $(mdocdir)
diff --git a/tmac/TODO b/tmac/TODO
new file mode 100644
index 00000000..5213fc27
--- /dev/null
+++ b/tmac/TODO
@@ -0,0 +1,38 @@
+Support multiple line-spacing.
+
+Improve the device independence of the character definitions.
+
+If we have footnotes in the abstract in RP format, then the footnote
+will appear on the cover sheet, which it should, but also on the first
+page, which it should not.
+
+Should we allow multi-page cover-sheets?
+
+Warn about automatically numbered footnotes in floating keeps.
+
+When we bring back the footnote overflow at the top of page, it would
+be more efficient to avoid diverting it again. (Need to keep track of
+footnote height.)
+
+Possibly have a place above which the footnote trap must not be
+placed.
+
+Improved indexing, not using tm, controlled by string variable (eg
+-dIDX=file.idx).
+
+When changing from multi-column to narrower columns, we could avoid
+doing a @super-eject. (This might not be a good idea.)
+
+Think about cutmarks. Possibly implement CM.
+
+Implement thesis Mode (TM, CT).
+
+Implement more V10 features.
+
+Should this
+
+.LP
+.rs
+.sp \n(.tu
+
+print two pages?
diff --git a/tmac/doc-common b/tmac/doc-common
new file mode 100644
index 00000000..1be19597
--- /dev/null
+++ b/tmac/doc-common
@@ -0,0 +1,450 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. 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.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+.\"
+.\" @(#)doc-common 5.7 (Berkeley) 8/5/91
+.\"
+.\" %beginstrip%
+.nr %A 1
+.nr %J 1
+.nr %N 1
+.nr %O 1
+.nr %R 1
+.nr %T 1
+.nr %V 1
+.nr Ad 12n
+.nr Ac 3
+.nr Ao 12n
+.nr Ap 2
+.nr An 12n
+.nr Aq 12n
+.nr Ar 12n
+.nr Bc 3
+.nr Bl 1
+.nr Bo 12n
+.nr Bq 12n
+.nr Bx 12n
+.nr Cd 12n
+.nr Cm 10n
+.nr Co 15n
+.nr Cx 20n
+.nr Dc 3
+.nr Do 10n
+.nr Dq 12n
+.nr Ds 6n
+.nr Dq 12n
+.nr Dv 12n
+.nr tI \n(Dsu
+.nr Ec 3
+.nr El 1
+.nr Eo 12n
+.nr Eq 12n
+.nr Em 10n
+.nr Er 12n
+.nr Ev 15n
+.nr Ex 10n
+.nr Fa 12n
+.nr Fl 10n
+.nr Fc 3
+.nr Fo 16n
+.nr Fn 16n
+.nr Hl 1
+.nr I1 6n
+.nr I2 12n
+.nr I3 18n
+.nr Ic 10n
+.nr Li 16n
+.nr Ms 6n
+.nr Nm 10n
+.nr No 12n
+.nr Ns 2
+.nr Oo 10n
+.nr Oc 3
+.nr Op 14n
+.nr Pa 32n
+.nr Pf 12n
+.nr Pc 3
+.nr Po 12n
+.nr Pq 12n
+.nr Ql 16n
+.nr Qc 3
+.nr Qo 12n
+.nr Qq 12n
+.nr Sc 3
+.nr So 12n
+.nr Sq 12n
+.nr Sy 6n
+.nr Sx 16n
+.nr Ra 1
+.nr Rj 1
+.nr Rn 1
+.nr Ro 1
+.nr Rr 1
+.nr Rt 1
+.nr Rv 1
+.nr Tn 10n
+.nr Ta 1
+.nr Tv 1
+.nr Tx 22n
+.nr Ux 10n
+.nr Va 12n
+.nr Xc 3
+.nr Xo 1
+.nr Xr 10n
+.nr Yr \n(yr+1900
+.ds sV \& \&
+.ds hV \&\ \&
+.ds iV \& \&
+.ds tV \&\\t\&
+.\" Punctuation values (3 = closing punctuation, 4 = opening)
+.nr z. 3
+.nr z, 3
+.nr z: 3
+.nr z; 3
+.nr z( 4
+.nr z) 3
+.nr z[ 4
+.nr z] 3
+.\" Matching pairs
+.ds z( z)
+.ds z[ z]
+.ds z< z>
+.\" This is disgusting, troff not parse ``if'' stmt properly
+.nr z0 0
+.nr z1 0
+.nr z2 0
+.nr z3 0
+.nr z4 0
+.nr z5 0
+.nr z6 0
+.nr z7 0
+.nr z8 0
+.nr z9 0
+.nr z# 0
+.\" Header assembly macros
+.de Dt
+.ds dT UNTITLED
+.ds vT LOCAL
+.ds cH Null
+.if !"\\$1"" .ds dT \\$1
+.if !"\\$2"" \{\
+. ds cH \\$2
+.\" . if "\\$3"" \{\
+. if \\$2>=1 .if \\$2<=8 \{\
+. ds vT System Reference Manual
+. if \\$2>1 .if \\$2<6 .ds vT System Programmer's Manual
+. if "\\$2"8" .ds vT System Manager's Manual
+. nr sN \\$2
+. \}
+. if "\\$2"unass" .ds vT DRAFT
+. if "\\$2"draft" .ds vT DRAFT
+. if "\\$2"paper" .ds vT UNTITLED
+.\" . \}
+.\}
+.if !"\\$3"" \{\
+. if "\\$3"USD" .ds vT User's Supplementary Documents
+. if "\\$3"PS1" .ds vT Programmers's Supplementary Documents
+. if "\\$3"AMD" .ds vT Ancestral Manual Documents
+. if "\\$3"SMM" .ds vT System Manager's Manual
+. if "\\$3"URM" .ds vT Reference Manual
+. if "\\$3"PRM" .ds vT Programmers's Manual
+. if "\\$3"IND" .ds vT Manual Master Index
+.\" . if "\\$3"CON" .ds vT Contributed Software Manual
+.\" . if "\\$3"IMP" .ds vT Implementation Notes
+.\" . if "\\$3"HOW" .ds vT How Pocket Manual
+. if "\\$3"LOCAL" .ds vT Local Manual
+. if "\\$3"tahoe" .as vT \ (Tahoe Architecture)
+. if "\\$3"vax" .as vT \ (VAX Architecture)
+. if "\\$3"hp300" .as vT \ (HP300 Architecture)
+. if "\\*(vT"LOCAL" .ds vT \\$3
+.\}
+..
+.\" NS Os macro - Operating System (behaviour changes after first call)
+.\" . ds vT \f(CODRAFT\fP\ \ \-\-\ \ \\*(vT\ \ \-\-\ \ \f(CODRAFT
+.\" . ds dD \f(CODRAFT\fP\ \ \-\-\ \ \\*(dD\ \ \-\-\ \ \f(CODRAFT
+.\" .ds vT \s+4\f(CODRAFT\fP\s-4\ \ \-\-\ \ \\*(vT\ \ \-\-\ \ \s+4\f(CODRAFT\s-4
+.\" .ds dD \s+4\f(CODRAFT\fP\s-4\ \ \-\-\ \ \\*(dD\ \ \-\-\ \ \s+4\f(CODRAFT\s-4
+.de Os
+.ds oS Null
+.if "\\$1"" \{\
+. ds oS BSD Experimental
+.\}
+.if "\\$2"" \{\
+. ds aa Non-Null
+.\}
+.if "\\$1"ATT" \{\
+. ds oS AT&T
+. if "\\$2"" .as oS \0UNIX
+. if "\\$2"7th" .as oS \07th Edition
+. if "\\$2"7" .as oS \07th Edition
+. if "\\$2"III" .as oS \0System III
+. if "\\$2"3" .as oS \0System III
+. if "\\$2"V" .as oS \0System V
+. if "\\$2"V.2" .as oS \0System V Release 2
+. if "\\$2"V.3" .as oS \0System V Release 3
+. if "\\$2"V.4" .as oS \0System V Release 4
+.\}
+.if "\\$1"BSD" \{\
+. if "\\$2"3" .ds oS 3rd Berkeley Distribution
+. if "\\$2"4" .ds oS 4th Berkeley Distribution
+. if "\\$2"4.1" .ds oS 4.1 Berkeley Distribution
+. if "\\$2"4.2" .ds oS 4.2 Berkeley Distribution
+. if "\\$2"4.3" .ds oS 4.3 Berkeley Distribution
+. if "\\$2"4.3T" .ds oS 4.3-Tahoe Berkeley Distribution
+. if "\\$2"4.3R" .ds oS 4.3-Reno Berkeley Distribution
+. if "\\$2"4.3t" .ds oS 4.3-Tahoe Berkeley Distribution
+. if "\\$2"4.3r" .ds oS 4.3-Reno Berkeley Distribution
+. if "\\$2"4.4" .ds oS BSD Experimental
+.\}
+.if "\\*(oS"Null" .ds oS \0\\$1
+.if "\\*(aa"Non-Null" .as oS \0\\$2
+.rm aa
+..
+.de Dd
+.if !"\\*(dD"" .nr gX 1
+.ie \\n(.$>0 \{\
+. ie \\n(.$==3 \{\
+. ds dD \\$1 \\$2 \\$3
+. \}
+. el \{\
+. if "\\n(mo"1" .ds dD January
+. if "\\n(mo"2" .ds dD February
+. if "\\n(mo"3" .ds dD March
+. if "\\n(mo"4" .ds dD April
+. if "\\n(mo"5" .ds dD May
+. if "\\n(mo"6" .ds dD June
+. if "\\n(mo"7" .ds dD July
+. if "\\n(mo"8" .ds dD August
+. if "\\n(mo"9" .ds dD September
+. if "\\n(mo"10" .ds dD October
+. if "\\n(mo"11" .ds dD November
+. if "\\n(mo"12" .ds dD December
+. as dD \&\ \\n(dy, \\n(Yr
+. \}
+.\}
+.el \{\
+. ds dD Epoch
+.\}
+..
+.de hM
+.ev 1
+.pL
+.if !\\n(cR 'sp \\n(Hmu
+.tl @\\*(Hs\\*(hT\fP@\\*(Vs\\*(vT\fP@\\*(Hs\\*(hT\fP@
+'sp \\n(Hmu
+.ev
+..
+.de fM
+.ie \\n(cR 'br
+.el \{\
+. ev 1
+. pL
+. if !\\n(cR \{\
+' sp \\n(Fmu
+. tl @\\*(Hs\\*(oS\fP@\\*(Vs\\*(dD\fP@%@
+' bp
+. \}
+. ev
+.\}
+.\" .tm IN 444 fM .k == \\n(.k and nl == \\n(nl
+..
+.de lM
+.fl
+.if \\n(cR \{\
+' sp
+. tl @\\*(Hs\\*(oS\fP@\\*(Vs\\*(dD\fP@%@
+. pl \\n(nlu
+.\}
+..
+.de Pp
+.sp \\n(Ppu
+.ne 2
+.ns
+..
+.de Lp
+.Pp
+..
+.de LP
+.tm Not a \-mdoc command: .LP
+..
+.de PP
+.tm Not a \-mdoc command: .PP
+..
+.de pp
+.tm Not a \-mdoc command: .pp
+..
+.de Nd
+\&\-\& \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Ss
+.sp
+.ne 2
+.ti -.25i
+\&\\*(sH\\$1 \|\\$2 \|\\$3 \|\\$4 \|\\$5 \|\\$6 \|\\$7 \|\\$8 \|\\$9
+\&\fP\s0
+.ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 6i 6.5i
+.if !\\n(cR .ne 2
+.br
+..
+.de Rd
+.tm MDOC REGISTER DUMP
+.tm Db==\\n(Db register DEBUG MODE
+.tm L[0-9] registers - stack of list types
+.tm L0==\\n(L0
+.tm L1==\\n(L1
+.tm L2==\\n(L2
+.tm L3==\\n(L3
+.tm L4==\\n(L4
+.tm L5==\\n(L5
+.tm L6==\\n(L6
+.tm L7==\\n(L7
+.tm L8==\\n(L8
+.tm L9==\\n(L9
+.tm O[0-9] registers - stack of indent
+.tm O0==\\n(O0
+.tm O1==\\n(O1
+.tm O2==\\n(O2
+.tm O3==\\n(O3
+.tm O4==\\n(O4
+.tm O5==\\n(O5
+.tm O6==\\n(O6
+.tm O7==\\n(O7
+.tm O8==\\n(O8
+.tm O9==\\n(O9
+.tm aC==\\n(aC register argument counter (aV/fV)
+.tm aJ==\\n(aJ register (for vR)
+.tm aN==\\n(aN register
+.tm aP==\\n(aP register argument pointer (aV)
+.tm aT==\\n(aT register argument type
+.tm aa==\\n(aa local register
+.tm bK==\\n(bK register - Book Name flag
+.tm cF==\\n(cF register save current font
+.tm cI==\\n(cI register - column indent width
+.tm cZ==\\n(cZ register save current font size
+.tm dK==\\n(dK register - Date flag
+.tm d[0-9] registers - display-type stack
+.tm d0==\\n(d0
+.tm d1==\\n(d1
+.tm d2==\\n(d2
+.tm d3==\\n(d3
+.tm d4==\\n(d4
+.tm d5==\\n(d5
+.tm d6==\\n(d6
+.tm d7==\\n(d7
+.tm d8==\\n(d8
+.tm d9==\\n(d9
+.tm dZ==\\n(dZ register diversion count
+.tm fD==\\n(fD register subroutine test (in synopsis only)
+.tm fV==\\n(fV register argument counter (must set to \\n(.$ prior to
+.tm fY==\\n(fY register - dick with old style function declarations (fortran)
+.tm fZ==\\n(fZ register also subroutine count (in synopsis only)
+.tm h[0-9] register horizontal tag stack (continuous if 1, break if
+.tm h0==\\n(h0
+.tm h1==\\n(h1
+.tm h2==\\n(h2
+.tm h3==\\n(h3
+.tm h4==\\n(h4
+.tm h5==\\n(h5
+.tm h6==\\n(h6
+.tm h7==\\n(h7
+.tm h8==\\n(h8
+.tm h9==\\n(h9
+.tm iD==\\n(iD local register
+.tm iI==\\n(iI local register (indent for inline debug mode)
+.tm iN==\\n(iN register DEBUG MODE (inline if 1, to stderr if
+.tm iS==\\n(iS register - indent second command line in a synopsis
+.tm jK==\\n(jK register - [reference] Journal Name flag
+.tm jM==\\n(jM local register
+.tm jN==\\n(jN local register
+.tm lC==\\n(lC register - list type stack counter
+.tm lK==\\n(lK register count of lines read from input file
+.tm nK==\\n(nK register - [reference] issue number flag
+.tm nU==\\n(nU register count
+.tm oK==\\n(oK register - [reference] optional information flag
+.tm oM==\\n(oM register (extension possible)
+.tm o[0-9] register offset stack (nested tags)
+.tm o0==\\n(o0
+.tm o1==\\n(o1
+.tm o2==\\n(o2
+.tm o3==\\n(o3
+.tm o4==\\n(o4
+.tm o5==\\n(o5
+.tm o6==\\n(o6
+.tm o7==\\n(o7
+.tm o8==\\n(o8
+.tm o9==\\n(o9
+.tm oM==\\n(oM register open ended line flag
+.tm pK==\\n(pK register - [reference] page number flag
+.tm qK==\\n(qK register - Corporate or Foreign Author flag
+.tm rK==\\n(rK register - [reference] report flag
+.tm rS==\\n(rS register - Reference Start flag
+.tm sM==\\n(sM register - default is one (space mode on)
+.tm tK==\\n(tK register - reference title flag
+.tm tP==\\n(tP register tag flag (for diversions)
+.tm tX==\\n(tX register (initial class)
+.tm tY==\\n(tY register (next possible lC value)
+.tm t[0-9] register tag string stack (nested tags)
+.tm t0==\\n(t0
+.tm t1==\\n(t1
+.tm t2==\\n(t2
+.tm t3==\\n(t3
+.tm t4==\\n(t4
+.tm t5==\\n(t5
+.tm t6==\\n(t6
+.tm t7==\\n(t7
+.tm t8==\\n(t8
+.tm t9==\\n(t9
+.tm uK==\\n(uK register - reference author(s) counter
+.tm vK==\\n(vK register - reference volume flag
+.tm v[0-9] register vertical tag break stack
+.tm v0==\\n(v0
+.tm v1==\\n(v1
+.tm v2==\\n(v2
+.tm v3==\\n(v3
+.tm v4==\\n(v4
+.tm v5==\\n(v5
+.tm v6==\\n(v6
+.tm v7==\\n(v7
+.tm v8==\\n(v8
+.tm v9==\\n(v9
+.tm w[0-9] register tag stack (nested tags)
+.tm w0==\\n(w0
+.tm w1==\\n(w1
+.tm w2==\\n(w2
+.tm w3==\\n(w3
+.tm w4==\\n(w4
+.tm w5==\\n(w5
+.tm w6==\\n(w6
+.tm w7==\\n(w7
+.tm w8==\\n(w8
+.tm w9==\\n(w9
+.tm xX==\\n(xX local register
+.tm END OF REGISTER DUMP
+..
diff --git a/tmac/doc-ditroff b/tmac/doc-ditroff
new file mode 100644
index 00000000..039db7dd
--- /dev/null
+++ b/tmac/doc-ditroff
@@ -0,0 +1,281 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. 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.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+.\"
+.\" @(#)doc-ditroff 5.8 (Berkeley) 8/5/91
+.\"
+.\" tmac.mdoc-ditroff
+.\" %beginstrip%
+.\"
+.\" -rC1 numbers pages continuously; initialize to avoid warnings
+.if \n(.g .if !rC .nr C 0
+.ds aD \fI\s10
+.ds aR \f(CO\s10
+.ds cM \f(CB\s10
+.ds dF \fR\s10
+.ds eM \fI\s10
+.ds eR \fC\s10
+.ds eV \fC\s10
+.ds fA \f(CO\s10
+.ds fD \f(CB\s10
+.ds fL \f(CB\s10
+.ds fN \f(CB\s10
+.ds fP \fP\s0
+.ds fS \s0
+.ds fT \f(CO\s10
+.ds Hs \fR\s10
+.ds iC \f(CB\s10
+.ds lI \fC
+.ds lP \fR\|(\|\fP\s10
+.ds lp \fR(\fP\s10
+.ds rP \fR\|)\|\fP\s10
+.ds rp \fR)\fP\s10
+.ds lB \fR\^[\^\fP\s10
+.ds rB \fR\^]\fP\s10
+.ds mL \fB\s10
+.ds nM \f(CB\s10
+.ds nO \fR\s10
+.ds nT \s0
+.ds pA \fC\s10
+.ds Pu \fR{\ .\ ,\ :\ ;\ (\ )\ [\ ]\ \fR}
+.ds rA \fR\s10
+.ds rT \f(CO\s10
+.ds sH \fB\s10
+.ds sP \s0
+.ds sY \fB\s10
+.ds sX \fR\s10
+.ds tF \fR
+.ds tN \s9
+.ds vA \fI\s10
+.ds Vs \fR\s10
+.ds vT \f(CB\s10
+.ds xR \fC\s10
+.tr *\(**
+.nr sI \w\fC,u*5
+.nr Ti \n(sIu
+.nr Pp .5v
+.ds lS \0
+.nr lS \w'\0'u
+.nr dI 6n
+.de pL
+.nr Hm .5i
+.nr Fm .5i
+.nr ll 6.5i
+.ll 6.5i
+.nr lt 6.5i
+.lt 6.5i
+.nr po 1i
+.po 1.i
+.nr dV .5v
+..
+.ds <= \(<=
+.ds >= \(>=
+.ie \n(.g \{\
+. ds Lq \(lq
+. ds Rq \(rq
+.\}
+.el \{\
+. ds Lq \&``
+. ds Rq \&''
+.\}
+.ds ua \(ua
+.ds aa \(aa
+.ds ga \(ga
+.ds sR \&'
+.ds sL \&`
+.ds q \&"
+.\" Math stuff
+.ds Pi \(*p
+.ds Ne \(!=
+.ds Le \(<=
+.ds Ge \(>=
+.ds Lt <
+.ds Gt >
+.ds Pm \(+-
+.ds If \(if
+.ds Na \fINaN\fP
+.ds Ba \fR\&|\fP
+.\"
+.nr gX 0
+.de hK
+.ds hT \\*(dT
+.if !"\\*(cH"Null" \{\
+. ie !"\\*(gP"Null" .as hT \|(\|\\*(cH\\*(gP\|)
+. el .as hT \\|(\\|\\*(cH\\|)
+.\}
+.if "\\*(cH"Null" \{\
+. if !"\\*(gP"Null" .as hT \&\|(\|\\*(gP\|)
+.\}
+.wh 0 hM
+.wh -1.25i fM
+.nr nL \\n(nl
+.ie \\n(gX==1 \{\
+. rm n1
+. bp
+.\}
+.el \{\
+' bp
+.\}
+.\" Don't set the page number if this is the first page,
+.\" in case the user has used -n.
+.if \\n(nL>0 \{\
+. if !\\nC \{\
+. nr % 1
+. \}
+.\}
+.nr gX 0
+.em lM
+..
+.\"
+.nr fW \w\fC0
+.de sW
+.nr sW \w\fC\\$1
+.ie \\n(sW>=\\n(fW \{\
+. ie \\n(sW%\\n(fW .nr sW (\\n(sW/\\n(fW)+1
+. el .nr sW \\n(sW/\\n(fW
+.\}
+.el \{\
+. ie \\n(sW>0 .nr sW 1
+. el .nr sW 0
+.\}
+..
+.\"
+.de aW
+.nr sW \w\fC\\*(A\\$1
+.ie \\n(sW>=\\n(fW \{\
+. ie \\n(sW%\\n(fW .nr sW (\\n(sW/\\n(fW)+1
+. el .nr sW \\n(sW/\\n(fW
+.\}
+.el \{\
+. ie \\n(sW>0 .nr sW 1
+. el .nr sW 0
+.\}
+..
+.\" NS Ql macro - Quoted literal define
+.de Ql
+.if \\n(aC==0 \{\
+. ds mN Ql
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. nr fV \\n(.$
+. fV
+.\}
+.nr aP \\n(aP+1
+.aW \\n(aP
+.nr aP \\n(aP-1
+.if \\n(sW>2 .Li
+.if \\n(sW<=2 \{\
+.\" Db on
+. if (\\n(aP>0) \{\
+. ds A\\n(aP Li
+. nr aP \\n(aP -1
+. \}
+. if (\\n(aP==0) \{\
+. rm C0 C1 C2 C3 C4 C5 C6 C7 C8 C9
+. rm S1 S2 S3 S4 S5 S6 S7 S8 S9
+. rn A8 A9
+. rn A7 A8
+. rn A6 A7
+. rn A5 A6
+. rn A4 A5
+. rn A3 A4
+. rn A2 A3
+. rn A1 A2
+. ds A1 Li
+. nr fV \\n(aC+1
+. nr aC 0
+. fV
+. \}
+. ds qL \&\\*(sL
+. ds qR \&\\*(sR
+. En
+.\" Db off
+.\}
+..
+.\" NS Sh macro - Section Headers
+.\" NS nS register - Section Header SYNOPSIS flag
+.\" NS nF register - Section Header FILES flag
+.\" NS nA register - Section Header SEE ALSO flag
+.\" NS nT register - Section Header STANDARDS flag
+.de Sh
+.nr nS 0
+.nr sE 0
+.nr iS 0
+'ad
+.ie "\\$1"NAME" \{\
+. hK
+' in 0
+.\}
+.el \{\
+. nr nS 0
+. nr nA 0
+. nr nF 0
+. nr nT 0
+. nr nY 0
+. nr oT 0
+. if "\\$1"SYNOPSIS" \{\
+. na
+. nr nS 1
+. \}
+. if "\\$1"DESCRIPTION" \{\
+. nr fY 0
+. nr fZ 0
+. nr fB 0
+. nr Fb 0
+. ds Fb
+. \}
+. if "\\$1"SEE" \{\
+. nr nA 1
+. na
+. \}
+. if "\\$1"FILES" .nr nF 1
+. if "\\$1"STANDARDS" .nr nT 1
+. if "\\$1"AUTHORS" .nr nY 1
+. if "\\$1"SEE" .nr sE 1
+. in 0
+. nr aN 0
+.\}
+.pL
+'sp
+.ns
+.ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 6i 6.5i
+.if !\\n(cR .ne 3
+'fi
+\&\\*(sH\\$1 \|\\$2 \|\\$3 \|\\$4 \|\\$5 \|\\$6 \|\\$7 \|\\$8 \|\\$9
+\&\fP\s0\&
+.in \\n(.iu+\\n(Tiu
+.ns
+..
diff --git a/tmac/doc-nroff b/tmac/doc-nroff
new file mode 100644
index 00000000..c036f218
--- /dev/null
+++ b/tmac/doc-nroff
@@ -0,0 +1,225 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. 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.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+.\"
+.\" @(#)doc-nroff 5.6 (Berkeley) 8/5/91
+.\"
+.\" tmac.mdoc-nroff
+.\" %beginstrip%
+.\"
+.ds aD \fI
+.ds aR \fI
+.ds cM \fB
+.ds dF \fR
+.ds eM \fI
+.ds eR \fR
+.ds eV \fR
+.ds fA \fI
+.ds fD \fB
+.ds fL \fB
+.ds fN \fB
+.ds fP \fP
+.ds fS
+.ds fT \fI
+.ds Hs \fR
+.ds iC \fB
+.ds lI \fR
+.ds lP \fR\|(\fP
+.ds rP \fR\|)\fP
+.ds lp \fR\|(\fP
+.ds rp \fR\|)\fP
+.ds lB \fR\|[\|\fP
+.ds rB \fR\|]\fP
+.ds mL \fB
+.ds nM \fB
+.ds nO \fR
+.ds pA \fI
+.ds Pu {\ .\ ,\ ;\ :\ (\ )\ [\ ]}
+.ds rA \fR
+.ds rT \fI
+.ds sH \fB
+.ds sP
+.ds sY \fB
+.ds sX \fI
+.ds tF \fR
+.ds tN
+.ds vA \fI
+.ds Vs \fR
+.ds vT \fB
+.ds xR \fR
+.\" MISCELLANEOUS
+.nr sI .5i
+.nr Ti .5i
+.nr cR 1
+.nr Pp 1v
+.ds lS \0\0
+.nr lS \w'\0\0'u
+.nr dI 6n
+.\"
+.de pL
+.ie \\n(cR .nr Hm 0
+.el .nr Hm .5i
+.nr Fm .5i
+.nr ll 78n
+.ll 78n
+.nr lt 78n
+.lt 78n
+.nr po 0i
+.po 0i
+.nr dV 1v
+.ad l
+.na
+..
+.ds <= \&<\&=
+.ds >= \&>\&=
+.ds Rq ''
+.ds Lq ``
+.ds ua ^
+.ds aa \'
+.ds ga \`
+.ds sL `
+.ds sR '
+.ds q \&"
+.\" Math stuff
+.ds Pi pi
+.ds Ne !=
+.ds Le <=
+.ds Ge >=
+.ds Lt <
+.ds Gt >
+.ds Pm +-
+.ds If infinity
+.ds Na \fINaN\fP
+.ds Ba \fR\&|\fP
+
+.\"
+.de hK
+.nr % 1
+.ds hT \\*(dT
+.if !"\\*(cH"Null" \{\
+. ie !"\\*(gP"Null" .as hT \|(\|\\*(cH\\*(gP\|)
+. el .as hT \\|(\\|\\*(cH\\|)
+.\}
+.if "\\*(cH"Null" .if !"\\*(gP"Null" .as hT \&\|(\|\\*(gP\|)
+.ie \\n(cR \{\
+. hM
+. wh -1v fM
+.\}
+.el \{\
+. wh 0 hM
+. wh -1.167i fM
+.\}
+.if \\n(nl==0:\\n(nl==-1 'bp
+.em lM
+..
+.nr fW \w'0'
+.de sW
+.nr sW \w\\$1
+.ie \\n(sW>=\\n(fW \{\
+. ie \\n(sW%\\n(fW .nr sW (\\n(sW/\\n(fW)+1
+. el .nr sW \\n(sW/\\n(fW
+.\}
+.el .nr sW 0
+..
+.de aW
+.nr sW \w\\*(A\\$1
+.ie \\n(sW>=\\n(fW \{\
+. ie \\n(sW%\\n(fW .nr sW (\\n(sW/\\n(fW)+1
+. el .nr sW \\n(sW/\\n(fW
+.\}
+.el .nr sW 0
+..
+.\" NS Ql macro - Quoted literal define
+.de Ql
+.if \\n(aC==0 \{\
+. ds mN Ql
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+.\}
+.ds qL \&\\*(sL
+.ds qR \&\\*(sR
+.En \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Sh macro - Section Headers
+.\" NS nS register - Section Header SYNOPSIS flag
+.\" NS nF register - Section Header FILES flag
+.\" NS nA register - Section Header SEE ALSO flag
+.\" NS nT register - Section Header STANDARDS flag
+.de Sh
+.nr nS 0
+.nr sE 0
+.nr iS 0
+.ie "\\$1"NAME" \{\
+. hK
+' in 0
+.\}
+.el \{\
+. nr nS 0
+. nr nA 0
+. nr nF 0
+. nr nT 0
+. nr nY 0
+. nr aN 0
+. nr oT 0
+. if "\\$1"SEE" .nr nA 1
+. if "\\$1"FILES" .nr nF 1
+. if "\\$1"STANDARDS" .nr nT 1
+. if "\\$1"SYNOPSIS" .nr nS 1
+. if "\\$1"DESCRIPTION" \{\
+. rr fB
+. rr Fb
+. ds Fb
+. nr fY 0
+. nr fZ 0
+. \}
+. if "\\$1"AUTHORS" .nr nY 1
+. in 0
+.\}
+.pL
+'sp
+.ns
+.ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 6i 6.5i
+.if !\\n(cR .ne 3
+'fi
+\&\\*(sH\\$1 \|\\$2 \|\\$3 \|\\$4 \|\\$5 \|\\$6 \|\\$7 \|\\$8 \|\\$9
+\&\fP\s0\&
+.in \\n(.iu+\\n(Tiu
+.if "\\$1"SEE" .nr sE 1
+.ns
+..
diff --git a/tmac/doc-syms b/tmac/doc-syms
new file mode 100644
index 00000000..57e682aa
--- /dev/null
+++ b/tmac/doc-syms
@@ -0,0 +1,236 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. 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.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+.\"
+.\" @(#)doc-syms 5.6 (Berkeley) 8/5/91
+.\"
+.\" %beginstrip%
+.\" NS Ux macro - UNIX
+.de Ux
+.nr cF \\n(.f
+.nr cZ \\n(.s
+.ds aa \&\f\\n(cF\s\\n(cZ
+.as b1 \&\\*(tNUNIX\\*(aa
+.rm aa
+.if \\n(aC==0 \{\
+. if \\n(.$>0 .aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.\}
+.ie \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. ie \\n(C\\n(aP==1 \{\
+. \\*(A\\n(aP
+. \}
+. el .nR
+.\}
+.el .aZ
+..
+.\" NS Bx macro -BSD UNIX (fix smaller nroff version)
+.de Bx
+.nr cF \\n(.f
+.nr cZ \\n(.s
+.ds aa \&\f\\n(cF\s\\n(cZ
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 \&\\*(tNBSD\\*(aa \\*(tNUNIX\\*(aa
+. el .aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.\}
+.if "\\$1"-alpha" \{\
+\&currently in alpha test.
+. aY
+.\}
+.if "\\$1"-beta" \{\
+\&currently in beta test.
+. aY
+.\}
+.if "\\$1"-devel" \{\
+\&currently under development.
+. aY
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. ie \\n(C\\n(aP==2 \{\
+. as b1 \&\\*(A\\n(aP\&\\*(tNBSD\\*(aa
+. ie \\n(aC>\\n(aP \{\
+. nr jj \\n(aP+1
+. ie \\n(C\\n(jj==2 \{\
+. if "\\*(A\\n(jj"Reno" \{\
+. nr aP \\n(aP+1
+. as b1 \&\-\\*(A\\n(jj
+. \}
+. if "\\*(A\\n(jj"reno" \{\
+. nr aP \\n(aP+1
+. as b1 \&\-Reno
+. \}
+. if "\\*(A\\n(jj"Tahoe" \{\
+. nr aP \\n(aP+1
+. as b1 \&\-\\*(A\\n(jj
+. \}
+. if "\\*(A\\n(jj"tahoe" \{\
+. nr aP \\n(aP+1
+. as b1 \&\-Tahoe
+. \}
+. ie \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. nR
+. \}
+. el .aZ
+. \}
+. el \{\
+. nr aP \\n(aP+1
+. nR
+. \}
+. rr jj
+. \}
+. el .aZ
+. \}
+. el \{\
+. as b1 \&\\*(tNBSD\\*(aa U\\*(tNNIX\\*(aa
+. nR
+. \}
+.\}
+..
+.\" Ns Ud macro - prints "currently under development" (HISTORY section)
+.de Ud
+\&currently under development.
+..
+.\" Ns At macro - AT&T UNIX
+.de At
+.nr cF \\n(.f
+.nr cZ \\n(.s
+.ds aa \&\f\\n(cF\s\\n(cZ
+.if \\n(.$==2 \{\
+. if "\\$1"32v" \&Version 32V \\*(tNAT&T UNIX\\*(aa\\$2
+. if "\\$1"v6" \&Version 6 \\*(tNAT&T UNIX\\*(aa\\$2
+. if "\\$1"v7" \&Version 7 \\*(tNAT&T UNIX\\*(aa\\$2
+. if "\\$1"V" \&\\*(tNAT&T\\*(aa System V \\*(tNUNIX\\*(aa\\$2
+. if "\\$1"V.1" \&\\*(tNAT&T\\*(aa System V.1 \\*(tNUNIX\\*(aa\\$2
+. if "\\$1"V.4" \&\\*(tNAT&T\\*(aa System V.4 \\*(tNUNIX\\*(aa\\$2
+.\}
+.if \\n(.$==1 \{\
+. if "\\$1"32v" \&Version 32V \\*(tNAT&T UNIX\\*(aa
+. if "\\$1"v6" \&Version 6 \\*(tNAT&T UNIX\\*(aa
+. if "\\$1"v7" \&Version 7 \\*(tNAT&T UNIX\\*(aa
+. if "\\$1"V" \&\\*(tNAT&T\\*(aa System V \\*(tNUNIX\\*(aa
+. if "\\$1"V.1" \&\\*(tNAT&T\\*(aa System V.1 \\*(tNUNIX\\*(aa
+. if "\\$1"V.4" \&\\*(tNAT&T\\*(aa System V.4 \\*(tNUNIX\\*(aa
+.\}
+..
+.\" The Bt macro should go away now
+.\" Ns Bt macro - prints "is currently in beta test." (HISTORY section)
+.de Bt
+\&is currently in beta test.
+..
+.\" NS St macro - standards (posix, ansi - formal standard names)
+.ds Px \\*(tNPOSIX
+.ds Ai \\*(tNANSI
+.de St
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 \{\
+.tm Usage: .St [-p1003.1-88 | -p1003.2 | -ansiC-89 | -iso ] \\*(Pu ... (#\\n(.c)
+. \}
+. el \{\
+. ds mN St
+. nr aP 0
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. ds aa \&\f\\n(cF\s\\n(cZ
+. nr aP \\n(aP+1
+. if "\\*(A\\n(aP"-p1003.1-88" \{\
+. ie \\n(sT==1 \{\
+. ds b1 \&\\*(tNIEEE Std\\*(aa1003.1-1988\\*(sV
+. as b1 (``\\*(tN\\*(Px\\*(aa'')
+. \}
+. el \{\
+. ds b1 \&\\*(tNIEEE Std\\*(aa1003.1-1988\\*(sV
+. as b1 (``\\*(tN\\*(Px\\*(aa'')
+. \}
+. \}
+. if "\\*(A\\n(aP"-p1003.2" \{\
+. ie \\n(sT==1 \{\
+. ds b1 \&\\*(tNIEEE Std\\*(aa1003.2
+. as b1 (``\\*(tN\\*(Px\\*(aa'')
+. \}
+. el \{\
+. ds b1 \&\\*(tNIEEE Std\\*(aa1003.2\\*(sV
+. as b1 (``\\*(tN\\*(Px\\*(aa'')
+. \}
+. \}
+. if "\\*(A\\n(aP"-ansiC" \{\
+. ie \\n(sT==1 \{\
+. ds b1 \&\\*(tNANSI C\\*(aa3.159-1989\\*(sV
+. as b1 (``\\*(tNANSI C\\*(aa'')
+. \}
+. el \{\
+. ds b1 \&\\*(tNANSI C\\*(aa3.159-1989\\*(sV
+. as b1 (``\\*(tNANSI C\\*(aa'')
+. \}
+. \}
+. if "\\*(A\\n(aP"-ansiC-89" \{\
+. ie \\n(sT==1 \{\
+. ds b1 \&\\*(tNANSI C\\*(aa3.159-1989\\*(sV
+. as b1 (``\\*(tNANSI C\\*(aa'')
+. \}
+. el \{\
+. ds b1 \&\\*(tNANSI C\\*(aa3.159-1989\\*(sV
+. as b1 (``\\*(tNANSI C\\*(aa'')
+. \}
+. \}
+. if "\\*(A\\n(aP"-iso8802-3" \{\
+. ie \\n(sT==1 \{\
+. ds b1 \&\\*(tNISO \\*(aa8802-3: 1989
+.\" . ds b1 \&\\*(tNISO \\*(aa8802-3: 1989\\*(sV
+.\" . as b1 (``\\*(tNANSI C\\*(aa'')
+. \}
+. el \{\
+. ds b1 \&\\*(tNISO \\*(aa8802-3: 1989
+.\" . ds b1 \&\\*(tNISO \\*(aa8802-3: 1989\\*(sV
+.\" . as b1 (``\\*(tNANSI C\\*(aa'')
+. \}
+. \}
+. ie \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. nR
+. \}
+. el .aZ
+.\}
+..
diff --git a/tmac/eqnrc b/tmac/eqnrc
new file mode 100644
index 00000000..a8bc8365
--- /dev/null
+++ b/tmac/eqnrc
@@ -0,0 +1,63 @@
+.\" Startup file for eqn.
+.EQ
+sdefine << %{ < back 20 < }%
+sdefine >> %{ > back 20 > }%
+
+sdefine dot %accent "\fR\(a.\fP"%
+sdefine dotdot %accent "\fR\(ad\fP"%
+sdefine vec %accent {up 52 "\s[\En[.s]/2u]\(->\s0"}%
+sdefine dyad %accent {up 52 "\s[\En[.s]/2u]\(<>\s0"}%
+
+sdefine cdot %type "binary" \(md%
+
+ifdef X75 ! define X %1% !
+ifdef X100 ! define X %1% !
+ifdef X75-12 ! define X %1% !
+ifdef X100-12 ! define X %1% !
+
+ifdef ps ! define ps|X|html %1% !
+ifdef X ! define ps|X|html %1% !
+ifdef html ! define ps|X|html %1% !
+
+ifdef ps|X|html ! sdefine inf %"\s[\En[.s]*13u/10u]\v'12M'\(if\v'-12M'\s0"% !
+
+ifdef dvi !
+sdefine int %{type "operator" vcenter \(is}%
+sdefine sum %{type "operator" vcenter \[sum]}%
+sdefine prod %{type "operator" vcenter \[product]}%
+sdefine coprod %{type "operator" vcenter \[coproduct]}%
+set num1 68
+set num2 39
+set denom1 69
+set denom2 34
+set sup1 41
+set sup2 36
+set sup3 29
+set sup_drop 39
+set sub_drop 5
+set axis_height 25
+set x_height 43
+set default_rule_thickness 4
+set big_op_spacing1 11
+set big_op_spacing2 16
+set big_op_spacing3 20
+set big_op_spacing4 60
+set big_op_spacing5 10
+!
+
+ifdef X ! set axis_height 32 !
+
+ifdef ps|X|html ! set draw_lines 1 !
+
+ifdef ascii ! define n %1% !
+ifdef latin1 ! define n %1% !
+ifdef utf8 ! define n %1% !
+ifdef n !
+set nroff 1
+!
+
+undef X
+undef ps|X
+undef n
+undef html
+.EN
diff --git a/tmac/fixmacros.sed b/tmac/fixmacros.sed
new file mode 100644
index 00000000..63cce22a
--- /dev/null
+++ b/tmac/fixmacros.sed
@@ -0,0 +1,6 @@
+s/^\([.'][ ]*[^\\ ][^ \\]\)\([^ ]\)/\1 \2/
+s/^\(\\![.'][ ]*[^\\ ][^ \\]\)\([^ ]\)/\1 \2/
+s/\([.'][ ]*i[ef] *[^ ]* [.'][ ]*[^\\0-9 ][^ \\]\)\([^ ]\)/\1 \2/
+s/\([.'][ ]*i[ef] *[^ ]* \\{[.'][ ]*[^\\0-9 ][^ \\]\)\([^ ]\)/\1 \2/
+s/\([.'][ ]*[da]s *[^ \\][^ \\]\)\([^ ]\)/\1 \2/
+s/\\\*\[/\\*[[]/
diff --git a/tmac/groff_man.man b/tmac/groff_man.man
new file mode 100644
index 00000000..57eb9ec4
--- /dev/null
+++ b/tmac/groff_man.man
@@ -0,0 +1,171 @@
+.TH GROFF_MAN @MAN7EXT@ "@MDATE@" "Groff Version @VERSION@"
+.
+.SH NAME
+.
+groff_man \- groff `an' macros to support generation of man pages
+.SH SYNOPSIS
+.B groff
+.B \-m@TMAC_AN_PREFIX@an
+[
+.IR options .\|.\|.
+]
+[
+.IR files .\|.\|.
+]
+.
+.SH DESCRIPTION
+.
+The
+.B tmac.an
+macros used to generate man pages with
+.I groff
+were written by James Clark.
+This document provides a brief summary of the use of each macro in that
+package.
+.TP
+.BI .TP " title section " [ extra1 "] [" extra2 "] [" extra3 ]
+Sets the title of the man page to
+.I title
+and the section to
+.IR section ,
+which must take on a value between 1 and\ 8.
+The value
+.I section
+may also have a string appended, e.g. `.pm', to indicate a specific
+subsection of the man pages.
+.TP
+.BI .SH " text for a heading"
+Sets up an unindented and unnumbered section heading.
+Prints out all the text following `.SH' up to the end of the line in bold
+face, with a size slightly smaller than that for indented section headings.
+.TP
+.BI .SS " text for a heading"
+Sets up an indented section heading.
+Prints out all the text following `.SS' up to the end of the line in bold
+face, with a size slightly larger than that for unindented section headings.
+.TP
+.BI ".TP [" nnn ]
+Sets up an indented paragraph.
+The indentation is set to
+.I nnn
+if that argument is supplied.
+The first line of text following this macro is interpreted as a string to be
+printed flush-left, as it is appropriate for a label.
+It is not interpreted as part of a paragraph, so there is no attempt to fill
+the first line with text from the following input lines.
+Nevertheless, if the label is not as wide as the indentation, then the
+paragraph starts at the same line (but indented), continuing on the
+following lines.
+If the label is wider than the indentation, then the descriptive part of the
+paragraph begins on the line following the label, entirely indented.
+The `.TP' macro is the macro used for the explanations you are just reading.
+.TP
+.BR ".LP " or " .PP " or " .P"
+These macros are mutual aliases.
+Any of them causes a line break at the current position, followed by a
+vertical space downwards by the amount that is set in the `PD' counter.
+.TP
+.BI ".IP [" designator "] [" nnn ]
+Sets up an indented paragraph, using
+.I designator
+as a tag to mark its beginning.
+The indentation is permanently set to
+.I nnn
+if that argument is supplied.
+To set the indentation back to the previous level, one must call some other
+macro that uses indented paragraphs, and explicitly provide it with the
+value of the previous indentation.
+.IP
+For example, the following paragraphs were all set up with bullets as the
+designator, using `.IP \\(bu 4':
+.IP \(bu 4
+`IP' is one of the three macros used in
+.B tmac.an
+to format lists.
+.IP \(bu 4
+`HP' is another.
+This macro produces a paragraph with a left hanging indentation.
+.IP \(bu 4
+`TP' is another.
+This macro produces an unindented label (given by the text on the first line
+following `TP'), followed by an indented paragraph with appropriately
+descriptive text.
+.TP
+.BI ".HP [" nnn ]
+Sets up paragraphs with hanging left indentation.
+The indentation is set to
+.I nnn
+if that argument is supplied.
+The following pargraph illustrates the effect of this macro with the hanging
+indentation set to\ 2:
+.HP 2
+This is a pagraph following an invocation of the `.HP' macro.
+As you can see, it produces a paragraph where all lines but the first are
+flushed right and are shorter than the preceding lines.
+.
+.SH "MACROS TO SET FONTS"
+.
+.TP
+.BI .SM
+Causes the text on the same line or the text on the next line to appear in a
+font that is one point size smaller than the default font.
+.TP
+.BI .SB
+Causes the text on the same line or the text on the next line to appear in
+small boldface font.
+.TP
+.BI ".BI " text
+Causes text on the same line to appear alternately in bold face and italic.
+The text must be on the same line as the macro call.
+Thus `.BI this word and that' would cause `this' and `and' to appear in bold
+face, while `word' and `that' appear in italics.
+.TP
+.BI ".IB " text
+Causes text to appear alternately in italic and bold face.
+The text must be on the same line as the macro call.
+.TP
+.BI ".BR " text
+Causes text on the same line to appear alternately in bold face and roman.
+The text must be on the same line as the macro call.
+.TP
+.BI ".RB " text
+Causes text on the same line to appear alternately in roman and bold face.
+The text must be on the same line as the macro call.
+.TP
+.BI ".R " text
+Causes text to appear in roman font.
+If no text is present on the line where the macro is called, then the text
+of the next line appears in roman.
+This is the default font to which text is returned at the end of processing
+of the other macros.
+.TP
+.BI ".B " text
+Causes text to appear in bold face.
+If no text is present on the line where the macro is called, then the text
+of the next line appears in bold face.
+.TP
+.BI ".I " text
+Causes text to appear in italic.
+If no text is present on the line where the macro is called, then the text
+of the next line appears in italic.
+.
+.SH "SEE ALSO"
+.
+Since the
+.B tmac.an
+macros consist of groups of
+.I groff
+requests, one can, in principle, supplement the functionality of the
+.B tmac.an
+macros with individual
+.I groff
+requests where necessary.
+A complete list of these requests is available on the WWW at
+.ce 1
+http://www.cs.pdx.edu/~trent/gnu/groff/groff_toc.html
+.
+.SH AUTHOR
+.
+This manual page was originally written for the Debian GNU/Linux system by
+Susan G. Kleinmann <sgk@debian.org>, corrected by Werner Lemberg
+<wl@gnu.org>, and is now part of the GNU troff distribution.
diff --git a/tmac/groff_markup.man b/tmac/groff_markup.man
new file mode 100755
index 00000000..46233cea
--- /dev/null
+++ b/tmac/groff_markup.man
@@ -0,0 +1,319 @@
+.TH GROFF_MARKUP @MAN7EXT@ "@MDATE@" "Groff Version @VERSION@"
+.\" Copyright (C) 2000 Free Software Foundation, Inc.
+.\" Written by Gaius Mulley (gaius@glam.ac.uk)
+.\"
+.\" This file is part of groff.
+.\"
+.\" groff 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.
+.\"
+.\" groff 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 groff; see the file COPYING. If not, write to the Free Software
+.\" Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+.\"
+.\" user level guide to using the -markup macroset
+.\"
+.do mso tmac.arkup
+.LINE
+.SH NAME
+groff_markup \- groff macros for authoring web pages
+.LINE
+.SH SYNOPSIS
+.B "groff \-markup"
+[ options ]
+file ...
+.SH DESCRIPTION
+This manual page describes the GNU \-markup macros, which is part of the
+groff document formatting system.
+The manual page is very a basic guide, and the html device driver
+.RB ( grohtml )
+is still very alpha.
+It has been included into the distribution so that a lot of people have a
+chance to test it.
+Note that this macro file will be automatically called (via the
+\fCtroffrc\fP file) if you use \fC-Thtml\fP.
+.PP
+To see the hyperlinks in action, please format this man page with the
+.B grohtml
+device.
+.PP
+Here is a summary of the functions found in this macro set.
+.SH SYNPOSIS
+.ta 2iL
+\&.HTMLINDEX determine automatic link cut off
+.br
+ point for sections/headers
+.br
+\&.BODYCOLOR specify colours on a web page
+.br
+\&.BACKGROUND specify background image
+.br
+\&.URL create a url using two parameters
+.br
+\&.MAILTO create a html email address
+.br
+\&.FTP create an ftp reference
+.br
+\&.IMAGE include an image file
+.br
+\&.HTML pass an html raw request to the
+.br
+ device driver
+.br
+\&.TAG generate an html name tag from $1
+.br
+.\"\&.CDFTP optionally create two different links
+.\".br
+.\" depending on hostname
+.\".br
+\&.LINE create a full width horizontal rule
+.br
+.PP
+Output of the
+.IR pic ,
+.IR eqn ,
+.IR refer ,
+and
+.I tbl
+preprocessors is acceptable as input.
+.SH REQUESTS
+.TP
+.B HTMLINDEX
+determines the cut off point for automatic link generation to headings.
+By default all headings found in a troff document have links created to them
+at the top of the html web page.
+It maybe that many of the lower heading levels do not require links.
+Alternatively some web pages may not need any heading links at all, in which
+case:
+.sp
+.nf
+\fC\&.HTMLINDEX 0\fP
+.fi
+.sp
+will tell
+.B grohtml
+not to generate links.
+An \fCHTMLINDEX\fP of 2 will mean that a heading
+.sp
+.B "1.1.1 Some Title"
+.sp
+will not be included in the links either as it is said to have a heading
+level of three.
+.TP
+.B BODYCOLOR
+takes five parameters: foreground, background, active hypertext link,
+hypertext link not yet visited, and visited hypertext link colour.
+.TP
+.B BACKGROUND
+the only parameter to this macro is the background image file.
+.TP
+.B URL
+generates
+.TAG URL
+a URL using either two or three arguments.
+$1 is the name of the link, $2 is the actual URL, and $3 is optional stuff
+to be printed immediately after $2.
+Here is how to encode
+.URL "homepage for groff" http://groff.ffii.org/ :
+.sp
+.nf
+\s-2\fC\&.URL "homepage for groff" http://groff.ffii.org/ :\fP\s+2
+.fi
+.sp
+If this is processed by a device other than \fC-Thtml\fP
+it appears as:
+homepage for groff \(lahttp://groff.ffii.org\(ra.
+The URL macro can be of any type; for example we can reference
+.URL "Eric Raymond's pic guide" pic.html
+by:
+.sp
+.nf
+\s-2\fC\&.URL "Eric Raymond's pic guide" pic.html\fP\s+2
+.fi
+.sp
+.TP
+.B MAILTO
+generates an email html reference.
+The first argument is mandatory as the email address.
+The optional second argument is the text you see in your browser, and
+an optional third argument is stuff printed immediately after the
+second argument.
+For example, the groff maintainers are
+.MAILTO wl@gnu.org "Werner Lemberg"
+and
+.MAILTO Ted.Harding@nessie.mcc.ac.uk "Ted Harding" .
+This is achieved by the following macros:
+.sp
+.nf
+\s-2\fC\&.MAILTO wl@gnu.org "Werner Lemberg"\fP
+.sp
+\fC\&.MAILTO Ted.Harding@nessie.mcc.ac.uk \\
+.br
+"Ted Harding" .\s+2\fP
+.fi
+.sp
+Note that all the urls actually are treated as consuming no textual space
+in groff.
+This could be considered as a bug since it causes some problems.
+To circumvent this, \fCtmac.arkup\fP inserts a zero-width character which
+expands to a harmless space (only if in HTML mode)
+.TP
+.B FTP
+indicates that data can be obtained via ftp.
+The first argument is the browser text and the second is the url.
+A third argument, similar to the macros above, is intended for stuff printed
+immediately after the second argument.
+The second and the third parameter are optional.
+As an example, here the location of the
+.FTP "current groff development distribution" \
+ftp://ftp.ffii.org/pub/groff/devel/groff-current.tar.gz .
+The macro example above was specified by:
+.sp
+\s-2\fC\&.FTP "current groff development distribution" \\
+.br
+ftp://ftp.ffii.org/pub/groff/devel/groff-current.tar.gz .\fP\s+2
+.sp
+.TP
+.B IMAGE
+allows the document to include pictures.
+The first argument is the image file.
+The next two arguments are optional:
+Argument two is the width in pixels (default is 400 pixels if absent).
+The third argument is the height in pixels (default is the width value if
+absent).
+.sp
+.TP
+.B HTML
+all text after this macro is treated as raw html.
+If the document is processed \fIwithout\fP \fC-Thtml\fP then
+the macro is ignored.
+This macro is a building block for other higher level macros.
+.sp
+For example, the \fCBACKGROUND\fP macro is defined as:
+.nf
+\fC\&.de BACKGROUND
+\&. HTML <body background=\\$1>
+\&..
+\fP
+.fi
+.TP
+.B TAG
+generates an html name tag from its argument.
+This can then be referenced using the
+.URL URL #URL
+macro.
+As you can see, you must precede the tag name with `\fC#\fP' since it is
+a local reference.
+This link was achieved via placing a TAG in the URL description above;
+the source looks like this:
+.sp
+\s-2\fC\&.TP
+.br
+\&.B URL
+.br
+generates
+.br
+\&.TAG URL
+.br
+a URL using either two or three
+.br
+arguments.
+.br
+$1 is the name of the link, $2 is the actual URL
+.br
+\fP\s+2etc.
+.sp
+.\".TP
+.\".B CDFTP
+.\"takes four arguments.
+.\"Basically it is the FTP macro with optional local reference.
+.\"It was designed to allow the same groff source to be built on two different
+.\"machines and access the ftp data differently.
+.\"For example, on a web server you might wish for the web page to reference
+.\"a web site.
+.\"However, if you were producing a CDROM of your information you might wish
+.\"for the ftp data to be also stored on your CDROM and referenced as a file.
+.\"An example to get the current groff development distribution
+.\".CDFTP merlin "click here." \
+.\"ftp://ftp.ffii.org/pub/groff/devel/groff-current.tar.gz \
+.\"../../groff.tar.gz
+.\"The source for this CDFTP invocation is
+.\".sp
+.\"\fC\s-2\&.CDFTP merlin "click here." \
+.\"ftp://ftp.ffii.org/pub/groff/devel/groff-current.tar.gz \
+.\"../../groff.tar.gz\fP\s+2
+.\".sp
+.\"which means if the html is generated on machine \fCmerlin\fP
+.\"then generate a URL to \fC../../groff.tar.gz\fP.
+.\"Otherwise construct an FTP URL to
+.\"\fCftp://ftp.ffii.org/pub/groff/devel/groff-current.tar.gz\fP.
+.TP
+.B LINE
+generates a full width horizontal rule.
+Example:
+.sp
+\fC\s-2\&.LINE\fP\s+2
+.sp
+.SH
+SECTION HEADING LINKS
+.LP
+By default
+.B grohtml
+generates links to all section headings and places these at the top of the
+html document.
+.B Grohtml
+has to guess what a section heading looks like \(em remember that all
+.B grohtml
+actually sees is a device independent language telling it where to place
+text, draw lines, change font sizes and faces etc.
+It believes a section heading to be a line of bold text which starts at the
+left most margin.
+Consequently it may misinterpret.
+Users can turn off all heading and title guessing by giving invoking groff
+with \fCgroff -P-g\fP.
+.SH
+LIMITATIONS OF GROHTML
+.LP
+Although basic text can be translated in a straightforward fashion there are
+some areas where
+.B grohtml
+has to try and guess text relationship.
+In particular, whenever
+.B grohtml
+encounters text tables and indented paragraphs or two column mode it will
+try and utilize the html table construct to preserve columns.
+.B Grohtml
+also attempts to work out which lines should be automatically formatted by
+the browser.
+Ultimately in trying to make reasonable guesses most of the time it will
+make mistakes.
+Hopefully these mistakes will happen less and less as we get bug reports
+and patches :-).
+.PP
+Tbl, pic, eqn's are also generated using images which may be
+considered a limitation.
+.SH FILES
+@MACRODIR@/tmac.arkup
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@)
+.BR grohtml (@MAN1EXT@),
+.LP
+.SH AUTHOR
+.B Grohtml
+is written by
+.MAILTO gaius@glam.ac.uk "Gaius Mulley"
+.LINE
+.SH BUGS
+Report bugs to the
+.MAILTO bug-groff@gnu.org "Groff Bug Mailing List" .
+Include a complete, self-contained example that will allow the bug to be
+reproduced, and say which version of groff you are using.
+.LINE
diff --git a/tmac/groff_mdoc.man b/tmac/groff_mdoc.man
new file mode 100644
index 00000000..2112eba4
--- /dev/null
+++ b/tmac/groff_mdoc.man
@@ -0,0 +1,422 @@
+.\" $NetBSD: mdoc.7,v 1.14 1999/08/30 00:41:28 ross Exp $
+.\"
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. 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.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+.\"
+.\" @(#)mdoc.7 8.2 (Berkeley) 12/30/93
+.\"
+.Dd November 24, 1997
+.Os
+.Dt MDOC 7
+.Sh NAME
+.Nm mdoc
+.Nd quick reference guide for the
+.Nm \-mdoc
+macro package
+.Sh SYNOPSIS
+.Nm groff
+.Fl m Ns Ar doc
+.Ar files ...
+.Sh DESCRIPTION
+The
+.Nm \-mdoc
+package is a set of content-based and domain-based macros
+used to format the
+.Bx
+man pages.
+The macro names and their meanings are
+listed below for quick reference; for
+a detailed explanation on using the package,
+see the tutorial sampler
+.Xr mdoc.samples 7 .
+.Pp
+The macros are described in two groups, the first
+includes the structural and physical page layout macros.
+The second contains the manual and general text domain
+macros which differentiate the
+.Nm -\mdoc
+package from other
+.Xr troff
+formatting packages.
+.Sh PAGE STRUCTURE DOMAIN
+.Ss Title Macros
+To create a valid manual page, these three macros, in this order,
+are required:
+.Bl -tag -width "xxxx.Os OPERATINGxSYSTEM [version/release]" -compact
+.It Li "\&.Dd " Ar "Month day, year"
+Document date.
+.It Li "\&.Dt " Ar "DOCUMENT_TITLE [section] [volume]"
+Title, in upper case.
+.It Li "\&.Os " Ar "OPERATING_SYSTEM [version/release]"
+Operating system
+.Pq Tn BSD .
+.El
+.Ss Page Layout Macros
+Section headers, paragraph breaks, lists and displays.
+.Bl -tag -width flag -compact
+.It Li \&.Sh
+Section Headers.
+Valid headers, in the order of presentation:
+.Bl -tag -width "RETURN VALUES" -compact
+.It Ar NAME
+Name section, should include the
+.Ql \&.Nm
+or
+.Ql \&.Fn
+and the
+.Ql \&.Nd
+macros.
+.It Ar SYNOPSIS
+Usage.
+.It Ar DESCRIPTION
+General description, should include
+options and parameters.
+.It Ar RETURN VALUES
+Sections two and three function calls.
+.It Ar ENVIRONMENT
+Describe environment variables.
+.It Ar FILES
+Files associated with the subject.
+.It Ar EXAMPLES
+Examples and suggestions.
+.It Ar DIAGNOSTICS
+Normally used for section four device interface diagnostics.
+.It Ar ERRORS
+Sections two and three error and signal
+handling.
+.It Ar SEE ALSO
+Cross references and citations.
+.It Ar STANDARDS
+Conformance to standards if applicable.
+.It Ar HISTORY
+If a standard is not applicable, the history
+of the subject should be given.
+.It Ar BUGS
+Gotchas and caveats.
+.It Ar SECURITY CONSIDERATIONS
+Security issues to be aware of.
+.It Ar other
+Customized headers may be added at
+the authors discretion.
+.El
+.It Li \&.Ss
+Subsection Headers.
+.It Li \&.Pp
+Paragraph Break.
+Vertical space (one line).
+.It Li \&.D1
+(D-one) Display-one
+Indent and display one text line.
+.It Li \&.Dl
+(D-ell) Display-one literal.
+Indent and display one line of literal text.
+.It Li \&.Bd
+Begin-display block.
+Display options:
+.Bl -tag -width "xoffset string " -compact
+.It Fl ragged
+Unjustified (ragged edges).
+.It Fl filled
+Filled, and if
+.Xr troff 1 ,
+also justified.
+.It Fl unfilled
+Unfilled, unjustified.
+.It Fl literal
+Literal text or code.
+.It Fl file Ar name
+Read in named
+.Ar file
+and display.
+.It Fl offset Ar string
+Offset display.
+Acceptable
+.Ar string
+values:
+.Bl -tag -width indent-two -compact
+.It Ar left
+Align block on left (default).
+.It Ar center
+Approximate center margin.
+.It Ar indent
+Six constant width spaces (a tab).
+.It Ar indent-two
+Two tabs.
+.It Ar right
+Left aligns block 2 inches from
+right.
+.It Ar xx Ns Cm n
+Where
+.Ar xx
+is a number from
+.No \&4 Ns Cm n
+to
+.No \&9\&9 Ns Cm n .
+.It Ar Aa
+Where
+.Ar Aa
+is a callable macro name.
+.It Ar string
+The width of
+.Ar string
+is used.
+.El
+.El
+.It Li \&.Ed
+End-display (matches \&.Bd).
+.It Li \&.Bl
+Begin-list.
+Create lists or columns. Options:
+.Bl -tag -width flag -compact
+.It Em List-types
+.Bl -column "xbullet " -compact
+.It Fl bullet Ta "Bullet Item List"
+.It Fl dash Ta "Dash Item List"
+.It Fl hyphen Ta "(as per" Fl dash ")"
+.It Fl item Ta "Unlabeled List"
+.It Fl enum Ta "Enumerated List"
+.It Fl tag Ta "Tag Labeled List"
+.It Fl diag Ta "Diagnostic List"
+.It Fl hang Ta "Hanging Labeled List"
+.It Fl ohang Ta "Overhanging Labeled List"
+.It Fl inset Ta "Inset or Run-on Labeled List"
+.It Fl column Ta "Multiple Columns"
+.El
+.It Em List-parameters
+.Bl -tag -width "xcompact " -compact
+.It Fl offset
+(All lists.) See
+.Ql \&.Bd
+begin-display above.
+.It Fl width
+.Pf ( Fl tag
+and
+.Fl hang
+lists only.)
+See
+.Ql \&.Bd .
+This parameter is effectively required for
+.Fl tag
+lists.
+.It Fl compact
+(All lists.)
+Suppresses blank lines.
+.El
+.El
+.It Li \&.El
+End-list.
+.It Li \&.It
+List item.
+.El
+.Sh MANUAL AND GENERAL TEXT DOMAIN MACROS
+The manual and general text domain macros are special in that
+most of them are parsed for callable macros
+for example:
+.Bl -tag -width ".Op Fl s Ar filex" -offset indent
+.It Li "\&.Op Fl s Ar file"
+Produces
+.Op Fl s Ar file
+.El
+.Pp
+In this example, the option enclosure macro
+.Ql \&.Op
+is parsed, and calls the callable content macro
+.Ql \&Fl
+which operates on the argument
+.Ql s
+and then calls the callable content macro
+.Ql \&Ar
+which operates on the argument
+.Ql file .
+Some macros may be callable, but are not parsed and vice versa.
+These macros are indicated in the
+.Em parsed
+and
+.Em callable
+columns below.
+.Pp
+Unless stated, manual domain macros share a common syntax:
+.Pp
+.Dl \&.Va argument [\ .\ ,\ ;\ :\ (\ )\ [\ ]\ argument \...\ ]
+.Pp
+.Sy Note :
+Opening and closing
+punctuation characters are only recognized as such if they are presented
+one at a time.
+The string
+.Ql "),"
+is not recognized as punctuation and will be output with a leading white
+space and in what ever font the calling macro uses.
+The
+argument list
+.Ql "] ) ,"
+is recognized as three sequential closing punctuation characters
+and a leading white space is not output between the characters
+and the previous argument (if any).
+The special meaning of a punctuation character may be escaped
+with the string
+.Ql \e& .
+For example the following string,
+.Bl -tag -width "&.Ar file1\ , file2\ , file3\ )\ ." -offset indent
+.It Li "\&.Ar file1\ , file2\ , file3\ )\ ."
+Produces
+.Ar file1 , file2 , file3 ) .
+.El
+.ne 1i
+.Ss Manual Domain Macros
+.Bl -column "Name" "Parsed" "Callable" -compact
+.It Em Name Parsed Callable Description
+.It Li \&Ad Ta Yes Ta Yes Ta Address. "(This macro may be deprecated.)"
+.It Li \&Ar Ta Yes Ta Yes Ta "Command line argument."
+.It Li \&Cd Ta \&No Ta \&No Ta "Configuration declaration (section four only)."
+.It Li \&Cm Ta Yes Ta Yes Ta "Command line argument modifier."
+.It Li \&Dv Ta Yes Ta Yes Ta "Defined variable (source code)."
+.It Li \&Er Ta Yes Ta Yes Ta "Error number (source code)."
+.It Li \&Ev Ta Yes Ta Yes Ta "Environment variable."
+.It Li \&Fa Ta Yes Ta Yes Ta "Function argument."
+.It Li \&Fd Ta \&No Ta \&No Ta "Function declaration."
+.It Li \&Fl Ta Yes Ta Yes Ta "Command line flag."
+.It Li \&Fn Ta Yes Ta Yes Ta "Function call (also .Fo and .Fc)."
+.It Li \&Ic Ta Yes Ta Yes Ta "Interactive command."
+.It Li \&Li Ta Yes Ta Yes Ta "Literal text."
+.It Li \&Nm Ta Yes Ta Yes Ta "Command name."
+.It Li \&Op Ta Yes Ta Yes Ta "Option (also .Oo and .Oc)."
+.It Li \&Ot Ta Yes Ta Yes Ta "Old style function type (Fortran only)."
+.It Li \&Pa Ta Yes Ta Yes Ta "Pathname or file name."
+.It Li \&St Ta Yes Ta Yes Ta "Standards (-p1003.2, -p1003.1 or -ansiC)"
+.It Li \&Va Ta Yes Ta Yes Ta "Variable name."
+.It Li \&Vt Ta Yes Ta Yes Ta "Variable type (Fortran only)."
+.It Li \&Xr Ta Yes Ta Yes Ta "Manual Page Cross Reference."
+.El
+.Ss General Text Domain Macros
+.Bl -column "Name" "Parsed" "Callable" -compact
+.It Em "Name Parsed Callable Description"
+.It Li \&%A Ta Yes Ta \&No Ta "Reference author."
+.It Li \&%B Ta Yes Ta Yes Ta "Reference book title."
+.It Li \&%\&C Ta \&No Ta \&No Ta "Reference place of publishing (city)."
+.It Li \&%\&D Ta \&No Ta \&No Ta "Reference date."
+.It Li \&%J Ta Yes Ta Yes Ta "Reference journal title."
+.It Li \&%N Ta \&No Ta \&No Ta "Reference issue number."
+.It Li \&%\&O Ta \&No Ta \&No Ta "Reference optional information."
+.It Li \&%P Ta \&No Ta \&No Ta "Reference page number(s)."
+.It Li \&%R Ta \&No Ta \&No Ta "Reference report Name."
+.It Li \&%T Ta Yes Ta Yes Ta "Reference article title."
+.It Li \&%V Ta \&No Ta \&No Ta "Reference volume."
+.It Li \&Ac Ta Yes Ta Yes Ta "Angle close quote."
+.It Li \&Ao Ta Yes Ta Yes Ta "Angle open quote."
+.It Li \&Ap Ta Yes Ta Yes Ta "Insert apostrophe; switch to .No mode "
+.It Li \&Aq Ta Yes Ta Yes Ta "Angle quote."
+.It Li \&At Ta \&No Ta \&No Ta Tn "AT&T UNIX."
+.It Li \&Bc Ta Yes Ta Yes Ta "Bracket close quote."
+.It Li \&Bf Ta \&No Ta \&No Ta "Begin font mode."
+.It Li \&Bo Ta Yes Ta Yes Ta "Bracket open quote."
+.It Li \&Bq Ta Yes Ta Yes Ta "Bracket quote."
+.It Li \&Bx Ta Yes Ta Yes Ta "BSD" .
+.It Li \&Db Ta \&No Ta \&No Ta "Debug (default is \\*qoff\\*q)."
+.It Li \&Dc Ta Yes Ta Yes Ta "Double close quote."
+.It Li \&Do Ta Yes Ta Yes Ta "Double open quote."
+.It Li \&Dq Ta Yes Ta Yes Ta "Double quote."
+.It Li \&Ec Ta Yes Ta Yes Ta "Enclose string close quote."
+.It Li \&Ef Ta \&No Ta \&No Ta "End font mode."
+.It Li \&Em Ta Yes Ta Yes Ta "Emphasis (traditional English)."
+.It Li \&Eo Ta Yes Ta Yes Ta "Enclose string open quote."
+.It Li \&Fx Ta \&No Ta \&No Ta "FreeBSD."
+.It Li \&No Ta Yes Ta Yes Ta "Normal text (no-op)."
+.It Li \&Ns Ta Yes Ta Yes Ta "No space."
+.It Li \&Nx Ta \&No Ta \&No Ta "NetBSD."
+.It Li \&Pc Ta Yes Ta Yes Ta "Parenthesis close quote."
+.It Li \&Pf Ta Yes Ta \&No Ta "Prefix string."
+.It Li \&Po Ta Yes Ta Yes Ta "Parenthesis open quote."
+.It Li \&Pq Ta Yes Ta Yes Ta "Parentheses quote."
+.It Li \&Qc Ta Yes Ta Yes Ta "Strait Double close quote."
+.It Li \&Ql Ta Yes Ta Yes Ta "Quoted literal."
+.It Li \&Qo Ta Yes Ta Yes Ta "Strait Double open quote."
+.It Li \&Qq Ta Yes Ta Yes Ta "Strait Double quote."
+.It Li \&Re Ta \&No Ta \&No Ta "Reference end."
+.It Li \&Rs Ta \&No Ta \&No Ta "Reference start."
+.It Li \&Sc Ta Yes Ta Yes Ta "Single close quote."
+.It Li \&So Ta Yes Ta Yes Ta "Single open quote."
+.It Li \&Sq Ta Yes Ta Yes Ta "Single quote."
+.It Li \&Sm Ta \&No Ta \&No Ta "Space mode (default is \\*qon\\*q)."
+.It Li \&Sx Ta Yes Ta Yes Ta "Section Cross Reference."
+.It Li \&Sy Ta Yes Ta Yes Ta "Symbolic (traditional English)."
+.It Li \&Tn Ta Yes Ta Yes Ta "Trade or type name (small Caps)."
+.It Li \&Ux Ta Yes Ta Yes Ta "UNIX."
+.It Li \&Xc Ta Yes Ta Yes Ta "Extend argument list close."
+.It Li \&Xo Ta Yes Ta Yes Ta "Extend argument list open."
+.El
+.\" .It Sy \&Hf Ta \&No Ta \&No Ta "Include file with header"
+.Pp
+Macro names ending in
+.Ql q
+quote remaining items on the argument list.
+Macro names ending in
+.Ql o
+begin a quote which may span more than one line of input and
+are close quoted with the matching macro name ending in
+.Ql c .
+Enclosure macros may be nested and are limited to
+eight arguments.
+.Pp
+Note: the extended argument list macros
+.Pf ( Ql \&.Xo ,
+.Ql \&.Xc )
+and the function enclosure macros
+.Pf ( Ql \&.Fo ,
+.Ql \&.Fc )
+are irregular.
+The extended list macros are used when the number of macro arguments
+would exceed the
+.Xr troff
+limitation of nine arguments.
+.Sh CONFIGURATION
+For site specific configuration of the macro package,
+see the file
+.Pa /usr/src/share/tmac/README .
+.Sh FILES
+.Bl -tag -width "tmac.doc-ditroff" -compact
+.It Pa tmac.doc
+Manual and general text domain macros.
+.It Pa tmac.doc-common
+Common structural macros and definitions.
+.It Pa tmac.doc-nroff
+Site dependent
+.Xr nroff
+style file.
+.It Pa tmac.doc-ditroff
+Site dependent
+.Xr troff
+style file.
+.It Pa tmac.doc-syms
+Special defines (such as the standards macro).
+.El
+.Sh SEE ALSO
+.Xr mdoc.samples 7
diff --git a/tmac/groff_mdoc.samples.man b/tmac/groff_mdoc.samples.man
new file mode 100755
index 00000000..cdbbc21c
--- /dev/null
+++ b/tmac/groff_mdoc.samples.man
@@ -0,0 +1,2925 @@
+.\" $NetBSD: mdoc.samples.7,v 1.21 1999/08/23 21:54:20 ross Exp $
+.\"
+.\" Copyright (c) 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. 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.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+.\"
+.\" @(#)mdoc.samples.7 8.2 (Berkeley) 12/30/93
+.\"
+.\" This tutorial sampler invokes every macro in the package several
+.\" times and is guaranteed to give a worst case performance
+.\" for an already extremely slow package.
+.\"
+.Dd November 24, 1997
+.Os
+.Dt MDOC.SAMPLES 7
+.Sh NAME
+.Nm mdoc.samples
+.Nd tutorial sampler for writing
+.Bx
+manuals with
+.Nm \-mdoc
+.Sh SYNOPSIS
+.Nm man mdoc.samples
+.Sh DESCRIPTION
+A tutorial sampler for writing
+.Bx
+manual pages with the
+.Nm \-mdoc
+macro package, a
+.Em content Ns \-based
+and
+.Em domain Ns \-based
+formatting
+package for
+.Xr troff 1 .
+Its predecessor, the
+.Xr \-man 7
+package,
+addressed page layout leaving the
+manipulation of fonts and other
+typesetting details to the individual author.
+In
+.Nm \-mdoc ,
+page layout macros
+make up the
+.Em "page structure domain"
+which consists of macros for titles, section headers, displays
+and lists. Essentially items which affect the physical position
+of text on a formatted page.
+In addition to the page structure domain, there are two more domains,
+the manual domain and the general text domain.
+The general text domain is defined as macros which
+perform tasks such as quoting or emphasizing pieces of text.
+The manual domain is defined as macros that are a subset of the
+day to day informal language used to describe commands, routines
+and related
+.Bx
+files.
+Macros in the manual domain handle
+command names, command line arguments and options, function names,
+function parameters, pathnames, variables, cross
+references to other manual pages, and so on.
+These domain
+items have value
+for both the author and the future user of the manual page.
+It is hoped the consistency gained
+across the manual set will provide easier
+translation to future documentation tools.
+.Pp
+Throughout the
+.Ux
+manual pages, a manual entry
+is simply referred
+to as a man page, regardless of actual length and without
+sexist intention.
+.Sh GETTING STARTED
+Since a tutorial document is normally read when a person
+desires to use the material immediately, the assumption has
+been made that the user of this document may be impatient.
+The material presented in the remained of this document is
+outlined as follows:
+.Bl -enum -offset indent
+.It
+.Tn "TROFF IDIOSYNCRASIES"
+.Bl -tag -width flag -compact -offset indent
+.It "Macro Usage" .
+.It "Passing Space Characters in an Argument" .
+.It "Trailing Blank Space Characters (a warning)" .
+.It "Escaping Special Characters" .
+.El
+.It
+.Tn "THE ANATOMY OF A MAN PAGE"
+.Bl -tag -width flag -compact -offset indent
+.It "A manual page template" .
+.El
+.It
+.Tn "INTRODUCTION OF TITLE MACROS" .
+.It
+.Tn "INTRODUCTION OF MANUAL AND GENERAL TEXT DOMAINS" .
+.Bl -tag -width flag -compact -offset indent
+.It "What's in a name..." .
+.It "General Syntax" .
+.El
+.It
+.Tn "MANUAL DOMAIN"
+.Bl -tag -width flag -compact -offset indent
+.It "Addresses" .
+.It "Arguments" .
+.It "Configuration Declarations (section four only)" .
+.It "Command Modifier" .
+.It "Defined Variables" .
+.It "Errno's (Section two only)" .
+.It "Environment Variables" .
+.It "Function Argument" .
+.It "Function Declaration" .
+.It "Flags" .
+.It "Functions (library routines)" .
+.It "Function Types" .
+.\" .It "Header File (including source code)" .
+.It "Interactive Commands" .
+.It "Literals" .
+.It "Names" .
+.It "Options" .
+.It "Pathnames" .
+.It "Variables" .
+.It "Cross References" .
+.El
+.It
+.Tn "GENERAL TEXT DOMAIN"
+.Bl -tag -width flag -compact -offset indent
+.It "AT&T Macro" .
+.It "BSD Macro" .
+.It "UNIX Macro" .
+.It "Emphasis Macro" .
+.It "Enclosure/Quoting Macros"
+.Bl -tag -width flag -compact -offset indent
+.It "Angle Bracket Quote/Enclosure" .
+.It "Bracket Quotes/Enclosure" .
+.It "Double Quote macro/Enclosure" .
+.It "Parenthesis Quote/Enclosure" .
+.It "Single Quotes/Enclosure" .
+.It "Prefix Macro" .
+.El
+.It "Extended Arguments" .
+.It "No\-Op or Normal Text Macro" .
+.It "No Space Macro" .
+.It "Section Cross References" .
+.It "Symbolic Macro" .
+.It "References and Citations" .
+.It "Trade Names (Acronyms and Type Names)" .
+.El
+.It
+.Tn "PAGE STRUCTURE DOMAIN"
+.Bl -tag -width flag -compact -offset indent
+.It "Section Headers" .
+.It "Paragraphs and Line Spacing" .
+.It "Keeps" .
+.It "Displays" .
+.It "Lists and Columns" .
+.El
+.It
+.Tn "PREDEFINED STRINGS"
+.It
+.Tn "DIAGNOSTICS"
+.It
+.Tn "FORMATTING WITH GROFF, TROFF AND NROFF"
+.It
+.Tn "BUGS"
+.El
+.ne 7
+.Sh TROFF IDIOSYNCRASIES
+The
+.Nm \-mdoc
+package attempts to simplify the process of writing a man page.
+Theoretically, one should not have to learn the dirty details of
+.Xr troff 1
+to use
+.Nm \-mdoc ;
+however, there are a few
+limitations which are unavoidable and best gotten out
+of the way.
+And, too, be forewarned, this package is
+.Em not
+fast.
+.Ss Macro Usage
+As in
+.Xr troff 1 ,
+a macro is called by placing a
+.Ql \&\.
+(dot character)
+at the beginning of
+a line followed by the two character name for the macro.
+Arguments may follow the macro separated by spaces.
+It is the dot character at the beginning of the line which causes
+.Xr troff 1
+to interpret the next two characters as a macro name.
+To place a
+.Ql \&\.
+(dot character)
+at the beginning of a line in some context other than
+a macro invocation, precede the
+.Ql \&\.
+(dot) with the
+.Ql \e&
+escape sequence.
+The
+.Ql \e&
+translates literally to a zero width space, and is never displayed in the
+output.
+.Pp
+In general,
+.Xr troff 1
+macros accept up to nine arguments, any
+extra arguments are ignored.
+Most macros in
+.Nm \-mdoc
+accept nine arguments and,
+in limited cases, arguments may be continued or extended
+on the
+next line (See
+.Sx Extended Arguments ) .
+A few macros handle quoted arguments (see
+.Sx Passing Space Characters in an Argument
+below).
+.Pp
+Most of the
+.Nm \-mdoc
+general text domain and manual domain macros are special
+in that their argument lists are
+.Em parsed
+for callable macro names.
+This means an argument on the argument list which matches
+a general text or manual domain macro name and is determined
+to be callable will be executed
+or called when it is processed.
+In this case
+the argument, although the name of a macro,
+is not preceded by a
+.Ql \&\.
+(dot).
+It is in this manner that many macros are nested; for
+example
+the option macro,
+.Ql \&.Op ,
+may
+.Em call
+the flag and argument macros,
+.Ql \&Fl
+and
+.Ql \&Ar ,
+to specify an optional flag with an argument:
+.Bl -tag -width "\&.Op \&Fl s \&Ar bytes" -offset indent
+.It Op Fl s Ar bytes
+is produced by
+.Li \&.Op \&Fl s \&Ar bytes
+.El
+.Pp
+To prevent a two character
+string from being interpreted as a macro name, precede
+the string with the
+escape sequence
+.Ql \e& :
+.Bl -tag -width "\&.Op \&Fl s \&Ar bytes" -offset indent
+.It Op \&Fl s \&Ar bytes
+is produced by
+.Li \&.Op \e&Fl s \e&Ar bytes
+.El
+.Pp
+Here the strings
+.Ql \&Fl
+and
+.Ql \&Ar
+are not interpreted as macros.
+Macros whose argument lists are parsed for callable arguments
+are referred to
+as parsed and macros which may be called from an argument
+list are referred to as callable
+throughout this document and in the companion quick reference
+manual
+.Xr mdoc 7 .
+This is a technical
+.Em faux pas
+as almost all of the macros in
+.Nm \-mdoc
+are parsed, but as it was cumbersome to constantly refer to macros
+as being callable and being able to call other macros,
+the term parsed has been used.
+.Ss Passing Space Characters in an Argument
+Sometimes it is desirable to give as one argument a string
+containing one or more blank space characters.
+This may be necessary
+to defeat the nine argument limit or to specify arguments to macros
+which expect particular arrangement of items in the argument list.
+For example,
+the function macro
+.Ql \&.Fn
+expects the first argument to be the name of a function and any
+remaining arguments to be function parameters.
+As
+.Tn "ANSI C"
+stipulates the declaration of function parameters in the
+parenthesized parameter list, each parameter is guaranteed
+to be at minimum a two word string.
+For example,
+.Fa int foo .
+.Pp
+There are two possible ways to pass an argument which contains
+an embedded space.
+.Em Implementation note :
+Unfortunately, the most convenient way
+of passing spaces in between quotes by reassigning individual
+arguments before parsing was fairly expensive speed wise
+and space wise to implement in all the macros for
+.Tn AT&T
+.Xr troff .
+It is not expensive for
+.Xr groff
+but for the sake of portability, has been limited
+to the following macros which need
+it the most:
+.Pp
+.Bl -tag -width 4n -offset indent -compact
+.It Li \&Cd
+Configuration declaration (section 4
+.Sx SYNOPSIS )
+.It Li \&Bl
+Begin list (for the width specifier).
+.It Li \&Em
+Emphasized text.
+.It Li \&Fn
+Functions (sections two and four).
+.It Li \&It
+List items.
+.It Li \&Li
+Literal text.
+.It Li \&Sy
+Symbolic text.
+.It Li \&%B
+Book titles.
+.It Li \&%J
+Journal names.
+.It Li \&%O
+Optional notes for a reference.
+.It Li \&%R
+Report title (in a reference).
+.It Li \&%T
+Title of article in a book or journal.
+.El
+.Pp
+One way of passing a string
+containing blank spaces is to use the hard or unpaddable space character
+.Ql \e\ ,
+that is, a blank space preceded by the escape character
+.Ql \e .
+This method may be used with any macro but has the side effect
+of interfering with the adjustment of text
+over the length of a line.
+.Xr Troff
+sees the hard space as if it were any other printable character and
+cannot split the string into blank or newline separated pieces as one
+would expect.
+The method is useful for strings which are not expected
+to overlap a line boundary.
+For example:
+.Bl -tag -width "fetch(char *str)" -offset indent
+.It Fn fetch char\ *str
+is created by
+.Ql \&.Fn fetch char\e *str
+.It Fn fetch "char *str"
+can also be created by
+.Ql \&.Fn fetch "\\*q*char *str\\*q"
+.El
+.Pp
+If the
+.Ql \e
+or quotes
+were omitted,
+.Ql \&.Fn
+would see three arguments and
+the result would be:
+.Pp
+.Dl Fn fetch char *str
+.Pp
+For an example of what happens when the parameter list overlaps
+a newline boundary, see the
+.Sx BUGS
+section.
+.Ss Trailing Blank Space Characters
+.Xr Troff
+can be confused by blank space characters at the end of a line.
+It
+is a wise preventive measure to globally remove all blank spaces
+from <blank-space><end-of-line> character sequences.
+Should the need
+arise to force a blank character at the end of a line,
+it may be forced with an unpaddable space and the
+.Ql \e&
+escape character.
+For example,
+.Ql string\e\ \e& .
+.Ss Escaping Special Characters
+Special characters
+like the newline character
+.Ql \en ,
+are handled by replacing the
+.Ql \e
+with
+.Ql \ee
+(e.g.
+.Ql \een )
+to preserve
+the backslash.
+.Sh THE ANATOMY OF A MAN PAGE
+The body of a man page is easily constructed from a basic
+template found in the file:
+.Bd -literal -offset indent
+\&.\e" /usr/share/misc/mdoc.template:
+\&.\e" The following six lines are required.
+\&.Dd Month day, year
+\&.Os OPERATING_SYSTEM [version/release]
+\&.Dt DOCUMENT_TITLE [section number] [volume]
+\&.Sh NAME
+\&.Sh SYNOPSIS
+\&.Sh DESCRIPTION
+\&.\e" The following requests should be uncommented and
+\&.\e" used where appropriate. This next request is
+\&.\e" for sections 2 and 3 function return values only.
+\&.\e" .Sh RETURN VALUES
+\&.\e" This next request is for sections 1, 6, 7 & 8 only
+\&.\e" .Sh ENVIRONMENT
+\&.\e" .Sh FILES
+\&.\e" .Sh EXAMPLES
+\&.\e" This next request is for sections 1, 6, 7 & 8 only
+\&.\e" (command return values (to shell) and
+\&.\e" fprintf/stderr type diagnostics)
+\&.\e" .Sh DIAGNOSTICS
+\&.\e" The next request is for sections 2 and 3 error
+\&.\e" and signal handling only.
+\&.\e" .Sh ERRORS
+\&.\e" .Sh SEE ALSO
+\&.\e" .Sh STANDARDS
+\&.\e" .Sh HISTORY
+\&.\e" .Sh AUTHORS
+\&.\e" .Sh BUGS
+.Ed
+.Pp
+The first items in the template are the macros
+.Pq Li \&.Dd , \&.Os , \&.Dt ;
+the document date,
+the operating system the man page or subject source is developed
+or modified for,
+and the man page title
+.Pq Em in upper case
+along with the section of the manual the page
+belongs in.
+These macros identify the page,
+and are discussed below in
+.Sx TITLE MACROS .
+.Pp
+The remaining items in the template are section headers
+.Pq Li \&.Sh ;
+of which
+.Sx NAME ,
+.Sx SYNOPSIS
+and
+.Sx DESCRIPTION
+are mandatory.
+The
+headers are
+discussed in
+.Sx PAGE STRUCTURE DOMAIN ,
+after
+presentation of
+.Sx MANUAL DOMAIN .
+Several content macros are used to demonstrate page layout macros;
+reading about content macros before page layout macros is
+recommended.
+.Sh TITLE MACROS
+The title macros are the first portion of the page structure
+domain, but are presented first and separate for someone who
+wishes to start writing a man page yesterday.
+Three header macros designate the document title or manual page title,
+the operating system,
+and the date of authorship.
+These macros are one called once at the very beginning of the document
+and are used to construct the headers and footers only.
+.Bl -tag -width 6n
+.It Li \&.Dt DOCUMENT_TITLE section# [volume]
+The document title is the
+subject of the man page and must be in
+.Tn CAPITALS
+due to troff
+limitations.
+The section number may be 1,\ ...,\ 9,
+and if it is specified,
+the volume title may be omitted.
+A volume title may be arbitrary or one of the following:
+.\" .Cl
+.\" USD UNIX User's Supplementary Documents
+.\" .Cl
+.\" PS1 UNIX Programmer's Supplementary Documents
+.Pp
+.Bl -column SMM -offset indent -compact
+.It Li AMD NetBSD Ancestral Manual Documents
+.It Li SMM NetBSD System Manager's Manual
+.It Li URM NetBSD Reference Manual
+.It Li PRM NetBSD Programmer's Manual
+.It Li KM NetBSD Kernel Manual
+.El
+.Pp
+The default volume labeling is
+.Li URM
+for sections 1, 6, and 7;
+.Li SMM
+for section 8;
+.Li PRM
+for sections 2, 3, 4, and 5;
+.Li KM
+for section 9.
+.\" .Cl
+.\" MMI UNIX Manual Master Index
+.\" .Cl
+.\" CON UNIX Contributed Software Manual
+.\" .Cl
+.\" LOC UNIX Local Manual
+.It Li \&.Os operating_system release#
+The name of the operating system
+should be the common acronym, e.g.
+.Tn BSD
+or
+.Tn ATT .
+The release should be the standard release
+nomenclature for the system specified, e.g. 4.3, 4.3+Tahoe, V.3,
+V.4.
+Unrecognized arguments are displayed as given in the page footer.
+For instance, a typical footer might be:
+.Pp
+.Dl \&.Os BSD 4.3
+.Pp
+or for a locally produced set
+.Pp
+.Dl \&.Os CS Department
+.Pp
+The Berkeley default,
+.Ql \&.Os
+without an argument, has been defined as
+.Nx 1.4
+in the site specific file
+.Pa /usr/share/tmac/tmac.doc-common .
+Note, if the
+.Ql \&.Os
+macro is not present, the bottom left corner of the page
+will be ugly.
+.It Li \&.Dd month day, year
+The date should be written formally:
+.Pp
+.ne 5
+.Dl January 25, 1989
+.sp
+Note that the date must not be placed in quotes!
+.El
+.Sh MANUAL DOMAIN
+.Ss What's in a name...
+The manual domain macro names are derived from the day to day
+informal language used to describe commands, subroutines and related
+files.
+Slightly
+different variations of this language are used to describe
+the three different aspects of writing a man page.
+First, there is the description of
+.Nm \-mdoc
+macro request usage.
+Second is the description of a
+.Ux
+command
+.Em with
+.Nm \-mdoc
+macros and third,
+the
+description of a command to a user in the verbal sense;
+that is, discussion of a command in the text of a man page.
+.Pp
+In the first case,
+.Xr troff 1
+macros are themselves a type of command;
+the general syntax for a troff command is:
+.Bd -filled -offset indent
+\&.Va argument1 argument2 ... argument9
+.Ed
+.Pp
+The
+.Ql \&.Va
+is a macro command or request, and anything following it is an argument to
+be processed.
+In the second case,
+the description of a
+.Ux
+command using the content macros is a
+bit more involved;
+a typical
+.Sx SYNOPSIS
+command line might be displayed as:
+.Bd -filled -offset indent
+.Nm filter
+.Op Fl flag
+.Ar infile outfile
+.Ed
+.Pp
+Here,
+.Nm filter
+is the command name and the
+bracketed string
+.Fl flag
+is a
+.Em flag
+argument designated as optional by the option brackets.
+In
+.Nm \-mdoc
+terms,
+.Ar infile
+and
+.Ar outfile
+are
+called
+.Em arguments .
+The macros which formatted the above example:
+.Bd -literal -offset indent
+\&.Nm filter
+\&.Op \&Fl flag
+\&.Ar infile outfile
+.Ed
+.Pp
+In the third case, discussion of commands and command syntax
+includes both examples above, but may add more detail.
+The
+arguments
+.Ar infile
+and
+.Ar outfile
+from the example above might be referred to as
+.Em operands
+or
+.Em file arguments .
+Some command line argument lists are quite long:
+.Bl -tag -width make -offset indent
+.It Nm make
+.Op Fl eiknqrstv
+.Op Fl D Ar variable
+.Op Fl d Ar flags
+.Op Fl f Ar makefile
+.Bk -words
+.Op Fl I Ar directory
+.Ek
+.Op Fl j Ar max_jobs
+.Op Ar variable=value
+.Bk -words
+.Op Ar target ...
+.Ek
+.El
+.Pp
+Here one might talk about the command
+.Nm make
+and qualify the argument
+.Ar makefile ,
+as an argument to the flag,
+.Fl f ,
+or discuss the optional
+file
+operand
+.Ar target .
+In the verbal context, such detail can prevent confusion,
+however the
+.Nm \-mdoc
+package
+does not have a macro for an argument
+.Em to
+a flag.
+Instead the
+.Ql \&Ar
+argument macro is used for an operand or file argument like
+.Ar target
+as well as an argument to a flag like
+.Ar variable .
+The make command line was produced from:
+.Bd -literal -offset indent
+\&.Nm make
+\&.Op Fl eiknqrstv
+\&.Op Fl D Ar variable
+\&.Op Fl d Ar flags
+\&.Op Fl f Ar makefile
+\&.Op Fl I Ar directory
+\&.Op Fl j Ar max_jobs
+\&.Op Ar variable=value
+\&.Bk -words
+\&.Op Ar target ...
+\&.Ek
+.Ed
+.Pp
+The
+.Ql \&.Bk
+and
+.Ql \&.Ek
+macros are explained in
+.Sx Keeps .
+.Ss General Syntax
+The manual domain and general text domain macros share a similar
+syntax with a few minor deviations:
+.Ql \&.Ar ,
+.Ql \&.Fl ,
+.Ql \&.Nm ,
+and
+.Ql \&.Pa
+differ only when called without arguments;
+.Ql \&.Fn
+and
+.Ql \&.Xr
+impose an order on their argument lists
+and the
+.Ql \&.Op
+and
+.Ql \&.Fn
+macros
+have nesting limitations.
+All content macros
+are capable of recognizing and properly handling punctuation,
+provided each punctuation character is separated by a leading space.
+If an request is given:
+.Pp
+.Dl \&.Li sptr, ptr),
+.Pp
+The result is:
+.Pp
+.Dl Li sptr, ptr),
+.Pp
+The punctuation is not recognized and all is output in the
+literal font. If the punctuation is separated by a leading
+white space:
+.Pp
+.Dl \&.Li "sptr , ptr ) ,"
+.Pp
+The result is:
+.Pp
+.Dl Li sptr , ptr ) ,
+.Pp
+The punctuation is now recognized and is output in the
+default font distinguishing it from the strings in literal font.
+.Pp
+To remove the special meaning from a punctuation character
+escape it with
+.Ql \e& .
+.Xr Troff
+is limited as a macro language, and has difficulty
+when presented with a string containing
+a member of the mathematical, logical or
+quotation set:
+.Bd -literal -offset indent-two
+\&{+,\-,/,*,\&%,<,>,<=,>=,=,==,&,`,',"}
+.Ed
+.Pp
+The problem is that
+.Xr troff
+may assume it is supposed to actually perform the operation
+or evaluation suggested by the characters. To prevent
+the accidental evaluation of these characters,
+escape them with
+.Ql \e& .
+Typical syntax is shown in the first content macro displayed
+below,
+.Ql \&.Ad .
+.Ss Address Macro
+The address macro identifies an address construct
+of the form addr1[,addr2[,addr3]].
+.Pp
+.Dl Usage: .Ad address ... \*(Pu
+.Bl -tag -width ".Ad f1 , f2 , f3 :" -compact -offset 14n
+.It Li \&.Ad addr1
+.Ad addr1
+.It Li \&.Ad addr1\ .
+.Ad addr1 .
+.It Li \&.Ad addr1\ , file2
+.Ad addr1 , file2
+.It Li \&.Ad f1\ , f2\ , f3\ :
+.Ad f1 , f2 , f3 :
+.It Li \&.Ad addr\ )\ )\ ,
+.Ad addr ) ) ,
+.El
+.Pp
+It is an error to call
+.Li \&.Ad
+without arguments.
+.Li \&.Ad
+is callable by other macros and is parsed.
+.Ss Argument Macro
+The
+.Li \&.Ar
+argument macro may be used whenever
+a command line argument is referenced.
+.Pp
+.Dl Usage: .Ar argument ... \*(Pu
+.Bl -tag -width ".Ar file1 file2" -compact -offset 15n
+.It Li \&.Ar
+.Ar
+.It Li \&.Ar file1
+.Ar file1
+.It Li \&.Ar file1\ .
+.Ar file1 .
+.It Li \&.Ar file1 file2
+.Ar file1 file2
+.It Li \&.Ar f1 f2 f3\ :
+.Ar f1 f2 f3 :
+.It Li \&.Ar file\ )\ )\ ,
+.Ar file ) ) ,
+.El
+.Pp
+If
+.Li \&.Ar
+is called without arguments
+.Ql Ar
+is assumed.
+The
+.Li \&.Ar
+macro is parsed and is callable.
+.Ss Configuration Declaration (section four only)
+The
+.Ql \&.Cd
+macro is used to demonstrate a
+.Xr config 8
+declaration for a device interface in a section four manual.
+This macro accepts quoted arguments (double quotes only).
+.Pp
+.Bl -tag -width "device le0 at scode?" -offset indent
+.It Cd "device le0 at scode?"
+produced by:
+.Ql ".Cd device le0 at scode?" .
+.El
+.Ss Command Modifier
+The command modifier is identical to the
+.Ql \&.Fl
+(flag) command with the exception
+the
+.Ql \&.Cm
+macro does not assert a dash
+in front of every argument.
+Traditionally flags are marked by the
+preceding dash, some commands or subsets of commands do not use them.
+Command modifiers may also be specified in conjunction with interactive
+commands such as editor commands.
+See
+.Sx Flags .
+.Ss Defined Variables
+A variable which is defined in an include file is specified
+by the macro
+.Ql \&.Dv .
+.Pp
+.Dl Usage: .Dv defined_variable ... \*(Pu
+.Bl -tag -width ".Dv MAXHOSTNAMELEN" -compact -offset 14n
+.It Li ".Dv MAXHOSTNAMELEN"
+.Dv MAXHOSTNAMELEN
+.It Li ".Dv TIOCGPGRP )"
+.Dv TIOCGPGRP )
+.El
+.Pp
+It is an error to call
+.Ql \&.Dv
+without arguments.
+.Ql \&.Dv
+is parsed and is callable.
+.Ss Errno's (Section two only)
+The
+.Ql \&.Er
+errno macro specifies the error return value
+for section two library routines.
+The second example
+below shows
+.Ql \&.Er
+used with the
+.Ql \&.Bq
+general text domain macro, as it would be used in
+a section two manual page.
+.Pp
+.Dl Usage: .Er ERRNOTYPE ... \*(Pu
+.Bl -tag -width ".Bq Er ENOTDIR" -compact -offset 14n
+.It Li \&.Er ENOENT
+.Er ENOENT
+.It Li \&.Er ENOENT\ )\ ;
+.Er ENOENT ) ;
+.It Li \&.Bq \&Er ENOTDIR
+.Bq Er ENOTDIR
+.El
+.Pp
+It is an error to call
+.Ql \&.Er
+without arguments.
+The
+.Ql \&.Er
+macro is parsed and is callable.
+.Ss Environment Variables
+The
+.Ql \&.Ev
+macro specifies an environment variable.
+.Pp
+.Dl Usage: .Ev argument ... \*(Pu
+.Bl -tag -width ".Ev PRINTER ) ) ," -compact -offset 14n
+.It Li \&.Ev DISPLAY
+.Ev DISPLAY
+.It Li \&.Ev PATH\ .
+.Ev PATH .
+.It Li \&.Ev PRINTER\ )\ )\ ,
+.Ev PRINTER ) ) ,
+.El
+.Pp
+It is an error to call
+.Ql \&.Ev
+without arguments.
+The
+.Ql \&.Ev
+macro is parsed and is callable.
+.Ss Function Argument
+The
+.Ql \&.Fa
+macro is used to refer to function arguments (parameters)
+outside of the
+.Sx SYNOPSIS
+section of the manual or inside
+the
+.Sx SYNOPSIS
+section should a parameter list be too
+long for the
+.Ql \&.Fn
+macro and the enclosure macros
+.Ql \&.Fo
+and
+.Ql \&.Fc
+must be used.
+.Ql \&.Fa
+may also be used to refer to structure members.
+.Pp
+.Dl Usage: .Fa function_argument ... \*(Pu
+.Bl -tag -width ".Fa d_namlen\ )\ )\ ," -compact -offset 14n
+.It Li \&.Fa d_namlen\ )\ )\ ,
+.Fa d_namlen ) ) ,
+.It Li \&.Fa iov_len
+.Fa iov_len
+.El
+.Pp
+It is an error to call
+.Ql \&.Fa
+without arguments.
+.Ql \&.Fa
+is parsed and is callable.
+.Ss Function Declaration
+The
+.Ql \&.Fd
+macro is used in the
+.Sx SYNOPSIS
+section with section two or three
+functions.
+The
+.Ql \&.Fd
+macro does not call other macros and is not callable by other
+macros.
+.Pp
+.Dl Usage: .Fd include_file (or defined variable)
+.Pp
+In the
+.Sx SYNOPSIS
+section a
+.Ql \&.Fd
+request causes a line break if a function has already been presented
+and a break has not occurred.
+This leaves a nice vertical space
+in between the previous function call and the declaration for the
+next function.
+.Ss Flags
+The
+.Ql \&.Fl
+macro handles command line flags.
+It prepends
+a dash,
+.Ql \- ,
+to the flag.
+For interactive command flags, which
+are not prepended with a dash, the
+.Ql \&.Cm
+(command modifier)
+macro is identical, but without the dash.
+.Pp
+.Dl Usage: .Fl argument ... \*(Pu
+.Bl -tag -width ".Fl \-s \-t \-v" -compact -offset 14n
+.It Li \&.Fl
+.Fl
+.It Li \&.Fl cfv
+.Fl cfv
+.It Li \&.Fl cfv\ .
+.Fl cfv .
+.It Li \&.Fl s v t
+.Fl s v t
+.It Li \&.Fl -\ ,
+.Fl - ,
+.It Li \&.Fl xyz\ )\ ,
+.Fl xyz ) ,
+.El
+.Pp
+The
+.Ql \&.Fl
+macro without any arguments results
+in a dash representing stdin/stdout.
+Note that giving
+.Ql \&.Fl
+a single dash, will result in two dashes.
+The
+.Ql \&.Fl
+macro is parsed and is callable.
+.Ss Functions (library routines)
+The .Fn macro is modeled on ANSI C conventions.
+.Bd -literal
+Usage: .Fn [type] function [[type] parameters ... \*(Pu]
+.Ed
+.Bl -tag -width ".Fn .int align. .const * char *sptrsxx" -compact
+.It Li "\&.Fn getchar"
+.Fn getchar
+.It Li "\&.Fn strlen ) ,"
+.Fn strlen ) ,
+.It Li \&.Fn "\\*qint align\\*q" "\\*qconst * char *sptrs\\*q" ,
+.Fn "int align" "const * char *sptrs" ,
+.El
+.Pp
+It is an error to call
+.Ql \&.Fn
+without any arguments.
+The
+.Ql \&.Fn
+macro
+is parsed and is callable,
+note that any call to another macro signals the end of
+the
+.Ql \&.Fn
+call (it will close-parenthesis at that point).
+.Pp
+For functions that have more than eight parameters (and this
+is rare), the
+macros
+.Ql \&.Fo
+(function open)
+and
+.Ql \&.Fc
+(function close)
+may be used with
+.Ql \&.Fa
+(function argument)
+to get around the limitation. For example:
+.Bd -literal -offset indent
+\&.Fo "int res_mkquery"
+\&.Fa "int op"
+\&.Fa "char *dname"
+\&.Fa "int class"
+\&.Fa "int type"
+\&.Fa "char *data"
+\&.Fa "int datalen"
+\&.Fa "struct rrec *newrr"
+\&.Fa "char *buf"
+\&.Fa "int buflen"
+\&.Fc
+.Ed
+.Pp
+Produces:
+.Bd -filled -offset indent
+.Fo "int res_mkquery"
+.Fa "int op"
+.Fa "char *dname"
+.Fa "int class"
+.Fa "int type"
+.Fa "char *data"
+.Fa "int datalen"
+.Fa "struct rrec *newrr"
+.Fa "char *buf"
+.Fa "int buflen"
+.Fc
+.Ed
+.Pp
+The
+.Ql \&.Fo
+and
+.Ql \&.Fc
+macros are parsed and are callable.
+In the
+.Sx SYNOPSIS
+section, the function will always begin at
+the beginning of line.
+If there is more than one function
+presented in the
+.Sx SYNOPSIS
+section and a function type has not been
+given, a line break will occur, leaving a nice vertical space
+between the current function name and the one prior.
+At the moment,
+.Ql \&.Fn
+does not check its word boundaries
+against troff line lengths and may split across a newline
+ungracefully.
+This will be fixed in the near future.
+.Ss Function Type
+This macro is intended for the
+.Sx SYNOPSIS
+section.
+It may be used
+anywhere else in the man page without problems, but its main purpose
+is to present the function type in kernel normal form for the
+.Sx SYNOPSIS
+of sections two and three
+(it causes a page break allowing the function name to appear
+on the next line).
+.Pp
+.Dl Usage: .Ft type ... \*(Pu
+.Bl -tag -width "\&.Ft struct stat" -offset 14n -compact
+.It Li \&.Ft struct stat
+.Ft struct stat
+.El
+.Pp
+The
+.Ql \&.Ft
+request is not callable by other macros.
+.Ss Interactive Commands
+The
+.Ql \&.Ic
+macro designates an interactive or internal command.
+.Pp
+.Dl Usage: .Li argument ... \*(Pu
+.Bl -tag -width ".Ic setenv , unsetenvxx" -compact -offset 14n
+.It Li \&.Ic :wq
+.Ic :wq
+.It Li \&.Ic do while {...}
+.Ic do while {...}
+.It Li \&.Ic setenv\ , unsetenv
+.Ic setenv , unsetenv
+.El
+.Pp
+It is an error to call
+.Ql \&.Ic
+without arguments.
+The
+.Ql \&.Ic
+macro is parsed and is callable.
+.Ss Literals
+The
+.Ql \&.Li
+literal macro may be used for special characters,
+variable constants, anything which should be displayed as it
+would be typed.
+.Pp
+.Dl Usage: .Li argument ... \*(Pu
+.Bl -tag -width ".Li cntrl-D ) ," -compact -offset 14n
+.It Li \&.Li \een
+.Li \en
+.It Li \&.Li M1 M2 M3\ ;
+.Li M1 M2 M3 ;
+.It Li \&.Li cntrl-D\ )\ ,
+.Li cntrl-D ) ,
+.It Li \&.Li 1024\ ...
+.Li 1024 ...
+.El
+.Pp
+The
+.Ql \&.Li
+macro is parsed and is callable.
+.Ss Name Macro
+The
+.Ql \&.Nm
+macro is used for the document title or subject name.
+It has the peculiarity of remembering the first
+argument it was called with, which should
+always be the subject name of the page.
+When called without
+arguments,
+.Ql \&.Nm
+regurgitates this initial name for the sole purpose
+of making less work for the author.
+If trailing punctuation is required with this feature,
+use
+.Qq
+as a first argument to
+.Ql \&.Nm .
+Note:
+a section two
+or three document function name is addressed with the
+.Ql \&.Nm
+in the
+.Sx NAME
+section, and with
+.Ql \&.Fn
+in the
+.Sx SYNOPSIS
+and remaining sections.
+For interactive commands, such as the
+.Ql while
+command keyword in
+.Xr csh 1 ,
+the
+.Ql \&.Ic
+macro should be used.
+While the
+.Ql \&.Ic
+is nearly identical
+to
+.Ql \&.Nm ,
+it can not recall the first argument it was invoked with.
+.Pp
+.Dl Usage: .Nm argument ... \*(Pu
+.Bl -tag -width ".Nm mdoc.samples" -compact -offset 14n
+.It Li \&.Nm mdoc.samples
+.Nm mdoc.samples
+.It Li \&.Nm \e-mdoc
+.Nm \-mdoc
+.It Li \&.Nm foo\ )\ )\ ,
+.Nm foo ) ) ,
+.It Li \&.Nm
+.Nm
+.It Li \&.Nm \&"\&"\ :
+.Nm "" :
+.El
+.Pp
+The
+.Ql \&.Nm
+macro is parsed and is callable.
+.Ss Options
+The
+.Ql \&.Op
+macro
+places option brackets around the any remaining arguments on the command
+line, and places any
+trailing punctuation outside the brackets.
+The macros
+.Ql \&.Oc
+and
+.Ql \&.Oo
+may be used across one or more lines.
+.Pp
+.Dl Usage: .Op options ... \*(Pu
+.Bl -tag -width ".Op Fl c Ar objfil Op Ar corfil ," -compact -offset indent
+.It Li \&.Op
+.Op
+.It Li ".Op Fl k"
+.Op Fl k
+.It Li ".Op Fl k ) ."
+.Op Fl k ) .
+.It Li ".Op Fl k Ar kookfile"
+.Op Fl k Ar kookfile
+.It Li ".Op Fl k Ar kookfile ,"
+.Op Fl k Ar kookfile ,
+.It Li ".Op Ar objfil Op Ar corfil"
+.Op Ar objfil Op Ar corfil
+.It Li ".Op Fl c Ar objfil Op Ar corfil ,"
+.Op Fl c Ar objfil Op Ar corfil ,
+.It Li \&.Op word1 word2
+.Op word1 word2
+.El
+.Pp
+The
+.Ql \&.Oc
+and
+.Ql \&.Oo
+macros:
+.Bd -literal -offset indent
+\&.Oo
+\&.Op \&Fl k \&Ar kilobytes
+\&.Op \&Fl i \&Ar interval
+\&.Op \&Fl c \&Ar count
+\&.Oc
+.Ed
+.Pp
+Produce:
+.Oo
+.Op Fl k Ar kilobytes
+.Op Fl i Ar interval
+.Op Fl c Ar count
+.Oc
+.Pp
+The macros
+.Ql \&.Op ,
+.Ql \&.Oc
+and
+.Ql \&.Oo
+are parsed and are callable.
+.Ss Pathnames
+The
+.Ql \&.Pa
+macro formats path or file names.
+.Pp
+.Dl Usage: .Pa pathname \*(Pu
+.Bl -tag -width ".Pa /tmp/fooXXXXX ) ." -compact -offset 14n
+.It Li \&.Pa /usr/share
+.Pa /usr/share
+.It Li \&.Pa /tmp/fooXXXXX\ )\ .
+.Pa /tmp/fooXXXXX ) .
+.El
+.Pp
+The
+.Ql \&.Pa
+macro is parsed and is callable.
+.Ss Variables
+Generic variable reference:
+.Pp
+.Dl Usage: .Va variable ... \*(Pu
+.Bl -tag -width ".Va char s ] ) ) ," -compact -offset 14n
+.It Li \&.Va count
+.Va count
+.It Li \&.Va settimer ,
+.Va settimer ,
+.It Li \&.Va int\ *prt\ )\ :
+.Va int\ *prt ) :
+.It Li \&.Va char\ s\ ]\ )\ )\ ,
+.Va char\ s ] ) ) ,
+.El
+.Pp
+It is an error to call
+.Ql \&.Va
+without any arguments.
+The
+.Ql \&.Va
+macro is parsed and is callable.
+.Ss Manual Page Cross References
+The
+.Ql \&.Xr
+macro expects the first argument to be
+a manual page name, and the second argument, if it exists,
+to be either a section page number or punctuation.
+Any
+remaining arguments are assumed to be punctuation.
+.Pp
+.Dl Usage: .Xr man_page [1,...,9] \*(Pu
+.Bl -tag -width ".Xr mdoc 7 ) ) ," -compact -offset 14n
+.It Li \&.Xr mdoc
+.Xr mdoc
+.It Li \&.Xr mdoc\ ,
+.Xr mdoc ,
+.It Li \&.Xr mdoc 7
+.Xr mdoc 7
+.It Li \&.Xr mdoc 7\ )\ )\ ,
+.Xr mdoc 7 ) ) ,
+.El
+.Pp
+The
+.Ql \&.Xr
+macro is parsed and is callable.
+It is an error to call
+.Ql \&.Xr
+without
+any arguments.
+.Sh GENERAL TEXT DOMAIN
+.Ss AT&T Macro
+.Bd -literal -offset indent -compact
+Usage: .At [v1 .. v7 | 32v | V.1 | V.4] ... \*(Pu
+.Ed
+.Bl -tag -width ".At v6 ) ," -compact -offset 14n
+.It Li ".At"
+.At
+.It Li ".At v6 ."
+.At v6 .
+.El
+.Pp
+The
+.Ql \&.At
+macro is
+.Em not
+parsed and
+.Em not
+callable. It accepts at most two arguments.
+.Ss BSD Macro
+.Dl Usage: .Bx [Version/release] ... \*(Pu
+.Bl -tag -width ".Bx 4.3 ) ," -compact -offset 14n
+.It Li ".Bx"
+.Bx
+.It Li ".Bx 4.3 ."
+.Bx 4.3 .
+.El
+.Pp
+The
+.Ql \&.Bx
+macro is parsed and is callable.
+.Ss NetBSD Macro
+.Dl Usage: .Nx [Version/release] ... \*(Pu
+.Bl -tag -width ".Nx 1.4 ) ," -compact -offset 14n
+.It Li ".Nx"
+.Nx
+.It Li ".Nx 1.4 ."
+.Nx 1.4 .
+.El
+.Pp
+The
+.Ql \&.Nx
+macro is parsed and is callable.
+.Ss FreeBSD Macro
+.Dl Usage: .Fx [Version/release] ... \*(Pu
+.Bl -tag -width ".Fx 2.2 ) ," -compact -offset 14n
+.It Li ".Fx"
+.Fx
+.It Li ".Fx 2.2 ."
+.Fx 2.2 .
+.El
+.Pp
+The
+.Ql \&.Fx
+macro is parsed and is callable.
+.Ss UNIX Macro
+.Dl Usage: .Ux ... \*(Pu
+.Bl -tag -width ".Ux 4.3 ) ," -compact -offset 14n
+.It Li ".Ux"
+.Ux
+.El
+.Pp
+The
+.Ql \&.Ux
+macro is parsed and is callable.
+.Ss Emphasis Macro
+Text may be stressed or emphasized with the
+.Ql \&.Em
+macro.
+The usual font for emphasis is italic.
+.Pp
+.Dl Usage: .Em argument ... \*(Pu
+.Bl -tag -width ".Em vide infra ) ) ," -compact -offset 14n
+.It Li ".Em does not"
+.Em does not
+.It Li ".Em exceed 1024 ."
+.Em exceed 1024 .
+.It Li ".Em vide infra ) ) ,"
+.Em vide infra ) ) ,
+.El
+.\" .Pp
+.\" The emphasis can be forced across several lines of text by using
+.\" the
+.\" .Ql \&.Bf
+.\" macro discussed in
+.\" .Sx Modes
+.\" under
+.\" .Sx PAGE STRUCTURE DOMAIN .
+.\" .Pp
+.\" .Bf -emphasis
+.\" We are certain the reason most people desire a Harvard MBA
+.\" so they can become to be successful philanthropists. Only
+.\" mathematicians and physicists go to graduate school strictly
+.\" to acquire infinite wealthy and fame. Its that inifinity
+.\" word that does it to them. Ruins them.
+.\" .Ef
+.Pp
+The
+.Ql \&.Em
+macro is parsed and is callable.
+It is an error to call
+.Ql \&.Em
+without arguments.
+.Ss Enclosure and Quoting Macros
+The concept of enclosure is similar to quoting.
+The object being to enclose one or more strings between
+a pair of characters like quotes or parentheses.
+The terms quoting and enclosure are used
+interchangeably throughout this document.
+Most of the
+one line enclosure macros end
+in small letter
+.Ql q
+to give a hint of quoting, but there are a few irregularities.
+For each enclosure macro
+there is also a pair of open and close macros which end
+in small letters
+.Ql o
+and
+.Ql c
+respectively.
+These can be used across one or more lines of text
+and while they have nesting limitations, the one line quote macros
+can be used inside
+of them.
+.Pp
+.ne 5
+.Bd -filled -offset indent
+.Bl -column "quote " "close " "open " "Enclose Stringx(in XX) " XXstringXX
+.Em " Quote Close Open Function Result"
+\&.Aq .Ac .Ao Angle Bracket Enclosure <string>
+\&.Bq .Bc .Bo Bracket Enclosure [string]
+\&.Dq .Dc .Do Double Quote ``string''
+ .Ec .Eo Enclose String (in XX) XXstringXX
+\&.Pq .Pc .Po Parenthesis Enclosure (string)
+\&.Ql Quoted Literal `st' or string
+\&.Qq .Qc .Qo Straight Double Quote "string"
+\&.Sq .Sc .So Single Quote `string'
+.El
+.Ed
+.Pp
+Except for the irregular macros noted below, all
+of the quoting macros are parsed and callable.
+All handle punctuation properly, as long as it
+is presented one character at a time and separated by spaces.
+The quoting macros examine opening and closing punctuation
+to determine whether it comes before or after the
+enclosing string. This makes some nesting possible.
+.Bl -tag -width xxx,xxxx
+.It Li \&.Ec , \&.Eo
+These macros expect the first argument to be the
+opening and closing strings respectively.
+.It Li \&.Ql
+The quoted literal macro behaves differently for
+.Xr troff
+than
+.Xr nroff .
+If formatted with
+.Xr nroff ,
+a quoted literal is always quoted. If formatted with
+troff, an item is only quoted if the width
+of the item is less than three constant width characters.
+This is to make short strings more visible where the font change
+to literal (constant width) is less noticeable.
+.It Li \&.Pf
+The prefix macro is not callable, but it is parsed:
+.Bl -tag -width "(namexx" -offset indent
+.It Li ".Pf ( Fa name2"
+becomes
+.Pf ( Fa name2 .
+.El
+.It Li \&.Ns
+The
+.Ql \&.Ns
+(no space) macro, which
+.Em is
+callable,
+performs the analogous suffix function.
+.It Li ".Ap
+The \&.Ap macro inserts an apostrophe and exits any special text modes,
+continuing in
+.Li \&.No
+mode.
+.El
+.Pp
+.ne 4
+Examples of quoting:
+.Bl -tag -width ".Aq Pa ctype.h ) ,xxxxxxxx" -compact -offset indent
+.It Li \&.Aq
+.Aq
+.It Li \&.Aq \&Ar ctype.h\ )\ ,
+.Aq Ar ctype.h ) ,
+.It Li \&.Bq
+.Bq
+.It Li \&.Bq \&Em Greek \&, French \&.
+.Bq Em Greek , French .
+.It Li \&.Dq
+.Dq
+.It Li ".Dq string abc ."
+.Dq string abc .
+.It Li ".Dq \'^[A-Z]\'"
+.Dq \'^[A-Z]\'
+.It Li "\&.Ql man mdoc"
+.Ql man mdoc
+.It Li \&.Qq
+.Qq
+.It Li "\&.Qq string ) ,"
+.Qq string ) ,
+.It Li "\&.Qq string Ns ),"
+.Qq string Ns ),
+.It Li \&.Sq
+.Sq
+.It Li "\&.Sq string
+.Sq string
+.It Li "\&.Em or Ap ing
+.Em or Ap ing
+.El
+.Pp
+For a good example of nested enclosure macros, see the
+.Ql \&.Op
+option macro.
+It was created from the same
+underlying enclosure macros as those presented in the list
+above.
+The
+.Ql \&.Xo
+and
+.Ql \&.Xc
+extended argument list macros
+were also built from the same underlying routines and are a good
+example of
+.Nm \-mdoc
+macro usage at its worst.
+.Ss No\-Op or Normal Text Macro
+The macro
+.Li \&.No
+is
+a hack for words in a macro command line which should
+.Em not
+be formatted and follows the conventional syntax
+for content macros.
+.Ss No Space Macro
+The
+.Ql \&.Ns
+macro eliminates unwanted spaces in between macro requests.
+It is useful for old style argument lists where there is no space
+between the flag and argument:
+.Bl -tag -width ".Op Fl I Ns Ar directoryxx" -offset indent
+.It Li ".Op Fl I Ns Ar directory"
+produces
+.Op Fl I Ns Ar directory
+.El
+.Pp
+Note: the
+.Ql \&.Ns
+macro always invokes the
+.Ql \&.No
+macro after eliminating the space unless another macro name
+follows it.
+The macro
+.Ql \&.Ns
+is parsed and is callable.
+.Ss Section Cross References
+The
+.Ql \&.Sx
+macro designates a reference to a section header
+within the same document.
+It is parsed and is callable.
+.Pp
+.Bl -tag -width "Li \&.Sx FILES" -offset 14n
+.It Li \&.Sx FILES
+.Sx FILES
+.El
+.Ss Symbolic
+The symbolic emphasis macro is generally a boldface macro in
+either the symbolic sense or the traditional English usage.
+.Pp
+.Dl Usage: .Sy symbol ... \*(Pu
+.Bl -tag -width ".Sy Important Noticex" -compact -offset 14n
+.It Li \&.Sy Important Notice
+.Sy Important Notice
+.El
+.Pp
+The
+.Ql \&.Sy
+macro is parsed and is callable.
+Arguments to
+.Ql \&.Sy
+may be quoted.
+.Ss References and Citations
+The following macros make a modest attempt to handle references.
+At best, the macros make it convenient to manually drop in a subset of
+refer style references.
+.Pp
+.Bl -tag -width 6n -offset indent -compact
+.It Li ".Rs"
+Reference Start.
+Causes a line break and begins collection
+of reference information until the
+reference end macro is read.
+.It Li ".Re"
+Reference End.
+The reference is printed.
+.It Li ".%A"
+Reference author name, one name per invocation.
+.It Li ".%B"
+Book title.
+.It Li ".\&%C"
+City/place.
+.It Li ".\&%D"
+Date.
+.It Li ".%J"
+Journal name.
+.It Li ".%N"
+Issue number.
+.It Li ".%O"
+Optional information.
+.It Li ".%P"
+Page number.
+.It Li ".%R"
+Report name.
+.It Li ".%T"
+Title of article.
+.It Li ".%V"
+Volume(s).
+.El
+.Pp
+The macros beginning with
+.Ql %
+are not callable, and are parsed only for the trade name macro which
+returns to its caller.
+(And not very predictably at the moment either.)
+The purpose is to allow trade names
+to be pretty printed in
+.Xr troff Ns / Ns Xr ditroff
+output.
+.Ss Trade Names (or Acronyms and Type Names)
+The trade name macro is generally a small caps macro for
+all upper case words longer than two characters.
+.Pp
+.Dl Usage: .Tn symbol ... \*(Pu
+.Bl -tag -width ".Tn ASCII" -compact -offset 14n
+.It Li \&.Tn DEC
+.Tn DEC
+.It Li \&.Tn ASCII
+.Tn ASCII
+.El
+.Pp
+The
+.Ql \&.Tn
+macro
+is parsed and is callable by other macros.
+.Ss Extended Arguments
+The
+.Li \&.Xo
+and
+.Li \&.Xc
+macros allow one to extend an argument list
+on a macro boundary.
+Argument lists cannot
+be extended within a macro
+which expects all of its arguments on one line such
+as
+.Ql \&.Op .
+.Pp
+Here is an example of
+.Ql \&.Xo
+using the space mode macro to turn spacing off:
+.Bd -literal -offset indent
+\&.Sm off
+\&.It Xo Sy I Ar operation
+\&.No \een Ar count No \een
+\&.Xc
+\&.Sm on
+.Ed
+.Pp
+Produces
+.Bd -filled -offset indent
+.Bl -tag -width flag -compact
+.Sm off
+.It Xo Sy I Ar operation
+.No \en Ar count No \en
+.Xc
+.Sm on
+.El
+.Ed
+.Pp
+Another one:
+.Bd -literal -offset indent
+\&.Sm off
+\&.It Cm S No \&/ Ar old_pattern Xo
+\&.No \&/ Ar new_pattern
+\&.No \&/ Op Cm g
+\&.Xc
+\&.Sm on
+.Ed
+.Pp
+Produces
+.Bd -filled -offset indent
+.Bl -tag -width flag -compact
+.Sm off
+.It Cm S No \&/ Ar old_pattern Xo
+.No \&/ Ar new_pattern
+.No \&/ Op Cm g
+.Xc
+.Sm on
+.El
+.Ed
+.Pp
+Another example of
+.Ql \&.Xo
+and using enclosure macros:
+Test the value of an variable.
+.Bd -literal -offset indent
+\&.It Xo
+\&.Ic .ifndef
+\&.Oo \e&! Oc Ns Ar variable
+\&.Op Ar operator variable ...
+\&.Xc
+.Ed
+.Pp
+Produces
+.Bd -filled -offset indent
+.Bl -tag -width flag -compact
+.It Xo
+.Ic .ifndef
+.Oo \&! Oc Ns Ar variable
+.Op Ar operator variable ...
+.Xc
+.El
+.Ed
+.Pp
+All of the above examples have used the
+.Ql \&.Xo
+macro on the argument list of the
+.Ql \&.It
+(list-item)
+macro.
+The extend macros are not used very often, and when they are
+it is usually to extend the list-item argument list.
+Unfortunately, this is also where the extend macros are the
+most finicky.
+In the first two examples, spacing was turned off;
+in the third, spacing was desired in part of the output but
+not all of it.
+To make these macros work in this situation make sure
+the
+.Ql \&.Xo
+and
+.Ql \&.Xc
+macros are placed as shown in the third example.
+If the
+.Ql \&.Xo
+macro is not alone on the
+.Ql \&.It
+argument list, spacing will be unpredictable.
+The
+.Ql \&.Ns
+(no space macro)
+must not occur as the first or last macro on a line
+in this situation.
+Out of 900 manual pages (about 1500 actual pages)
+currently released with
+.Bx
+only fifteen use the
+.Ql \&.Xo
+macro.
+.Sh PAGE STRUCTURE DOMAIN
+.Ss Section Headers
+The first three
+.Ql \&.Sh
+section header macros
+list below are required in every
+man page.
+The remaining section headers
+are recommended at the discretion of the author
+writing the manual page.
+The
+.Ql \&.Sh
+macro can take up to nine arguments.
+It is parsed and but is not callable.
+.Bl -tag -width ".Sh SYNOPSIS"
+.It \&.Sh NAME
+The
+.Ql \&.Sh NAME
+macro is mandatory.
+If not specified,
+the headers, footers and page layout defaults
+will not be set and things will be rather unpleasant.
+The
+.Sx NAME
+section consists of at least three items.
+The first is the
+.Ql \&.Nm
+name macro naming the subject of the man page.
+The second is the Name Description macro,
+.Ql \&.Nd ,
+which separates the subject
+name from the third item, which is the description.
+The
+description should be the most terse and lucid possible,
+as the space available is small.
+.It \&.Sh SYNOPSIS
+The
+.Sx SYNOPSIS
+section describes the typical usage of the
+subject of a man page.
+The macros required
+are either
+.Ql ".Nm" ,
+.Ql ".Cd" ,
+.Ql ".Fn" ,
+(and possibly
+.Ql ".Fo" ,
+.Ql ".Fc" ,
+.Ql ".Fd" ,
+.Ql ".Ft"
+macros).
+The function name
+macro
+.Ql ".Fn"
+is required
+for manual page sections 2 and 3, the command and general
+name macro
+.Ql \&.Nm
+is required for sections 1, 5, 6, 7, 8.
+Section 4 manuals require a
+.Ql ".Nm" , ".Fd"
+or a
+.Ql ".Cd"
+configuration device usage macro.
+Several other macros may be necessary to produce
+the synopsis line as shown below:
+.Pp
+.Bd -filled -offset indent
+.Nm cat
+.Op Fl benstuv
+.Op Fl
+.Ar
+.Ed
+.Pp
+The following macros were used:
+.Pp
+.Dl \&.Nm cat
+.Dl \&.Op \&Fl benstuv
+.Dl \&.Op \&Fl
+.Dl \&.Ar
+.Pp
+.Sy Note :
+The macros
+.Ql \&.Op ,
+.Ql \&.Fl ,
+and
+.Ql \&.Ar
+recognize the pipe bar character
+.Ql \*(Ba ,
+so a command line such as:
+.Pp
+.Dl ".Op Fl a | Fl b"
+.Pp
+will not go orbital.
+.Xr Troff
+normally interprets a \*(Ba as a special operator.
+See
+.Sx PREDEFINED STRINGS
+for a usable \*(Ba
+character in other situations.
+.It \&.Sh DESCRIPTION
+In most cases the first text in the
+.Sx DESCRIPTION
+section
+is a brief paragraph on the command, function or file,
+followed by a lexical list of options and respective
+explanations.
+To create such a list, the
+.Ql \&.Bl
+begin-list,
+.Ql \&.It
+list-item and
+.Ql \&.El
+end-list
+macros are used (see
+.Sx Lists and Columns
+below).
+.El
+.Pp
+The following
+.Ql \&.Sh
+section headers are part of the
+preferred manual page layout and must be used appropriately
+to maintain consistency.
+They are listed in the order
+in which they would be used.
+.Bl -tag -width SYNOPSIS
+.It \&.Sh ENVIRONMENT
+The
+.Sx ENVIRONMENT
+section should reveal any related
+environment
+variables and clues to their behavior and/or usage.
+.It \&.Sh EXAMPLES
+There are several ways to create examples.
+See
+the
+.Sx EXAMPLES
+section below
+for details.
+.It \&.Sh FILES
+Files which are used or created by the man page subject
+should be listed via the
+.Ql \&.Pa
+macro in the
+.Sx FILES
+section.
+.It \&.Sh SEE ALSO
+References to other material on the man page topic and
+cross references to other relevant man pages should
+be placed in the
+.Sx SEE ALSO
+section.
+Cross references
+are specified using the
+.Ql \&.Xr
+macro.
+At this time
+.Xr refer 1
+style references are not accommodated.
+.Pp
+It is recommended that the cross references are sorted on the section
+number, and then alphabetically on the names within a section.
+.It \&.Sh STANDARDS
+If the command, library function or file adheres to a
+specific implementation such as
+.St -p1003.2
+or
+.St -ansiC
+this should be noted here.
+If the
+command does not adhere to any standard, its history
+should be noted in the
+.Sx HISTORY
+section.
+.It \&.Sh HISTORY
+Any command which does not adhere to any specific standards
+should be outlined historically in this section.
+.It \&.Sh AUTHORS
+Credits, if need be, should be placed here.
+.It \&.Sh DIAGNOSTICS
+Diagnostics from a command should be placed in this section.
+.It \&.Sh ERRORS
+Specific error handling, especially from library functions
+(man page sections 2 and 3) should go here.
+The
+.Ql \&.Er
+macro is used to specify an errno.
+.It \&.Sh BUGS
+Blatant problems with the topic go here...
+.El
+.Pp
+User specified
+.Ql \&.Sh
+sections may be added,
+for example, this section was set with:
+.Bd -literal -offset 14n
+\&.Sh PAGE LAYOUT MACROS
+.Ed
+.Ss Paragraphs and Line Spacing.
+.Bl -tag -width 6n
+.It \&.Pp
+The \&.Pp paragraph command may
+be used to specify a line space where necessary.
+The macro is not necessary after a
+.Ql \&.Sh
+or
+.Ql \&.Ss
+macro or before
+a
+.Ql \&.Bl
+macro.
+(The
+.Ql \&.Bl
+macro asserts a vertical distance unless the -compact flag is given).
+.El
+.\" This worked with version one, need to redo for version three
+.\" .Pp
+.\" .Ds I
+.\" .Cw (ax+bx+c) \ is\ produced\ by\ \&
+.\" .\".Cw (ax+bx+c) \&.Va_by_) \&_and_\& \&[?/]m_b1_e1_f1[?/]\&
+.\" .Cl Cx \t\t
+.\" .Li \&.Cx\ (
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Va ax
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Sy \+
+.\" .Cx
+.\" .Cl Cx \&(\&
+.\" .Va ax
+.\" .Cx +
+.\" .Va by
+.\" .Cx +
+.\" .Va c )
+.\" .Cx \t
+.\" .Em is produced by
+.\" .Cx \t
+.\" .Li \&.Va by
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Sy \+
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Va c )
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Cx
+.\" .Cx
+.\" .Cw
+.\" .De
+.\" .Pp
+.\" This example shows the same equation in a different format.
+.\" The spaces
+.\" around the
+.\" .Li \&+
+.\" signs were forced with
+.\" .Li \e :
+.\" .Pp
+.\" .Ds I
+.\" .Cw (ax\ +\ bx\ +\ c) \ is\ produced\ by\ \&
+.\" .\".Cw (ax+bx+c) \&.Va_by_) \&_and_\& \&[?/]m_b1_e1_f1[?/]\&
+.\" .Cl Cx \t\t
+.\" .Li \&.Cx\ (
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Va a
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Sy x
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Cx \e\ +\e\ \e&
+.\" .Cx
+.\" .Cl Cx \&(\&
+.\" .Va a
+.\" .Sy x
+.\" .Cx \ +\ \&
+.\" .Va b
+.\" .Sy y
+.\" .Cx \ +\ \&
+.\" .Va c )
+.\" .Cx \t
+.\" .Em is produced by
+.\" .Cl Cx \t\t
+.\" .Li \&.Va b
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Sy y
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Cx \e\ +\e\ \e&
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Va c )
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Cx
+.\" .Cx
+.\" .Cw
+.\" .De
+.\" .Pp
+.\" The incantation below was
+.\" lifted from the
+.\" .Xr adb 1
+.\" manual page:
+.\" .Pp
+.\" .Ds I
+.\" .Cw \&[?/]m_b1_e1_f1[?/]\& is\ produced\ by
+.\" .Cl Cx \t\t
+.\" .Li \&.Cx Op Sy ?/
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Nm m
+.\" .Cx
+.\" .Cl Cx Op Sy ?/
+.\" .Nm m
+.\" .Ad \ b1 e1 f1
+.\" .Op Sy ?/
+.\" .Cx \t
+.\" .Em is produced by
+.\" .Cx \t
+.\" .Li \&.Ar \e\ b1 e1 f1
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Op Sy ?/
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Cx
+.\" .Cx
+.\" .Cw
+.\" .De
+.\" .Pp
+.Ss Keeps
+The only keep that is implemented at this time is for words.
+The macros are
+.Ql \&.Bk
+(begin-keep)
+and
+.Ql \&.Ek
+(end-keep).
+The only option that
+.Ql \&.Bl
+accepts is
+.Fl words
+and is useful for preventing line breaks in the middle of options.
+In the example for the make command line arguments (see
+.Sx What's in a name ) ,
+the keep prevented
+.Xr nroff
+from placing up the
+flag and the argument
+on separate lines.
+(Actually, the option macro used to prevent this from occurring,
+but was dropped when the decision (religious) was made to force
+right justified margins in
+.Xr troff
+as options in general look atrocious when spread across a sparse
+line.
+More work needs to be done with the keep macros, a
+.Fl line
+option needs to be added.)
+.Ss Examples and Displays
+There are six types of displays, a quickie one line indented display
+.Ql \&.D1 ,
+a quickie one line literal display
+.Ql \&.Dl ,
+and block literal, block filled, block unfilled, and block ragged which use
+the
+.Ql \&.Bd
+begin-display
+and
+.Ql \&.Ed
+end-display macros.
+.Pp
+.Bl -tag -width \&.Dlxx
+.It Li \&.D1
+(D-one) Display one line of indented text.
+This macro is parsed, but it is not callable.
+.Pp
+.Dl Fl ldghfstru
+.Pp
+The above was produced by:
+.Li \&.Dl Fl ldghfstru .
+.It Li \&.Dl
+(D-ell)
+Display one line of indented
+.Em literal
+text.
+The
+.Ql \&.Dl
+example macro has been used throughout this
+file.
+It allows
+the indent (display) of one line of text.
+Its default font is set to
+constant width (literal) however
+it is parsed and will recognized other macros.
+It is not callable however.
+.Pp
+.Dl % ls -ldg /usr/local/bin
+.Pp
+The above was produced by
+.Li \&.Dl % ls -ldg /usr/local/bin .
+.It Li \&.Bd
+Begin-display.
+The
+.Ql \&.Bd
+display must be ended with the
+.Ql \&.Ed
+macro.
+Displays may be nested within lists, but may
+.Em not
+contain other displays; this also prohibits nesting
+of .D1 and .Dl one-line displays.
+.Ql \&.Bd
+has the following syntax:
+.Pp
+.Dl ".Bd display-type [-offset offset_value] [-compact]"
+.Pp
+The display-type must be one of the following four types and
+may have an offset specifier for indentation:
+.Ql \&.Bd .
+.Pp
+.Bl -tag -width "file file_name " -compact
+.It Fl ragged
+Fill, but do not adjust the right margin.
+.It Fl unfilled
+Do not fill: display a block of text as typed, the
+right (and left) margin edges are left ragged.
+.It Fl filled
+Display a filled (formatted) block.
+The block of text is formatted (the edges are filled \-
+not left unjustified).
+.It Fl literal
+Display a literal block, useful for source code or
+simple tabbed or spaced text.
+.It Fl file Ar file_name
+The file name following the
+.Fl file
+flag is read and displayed.
+Literal mode is
+asserted and tabs are set at 8 constant width character
+intervals, however any
+.Xr troff/ Ns Nm \-mdoc
+commands in file will be processed.
+.It Fl offset Ar string
+If
+.Fl offset
+is specified with one of the following strings, the string
+is interpreted to indicate the level of indentation for the
+forthcoming block of text:
+.Pp
+.Bl -tag -width "indent-two" -compact
+.It Ar left
+Align block on the current left margin,
+this is the default mode of
+.Ql \&.Bd .
+.It Ar center
+Supposedly center the block.
+At this time
+unfortunately, the block merely gets
+left aligned about an imaginary center margin.
+.It Ar indent
+Indents by one default indent value or tab.
+The default
+indent value is also used for the
+.Ql \&.D1
+display so one is guaranteed the two types of displays
+will line up.
+This indent is normally set to 6n or about two
+thirds of an inch (six constant width characters).
+.It Ar indent-two
+Indents two times the default indent value.
+.It Ar right
+This
+.Em left
+aligns the block about two inches from
+the right side of the page.
+This macro needs
+work and perhaps may never do the right thing by
+.Xr troff .
+.El
+.El
+.It ".Ed"
+End-display.
+.El
+.Ss Tagged Lists and Columns
+There are several types of lists which may be initiated with the
+.Ql ".Bl"
+begin-list macro.
+Items within the list
+are specified with the
+.Ql ".It"
+item macro and
+each list must end with the
+.Ql ".El"
+macro.
+Lists other than
+.Li \-enum
+may be nested within themselves and within displays.
+The use of columns inside of lists or lists inside of columns
+is unproven.
+.Pp
+In addition, several list attributes may be specified such as
+the width of a tag, the list offset, and compactness
+(blank lines between items allowed or disallowed).
+Most of this document has been formatted with a tag style list
+.Pq Fl tag .
+For a change of pace, the list-type used to present the list-types
+is an over-hanging list
+.Pq Fl ohang .
+This type of list is quite popular with
+.Tn TeX
+users, but might look a bit funny after having read many pages of
+tagged lists.
+The following list types are accepted by
+.Ql ".Bl" :
+.Pp
+.Bl -ohang -compact
+.It Fl bullet
+.It Fl dash
+.It Fl enum
+.It Fl hyphen
+.It Fl item
+These five are the simplest types of lists.
+Once the
+.Ql ".Bl"
+macro has been given, items in the list are merely
+indicated by a line consisting solely of the
+.Ql ".It"
+macro.
+For example, the source text for a simple enumerated list
+would look like:
+.Bd -literal -offset indent-two
+\&.Bl -enum -compact
+\&.It
+\&Item one goes here.
+\&.It
+\&And item two here.
+\&.It
+\&Lastly item three goes here.
+\&.El
+.Ed
+.Pp
+The results:
+.Pp
+.Bl -enum -offset indent-two -compact
+.It
+Item one goes here.
+.It
+And item two here.
+.It
+Lastly item three goes here.
+.El
+.Pp
+A simple bullet list construction:
+.Bd -literal -offset indent-two
+\&.Bl -bullet -compact
+\&.It
+\&Bullet one goes here.
+\&.It
+\&Bullet two here.
+\&.El
+.Ed
+.Pp
+Produces:
+.Bl -bullet -offset indent-two -compact
+.It
+Bullet one goes here.
+.It
+Bullet two here.
+.El
+.Pp
+.It Fl tag
+.It Fl diag
+.It Fl hang
+.It Fl ohang
+.It Fl inset
+These list-types collect arguments specified with the
+.Ql \&.It
+macro and create a label which may be
+.Em inset
+into the forthcoming text,
+.Em hanged
+from the forthcoming text,
+.Em overhanged
+from above and not indented or
+.Em tagged .
+This
+list was constructed with the
+.Ql Fl ohang
+list-type.
+The
+.Ql \&.It
+macro is parsed only for the inset, hang
+and tag list-types and is not callable.
+Here is an example of inset labels:
+.Bl -inset -offset indent
+.It Em Tag
+The tagged list (also called a tagged paragraph) is the
+most common type of list used in the Berkeley manuals. Use a
+.Fl width
+attribute as described below.
+.It Em Diag
+Diag lists create section four diagnostic lists
+and are similar to inset lists except callable
+macros are ignored.
+.It Em Hang
+Hanged labels are a matter of taste.
+.It Em Ohang
+Overhanging labels are nice when space is constrained.
+.It Em Inset
+Inset labels are useful for controlling blocks of
+paragraphs and are valuable for converting
+.Nm \-mdoc
+manuals to other formats.
+.El
+.Pp
+Here is the source text which produced the above example:
+.Bd -literal -offset indent
+\&.Bl -inset -offset indent
+\&.It Em Tag
+\&The tagged list (also called a tagged paragraph) is the
+\&most common type of list used in the Berkeley manuals.
+\&.It Em Diag
+\&Diag lists create section four diagnostic lists
+\&and are similar to inset lists except callable
+\&macros are ignored.
+\&.It Em Hang
+\&Hanged labels are a matter of taste.
+\&.It Em Ohang
+\&Overhanging labels are nice when space is constrained.
+\&.It Em Inset
+\&Inset labels are useful for controlling blocks of
+\&paragraphs and are valuable for converting
+\&.Nm \-mdoc
+\&manuals to other formats.
+\&.El
+.Ed
+.Pp
+Here is a hanged list with just one item:
+.Bl -hang -offset indent
+.It Em Hanged
+labels appear similar to tagged lists when the
+label is smaller than the label width.
+.It Em Longer hanged list labels
+blend in to the paragraph unlike
+tagged paragraph labels.
+.El
+.Pp
+And the unformatted text which created it:
+.Bd -literal -offset indent
+\&.Bl -hang -offset indent
+\&.It Em Hanged
+\&labels appear similar to tagged lists when the
+\&label is smaller than the label width.
+\&.It Em Longer hanged list labels
+\&blend in to the paragraph unlike
+\&tagged paragraph labels.
+\&.El
+.Ed
+.Pp
+The tagged list which follows uses a width specifier to control
+the width of the tag.
+.Pp
+.Bl -tag -width "PAGEIN" -compact -offset indent
+.It SL
+sleep time of the process (seconds blocked)
+.It PAGEIN
+number of disk
+.Tn I/O Ns 's
+resulting from references
+by the process to pages not loaded in core.
+.It UID
+numerical user-id of process owner
+.It PPID
+numerical id of parent of process process priority
+(non-positive when in non-interruptible wait)
+.El
+.Pp
+The raw text:
+.Bd -literal -offset indent
+\&.Bl -tag -width "PAGEIN" -compact -offset indent
+\&.It SL
+\&sleep time of the process (seconds blocked)
+\&.It PAGEIN
+\&number of disk
+\&.Tn I/O Ns 's
+\&resulting from references
+\&by the process to pages not loaded in core.
+\&.It UID
+\&numerical user-id of process owner
+\&.It PPID
+\&numerical id of parent of process process priority
+\&(non-positive when in non-interruptible wait)
+\&.El
+.Ed
+.Pp
+Acceptable width specifiers:
+.Bl -tag -width Ar -offset indent
+.It Fl width Ar "\&Fl"
+sets the width to the default width for a flag.
+All callable
+macros have a default width value.
+The
+.Ql \&.Fl ,
+value is presently
+set to ten constant width characters or about five sixth of
+an inch.
+.It Fl width Ar "24n"
+sets the width to 24 constant width characters or about two
+inches.
+The
+.Ql n
+is absolutely necessary for the scaling to work correctly.
+.It Fl width Ar "ENAMETOOLONG"
+sets width to the constant width length of the
+string given.
+.It Fl width Ar "\\*qint mkfifo\\*q"
+again, the width is set to the constant width of the string
+given.
+.El
+.Pp
+If a width is not specified for the tag list type, the first
+time
+.Ql \&.It
+is invoked, an attempt is made to determine an appropriate
+width.
+If the first argument to
+.Ql ".It"
+is a callable macro, the default width for that macro will be used
+as if the macro name had been supplied as the width.
+However,
+if another item in the list is given with a different callable
+macro name, a new and nested list is assumed. This effectively
+means that
+.Fl width
+is required for the tag list type.
+.Pp
+.It Fl column
+This list type generates multiple columns.
+The number of columns and the width of each column is determined by
+the arguments to the
+.Fl column
+list.
+Each
+.Ql ".It"
+argument is parsed to make a row, each column within the
+row is a separate argument separated by a tab or the
+.Ql ".Ta"
+macro.
+.El
+The table:
+.Bl -column "String" "Nroff" "Troff" -offset indent
+.It Sy "String" Ta Sy "Nroff" Ta Sy "Troff"
+.It Li "<=" Ta \&<\&= Ta \*(<=
+.It Li ">=" Ta \&>\&= Ta \*(>=
+.El
+.Pp
+was produced by:
+.Bd -literal -offset indent
+\&.Bl -column "String" "Nroff" "Troff" -offset indent
+\&.It Sy "String" Ta Sy "Nroff" Ta Sy "Troff"
+\&.It Li "<=" Ta \&<\&= Ta \*(<=
+\&.It Li ">=" Ta \&>\&= Ta \*(>=
+\&.El
+.Ed
+.Sh PREDEFINED STRINGS
+The following strings are predefined as may be used by
+preceding with the troff string interpreting sequence
+.Ql \&\e*(xx
+where
+.Em xx
+is the name of the defined string or as
+.Ql \&\e*x
+where
+.Em x
+is the name of the string.
+The interpreting sequence may be used any where in the text.
+.Pp
+.Bl -column "String " "Nroff " "Troff " -offset indent
+.It Sy "String Nroff Troff"
+.It Li "<=" Ta \&<\&= Ta \*(<=
+.It Li ">=" Ta \&>\&= Ta \*(>=
+.It Li "Rq" Ta "''" Ta \*(Rq
+.It Li "Lq" Ta "``" Ta \*(Lq
+.It Li "ua" Ta ^ Ta \*(ua
+.It Li "aa" Ta ' Ta \*(aa
+.It Li "ga" Ta \` Ta \*(ga
+.\" .It Li "sL" Ta ` Ta \*(sL
+.\" .It Li "sR" Ta ' Ta \*(sR
+.It Li "q" Ta \&" Ta \*q
+.It Li "Pi" Ta pi Ta \*(Pi
+.It Li "Ne" Ta != Ta \*(Ne
+.It Li "Le" Ta <= Ta \*(Le
+.It Li "Ge" Ta >= Ta \*(Ge
+.It Li "Lt" Ta < Ta \*(Gt
+.It Li "Gt" Ta > Ta \*(Lt
+.It Li "Pm" Ta +- Ta \*(Pm
+.It Li "If" Ta infinity Ta \*(If
+.It Li "Na" Ta \fINaN\fP Ta \*(Na
+.It Li "Ba" Ta \fR\&|\fP Ta \*(Ba
+.El
+.Pp
+.Sy Note :
+The string named
+.Ql q
+should be written as
+.Ql \e*q
+since it is only one char.
+.Sh DIAGNOSTICS
+The debugging facilities for
+.Nm \-mdoc
+are limited, but can help detect subtle errors such
+as the collision of an argument name with an internal
+register or macro name.
+(A what?)
+A register is an arithmetic storage class for
+.Xr troff
+with a one or two character name.
+All registers internal to
+.Nm \-mdoc
+for
+.Xr troff
+and
+.Xr ditroff
+are two characters and
+of the form <upper_case><lower_case> such as
+.Ql \&Ar ,
+<lower_case><upper_case> as
+.Ql \&aR
+or
+<upper or lower letter><digit> as
+.Ql \&C\&1 .
+And adding to the muddle,
+.Xr troff
+has its own internal registers all of which are either
+two lower case characters or a dot plus a letter or meta-character
+character.
+In one of the introduction examples, it was shown how to
+prevent the interpretation of a macro name with the escape sequence
+.Ql \e& .
+This is sufficient for the internal register names also.
+.Pp
+.\" Every callable macro name has a corresponding register
+.\" of the same name (<upper_case><lower_case>).
+.\" There are also specific registers which have
+.\" been used for stacks and arrays and are listed in the
+.\" .Sx Appendix .
+.\" .Bd -ragged -offset 4n
+.\" [A-Z][a-z] registers corresponding to macro names (example ``Ar'')
+.\" [a-z][A-Z] registers corresponding to macro names (example ``aR'')
+.\" C[0-9] argument types (example C1)
+.\" O[0-9] offset stack (displays)
+.\" h[0-9] horizontal spacing stack (lists)
+.\" o[0-9] offset (stack) (lists)
+.\" t[0-9] tag stack (lists)
+.\" v[0-9] vertical spacing stack (lists)
+.\" w[0-9] width tag/label stack
+.\" .Ed
+.\" .Pp
+If a non-escaped register name is given in the argument list of a request
+unpredictable behavior will occur.
+In general, any time huge portions
+of text do not appear where expected in the output, or small strings
+such as list tags disappear, chances are there is a misunderstanding
+about an argument type in the argument list.
+Your mother never intended for you to remember this evil stuff - so here
+is a way to find out whether or not your arguments are valid: The
+.Ql \&.Db
+(debug)
+macro displays the interpretation of the argument list for most
+macros.
+Macros such as the
+.Ql \&.Pp
+(paragraph)
+macro do not contain debugging information.
+All of the callable macros do,
+and it is strongly advised whenever in doubt,
+turn on the
+.Ql \&.Db
+macro.
+.Pp
+.Dl Usage: \&.Db [on | off]
+.Pp
+An example of a portion of text with
+the debug macro placed above and below an
+artificially created problem (a flag argument
+.Ql \&aC
+which should be
+.Ql \e&aC
+in order to work):
+.Bd -literal -offset indent
+\&.Db on
+\&.Op Fl aC Ar file )
+\&.Db off
+.Ed
+.Pp
+The resulting output:
+.Bd -literal -offset indent
+DEBUGGING ON
+DEBUG(argv) MACRO: `.Op' Line #: 2
+ Argc: 1 Argv: `Fl' Length: 2
+ Space: `' Class: Executable
+ Argc: 2 Argv: `aC' Length: 2
+ Space: `' Class: Executable
+ Argc: 3 Argv: `Ar' Length: 2
+ Space: `' Class: Executable
+ Argc: 4 Argv: `file' Length: 4
+ Space: ` ' Class: String
+ Argc: 5 Argv: `)' Length: 1
+ Space: ` ' Class: Closing Punctuation or suffix
+ MACRO REQUEST: .Op Fl aC Ar file )
+DEBUGGING OFF
+.Ed
+.Pp
+The first line of information tells the name of the calling
+macro, here
+.Ql \&.Op ,
+and the line number it appears on.
+If one or more files are involved
+(especially if text from another file is included) the line number
+may be bogus.
+If there is only one file, it should be accurate.
+The second line gives the argument count, the argument
+.Pq Ql \&Fl
+and its length.
+If the length of an argument is two characters, the
+argument is tested to see if it is executable (unfortunately, any
+register which contains a non-zero value appears executable).
+The third line gives the space allotted for a class, and the
+class type.
+The problem here is the argument aC should not be
+executable.
+The four types of classes are string, executable, closing
+punctuation and opening punctuation.
+The last line shows the entire
+argument list as it was read.
+In this next example, the offending
+.Ql \&aC
+is escaped:
+.Bd -literal -offset indent
+\&.Db on
+\&.Em An escaped \e&aC
+\&.Db off
+.Ed
+.Bd -literal -offset indent
+DEBUGGING ON
+DEBUG(fargv) MACRO: `.Em' Line #: 2
+ Argc: 1 Argv: `An' Length: 2
+ Space: ` ' Class: String
+ Argc: 2 Argv: `escaped' Length: 7
+ Space: ` ' Class: String
+ Argc: 3 Argv: `aC' Length: 2
+ Space: ` ' Class: String
+ MACRO REQUEST: .Em An escaped &aC
+DEBUGGING OFF
+.Ed
+.Pp
+The argument
+.Ql \e&aC
+shows up with the same length of 2 as the
+.Ql \e&
+sequence produces a zero width, but a register
+named
+.Ql \e&aC
+was not found and the type classified as string.
+.Pp
+Other diagnostics consist of usage statements and are self explanatory.
+.Sh GROFF, TROFF AND NROFF
+The
+.Nm \-mdoc
+package does not need compatibility mode with
+.Xr groff .
+.Pp
+The package inhibits page breaks, and the headers and footers
+which normally occur at those breaks with
+.Xr nroff ,
+to make the manual more efficient for viewing on-line.
+At the moment,
+.Xr groff
+with
+.Fl T Ns Ar ascii
+does eject the imaginary remainder of the page at end of file.
+The inhibiting of the page breaks makes
+.Xr nroff Ns 'd
+files unsuitable for hardcopy.
+There is a register named
+.Ql \&cR
+which can be set to zero in the site dependent style file
+.Pa /usr/src/share/tmac/doc-nroff
+to restore the old style behavior.
+.Sh FILES
+.Bl -tag -width /usr/share/misc/mdoc.template -compact
+.It Pa /usr/share/tmac/tmac.doc
+manual macro package
+.It Pa /usr/share/misc/mdoc.template
+template for writing a man page
+.El
+.Sh SEE ALSO
+.Xr mdoc 7 ,
+.Xr man 1 ,
+.Xr troff 1
+.Sh BUGS
+Undesirable hyphenation on the dash of a flag
+argument is not yet resolved, and causes
+occasional mishaps in the
+.Sx DESCRIPTION
+section.
+(line break on the hyphen).
+.Pp
+Predefined strings are not declared in documentation.
+.Pp
+Section 3f has not been added to the header routines.
+.Pp
+.Ql \&.Nm
+font should be changed in
+.Sx NAME
+section.
+.Pp
+.Ql \&.Fn
+needs to have a check to prevent splitting up
+if the line length is too short.
+Occasionally it
+separates the last parenthesis, and sometimes
+looks ridiculous if a line is in fill mode.
+.Pp
+The method used to prevent header and footer page
+breaks (other than the initial header and footer) when using
+nroff occasionally places an unsightly partially filled line (blank)
+at the would be bottom of the page.
+.Pp
+If the outer-most list definition doesn't have a
+.Fl width
+argument, the
+.Ql ".It"
+elements of inner lists may not work (producing a list where
+each successive element
+.Sq walks
+to the right).
+.Pp
+The list and display macros to not do any keeps
+and certainly should be able to.
+.\" Note what happens if the parameter list overlaps a newline
+.\" boundary.
+.\" to make sure a line boundary is crossed:
+.\" .Bd -literal
+.\" \&.Fn struct\e\ dictionarytable\e\ *dictionarylookup struct\e\ dictionarytable\e\ *tab[]
+.\" .Ed
+.\" .Pp
+.\" produces, nudge nudge,
+.\" .Fn struct\ dictionarytable\ *dictionarylookup char\ *h struct\ dictionarytable\ *tab[] ,
+.\" .Fn struct\ dictionarytable\ *dictionarylookup char\ *h struct\ dictionarytable\ *tab[] ,
+.\" nudge
+.\" .Fn struct\ dictionarytable\ *dictionarylookup char\ *h struct\ dictionarytable\ *tab[] .
+.\" .Pp
+.\" If double quotes are used, for example:
+.\" .Bd -literal
+.\" \&.Fn \*qstruct dictionarytable *dictionarylookup\*q \*qchar *h\*q \*qstruct dictionarytable *tab[]\*q
+.\" .Ed
+.\" .Pp
+.\" produces, nudge nudge,
+.\" .Fn "struct dictionarytable *dictionarylookup" "char *h" "struct dictionarytable *tab[]" ,
+.\" nudge
+.\" .Fn "struct dictionarytable *dictionarylookup" "char *h" "struct dictionarytable *tab[]" ,
+.\" nudge
+.\" .Fn "struct dictionarytable *dictionarylookup" "char *h" "struct dictionarytable *tab[]" .
+.\" .Pp
+.\" Not a pretty sight...
+.\" In a paragraph, a long parameter containing unpaddable spaces as
+.\" in the former example will cause
+.\" .Xr troff
+.\" to break the line and spread
+.\" the remaining words out.
+.\" The latter example will adjust nicely to
+.\" justified margins, but may break in between an argument and its
+.\" declaration.
+.\" In
+.\" .Xr nroff
+.\" the right margin adjustment is normally ragged and the problem is
+.\" not as severe.
diff --git a/tmac/groff_me.man b/tmac/groff_me.man
new file mode 100644
index 00000000..49196212
--- /dev/null
+++ b/tmac/groff_me.man
@@ -0,0 +1,274 @@
+.\" Copyright (c) 1980 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms are permitted
+.\" provided that the above copyright notice and this paragraph are
+.\" duplicated in all such forms and that any documentation,
+.\" advertising materials, and other materials related to such
+.\" distribution and use acknowledge that the software was developed
+.\" by the University of California, Berkeley. The name of the
+.\" University may not be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\" @(#)me.7 6.4 (Berkeley) 4/13/90
+.\"
+.\" Modified for groff by jjc@jclark.com
+.hc %
+.TH GROFF_ME @MAN7EXT@ "@MDATE@" "Groff Version @VERSION@"
+.UC 3
+.SH NAME
+groff_me \- troff macros for formatting papers
+.SH SYNOPSIS
+.B "groff \-me"
+[ options ]
+file ...
+.br
+.B "troff \-me"
+[ options ]
+file ...
+.SH DESCRIPTION
+This manual page describes the GNU version of the \-me macros,
+which is part of the groff document formatting system.
+This version can be used with both GNU troff and Unix troff.
+This package of
+.I troff
+macro definitions provides a canned formatting
+facility for tech%nical papers in various formats.
+.PP
+The macro requests are defined below.
+Many
+.I troff
+requests are unsafe in conjunction with
+this package, however, these requests may be used with
+impunity after the first .pp:
+.nf
+.IP
+.ta \w'.sz +n 'u
+\&.bp begin new page
+\&.br break output line here
+\&.sp n insert n spacing lines
+\&.ls n (line spacing) n=1 single, n=2 double space
+\&.na no alignment of right margin
+\&.ce n center next n lines
+\&.ul n underline next n lines
+.fi
+.PP
+Output of the
+.I pic,
+.I eqn,
+.I refer,
+and
+.I tbl
+preprocessors
+is acceptable as input.
+.SH FILES
+@MACRODIR@/tmac.e
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@)
+.br
+\-me Reference Manual, Eric P. Allman
+.br
+Writing Papers with Groff Using \-me
+.tr &.
+.SH REQUESTS
+This list is incomplete;
+see
+.I "The \-me Reference Manual"
+for interesting details.
+.PP
+.ta \w'.eh \'x\'y\'z\' 'u +\w'Initial 'u +\w'Cause 'u
+.br
+.di x
+ \ka
+.br
+.di
+.in \nau
+.ti 0
+Request Initial Cause Explanation
+.ti 0
+ Value Break
+.br
+.in \nau
+.ti 0
+\&.(c - yes Begin centered block
+.ti 0
+\&.(d - no Begin delayed text
+.ti 0
+\&.(f - no Begin footnote
+.ti 0
+\&.(l - yes Begin list
+.ti 0
+\&.(q - yes Begin major quote
+.ti 0
+\&.(x \fIx\fR - no Begin indexed item in index
+.I x
+.ti 0
+\&.(z - no Begin floating keep
+.ti 0
+\&.)c - yes End centered block
+.ti 0
+\&.)d - yes End delayed text
+.ti 0
+\&.)f - yes End footnote
+.ti 0
+\&.)l - yes End list
+.ti 0
+\&.)q - yes End major quote
+.ti 0
+\&.)x - yes End index item
+.ti 0
+\&.)z - yes End floating keep
+.ti 0
+\&.++ \fIm H\fR - no Define paper section.
+.I m
+defines the part of the paper, and can be
+.B C
+(chapter),
+.B A
+(appendix),
+.B P
+(preliminary, e.g., abstract, table of contents, etc.),
+.B B
+(bibliography),
+.B RC
+(chapters renumbered from page one each chapter),
+or
+.B RA
+(appendix renumbered from page one).
+.ti 0
+\&.+c \fIT\fR - yes Begin chapter (or appendix, etc., as
+set by .++).
+.I T
+is the chapter title.
+.ti 0
+\&.1c 1 yes One column format on a new page.
+.ti 0
+\&.2c 1 yes Two column format.
+.ti 0
+\&.EN - yes Space after equation
+produced by
+.I eqn
+or
+.IR neqn .
+.ti 0
+\&.EQ \fIx y\fR - yes Precede equation; break out and
+add space.
+Equation number is
+.IR y .
+The optional argument \fIx\fR
+may be
+.I I
+to indent equation (default),
+.I L
+to left-adjust the equation, or
+.I C
+to center the equation.
+.ti 0
+\&.GE - yes End \fIgremlin\fP picture.
+.ti 0
+\&.GS - yes Begin \fIgremlin\fP picture.
+.ti 0
+\&.PE - yes End \fIpic\fP picture.
+.ti 0
+\&.PS - yes Begin \fIpic\fP picture.
+.ti 0
+\&.TE - yes End table.
+.ti 0
+\&.TH - yes End heading section of table.
+.ti 0
+\&.TS \fIx\fR - yes Begin table; if \fIx\fR is
+.I H
+table has repeated heading.
+.ti 0
+\&.b \fIx\fR no no Print
+.I x
+in boldface; if no argument switch to boldface.
+.ti 0
+\&.ba \fI+n\fR 0 yes Augments the base indent by
+.I n.
+This indent is used to set the indent on regular text
+(like paragraphs).
+.ti 0
+\&.bc no yes Begin new column
+.ti 0
+\&.bi \fIx\fR no no Print
+.I x
+in bold italics (nofill only)
+.ti 0
+\&.bu - yes Begin bulleted paragraph
+.ti 0
+\&.bx \fIx\fR no no Print \fIx\fR in a box (nofill only).
+.ti 0
+\&.ef \fI\'x\'y\'z\'\fR \'\'\'\' no Set even footer to x y z
+.ti 0
+\&.eh \fI\'x\'y\'z\'\fR \'\'\'\' no Set even header to x y z
+.ti 0
+\&.fo \fI\'x\'y\'z\'\fR \'\'\'\' no Set footer to x y z
+.ti 0
+\&.hx - no Suppress headers and footers on next page.
+.ti 0
+\&.he \fI\'x\'y\'z\'\fR \'\'\'\' no Set header to x y z
+.ti 0
+\&.hl - yes Draw a horizontal line
+.ti 0
+\&.i \fIx\fR no no Italicize
+.I x;
+if
+.I x
+missing, italic text follows.
+.ti 0
+\&.ip \fIx y\fR no yes Start indented paragraph,
+with hanging tag
+.IR x .
+Indentation is
+.I y
+ens (default 5).
+.ti 0
+\&.lp yes yes Start left-blocked paragraph.
+.ti 0
+\&.np 1 yes Start numbered paragraph.
+.ti 0
+\&.of \fI\'x\'y\'z\'\fR \'\'\'\' no Set odd footer to x y z
+.ti 0
+\&.oh \fI\'x\'y\'z\'\fR \'\'\'\' no Set odd header to x y z
+.ti 0
+\&.pd - yes Print delayed text.
+.ti 0
+\&.pp no yes Begin paragraph.
+First line indented.
+.ti 0
+\&.r yes no Roman text follows.
+.ti 0
+\&.re - no Reset tabs to default values.
+.ti 0
+\&.sh \fIn x\fR - yes Section head follows,
+font automatically bold.
+.I n
+is level of section,
+.I x
+is title of section.
+.ti 0
+\&.sk no no Leave the next page blank.
+Only one page is remembered ahead.
+.ti 0
+\&.sm \fIx\fR - no Set
+.I x
+in a smaller pointsize.
+.ti 0
+\&.sz \fI+n\fR 10p no Augment the point size by
+.I n
+points.
+.ti 0
+\&.tp no yes Begin title page.
+.ti 0
+\&.u \fIx\fR - no Underline argument (even in \fItroff\fR).
+(Nofill only).
+.ti 0
+\&.uh - yes Like .sh but unnumbered.
+.ti 0
+\&.xp \fIx\fR - no Print index
+.I x.
diff --git a/tmac/groff_ms.man b/tmac/groff_ms.man
new file mode 100644
index 00000000..0e1f64c7
--- /dev/null
+++ b/tmac/groff_ms.man
@@ -0,0 +1,235 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.TH GROFF_MS @MAN7EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+groff_ms \- groff ms macros
+.SH SYNOPSIS
+.B groff
+.B \-m@TMAC_S_PREFIX@s
+[
+.IR options .\|.\|.
+]
+[
+.IR files .\|.\|.
+]
+.SH DESCRIPTION
+This manual page describes the GNU version of the ms macros,
+which is part of the groff document formatting system.
+The groff ms macros are intended to be compatible with the
+documented behaviour of the 4.3
+.SM BSD
+Unix ms macros subject to the following limitations:
+.IP \(bu
+the internals of groff ms are not similar to the internals of Unix ms
+and so documents that depend upon implementation details of Unix ms
+may well not work with groff ms;
+.IP \(bu
+there is no support for typewriter-like devices;
+.IP \(bu
+Berkeley localisms, in particular the
+.B TM
+and
+.B CT
+macros, are not implemented;
+.IP \(bu
+groff ms
+does not provide cut marks;
+.IP \(bu
+multiple line spacing is not allowed
+(use a larger vertical spacing instead);
+.IP \(bu
+groff ms does not work in compatibility mode (eg with the
+.B \-C
+option);
+.IP \(bu
+the error-handling policy of groff ms
+is to detect and report errors,
+rather than silently to ignore them.
+.LP
+The groff ms macros make use of many features of GNU troff
+and therefore cannot be used with any other troff.
+.LP
+Bell Labs localisms are not implemented in either the
+.SM BSD
+ms macros or in the groff ms macros.
+.LP
+Some Unix ms documentation says that the
+.B CW
+and
+.B GW
+number registers can be used to control the column width and
+gutter width respectively.
+This is not the case.
+These number registers are not used in groff ms.
+.LP
+Macros that cause a reset set the indent.
+Macros that change the indent do not increment or decrement
+the indent, but rather set it absolutely.
+This can cause problems for documents that define
+additional macros of their own.
+The solution is to use not the
+.B in
+request but instead the
+.B RS
+and
+.B RE
+macros.
+.LP
+The number register
+.B GS
+is set to 1 by the groff ms macros,
+but is not used by the Unix ms macros.
+It is intended that documents that need to determine whether
+they are being formatted with Unix ms or groff ms make use of this
+number register.
+.LP
+Footnotes are implemented so that they can safely be used within
+keeps and displays.
+Automatically numbered footnotes within floating keeps are
+not recommended.
+It is safe to have another
+.B \e**
+between a
+.B \e**
+and the corresponding
+.BR .FS ;
+it is required only that each
+.B .FS
+occur after the corresponding
+.B \e**
+and that the occurrences of
+.B .FS
+are in the same order as the corresponding occurrences of
+.BR \e** .
+.LP
+The strings
+.B \e*{
+and
+.B \e*}
+can be used to begin and end a superscript.
+.LP
+Some Unix V10 ms features are implemented.
+The
+.BR B ,
+.BR I
+and
+.B BI
+macros can have an optional third argument which will be printed
+in the current font before the first argument.
+There is a macro
+.B CW
+like
+.B B
+that changes to a constant-width font.
+.LP
+The following strings can be redefined to adapt the groff ms macros
+to languages other than English:
+.LP
+.nf
+.ta \w'REFERENCES'u+2n
+String Default Value
+.sp .3v
+REFERENCES References
+ABSTRACT ABSTRACT
+TOC Table of Contents
+MONTH1 January
+MONTH2 February
+MONTH3 March
+MONTH4 April
+MONTH5 May
+MONTH6 June
+MONTH7 July
+MONTH8 August
+MONTH9 September
+MONTH10 October
+MONTH11 November
+MONTH12 December
+.fi
+.LP
+The font family is reset from the string
+.BR FAM ;
+at initialization if this string is undefined it is set to the current
+font family.
+The point size, vertical spacing, and inter-paragraph spacing for footnotes
+are taken from the number registers
+.BR FPS ,
+.BR FVS ,
+and
+.BR FPD ;
+at initialization these are set to
+.BR \en(PS-2 ,
+.BR \en[FPS]+2 ,
+and
+.B \en(PD/2
+respectively; however, if any of these registers has been defined
+before initialization, it will not be set.
+The hyphenation flags (as set by the
+.B .hy
+request) are set from the
+.B HY
+register;
+if this has not been defined at initialization,
+it will be set to 14.
+.LP
+Right-aligned displays are available with
+.B ".DS R"
+and
+.BR .RD .
+.LP
+The following conventions are used for names of macros, strings and
+number registers.
+External names available to documents that use the groff ms
+macros contain only uppercase letters and digits.
+Internally the macros are divided into modules.
+Names used only within one module are of the form
+.IB module * name\fR.
+Names used outside the module in which they are defined are of the form
+.IB module @ name\fR.
+Names associated with a particular environment are of the form
+.IB environment : name;
+these are used only within the
+.B par
+module,
+and
+.I name
+does not have a module prefix.
+Constructed names used to implement arrays are of the form
+.IB array ! index\fR.
+Thus the groff ms macros reserve the following names:
+.IP \(bu
+names containing
+.BR * ;
+.IP \(bu
+names containing
+.BR @ ;
+.IP \(bu
+names containing
+.BR : ;
+.IP \(bu
+names containing only uppercase letters and digits.
+.SH FILES
+.B @MACRODIR@/tmac.@TMAC_S_PREFIX@s
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@),
+.BR @g@tbl (@MAN1EXT@),
+.BR @g@pic (@MAN1EXT@),
+.BR @g@eqn (@MAN1EXT@)
+.br
+.BR ms (@MAN7EXT@)
diff --git a/tmac/groff_msafer.man b/tmac/groff_msafer.man
new file mode 100755
index 00000000..0e0de775
--- /dev/null
+++ b/tmac/groff_msafer.man
@@ -0,0 +1,59 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1999 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.TH GROFF_MSAFER @MAN7EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+groff_msafer \- groff -msafer macros
+.SH SYNOPSIS
+.B groff
+.B \-msafer
+[
+.IR options .\|.\|.
+]
+[
+.IR files .\|.\|.
+]
+.SH DESCRIPTION
+The -msafer macros remove the
+.BR open ,
+.BR opena ,
+.BR pso ,
+.BR sy ,
+and
+.B pi
+requests.
+These macros should be used when processing input from
+an untrustworthy source.
+For maximum safety,
+they should be the first -m option on the command-line.
+Normally they are invoked using the
+.B \-S
+option of groff, which will also pass
+.B @g@pic
+the
+.B \-S
+flag.
+This is now the default; to get the old behaviour, use the
+.B \-U
+flag.
+.SH FILES
+.B @MACRODIR@/tmac.safer
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@),
+.BR @g@pic (@MAN1EXT@)
diff --git a/tmac/man.local b/tmac/man.local
new file mode 100644
index 00000000..7bb8f503
--- /dev/null
+++ b/tmac/man.local
@@ -0,0 +1,2 @@
+.\" This file is loaded after tmac.an.
+.\" Put any local modifications to tmac.an here.
diff --git a/tmac/man.ultrix b/tmac/man.ultrix
new file mode 100644
index 00000000..49d7b256
--- /dev/null
+++ b/tmac/man.ultrix
@@ -0,0 +1,103 @@
+.\" Install this as man.local if you're using Ultrix.
+.\" Ultrix specific additions to groff -man macros.
+.\" Written by James Clark from a specification by Martyn.Johnson@cl.cam.ac.uk.
+.\"
+.\" I1 and I2 are unimplemented.
+.de CT
+<CTRL/\\$1>
+..
+.de CW
+.ft CR
+..
+.de Ds
+.br
+.nf
+.ft R
+..
+.de De
+.ce 0
+.fi
+..
+.de EX
+.br
+.if \\n[.$] .in +(n;\\$1)
+.ft CR
+.nf
+..
+.de EE
+.fi
+.ft R
+.in \\n[an-margin]u
+..
+.de G
+.it 1 an-trap
+.ft H
+.if \\n[.$] \&\\$*
+..
+.de GL
+.it 1 an-trap
+.ft HI
+.if \\n[.$] \&\\$*
+..
+.if n .ig
+.de HB
+.ie \\n[.$] .ft HB
+.el \f[HB]\\$*\fP
+..
+.if t .ig
+.de HB
+.ie \\n[.$] .ul 999
+.el .ul
+\\$*
+..
+.als TB HB
+.de MS
+\&\f[CR]\\$1\fR(\\$2)\\$3
+..
+.de NT
+.br
+.ds an-note Note
+.ce 1
+.if \\n[.$] \{\
+. ie '\\$1'C' \{\
+. ce 99
+. if \\n[.$]>1 .ds an-note \\$2
+. \}
+. el \{\
+. ds an-note \\$1
+. if '\\$2'C' .ce 99
+. \}
+.\}
+.in \\n[an-margin]u+5n
+.ll \\n[LL]u-5n
+.sp .5v>?\n[.V]u
+\&\\*[an-note]
+.sp .5v>?\n[.V]u
+.
+..
+.de NE
+.ll \\n[LL]u
+.in \\n[an-margin]u
+.ce 0
+.sp .5v>?\n[.V]u
+..
+.de PN
+\&\f[CR]\\$1\fP\\$2
+..
+.de Pn
+.ie \\n(.$>1 \&\\$1\f[CR]\\$2\fP\\$3
+.el \&\f[CR]\\$1\fP\\$2
+..
+.de R
+.ft R
+.ul 0
+..
+.de RN
+<RETURN>
+..
+.de VS
+.if '\\$1'4' .mc \[br]
+..
+.de VE
+.mc
+..
diff --git a/tmac/mm.diff b/tmac/mm.diff
new file mode 100755
index 00000000..d6694aa3
--- /dev/null
+++ b/tmac/mm.diff
@@ -0,0 +1,70 @@
+*** tmac.m- Thu Aug 2 14:49:57 1990
+--- tmac.m Thu Aug 2 14:55:40 1990
+***************
+*** 744,749 ****
+ .fi
+ .di >A
+! \!.cs 3 48
+! .if !0\\$1-\\n(:d .if !\\n(:f \\*(}y\\$4\\\\f3\\a\\\\fP\\*(}3
+ .if !0\\$1-\\n(:d .if \\n(:f \\*(}y\\$4\\t\\*(}3
+ .if 0\\$1-\\n(:d \\*(}y\\$4\\*(}3
+--- 744,749 ----
+ .fi
+ .di >A
+! .cs 3 48
+! .if !0\\$1-\\n(:d .if !\\n(:f \\*(}y\\$4\?\f3\?\\a\?\fP\?\\*(}3
+ .if !0\\$1-\\n(:d .if \\n(:f \\*(}y\\$4\\t\\*(}3
+ .if 0\\$1-\\n(:d \\*(}y\\$4\\*(}3
+***************
+*** 750,754 ****
+ .br
+ \!.br
+! \!.cs 3
+ .di
+ .br
+--- 750,754 ----
+ .br
+ \!.br
+! .cs 3
+ .di
+ .br
+***************
+*** 1397,1406 ****
+ .tr ,+
+ .tr |.
+- .ie \\nE \{\
+- |ds\ >8\ \f3\\\\$1+\\\\$2+\\\\$3+\\\\$4+\\\\$5+\\\\$6+\\\\$7+\\\\$8+\\\\$9\fP
+- 'br \}
+- .el \{\
+ |ds\ >8\ \\\\$1+\\\\$2+\\\\$3+\\\\$4+\\\\$5+\\\\$6+\\\\$7+\\\\$8+\\\\$9
+- 'br \}
+ .br
+ \!.br
+--- 1397,1401 ----
+***************
+*** 1407,1410 ****
+--- 1402,1406 ----
+ .tr ,,++||
+ .di
++ .asciify >A
+ \\..
+ .>7 \\*(>1
+***************
+*** 1424,1429 ****
+--- 1420,1427 ----
+ .tr ||++
+ .di
++ .asciify >7
+ .de >A
+ .de >T
++ .if \\nE .ft 3
+ .if \\\\n(.$ \\\\$1
+ .if \\\\n(.$-1 \\\\$2
+***************
+*** 1435,1438 ****
+--- 1433,1437 ----
+ .if \\\\n(.$-7 \\\\$8
+ .if \\\\n(.$-8 \\\\$9
++ .if \\nE .ft
+ \\\\..
+ \\..
diff --git a/tmac/strip.sed b/tmac/strip.sed
new file mode 100644
index 00000000..b309e86f
--- /dev/null
+++ b/tmac/strip.sed
@@ -0,0 +1,2 @@
+/%beginstrip%/,$s/[ ]*\\".*//
+/^\.$/d
diff --git a/tmac/tmac.X b/tmac/tmac.X
new file mode 100755
index 00000000..53dd5963
--- /dev/null
+++ b/tmac/tmac.X
@@ -0,0 +1,46 @@
+.nr _C \n(.C
+.cp 0
+.ftr CW CR
+.ftr C CR
+.ftr CO CI
+.ftr CX CBI
+.ftr H HR
+.ftr HO HI
+.ftr HX HBI
+.ftr NX NBI
+.char \(ru \D'l .5m 0'
+.char \(ul \v'.25m'\D'l .5m 0'\v'-.25m'
+.char \(br \v'.25m'\D'l 0 -1m'\v'.75m'
+.char \(rn \v'-.75m'\D'l .5m 0'\v'.75m'
+.char ~ \v'-.55m'\\s[\\n(.s/2u]\v'.2m'\(ti\v'-.2m'\s0\v'.55m'
+.char ^ \v'-.55m'\\s[\\n(.s/2u]\v'.3m'\(ha\v'-.3m'\s0\v'.55m'
+.if !c\(va .char \(va \o'\(ua\(da'
+.if !c\(em .char \(em --
+.if !c\(en .char \(en \-
+.if !c\(fi .char \(fi fi
+.if !c\(fl .char \(fl fl
+.if !c\(ff .char \(ff ff
+.if !c\(Fi .char \(Fi ffi
+.if !c\(Fl .char \(Fl ffl
+.if !c\(ci .char \(ci \v'-.25m'\h'.05m'\D'c .5m'\h'.05m'\v'.25m'
+.if !c\(sq .char \(sq \h'.05m'\D'l .5m 0'\D'l 0 -.5m'\D'l -.5m 0'\D'l 0 .5m'\h'.55m'
+.if !c\(ga .char \(ga \Z'\v'-.7m'\D'l .22m .18m''\h'.33m'
+.if !c\(dg .char \(dg \Z'\h'.25m'\v'.15m'\D'l 0 -.8m'\v'.2m'\h'-.195m'\
+\D'l .39m 0''\h'.5m'
+.if !c\(dd .char \(dd \Z'\h'.25m'\v'.15m'\D'l 0 -.8m'\v'.2m'\h'-.195m'\
+\D'l .39m 0'\v'.4m'\D'l -.39m 0''\h'.5m'
+.if !c\(lq .char \(lq ``
+.if !c\(rq .char \(rq ''
+.if !c\(Bq .char \(bq ,,
+.if !c\(OE .char \(OE O\h'-.25m'E
+.if !c\(oe .char \(oe o\h'-.14m'e
+.if !c\(ah .char \(ah \v'-.55m'\s[\En[.s]/2u]v\s0\v'.55m'
+.if !c\(ao .char \(ao \v'-.55m'\s[\En[.s]*6u/10u]\D'c .25m'\s0\v'.55m'
+.if !c\(ho .char \(ho \s[\En[.s]/2u]\v'.4m'c\v'-.4m'\s0
+.if !c\(lh .tr \(lh\(lA
+.if !c\(rh .tr \(rh\(rA
+.if !c\(bq .tr \(bq,
+.if !c\(aq .tr \(aq'
+.if '\*(.T'X100' .char \[radicalex] \h'-\w'\(sr'u'\[radicalex]\h'\w'\(sr'u'
+.if !\n(_C .mso tmac.pspic
+.cp \n(_C
diff --git a/tmac/tmac.Xps b/tmac/tmac.Xps
new file mode 100755
index 00000000..92471abb
--- /dev/null
+++ b/tmac/tmac.Xps
@@ -0,0 +1,44 @@
+.do mso tmac.ps
+.nr _C \n(.C
+.cp 0
+.de Xps-char
+.char \\$1 \Z"\X'ps: invis'\\$2\X'ps: endinvis'"\\$1
+..
+.Xps-char \(bu \fS\(bu\fP
+.Xps-char \(em "\v'-.25m'\h'.05m'\D'l .9m 0'\h'.05m'"
+.Xps-char \(aq '
+.Xps-char \(bq ,
+.Xps-char \(Bq ,,
+.Xps-char \(lq ``
+.Xps-char \(rq ''
+.Xps-char \(OE OE
+.Xps-char \(oe oe
+.Xps-char \(Fn \fS\(Fn\fP
+.Xps-char \(vS \o'\(ahS'
+.Xps-char \(vs \o'\(ahs'
+.Xps-char \(vZ \o'\(ahZ'
+.Xps-char \(vz \o'\(ahz'
+.Xps-char \(/L \o'/L'
+.Xps-char \(/l \o'/l'
+.Xps-char \(:Y \o'\(adY'
+.Xps-char \(a" \(sd
+.Xps-char \(a. \v'-.6m'.
+.Xps-char \(ga "\Z'\v'-.7m'\D'l .22m .18m''\h'.33m'"
+.Xps-char \(ab \v'-.55m'\s'\\\\n(.s*6u/10u'u\s0
+.Xps-char \(ah \v'-.55m'\s[\En[.s]/2u]v\s0\v'.55m'
+.Xps-char \(ao "\v'-.55m'\s[\En[.s]*6u/10u]\D'c .25m'\s0\v'.55m'"
+.Xps-char \(ho \s[\En[.s]/2u]\v'.4m'c\v'-.4m'\s0
+.Xps-char \(.i i
+.Xps-char \(fo <
+.Xps-char \(fc >
+.Xps-char \(OK \s'\\\\n(.s*6u/10u'\e\s0/
+.Xps-char \(tm \v'-.3m'\s'\\\\n(.s*6u/10u'TM\s0\v'.3m'
+.Xps-char \(dd "\Z'\h'.25m'\v'.15m'\D'l 0 -.8m'\v'.2m'\h'-.195m'\
+\D'l .39m 0'\v'.4m'\D'l -.39m 0''\h'.5m'"
+.Xps-char \(dg "\Z'\h'.25m'\v'.15m'\D'l 0 -.8m'\v'.2m'\h'-.195m'\
+\D'l .39m 0''\h'.5m'"
+.Xps-char \(en \-
+.Xps-char \(%0 %\s'\\\\n(.s*6u/10u'\fI0\fP\s0
+.Xps-char \(lh \(->
+.Xps-char \(rh \(<-
+.cp \n(_C
diff --git a/tmac/tmac.a4 b/tmac/tmac.a4
new file mode 100755
index 00000000..14a0b4c0
--- /dev/null
+++ b/tmac/tmac.a4
@@ -0,0 +1,3 @@
+.\" Set up groff for A4 paper.
+.pl 29.7c
+.ll 21c-2i
diff --git a/tmac/tmac.an b/tmac/tmac.an
new file mode 100755
index 00000000..efd271eb
--- /dev/null
+++ b/tmac/tmac.an
@@ -0,0 +1,350 @@
+.\"Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+.\" Written by James Clark (jjc@jclark.com)
+.\"
+.\"This file is part of groff.
+.\"
+.\"groff 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.
+.\"
+.\"groff 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 groff; see the file COPYING. If not, write to the Free Software
+.\"Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+.\"
+.\" -rC1 => number pages continuously, rather than start each at 1
+.\" -rD1 => double-sided printing, ie different odd and even page footers
+.\" -rPnnn => number first page nnn
+.\" -rXnnn => number pages after nnn as nnna, nnnb, nnnc, ...
+.\"
+.\" The file man.local is loaded at the end. Put local additions there.
+.\" If you need to add things to TH, use `.am TH'.
+.\"
+.if !\n(.g .ab These man macros work only with groff.
+.nr _C \n(.C
+.cp 0
+.if !rD .nr D 0
+.if !rC .nr C 0
+.if rP .pn 0\nP
+.de set-an-margin
+. nr an-margin \\n[IN]
+..
+.\" .TH title section extra1 extra2 extra3
+.de TH
+.cp 0
+.de an-init \" We have to do it like this to get multiple man pages right.
+.ds an-title "\\$1
+.ds an-section "\\$2
+.ds an-extra1 "\\$3
+.ie \\n[.$]>3 .ds an-extra2 "\\$4
+.el .ds an-extra2 \"Sun Release 4.0
+.ie \\n[.$]>4 .ds an-extra3 "\\$5
+.el .ds an-extra3 \"System Programmer's Manual
+.ds an-init
+\\..
+.DT
+.ie '\*(.T'html' \{\
+. nr IN 1.2i
+.\}
+.el \{\
+. nr IN 7.2n
+.\}
+.nr LL 6.5i
+.PD
+.nr PS 10 \" normal point-size
+.nr SN 3n \" the indentation of sub-sub-headings relative to sub-headings
+.nr an-level 1
+.set-an-margin
+.nr an-prevailing-indent \\n[IN]
+.nr an-tag-sep 1n
+.nr an-no-space-flag 0
+.nr an-break-flag 0
+.nr an-div? 0
+.wh 0 an-header
+.wh -1i an-footer
+.wh -.5i an-p-footer
+.if \\n[nl]>0 \{\
+. ie \\nC .bp \\n%+1
+. el .bp 1
+.\}
+..
+.de DT
+.ta T .5i \" This sets tabs every .5 inches
+..
+.de PD
+.ie \\n[.$] .nr PD (v;\\$1)
+.el .nr PD .4v>?\n[.V]
+..
+.de an-header
+.an-init
+.ev 1
+.ie '\*(.T'html' \{\
+. tl ''''
+.\}
+.el \{\
+. sp .5i
+. tl '\\*[an-title](\\*[an-section])'\\*[an-extra3]'\\*[an-title](\\*[an-section])'
+. sp |1i
+.\}
+.ev
+.ns
+..
+.de an-footer
+'bp
+..
+.af an-page-letter a
+.de an-p-footer
+.ev 1
+.ie '\*(.T'html' \{\
+. ds an-page-string "
+. ds an-extra1 "
+. ds an-extra2 "
+.\}
+.el .ds an-page-string \\n%
+.if rX \{\
+. if \\n%>\\nX \{\
+. nr an-page-letter \\n%-\\nX
+. ds an-page-string \\nX\\n[an-page-letter]
+.\}\}
+.ie \\nD \{\
+. if o .tl '\\*[an-extra2]'\\*[an-extra1]'\\*[an-page-string]'
+. if e .tl '\\*[an-page-string]'\\*[an-extra1]'\\*[an-extra2]'
+.\}
+.el .tl '\\*[an-extra2]'\\*[an-extra1]'\\*[an-page-string]'
+.if '\*(.T'html' \{\
+. tl ''''
+.\}
+.ev
+..
+.de SH
+.sp \\n[PD]u
+.nr an-level 1
+.set-an-margin
+.nr an-prevailing-indent \\n[IN]
+.fi
+.in \\n[an-margin]u
+.ti 0
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.ps \\n[PS]-1
+.ft B
+.ne 2v+1u
+.if \\n[.$] \&\\$*
+..
+.de SS
+.sp \\n[PD]u
+.nr an-level 1
+.set-an-margin
+.nr an-prevailing-indent \\n[IN]
+.fi
+.in \\n[IN]u
+.ti \\n[SN]u
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.ps \\n[PS]
+.ft B
+.ne 2v+1u
+.if \\n[.$] \&\\$*
+..
+.de B
+.it 1 an-trap
+.ft B
+.if \\n[.$] \&\\$*
+..
+.de I
+.it 1 an-trap
+.ft I
+.if \\n[.$] \&\\$*
+..
+.de SM
+.it 1 an-trap
+.ps -1
+.if \\n[.$] \&\\$*
+..
+.de SB
+.it 1 an-trap
+.ps -1
+.ft B
+.if \\n[.$] \&\\$*
+..
+.de TP
+.sp \\n[PD]u
+.if \\n[.$] .nr an-prevailing-indent (n;\\$1)
+.it 1 an-trap
+.if !\\n[an-div?] .di an-div
+.in 0
+.nr an-div? 1
+..
+.de an-trap
+.ft R
+.ps \\n[PS]
+.if \\n[an-break-flag] \{\
+. br
+. nr an-break-flag 0
+.\}
+.if \\n[an-no-space-flag] \{\
+. ns
+. nr an-no-space-flag 0
+.\}
+.if \\n[an-div?] .an-do-tag
+..
+.de an-do-tag
+.nr an-div? 0
+.br
+.di
+.ie \\n[dl]+\\n[an-tag-sep]>\\n[an-prevailing-indent] \{\
+. in \\n[an-margin]u
+. ne 2v+1u
+. an-div
+. br
+. in \\n[an-margin]u+\\n[an-prevailing-indent]u
+.\}
+.el \{\
+. in \\n[an-margin]u+\\n[an-prevailing-indent]u
+. ti -\\n[an-prevailing-indent]u
+. chop an-div
+. ne 1v+1u
+\\*[an-div]\\h'|\\n[an-prevailing-indent]u'\c
+.\}
+..
+.de LP
+.br
+.sp \\n[PD]u
+.ps \\n[PS]
+.ft R
+.in \\n[an-margin]u
+.nr an-prevailing-indent \\n[IN]
+..
+.als PP LP
+.als P LP
+.de IP
+.ie !\\n[.$] \{\
+. ps \\n[PS]
+. ft R
+. sp \\n[PD]u
+. ne 1v+1u
+. in \\n[an-margin]u+\\n[an-prevailing-indent]u
+.\}
+.el \{\
+. ie \\n[.$]-1 .TP "\\$2"
+. el .TP
+\&\\$1
+.\}
+..
+.de HP
+.ps \\n[PS]
+.ft R
+.sp \\n[PD]u
+.ne 1v+1u
+.if \\n[.$] .nr an-prevailing-indent (n;\\$1)
+.in \\n[an-margin]u+\\n[an-prevailing-indent]u
+.ti \\n[an-margin]u
+..
+.ds an-empty \" this is referenced to avoid looping on eg .RB ( \\ )
+.de RI
+.if \\n[.$] \{\
+. ds an-result \&\\$1
+. shift
+. while \\n[.$]>=2 \{\
+. as an-result \,\fI\\$1\fR\/\\$2\\*[an-empty]
+. shift 2
+. \}
+. if \\n[.$] .as an-result \,\fI\\$1\fR
+\\*[an-result]
+.\}
+..
+.de IR
+.if \\n[.$] \{\
+. ds an-result \&\fI\\$1\fR
+. shift
+. while \\n[.$]>=2 \{\
+. as an-result \/\\$1\fI\,\\$2\fR
+. shift 2
+. \}
+. if \\n[.$] .as an-result \/\\$1
+\\*[an-result]
+.\}
+..
+.de IB
+.if \\n[.$] \{\
+. ds an-result \&\fI\\$1
+. shift
+. while \\n[.$]>=2 \{\
+. as an-result \/\\fB\\$1\fI\,\\$2\\*[an-empty]
+. shift 2
+. \}
+. if \\n[.$] .as an-result \/\\fB\\$1
+\\*[an-result]
+. ft R
+.\}
+..
+.de BI
+.if \\n[.$] \{\
+. ds an-result \&\fB\\$1
+. shift
+. while \\n[.$]>=2 \{\
+. as an-result \,\fI\\$1\fB\/\\$2\\*[an-empty]
+. shift 2
+. \}
+. if \\n[.$] .as an-result \,\fI\\$1
+\\*[an-result]
+. ft R
+.\}
+..
+.de RB
+.ds an-result \&
+.while \\n[.$]>=2 \{\
+. as an-result \fR\\$1\fB\\$2\\*[an-empty]
+. shift 2
+.\}
+.if \\n[.$] .as an-result \fR\\$1
+\\*[an-result]
+.ft R
+..
+.de BR
+.ds an-result \&
+.while \\n[.$]>=2 \{\
+. as an-result \fB\\$1\fR\\$2\\*[an-empty]
+. shift 2
+.\}
+.if \\n[.$] .as an-result \fB\\$1
+\\*[an-result]
+.ft R
+..
+.de RS
+.br
+.nr an-saved-margin\\n[an-level] \\n[an-margin]
+.nr an-saved-prevailing-indent\\n[an-level] \\n[an-prevailing-indent]
+.ie \\n[.$] .nr an-margin +(n;\\$1)
+.el .nr an-margin +\\n[an-prevailing-indent]
+.in \\n[an-margin]u
+.nr an-prevailing-indent \\n[IN]
+.nr an-level +1
+..
+.de RE
+.br
+.ie \\n[.$] .nr an-level (;\\$1)<?\\n[an-level]
+.el .nr an-level -1
+.nr an-level 1>?\\n[an-level]
+.nr an-margin \\n[an-saved-margin\\n[an-level]]
+.nr an-prevailing-indent \\n[an-saved-prevailing-indent\\n[an-level]]
+.in \\n[an-margin]u
+..
+.ds S \s[\\n[PS]]
+.ie c\[rg] .ds R \[rg]
+.el .ds R (Reg.)
+.ie c\[tm] .ds Tm \[tm]
+.el .ds Tm (TM)
+.ds lq \(lq
+.ds rq \(rq
+.hy 14
+.\" Load local modifications.
+.mso man.local
+.cp \n(_C
diff --git a/tmac/tmac.andoc b/tmac/tmac.andoc
new file mode 100755
index 00000000..8cf989c0
--- /dev/null
+++ b/tmac/tmac.andoc
@@ -0,0 +1,12 @@
+.\" Load either tmac.an or tmac.doc.
+.if !\n(.g .ab These macros require groff.
+.de Dd
+.rm Dd
+.do mso tmac.doc
+\\*(Dd\\
+..
+.de TH
+.rm TH
+.do mso tmac.an
+\\*(TH\\
+..
diff --git a/tmac/tmac.arkup b/tmac/tmac.arkup
new file mode 100755
index 00000000..ea3113d1
--- /dev/null
+++ b/tmac/tmac.arkup
@@ -0,0 +1,161 @@
+.\"
+.\" A simple set of macros to provide HTML documents with basic
+.\" www functionality. It will work with any macro set.
+.\"
+.de HTML
+. if '\*(.T'html' \{\
+.\" the following line makes the vertical mode leave, so to say
+\&
+\X^html:\\$*^
+. \}
+..
+.de HTMLINDEX
+. if '\*(.T'html' \X^index:\\$*^
+..
+.\"
+.\" BODYCOLOR - $1 is foreground color
+.\" $2 is background color
+.\" $3 is the color of an active hypertext link
+.\" $4 is the color of a hypertext link not yet visited
+.\" $5 is the color of a visited hypertext link
+.\"
+.de BODYCOLOR
+. HTML <body text=\\$1 bgcolor=\\$2 link=\\$3 alink=\\$4 vlink=\\$5>
+..
+.\"
+.\" BACKGROUND - $1 is the background image file
+.\"
+.de BACKGROUND
+. HTML <body background=\\$1>
+..
+.\"
+.\" URL - $1 is the classical underlined blue text
+.\" $2 is the url
+.\" $3 is optional stuff printed immediately after $3
+.\"
+.de URL
+. ie '\*(.T'html' \{\
+. HTML <a href="\\$2">\\$1</a>\\$3
+. \}
+. el \{\
+\\$1 \(la\fC\\$2\fP\(ra\\$3
+. \}
+..
+.\"
+.\" FTP - $1 is the classical underlined blue text
+.\" $2 is the ftp url
+.\" $3 is optional stuff printed immediately after $2
+.de FTP
+. ie '\*(.T'html' \{\
+. HTML <a href=\\$2>\\$1</a>\\$3
+. \}
+. el \{\
+\\$1 \(la\fC\\$2\fP\(ra\\$3
+. \}
+..
+.\"
+.\" MAILTO - generate html email reference
+.\" $1 is the email address (without the `mailto:' prefix)
+.\" $2 is the optional name
+.\" $3 is optional stuff printed immediately after $2 (resp. $1)
+.\"
+.\" example:
+.\"
+.\" Foobar has been written by
+.\" .MAILTO fred@foo.bar "Fredrick Bloggs" .
+.\"
+.de MAILTO
+.\"
+.\" force reset after a potential heading by performing some motion..
+.\" how do we do this --fixme--
+.\" \h'\w' ''\h'-\w' '' doesn't work..
+. ie '\*(.T'html' \{\
+. ie '\\$2'' \{\
+. HTML "<a href=mailto:\\$1>\\$1</a>\\$3"
+. \}
+. el \{\
+. HTML "<a href=mailto:\\$1>\\$2</a>\\$3"
+. \}
+. \}
+. el \{\
+. ie '\\$2'' \{\
+\fC\\$1\fP\\$3
+. \}
+. el \{\
+\\$2 \(la\fC\\$1\fP\(ra\\$3
+. \}
+. \}
+..
+.\"
+.\" TAG - generate an html name $1
+.\"
+.de TAG
+. HTML <a name="\\$1"></a>
+..
+.\"
+.\" IMAGE - reference an image
+.\" $1 is the image file
+.\" $2 is the x width (default if absent 400 pixels)
+.\" $3 is the y width (default if absent is the x value)
+.\"
+.de IMAGE
+. ie '\*(.T'html' \{\
+. nr HTMLWIDTH 400
+. if '\\$2'' \{\
+. nr HTMLWIDTH \\$2
+. \}
+. nr HTMLHEIGHT \\n[HTMLWIDTH]
+. if '\\$3'' \{\
+. nr HTMLHEIGHT \\$3
+. \}
+. HTML <img src="\\$1" width=\\n[HTMLWIDTH height=\\n[HTMLHEIGHT]>
+. \}
+. el \{\
+. B1
+\(la\fC\\$1\fP\(ra
+. B2
+. \}
+..
+.\"
+.\" CDFTP - if we are processing this on machine \\$1 then we create a
+.\" FTP reference using \\$2 --> \\$3
+.\"
+.\" otherwise we create a URL from \\$2 --> \\$4
+.\"
+.\" example:
+.\"
+.\" .CDFTP "foobar" "somegnusoftware.tar.gz" \
+.\" "ftp://ftp.gnu.org/gnu/somegnusoftware.tar.gz" \
+.\" "../../../TARGZ/somegnusoftware.tar.gz"
+.\"
+.\" meaning if we are on machine foobar then generate an ftp url
+.\" to the GNU anonymous ftp server otherwise generate a file url
+.\" to a local copy (cdrom maybe)
+.\"
+.\" Useful when one machine is designated as a cdrom burner and another
+.\" designated as an appache server.
+.\" The same source for web pages can be burnt onto a CD and also
+.\" served across the network. It doesn't solve the problem of one
+.\" machine doing both though :-(
+.\"
+.\"
+.\".de CDFTP
+.\". sy /bin/rm -f /tmp/tmac.n
+.\". sy /bin/echo ".ds HOSTNAME `hostname --short`" > /tmp/tmac.n
+.\". so /tmp/tmac.n
+.\". sy /bin/rm -f /tmp/tmac.n
+.\". ie '\\*[HOSTNAME]'\\$1' \{\
+.\". FTP "\\$2" "\\$3"
+.\". \}
+.\". el \{\
+.\". URL "\\$2" "\\$4"
+.\". \}
+.\"..
+.de LINE
+. HTML <hr>
+..
+.\"
+.\" it doesn't make sense to use hyphenation with html, so we turn it off.
+.\"
+.hy 0
+.nr HY 0
diff --git a/tmac/tmac.doc b/tmac/tmac.doc
new file mode 100755
index 00000000..e575df7c
--- /dev/null
+++ b/tmac/tmac.doc
@@ -0,0 +1,3427 @@
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. 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.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+.\"
+.\" @(#)doc 5.8 (Berkeley) 8/5/91
+.\" Modified by jjc@jclark.com as follows: the doc-* files are assumed to be
+.\" installed as mdoc/doc-* rather than tmac.doc-* (the filename
+.\" `tmac.doc-common' would be too long); when using groff, the doc-* files
+.\" are loaded using the `mso' request.
+.\"
+.\" .mdoc-parse - attempt to parse troff request arguments
+.\" %beginstrip%
+.if \n(.g \{\
+.cp 0
+.ftr C CR
+.\}
+.if \n(.g .ig
+.de sO
+.so /usr/share/tmac/\\$1
+..
+.if !\n(.g .ig
+.de sO
+.mso mdoc/\\$1
+..
+.if t \{\
+. sO doc-ditroff
+.\}
+.if n \{\
+. sO doc-nroff
+.\}
+.sO doc-common
+.sO doc-syms
+.\" NS Db macro - start/stop DEBUG MODE
+.\" NS Db register DEBUG MODE
+.\" NS iN register DEBUG MODE (inline if 1, to stderr if 0 (default))
+.nr Db 0
+.de Db
+.ie \\n(.$==0 \{\
+. ie \\n(Db==0 \{\
+.tm DEBUGGING ON
+. nr Db 1
+. \}
+. el \{\
+.tm DEBUGGING OFF
+. nr Db 0
+. \}
+.\}
+.el \{\
+. if "\\$1"on" \{\
+.tm DEBUGGING ON
+. nr Db 1
+. \}
+. if "\\$1"off" \{\
+.tm DEBUGGING OFF
+. nr Db 0
+. \}
+.\}
+..
+.\" NS aV macro - parse argument vector (recursive) (.aV arg ... )
+.\" NS fV macro - parse argument vector (recursive) (.fV)
+.\" NS aC register argument counter (aV/fV)
+.\" NS fV register argument counter (must set to \\n(.$ prior to reuqest) (fV)
+.\" NS A[0-9] argument vector (aV/fV)
+.\" NS C[0-9] reg. arg type(1=macro, 2=arg, 3=punct-suf, 4=punct-pre) (aV/fV)
+.\" NS S[0-9] space vector (sV)
+.\" NS aP register argument pointer (aV)
+.\" NS yU local string used for debugging
+.\" NS iI local register (indent for inline debug mode)
+.\" NS mN name of calling request (set in each user requestable macro)
+.de aV
+.nr aC \\n(aC+1
+.ie "\\$1"|" \{\
+. if "\\*(mN"Op" .ds A\\n(aC \fR\\$1\fP
+. if "\\*(mN"Ar" .ds A\\n(aC \fR\\$1\fP
+. if "\\*(mN"Fl" .ds A\\n(aC \fR\\$1\fP
+. if "\\*(mN"Cm" .ds A\\n(aC \fR\\$1\fP
+. if "\\*(mN"It" .ds A\\n(aC \fR\\$1\fP
+.\}
+.el .ds A\\n(aC \\$1
+.aU \\n(aC
+.nr C\\n(aC \\n(aT
+.s\\n(aT
+.if \\n(Db \{\
+. if \\n(aT==1 .ds yU Executable
+. if \\n(aT==2 .ds yU String
+. if \\n(aT==3 .ds yU Closing Punctuation or suffix
+. if \\n(aT==4 .ds yU Opening Punctuation or prefix
+. if \\n(iN==1 \{\
+. br
+. nr iI \\n(.iu
+. in -\\n(iIu
+. if \\n(aC==1 \{\
+\&\fBDEBUG(argv) MACRO:\fP `.\\*(mN' \fBLine #:\fP \\n(.c
+. \}
+\&\t\fBArgc:\fP \\n(aC \fBArgv:\fP `\\*(A\\n(aC' \fBLength:\fP \\n(sW
+\&\t\fBSpace:\fP `\\*(S\\n(aC' \fBClass:\fP \\*(yU
+. \}
+. if \\n(iN==0 \{\
+. if \\n(aC==1 \{\
+. tm DEBUG(argv) MACRO: `.\\*(mN' Line #: \\n(.c
+. \}
+. tm \tArgc: \\n(aC Argv: `\\*(A\\n(aC' Length: \\n(sW
+. tm \tSpace: `\\*(S\\n(aC' Class: \\*(yU
+. \}
+.\}
+.ie \\n(.$==1 \{\
+. nr aP 0
+. ie \\n(dZ==1 \{\
+. if \\n(oM>1 .as b1 \\*(S0
+. \}
+. el \{\
+. if \\n(oM>0 \{\
+. if \\n(fC==0 .as b1 \\*(S0
+. \}
+. \}
+. ds S0 \\*(S\\n(aC
+. if \\n(Db \{\
+. if \\n(iN==1 \{\
+\&MACRO REQUEST: \t.\\*(mN \\*(A1 \\*(A2 \\*(A3 \\*(A4 \\*(A5 \\*(A6 \\*(A7 \\*(A8 \\*(A9
+. br
+. in \\n(iIu
+. \}
+. if \\n(iN==0 \{\
+.tm \tMACRO REQUEST: .\\*(mN \\*(A1 \\*(A2 \\*(A3 \\*(A4 \\*(A5 \\*(A6 \\*(A7 \\*(A8 \\*(A9
+. \}
+. \}
+.\}
+.el .aV \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de fV
+.nr aC \\n(aC+1
+.if "\\*(A\\n(aC"|" \{\
+. if "\\*(mN"Op" .ds A\\n(aC \fR\\*(A\\n(aC\fP
+. if "\\*(mN"Ar" .ds A\\n(aC \fR\\*(A\\n(aC\fP
+. if "\\*(mN"Fl" .ds A\\n(aC \fR\&\\*(A\\n(aC\fP
+. if "\\*(mN"Cm" .ds A\\n(aC \fR\\*(A\\n(aC\fP
+. if "\\*(mN"It" .ds A\\n(aC \fR\\*(A\\n(aC\fP
+.\}
+.aU \\n(aC
+.nr C\\n(aC \\n(aT
+.s\\n(aT
+.if \\n(Db \{\
+. if \\n(aT==1 .ds yU Executable
+. if \\n(aT==2 .ds yU String
+. if \\n(aT==3 .ds yU Closing Punctuation or suffix
+. if \\n(aT==4 .ds yU Opening Punctuation or prefix
+. if \\n(iN==1 \{\
+. br
+. nr iI \\n(.iu
+. in -\\n(iIu
+. if \\n(aC==1 \{\
+\&\fBDEBUG(fargv) MACRO:\fP `.\\*(mN' \fBLine #:\fP \\n(.c
+. \}
+\&\t\fBArgc:\fP \\n(aC \fBArgv:\fP `\\*(A\\n(aC' \fBLength:\fP \\n(sW
+\&\t\fBSpace:\fP `\\*(S\\n(aC' \fBClass:\fP \\*(yU
+. \}
+. if \\n(iN==0 \{\
+. if \\n(aC==1 \{\
+. tm DEBUG(fargv) MACRO: `.\\*(mN' Line #: \\n(.c
+. \}
+. tm \tArgc: \\n(aC Argv: `\\*(A\\n(aC' Length: \\n(sW
+. tm \tSpace: `\\*(S\\n(aC' Class: \\*(yU
+. \}
+.\}
+.ie \\n(fV==1 \{\
+. nr aP 0
+. ie \\n(dZ==1 \{\
+. if \\n(oM>1 .as b1 \\*(S0
+. \}
+. el \{\
+. if \\n(oM>0 \{\
+. if \\n(fC==0 .as b1 \\*(S0
+. \}
+. \}
+. ds S0 \\*(S\\n(aC
+. nr fV 0
+. if \\n(Db \{\
+. ie \\n(iN \{\
+\&\tMACRO REQUEST: .\\*(mN \\*(A1 \\*(A2 \\*(A3 \\*(A4 \\*(A5 \\*(A6 \\*(A7 \\*(A8 \\*(A9
+. br
+. in \\n(iIu
+. \}
+. el \{\
+.tm \tMACRO REQUEST: .\\*(mN \\*(A1 \\*(A2 \\*(A3 \\*(A4 \\*(A5 \\*(A6 \\*(A7 \\*(A8 \\*(A9
+. \}
+. \}
+.\}
+.el \{\
+. nr fV \\n(fV-1
+. fV
+.\}
+..
+.\" NS aX macro - stuff saved strings into `b1' (used by -diag list)
+.de aX
+.nr aP \\n(aP+1
+.as b1 \&\\*(A\\n(aP
+.ie \\n(fV==1 \{\
+. nr aP 0
+. nr fV 0
+.\}
+.el \{\
+. as b1 \&\\*(sV
+. nr fV \\n(fV-1
+. aX
+.\}
+..
+.\" NS aI macro - append arg to arg vector: .aI [arg] [type] (used by .En only)
+.de aI
+.ie \\n(aC<9 \{\
+. nr aC \\n(aC+1
+. ds A\\n(aC \\$1
+. nr C\\n(aC \\$2
+. s\\$2
+. ds xV S\\n(aC
+.\}
+.el \{\
+. tm Usage: Too many arguments (maximum of 8 accepted) (#\\n(.c)
+. tm \\*(A1 \\*(A2 \\*(A3 \\*(A4 \\*(A5 \\*(A6 \\*(A7 \\*(A8 \\*(A9
+.\}
+..
+.\"
+.\" NS aZ macro - print buffer (pB) and clean up arg vectors (aY)
+.de aZ
+.pB
+.aY
+..
+.\" NS aY macro - clean up arg vector
+.de aY
+.rm C0 C1 C2 C3 C4 C5 C6 C7 C8 C9
+.rm A0 A1 A2 A3 A4 A5 A6 A7 A8 A9
+.rm S1 S2 S3 S4 S5 S6 S7 S8 S9
+.nr aC 0
+.nr aP 0
+..
+.\" NS pB macro - test for end of vector (eol) (print b1 buffer or divert)
+.de pB
+.ie \\n(dZ==1 \{\
+. if \\n(oM==1 \{\&\\*(b1
+. rm S0
+. ds b1
+. \}
+. if \\n(oM==0 \{\
+. x2
+. \}
+.\}
+.el \{\
+. ie \\n(oM==0 \{\&\\*(b1
+. rm S0
+. ds b1
+. \}
+. el \{\
+. if ((\\n(sM==1)&(\\n(tP==0)) \{\
+. x1
+. \}
+. \}
+.\}
+.hy
+..
+.\" NS x1 macro - save buffer and divert if tP flag set
+.\" NS eB diversion string
+.\" NS b2 string save of buffer
+.\" NS lK register count of lines read from input file
+.de x1
+.nr dZ \\n(dZ+1
+.ds b2 \\*(b1
+.ds b1
+.nr lK \\n(.c
+.ev 2
+.fi
+.di eB
+..
+.\"
+.\" NS x2 macro - end diversion and print
+.\" NS b0 string local temporary
+.de x2
+.br
+.di
+.ev
+.ie (\\n(.c-\\n(lK>1) \{\
+. ds b0 \&\\*(eB\\
+. ds b1 \\*(b2\\*(b0\\*(b1
+.\}
+.el .ds b1 \\*(b2\\*(b1
+\&\\*(b1
+.rm eB b2 b0 b1
+.nr dZ \\n(dZ-1
+..
+.\" NS Fl macro - flags (appends - and prints flags)
+.\" NS cF register save current font
+.\" NS cZ register save current font size
+.de Fl
+.as b1 \&\\*(fL
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 \{\
+. as b1 \&\|\-\|\fP\s0
+. pB
+. \}
+. el \{\
+. ds mN Fl
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>0 \{\
+. ie (\\n(aC-\\n(aP)==0 \{\
+. as b1 \&\|\-\fP\s0
+. aZ
+. \}
+. el \{\
+. nr aP \\n(aP+1
+. ie \\n(C\\n(aP==1 \{\
+. as b1 \&\|\-\fP\s0
+. \\*(A\\n(aP
+. \}
+. el \{\
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. if \\n(C\\n(aP==3 \{\
+. as b1 \&\|\-\|
+. \}
+. fR
+. \}
+. \}
+.\}
+..
+.\"
+.\" NS fR macro - Fl flag recursion routine (special handling)
+.\" NS jM local register
+.\" NS jN local register
+.\"
+.de fR
+.hy 0
+.nr jM \\n(C\\n(aP
+.ie \\n(jM==1 \{\
+. as b1 \&\fP\s0
+. \\*(A\\n(aP
+.\}
+.el \{\
+. nr jN \\n(aP
+. ie \\n(jM==2 \{\
+. ie !"\\*(A\\n(aP"\\*(Ba" \{\
+. ie !"\\*(A\\n(aP"\fR|\fP" \{\
+. ie "\\*(A\\n(aP"-" .as b1 \&\|\-\^\-\|
+. el .as b1 \&\|\-\\*(A\\n(aP
+. \}
+. el .as b1 \&\\*(A\\n(aP
+. \}
+. el .as b1 \&\\*(A\\n(aP
+. \}
+. el .as b1 \&\f\\n(cF\s\\n(cZ\\*(A\\n(aP\fP\s0
+. ie \\n(aC==\\n(aP \{\
+. if \\n(jM==4 .as b1 \&\|\-
+. as b1 \&\fP\s0
+. aZ
+. \}
+. el \{\
+. nr aP \\n(aP+1
+. ie ((\\n(C\\n(aP==3)&(\\n(C\\n(jN==4)) .as b1 \&\|\-
+. el .as b1 \&\\*(S\\n(jN
+. fR \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.rr jM jN
+..
+.\"
+.\" NS nR macro - general name recursion routine
+.\" NS jM local register
+.\" NS jN local register
+.de nR
+.hy 0
+.nr jM \\n(C\\n(aP
+.ie \\n(jM==1 \{\
+. as b1 \&\f\\n(cF\s\\n(cZ
+. \\*(A\\n(aP
+.\}
+.el \{\
+. nr jN \\n(aP
+. ie \\n(jM==2 .as b1 \&\\*(A\\n(aP
+. el .as b1 \&\f\\n(cF\s\\n(cZ\\*(A\\n(aP\fP\s0
+. ie \\n(aC==\\n(aP \{\
+. as b1 \&\f\\n(cF\s\\n(cZ
+. aZ
+. \}
+. el \{\
+. nr aP \\n(aP+1
+. as b1 \&\\*(S\\n(jN
+. nR
+. \}
+.\}
+.rr jM jN
+..
+.\" NS Ar macro - command line `argument' macro
+.\"
+.de Ar
+.as b1 \\*(aR
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 \{\
+. as b1 file\ ...\fP\s0
+. pB
+. \}
+. el \{\
+. ds mN Ar
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>0 \{\
+. ie (\\n(aC-\\n(aP)==0 \{\
+. as b1 \&file\ ...\fP\s0
+. aZ
+. \}
+. el \{\
+. nr aP \\n(aP+1
+. ie \\n(C\\n(aP==1 \{\
+. as b1 \&file\ ...\fP\s0
+. \\*(A\\n(aP
+. \}
+. el \{\
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. if \\n(C\\n(aP==3 \{\
+. as b1 \&file\ ...
+. \}
+. nR
+. \}
+. \}
+.\}
+..
+.\" NS Ad macro - Addresses
+.de Ad
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .Ad address ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN Ad
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. as b1 \\*(aD
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+.\}
+..
+.\" NS Cd macro - Config declaration (for section 4 SYNOPSIS) (not callable)
+.\" needs work - not very translatable
+.de Cd
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .Cd Configuration file declaration (#\\n(.c)
+. el \{\
+. ds mN Cd
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.br
+.if \\n(aC>\\n(aP \{\
+. as b1 \\*(nM
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. ie \\n(nS \{\
+. if "\\*(mN"Cd" \{\
+. rs
+. ie \\n(nS>1 .br
+. el \{\
+. if \\n(iS==0 .nr iS \\n(Dsu
+. \}
+. in +\\n(iSu
+. ti -\\n(iSu
+. nr nS \\n(nS+1
+. \}
+. nR
+. in -\\n(iSu
+. \}
+. el .nR
+.\}
+..
+.\" NS Cm macro - Interactive command modifier (flag)
+.de Cm
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .Cm Interactive command modifier ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN Cm
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. as b1 \\*(cM
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+.\}
+..
+.\" NS Dv macro - define variable
+.de Dv
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .Dv define_variable ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN Dv
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. as b1 \\*(eR
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+.\}
+..
+.\" NS Em macro - Emphasis
+.de Em
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 \{\
+. tm Usage: .Em text ... \\*(Pu (#\\n(.c)
+. \}
+. el \{\
+. ds mN Em
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. as b1 \\*(eM
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+.\}
+..
+.\" NS Er macro - Errnotype
+.de Er
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .Er ERRNOTYPE ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN Er
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. as b1 \\*(eR
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+.\}
+..
+.\" NS Ev macro - Environment variable
+.de Ev
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .Ev ENVIRONMENT_VARIABLE ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN Ev
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. as b1 \\*(eV
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+.\}
+..
+.\" NS Fd macro - function declaration - not callable (& no err check)
+.\" NS fD register subroutine test (in synopsis only)
+.\" NS fY register subroutine count (in synopsis only) (fortran only)
+.\" NS fZ register also subroutine count (in synopsis only)
+.de Fd
+.ds mN Fd
+.if \\n(nS>0 \{\
+.\" if a variable type was the last thing given, want vertical space
+. if \\n(fX>0 \{\
+. Pp
+. nr fX 0
+. \}
+.\" if a subroutine was the last thing given, want vertical space
+. if \\n(fZ>0 \{\
+. ie \\n(fD==0 \{\
+. Pp
+. rs
+. \}
+. el .br
+. \}
+. nr fD \\n(fD+1
+.\}
+.nr cF \\n(.f
+.nr cZ \\n(.s
+\&\\*(fD\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.br
+.ft \\n(cF
+.fs \\n(cZ
+..
+.\" NS Fr macro - function return value - not callable (at the moment)
+.de Fr
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .Fr Function_return_value... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN Fr
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. as b1 \\*(aR
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+.\}
+..
+.\" NS Ic macro - Interactive command
+.de Ic
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .Ic Interactive command ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN Ic
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. as b1 \\*(iC
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+.\}
+..
+.\" NS Li macro - literals
+.de Li
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage .Li argument ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN Li
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. as b1 \\*(lI
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+.\}
+..
+.\" NS Or macro - Pipe symbol (OR)
+.de Or
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .Or ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN Or
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. as b1 \\*(iC
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+.\}
+..
+.\" NS Ms macro - Math symbol
+.de Ms
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .Ms Math symbol ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN Ms
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. as b1 \\*(sY
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+.\}
+..
+.\" NS Nm macro - Name of command or page topic
+.\" NS n1 string - save first invocation of .Nm
+.\" NS iS register - indent second command line in a synopsis
+.de Nm
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 \{\
+. ie "\\*(n1"" .tm Usage: .Nm Name(s) ... \\*(Pu (#\\n(.c)
+. el \&\\*(nM\\*(n1\fP\s0
+. \}
+. el \{\
+. ds mN Nm
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.if \\n(aC>0 \{\
+. ie \\n(aC==\\n(aP \{\
+. as b1 \&\\*(nM\\*(n1\fP\s0
+. aZ
+. \}
+. el \{\
+. as b1 \\*(nM
+. nr aP \\n(aP+1
+. ie \\n(C\\n(aP==1 \{\
+. as b1 \&\\*(n1\fP\s0
+. \\*(A\\n(aP
+. \}
+. el \{\
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. if \\n(nS \{\
+. if "\\*(mN"Nm" \{\
+. rs
+. in -\\n(iSu
+. ie \\n(nS>1 .br
+. el \{\
+. if \\n(iS==0 \{\
+. sw \\$1
+. nr iS ((\\n(sWu+1)*\\n(fW)u
+. \}
+. \}
+. in +\\n(iSu
+. ti -\\n(iSu
+. nr nS \\n(nS+1
+. \}
+. \}
+. if "\\*(n1"" .ds n1 \\*(A\\n(aP
+. nR
+. \}
+. \}
+.\}
+..
+.\" NS Pa macro - Pathname
+.de Pa
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 \&\\*(pA~\fP\s0
+. el \{\
+. ds mN Pa
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. as b1 \\*(pA
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+.\}
+..
+.\" NS Sy macro - Symbolics
+.de Sy
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .Sy symbolic_text ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN Sy
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. as b1 \\*(sY
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+.\}
+..
+.\" NS Tn macro - Trade Name Macro
+.de Tn
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .Tn Trade_name(s) ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN Tn
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. as b1 \\*(tN\\*(tF
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+.\}
+..
+.\" NS nN macro - Trade Name Macro for inside of reference
+.de nN
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .Tn Trade_name(s) ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN Tn
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. as b1 \\*(tN
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. rR
+.\}
+..
+.\" NS Va macro - variable name macro
+.de Va
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .Va variable_name(s) ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN Va
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. as b1 \\*(vA
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+.\}
+..
+.\"
+.\" NS No macro - Normal text macro (default text style if mess up)
+.de No
+.as b1 \\*(nO
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .No must be called with arguments (#\\n(.c)
+. el \{\
+. ds mN No
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. ie \\n(C\\n(aP==1 \{\
+. \\*(A\\n(aP
+. \}
+. el \{\
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+. \}
+.\}
+..
+.\"------------------------------------------------------------------------
+.\" NS Op macro - Option Expression
+.de Op
+.if \\n(aC==0 \{\
+. ds mN Op
+.\}
+.\" .ds qL \&\\*(lO
+.\" .ds qR \&\\*(rO
+.ds qL \&\\*(lB
+.ds qR \&\\*(rB
+.En \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
+..
+.\" NS Aq macro - Enclose string in angle brackets
+.de Aq
+.if \\n(aC==0 .ds mN Aq
+.ds qL \&<
+.ds qR \&>
+.En \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Bq macro - Enclose string in square brackets
+.de Bq
+.if \\n(aC==0 .ds mN Bq
+.ds qL \&\\*(lB
+.ds qR \&\\*(rB
+.En \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Dq macro - Enclose string in double quotes
+.de Dq
+.if \\n(aC==0 .ds mN Dq
+.ds qL \&\\*(Lq
+.ds qR \&\\*(Rq
+.En \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Eq macro - Enclose string in double quotes
+.de Eq
+.if \\n(aC==0 .ds mN Eq
+.ds qL \\$1
+.ds qR \\$2
+.En \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Pq macro - Enclose string in parenthesis
+.de Pq
+.if \\n(aC==0 .ds mN Pq
+.ds qL \&\\*(lP
+.ds qR \&\\*(rP
+.En \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Ql macro - Quoted literal is in file mdoc-[dit|n|g]roff (too large
+.\" an if-else to carry along recursively for `if n ...')
+.\"
+.\" NS Sq macro - Enclose string in single quotes
+.de Qq
+.if \\n(aC==0 .ds mN Qq
+.ds qL \&\\*q
+.ds qR \&\\*q
+.En \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Sq macro - Enclose string in single quotes
+.de Sq
+.if \\n(aC==0 .ds mN Sq
+.ds qL \&\\*(sL
+.ds qR \&\\*(sR
+.En \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\"
+.\" NS Es macro - Set up strings for .En call
+.de Es
+.if \\n(aC==0 \{\
+. ie \\n(.$>2 .aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. el \{\
+. ds qL \\$1
+. ds qR \\$2
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. ds qL \\*(A\\n(aP
+. nr aP \\n(aP+1
+. ds qR \\*(A\\n(aP
+. ie \\n(aC>\\n(aP .c\\n(C\\n(aP
+. el .aZ
+.\}
+..
+.\" .tm En beg arg(A[\\n(aP])==\\*(A\\n(aP;
+.\" .tm En oM==\\n(oM; dZ==\\n(dZ; Xt==\\n(Xt; aC==\\n(aC
+.\" NS En macro - Enclose string with given args (eg [ and ] etc)
+.\" NS qL string variable set by calling macro
+.\" NS qR string variable set by calling macro
+.\" NS aJ register (for vR)
+.de En
+.ie \\n(aC==0 \{\
+. ie \\n(.$==0 \{\
+. as b1 \&\\*(qL\\*(qR
+. pB
+. \}
+. el \{\
+.\". as mN (En)
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. as b1 \&\\*(qL
+. \}
+.\}
+.el \{\
+. as b1 \&\\*(qL
+.\}
+.if \\n(aC>0 \{\
+. ie (\\n(aC-\\n(aP)==0 \{\
+. as b1 \&\\*(qR
+. aZ
+. \}
+. el \{\
+. ie \\n(C\\n(aC==3 \{\
+. nr aJ \\n(aC-1
+. vR
+. nr aJ \\n(aJ+1
+. ds A\\n(aJ \&\\*(qR\\*(A\\n(aJ
+. nr aJ 0
+. \}
+. el .aI \&\\*(qR 3
+. nr aP \\n(aP+1
+. if \\n(C\\n(aP==1 .\\*(A\\n(aP
+. if \\n(C\\n(aP>1 \{\
+. nr aP \\n(aP-1
+. No
+. \}
+. \}
+.\}
+..
+.\" NS vR macro - vector routine (for En, trace backwards past trail punct)
+.de vR
+.if \\n(C\\n(aJ==3 \{\
+. nr aJ \\n(aJ-1
+. vR
+.\}
+..
+.\"------------------------------------------------------------------------
+.\" NS Ao macro - Angle open
+.de Ao
+.if \\n(aC==0 .ds mN Ao
+.ds qL \&<
+.eO \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Ac macro - Angle close
+.de Ac
+.if \\n(aC==0 .ds mN Ac
+.ds qR \&>
+.eC \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Bo macro - Bracket open
+.de Bo
+.if \\n(aC==0 .ds mN Bo
+.ds qL \&[
+.eO \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Bc macro - Bracket close
+.de Bc
+.if \\n(aC==0 .ds mN Bc
+.ds qR \&]
+.eC \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Do macro - Double Quote open
+.de Do
+.if \\n(aC==0 .ds mN Do
+.ds qL \&\\*(Lq
+.eO \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Dc macro - Double Quote close
+.de Dc
+.if \\n(aC==0 .ds mN Dc
+.ds qR \&\\*(Rq
+.eC \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Eo macro - Enclose open
+.de Eo
+.if \\n(aC==0 .ds mN Eo
+.ds qL \\$1
+.eO \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Ec macro - Enclose close
+.de Ec
+.if \\n(aC==0 .ds mN Ec
+.ds qR \\$1
+.eC \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Oo macro - Option open
+.de Oo
+.if \\n(aC==0 .ds mN Oo
+.ds qL \&[
+.eO \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Oc macro - Option close
+.de Oc
+.if \\n(aC==0 .ds mN Oc
+.ds qR \&]
+.eC \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Po macro - Parenthesis open
+.de Po
+.if \\n(aC==0 .ds mN Po
+.ds qL \&(
+.eO \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Pc macro - Parenthesis close
+.de Pc
+.if \\n(aC==0 .ds mN Pc
+.ds qR \&)
+.eC \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Qo macro - Straight Double Quote open
+.de Qo
+.if \\n(aC==0 .ds mN Qo
+.ds qL \&\\*q
+.eO \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Qc macro - Straight Double Quote close
+.de Qc
+.if \\n(aC==0 .ds mN Qc
+.ds qR \&\\*q
+.eC \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS So macro - Single Quote open
+.de So
+.if \\n(aC==0 .ds mN So
+.ds qL \&\\*(sL
+.eO \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Sc macro - Single Quote close
+.de Sc
+.if \\n(aC==0 .ds mN Sc
+.ds qR \&\\*(sR
+.eC \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Xo macro - Extend open (continue)
+.de Xo
+.if \\n(aC==0 .ds mN Xo
+.\" .nr mN 1
+.ds qL
+.eO \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS Xe macro - Extend close (end)
+.de Xc
+.\" .nr mN 0
+.if \\n(aC==0 .ds mN Xc
+.ds qR
+.eC \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS eO macro - enclose string open
+.\" NS oM register (extension possible)
+.de eO
+.nr oM \\n(oM+1
+.\" .tm eO last arg==A[\\n(aC]==\\*(A\\n(aC; aP==\\n(aP; oM==\\n(oM; dZ==\\n(dZ;
+.ie \\n(aC==0 \{\
+. ie \\n(.$>0 \{\
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. as b1 \\*(qL
+. \}
+. el \{\
+. as b1 \\*(qL
+. if (\\n(dZ==0)&(\\n(sM==1) \{\
+. nr dZ \\n(dZ+1
+. ds b2 \\*(b1
+. ds b1
+. nr lK \\n(.c
+. ev 2
+. fi
+. di eB
+. \}
+. \}
+.\}
+.el \{\
+. as b1 \\*(qL
+.\}
+.ie \\n(aC>0 \{\
+. if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. ie \\n(C\\n(aP==1 .\\*(A\\n(aP
+. el \{\
+. nr aP \\n(aP-1
+. No
+. \}
+. \}
+. if \\n(aC==\\n(aP \{\
+. if \\n(tP==1 \{\
+.\" .tm SETTING Xt!!!
+. nr Xt 1
+. \}
+.\".\" . ds S0
+.\"CHANGED ds S0 \\*(iV
+. aY
+. \}
+.\}
+.el \{\
+. if \\n(oM>1 .as b1 \\*(sV
+.\}
+..
+.\"
+.\" NS eC macro - enclose string close
+.\" NS aa local register
+.de eC
+.nr oM \\n(oM-1
+.\" tm eC last arg==A[\\n(aC]==\\*(A\\n(aC; aP==\\n(aP; oM==\\n(oM; dZ==\\n(dZ;
+.as b1 \\*(qR
+.if \\n(aC==0 \{\
+. ie \\n(.$>0 \{\
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+. el \{\
+. ie "\\*(xB"" \{\
+. pB
+. \}
+. el \{\
+. pB
+.\\*(L\\n(lC
+. nr Xt 0
+. ds xB
+. \}
+. \}
+.\}
+.if \\n(aC>0 \{\
+. ie \\n(aC==\\n(aP \{\
+. ie \\n(oM==0 \{\
+. aZ
+. \}
+. el .aY
+. \}
+. el \{\
+. nr aa \\n(aP+1
+. if \\n(C\\n(aa==2 .as b1 \\*(S\\n(aC
+.\" tm CURRENT arg (aP==\\*(A\\n(aP and ap+1==\\*(A\\n(aa) tP==\\n(tP Xt==\\n(Xt
+. rr aa
+. if \\n(tP>0 \{\
+.\" tm UNSETTING Xt==\\n(Xt!!!!
+. if \\n(Xt>0 .nr Xt \\n(Xt-1
+.\" tm NOW Xt==\\n(Xt!!!!
+. \}
+. No
+. \}
+.\}
+..
+.\"------------------------------------------------------------------------
+.\" NS Pf macro - Prefix (calls .pF)
+.de Pf
+.if \\n(aC==0 .ds mN Pf
+.ds qL \&\\$1
+.pF \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" NS pF macro - Prefix (for prefixing open quotes, brackets etc)
+.de pF
+.ie \\n(aC==0 \{\
+. as b1 \&\\*(qL
+. ie \\n(.$<2 \{\
+. tm Warning: Missing arguments - prefix .Pf)
+. pB
+. \}
+. el .aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.\}
+.el \{\
+. ie (\\n(aC-\\n(aP)>1 \{\
+. nr aP \\n(aP+1
+. as b1 \&\\*(A\\n(aP
+. \}
+. el .tm Warning: .Pf: trailing prefix (#\\n(.c)
+.\}
+.if \\n(aC>0 \{\
+. ie (\\n(aC-\\n(aP)==0 .aZ
+. el \{\
+. nr aP \\n(aP+1
+. c\\n(C\\n(aP
+. \}
+.\}
+..
+.\" NS Ns macro - remove space (space remove done by .aV or .fV)
+.de Ns
+.if \\n(aC==0 \{\
+. ds mN Ns
+. ie \\n(.$>0 .aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. el .tm Usage: .Ns must be called with arguments (#\\n(.c)
+.\}
+.No
+..
+.de Ap
+.if \\n(aC==0 \{\
+. ds mN Ap
+. tm Usage: Ap "cannot be first request on a line (no .Ap)" (#\\n(.c)
+.\}
+.as b1 \&'
+.No
+..
+.\" NS Hv macro - Hard (unpaddable) Space vector
+.\" NS iV string inter-vector space
+.\" NS sV string inter-argument space
+.de Hv
+.ds iV \\*(sV
+.ds sV \\*(hV
+..
+.\" NS Sv macro - Soft Space vector (troff limitation)
+.de Sv
+.ds sV \\*(iV
+..
+.\" NS Tv macro - Tab Space vector
+.de Tv
+.ds sV \\*(tV
+..
+.\" NS Sm macro - Space mode
+.\" NS sM register - default is one (space mode on)
+.nr sM 1
+.de Sm
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm "Usage: .Sm [off | on]" (#\\n(.c)
+. el \{\
+. ds mN Sm
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>0 \{\
+. nr aP \\n(aP+1
+. if "\\*(A\\n(aP"on" \{\
+. ds sV \\*(iV
+. nr sM 1
+. \}
+. if "\\*(A\\n(aP"off" \{\
+. ds sV
+. rm S0 S1 S2 S3 S4 S5 S6 S7 S8 S9
+. nr sM 0
+. \}
+. ie \\n(aC>\\n(aP \{\
+. No
+. \}
+. el .aY
+.\}
+..
+.\"------------------------------------------------------------------------
+.\" Size and Argument type macros
+.\" NS aT macro - argument type
+.\" NS aU macro - argument type (same as .aT but uses A[1-9] strings
+.\" NS aT register argument type
+.if \n(.g \{\
+.de aT
+.nr aT 0
+.ie \\n(sW>2:(\A'\\$1'==0) \{\
+. nr aT 2
+.\}
+.el \{\
+. if \\n(sW==1 \{\
+. ie \\n(z\\$1>2 \{\
+. nr aT \\n(z\\$1
+. \}
+. el .nr aT 2
+. \}
+. if \\n(sW==2 \{\
+. ie \\n(\\$1 \{\
+. nr aT 1
+. \}
+. el .nr aT 2
+. \}
+.\}
+..
+.de aU
+.nr aT 0
+.aW \\$1
+.ie \\n(sW>2:(\A'\\*(A\\$1'==0) .nr aT 2
+.el \{\
+. if \\n(sW==1 \{\
+. ie \\n(z\\*(A\\$1>2 \{\
+. nr aT \\n(z\\*(A\\$1
+. \}
+. el .nr aT 2
+. \}
+. if \\n(sW==2 \{\
+. ie (\\n(\\*(A\\$1) \{\
+. nr aT 1
+. \}
+. el .nr aT 2
+. \}
+.\}
+..
+.\}
+.if !\n(.g \{\
+.de aT
+.nr aT 0
+.ie \\n(sW>2 \{\
+. nr aT 2
+.\}
+.el \{\
+. if \\n(sW==1 \{\
+. ie \\n(z\\$1>2 \{\
+. nr aT \\n(z\\$1
+. \}
+. el .nr aT 2
+. \}
+. if \\n(sW==2 \{\
+. ie \\n(\\$1 \{\
+. nr aT 1
+. \}
+. el .nr aT 2
+. \}
+.\}
+..
+.de aU
+.nr aT 0
+.aW \\$1
+.ie \\n(sW>2 .nr aT 2
+.el \{\
+. if \\n(sW==1 \{\
+. ie \\n(z\\*(A\\$1>2 \{\
+. nr aT \\n(z\\*(A\\$1
+. \}
+. el .nr aT 2
+. \}
+. if \\n(sW==2 \{\
+. ie (\\n(\\*(A\\$1) \{\
+. nr aT 1
+. \}
+. el .nr aT 2
+. \}
+.\}
+..
+.\}
+.\" NS s1 macro - set spacing for class type 1
+.\" NS s2 macro - set spacing for class type 2
+.\" NS s3 macro - set spacing for class type 3
+.\" NS s1 macro - set spacing for class type 1
+.\" NS s2 macro - set spacing for class type 2
+.\" NS s3 macro - set spacing for class type 3
+.\" NS s4 macro - set spacing for class type 4
+.\" NS S[0-9] string spacing
+.\" NS xX local register
+.\" NS aa local register
+.de s0
+.tm MDOC-ERROR: bogus type 0 (can't set space '\\*(A\\n(aC') (#\\n(.c)
+..
+.de s1
+.if \\n(\\*(A\\n(aC==3 \{\
+. nr xX \\n(aC-1
+. rm S\\n(xX
+. ds S\\n(aC \\*(sV
+.\}
+.if \\n(\\*(A\\n(aC==2 \{\
+. nr xX \\n(aC-1
+.\" this kludge can probably go away, but need to double check first
+. ie "\\*(A\\n(aC"Nb" .ds S\\n(xX \\*(hV
+. el .rm S\\n(xX
+.\}
+..
+.de s2
+.ds S\\n(aC \\*(sV
+..
+.de s3
+.if \\n(aC>1 \{\
+. nr xX \\n(aC-1
+. rm S\\n(xX
+.\}
+.ds S\\n(aC \\*(sV
+..
+.de s4
+.nr aa 0
+..
+.\" Class switches (on current argument aP)
+.\" NS c0 macro - catch errors (non-existent class type 0)
+.\" NS c1 macro - call request if type 1
+.\" NS c2 macro - call .No if type 2
+.\" NS c3 macro - call .No if type 3
+.\" NS c4 macro - call .No if type 4
+.de c0
+.tm MDOC-ERROR: bogus class 0 (can't determine '\\*(A\\n(aC') (#\\n(.c)
+..
+.de c1
+.\\*(A\\n(aP
+..
+.de c2
+.nr aP \\n(aP-1
+.No
+..
+.de c3
+.nr aP \\n(aP-1
+.No
+..
+.de c4
+.nr aP \\n(aP-1
+.No
+..
+.\" NS y1 macro - ignore if class 1
+.\" NS y2 macro - ignore if class 2
+.\" NS y3 macro - append if type 3
+.\" NS y4 macro - append if type 4
+.de y1
+.nr aa 1
+..
+.de y2
+.nr aa 1
+..
+.de y3
+.as b1 \\*(A\\n(aP
+.nr aP \\n(aP+1
+.n\\C\\n(aP
+..
+.de y4
+.as b1 \\*(A\\n(aP
+.nr aP \\n(aP+1
+.n\\C\\n(aP
+..
+.\"--------------------------------------------------------------------------
+.\" Ns Bf macro - Begin Font Mode (will be begin-mode/end-mode in groff & TeX)
+.\" Ns Ef macro - End Font Mode
+.de Bf
+.ds mN Bf
+.ie \\n(.$>0 \{\
+. nr bF \\n(.f
+. nr bZ \\n(.s
+. if "\\$1"Em" \&\\*(eM\c
+. if "\\$1"Li" \&\\*(lI\c
+. if "\\$1"Sy" \&\\*(sY\c
+. if "\\$1"-emphasis" \&\\*(eM\c
+. if "\\$1"-literal" \&\\*(lI\c
+. if "\\$1"-symbolic" \&\\*(sY\c
+.\}
+.el .tm Usage .Bf [Em | emphasis | Li | literal | Sy | symbolic] (#\\n(.c)
+..
+.de Ef
+.ds mN Ef
+.ie \\n(.$>0 .tm Usage .Ef (does not take arguments) (#\\n(.c)
+.el \&\f\\n(bF\s\\n(bZ
+..
+.\" Ns Bk macro - Begin Keep
+.\" Ns Ek macro - End Keep
+.\" Ns kS string - keep type
+.de Bk
+.ds mN Bk
+.ie \\n(.$==0 \{\
+.tm Usage: .Bk [-lines | -words] (#\\n(.c)
+.\}
+.el \{\
+. if !"\\*(kS"" .tm .Bk: nesting keeps not implemented yet. (#\\n(.c)
+. if "\\$1"-lines" .tm .Bd -lines: Not implemented yet. (#\\n(.c)
+. if "\\$1"-words" .Hv
+. ds kS \\$1
+.\}
+..
+.de Ek
+.ds mN Ek
+.ie \\n(.$>0 .tm Usage .Ek (does not take arguments) (#\\n(.c)
+.el \{\
+. if "\\*(kS"-lines" .tm .Bd -lines: Not implemented yet. (#\\n(.c)
+. if "\\*(kS"-words" .Sv
+. rm kS
+.\}
+..
+.\" NS Bd macro - Begin Display display-type [offset string]
+.\" NS Ed macro - end Display
+.\" NS O[0-9] registers - stack of indent
+.\" NS d[0-9] registers - display-type stack
+.de Bd
+.ds mN Bd
+.ie \\n(.$==0 \{\
+.tm Usage: .Bd [-literal | -filled | -ragged | -unfilled] [-offset [string]] [-compact] (#\\n(.c)
+.\}
+.el \{\
+. ds aa
+. nr bV 0
+. nr iD 0
+. nr dP \\n(dP+1
+. if "\\$1"-literal" \{\
+. nr iD \\n(iD+1
+. ds d\\n(dP dL
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. ie t \{\&\\*(lI
+' ta 9n 18n 27n 36n 45n 54n 63n 72n
+. \}
+. el \{\
+' ta 8n 16n 24n 32n 40n 48n 56n 64n 72n
+. \}
+. nf
+. \}
+. if "\\$1"-filled" \{\
+. nr iD \\n(iD+1
+. ds d\\n(dP dF
+. br
+. \}
+. if "\\$1"-ragged" \{\
+. nr iD \\n(iD+1
+. ds d\\n(dP dR
+. na
+. \}
+. if "\\$1"-unfilled" \{\
+. nr iD \\n(iD+1
+. ds d\\n(dP dU
+. nf
+. \}
+.\" .tm Here is argc: \\n(.$ and here is iD \\n(iD
+. if ((\\n(iD>=1)&(\\n(.$>\\n(iD)) \{\
+. bV \\$2 \\$3 \\$4
+. \}
+. if \\n(O\\n(dP>0 'in \\n(.iu+\\n(O\\n(dPu
+. if (\\n(bV==0) \{\
+. if (\\n(nS==0) \{\
+. ie "\\*(d\\n(dP"dR" .sp \\n(dVu
+. el 'sp \\n(dVu
+. \}
+. \}
+. if \\n(cR==0 .ne 2v
+. nr bV 0
+. nr iD 0
+.\}
+..
+.\" NS bV macro - resolve remaining .Bd arguments
+.de bV
+.\" .tm in bV with args: \\$1 \\$2 \\$3
+.nr iD 1
+.ds bY
+.if "\\$1"-offset" \{\
+. ds bY \\$2
+. if "\\*(bY"left" \{\
+. nr iD \\n(iD+1
+. nr O\\n(dP 0
+. \}
+. if "\\*(bY"right" \{\
+. nr iD \\n(iD+1
+. nr O\\n(dP (\\n(.l/3)u
+. \}
+. if "\\*(bY"center" \{\
+. nr iD \\n(iD+1
+. nr O\\n(dP (\\n(.l-\\n(.i)/4u
+. \}
+. if "\\*(bY"indent" \{\
+. nr iD \\n(iD+1
+. nr O\\n(dP \\n(dIu
+. \}
+. if "\\*(bY"indent-two" \{\
+. nr iD \\n(iD+1
+. nr O\\n(dP \\n(dIu+\\n(dIu
+. \}
+. if \\n(iD==1 \{\
+. nr iD \\n(iD+1
+. sW "\\*(bY"
+. ie \\n(sW>2 \{\
+. ie ((\\*(bY>9n)&(\\*(bY<100n)) \{\
+. nr O\\n(dP \\*(bY
+. \}
+. el .nr O\\n(dP (\\n(sW)*\\n(fWu
+. \}
+. el \{\
+. if \\n(sW==2 .aT \\*(bY
+. ie \\n(aT==1 \{\
+. nr O\\n(dP \\n(\\*(bY
+. \}
+. el .nr O\\n(dP \\*(bY
+. \}
+. \}
+.\}
+.if "\\$1"-compact" \{\
+. nr bV 1
+.\}
+.if \\n(iD<\\n(.$ \{\
+. ie "\\*(bY"" \{\
+. bV \\$2 \\$3
+. \}
+. el \{\
+. bV \\$3
+. \}
+.\}
+..
+.\" NS Ed macro - end display
+.de Ed
+.ds mN Ed
+.br
+.if \\n(dP==0 .tm mdoc: Extraneous .Ed
+.if "\\*(d\\n(dP"dL" \{\
+. ft \\n(cF
+. fz \\n(cZ
+.\}
+.in \\n(.iu-\\n(O\\n(dPu
+.rr O\\n(dP
+.rm d\\n(dP
+.nr dP \\n(dP-1
+.fi
+.if t .ad
+..
+.\"--------------------------------------------------------------------------
+.\" NS Bl macro - begin list (.Bl list-type)
+.\" NS L[0-9] registers - stack of list types
+.de Bl
+.ie \\n(.$==0 \{\
+.tm Usage: .Bl [[-hang | -tag] [-width]] [ -item | -enum | -bullet | -diag] (#\\n(.c)
+.\}
+.el \{\
+. ds mN Bl
+. nr aP 0
+. nr lC \\n(lC+1
+. ds A1 \\$2
+. ds A2 \\$3
+. ds A3 \\$4
+. ds A4 \\$5
+. ds A5 \\$6
+. ds A6 \\$7
+. ds A7 \\$8
+. ds A8 \\$9
+. nr fV \\n(.$-1
+. if "\\$1"-hang" \{\
+. nr aP \\n(aP+1
+. ds L\\n(lC hL
+. nr w\\n(lC 6n
+. nr tC 1
+. \}
+. if "\\$1"-tag" \{\
+. nr aP \\n(aP+1
+. ds L\\n(lC tL
+. nr tC 1
+. \}
+. if "\\$1"-item" \{\
+. nr aP \\n(aP+1
+. ds L\\n(lC iT
+. nr tC 1
+. \}
+. if "\\$1"-enum" \{\
+. nr aP \\n(aP+1
+. ds L\\n(lC nU
+. nr w\\n(lC 3n
+. nr tC 1
+. \}
+. if "\\$1"-bullet" \{\
+. nr aP \\n(aP+1
+. ds L\\n(lC bU
+. nr w\\n(lC 2n
+. nr tC 1
+. \}
+. if "\\$1"-dash" \{\
+. nr aP \\n(aP+1
+. ds L\\n(lC hU
+. nr w\\n(lC 2n
+. nr tC 1
+. \}
+. if "\\$1"-hyphen" \{\
+. nr aP \\n(aP+1
+. ds L\\n(lC hU
+. nr w\\n(lC 2n
+. nr tC 1
+. \}
+. if "\\$1"-inset" \{\
+. nr aP \\n(aP+1
+. ds L\\n(lC lL
+. nr tC 1
+. \}
+. if "\\$1"-diag" \{\
+. nr aP \\n(aP+1
+. ds L\\n(lC mL
+. nr mL 1
+. \}
+. if "\\$1"-ohang" \{\
+. nr aP \\n(aP+1
+. ds L\\n(lC oL
+. nr tC 1
+. \}
+. if "\\$1"-column" \{\
+. nr aP \\n(aP+1
+. ds L\\n(lC cL
+. \}
+. ie \\n(aP==0 \{\
+. tm \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. tm Usage: .Bl [[-inset|-tag] -width] [-item|-enum|-bullet|-diag] (#\\n(.c)
+. \}
+. el \{\
+. tY
+. if (\\n(aP==1)&(\\n(aP<\\n(.$) \{\
+. nr aP 0
+. lV
+. if "\\*(L\\n(lC"cL" \{\
+. W\\n(wV
+. nr w\\n(lC 0
+' in -\\n(eWu
+. ie \\n(v\\n(lC==1 \{\
+. nr aa 0
+. \}
+. el \{\
+. sp \\n(dVu
+. \}
+. nf
+. nr wV 0
+. \}
+. \}
+. \}
+. nr aP 0
+.\" . ds b1
+. aY
+.\" .tm Here is L[\\n(lC]==\\*(L\\n(lC
+.\}
+..
+.if \n(.g \{\
+. nr i 10
+. while \ni<100 \{\
+. nr num!\nin 1
+. nr i +1
+. \}
+.\}
+.\" NS lV macro - resolve remaining .Bl arguments
+.de lV
+.nr aP \\n(aP+1
+.if \\n(fV>=\\n(aP \{\
+. nr iD 0
+. if "\\*(A\\n(aP"-compact" \{\
+. nr iD 1
+. nr v\\n(lC 1
+. \}
+. if "\\*(A\\n(aP"-width" \{\
+. nr iD 1
+. nr aP \\n(aP+1
+. nr tW 1
+. ds t\\n(lC TagwidtH
+. ds tS \\*(A\\n(aP
+. aW \\n(aP
+. ie \\n(sW>2 \{\
+. nr w\\n(lC (\\n(sW)*\\n(fWu
+. if \\n(sW==3 \{\
+. ie \\n(.g \{\
+. if \A'\\*(tS' .if r num!\\*(tS \{\
+. nr w\\n(lC \\*(tS
+. \}
+. \}
+. el \{\
+. if (\\*(tS>9n)&(\\*(tS<99n) \{\
+. nr w\\n(lC \\*(tSu
+. \}
+. \}
+. \}
+. \}
+. el \{\
+. aT \\*(tS
+. ie \\n(aT==1 \{\
+. nr w\\n(lC \\n(\\*(tS
+. \}
+. el \{\
+. nr w\\n(lC \\*(tSu
+. \}
+. \}
+. \}
+. if "\\*(A\\n(aP"-offset" \{\
+. nr iD 1
+. nr aP \\n(aP+1
+. ie "\\*(A\\n(aP"indent" \{\
+. nr o\\n(lC \\n(Dsu
+. \}
+. el \{\
+. ds tS \\*(A\\n(aP
+. aW \\n(aP
+. ie \\n(sW>2 \{\
+. nr o\\n(lC (\\n(sW)*\\n(fWu
+. ie \\n(.g \{\
+. if \A'\\*(tS' .if r num!\\*(tS \{\
+. nr o\\n(lC \\*(tS
+. \}
+. \}
+. el \{\
+. if (\\*(tS>9n)&(\\*(tS<100n) \{\
+. nr o\\n(lC \\*(tS
+. \}
+. \}
+. \}
+. el \{\
+. ie \\n(C\\n(aP==1 .nr o\\n(lC \\n(\\*(tS
+. el .nr o\\n(lC \\*(tS
+. \}
+. \}
+. \}
+. if \\n(iD==0 \{\
+. if "\\*(L\\n(lC"cL" \{\
+. nr wV \\n(wV+1
+. ds A\\n(wV \\*(A\\n(aP
+. \}
+. \}
+. if \\n(fV>\\n(aP .lV
+.\}
+..
+.\" NS El macro - end list
+.\" NS iD local register
+.de El
+.ie \\n(.$>0 \{\
+. tm Usage: .El (#\\n(.c)
+.\}
+.el \{\
+. ds mN El
+. nr iD 0
+. if "\\*(L\\n(lC"cL" \{\
+. nr iD 1
+. cC
+. \}
+. if "\\*(L\\n(lC"nU" \{\
+. nr nU 0
+. \}
+. if \\n(mL>0 \{\
+. nr iD 1
+. nr mL 0
+. tZ
+. nr lC \\n(lC-1
+. tY
+. \}
+. if "\\*(L\\n(lC"iT" \{\
+' in \\n(.iu-\\n(o\\n(lCu
+. tZ
+. nr lC \\n(lC-1
+. tY
+. nr iD 1
+. \}
+. if "\\*(L\\n(lC"oL" \{\
+' in \\n(.iu-\\n(o\\n(lCu
+. tZ
+. nr lC \\n(lC-1
+. tY
+. nr iD 1
+. \}
+. if "\\*(L\\n(lC"lL" \{\
+' in \\n(.iu-\\n(o\\n(lCu
+. tZ
+. nr lC \\n(lC-1
+. tY
+. nr iD 1
+. \}
+. if \\n(iD==0 \{\
+. lE
+. \}
+. br
+. nr iD 0
+.\}
+..
+.\" NS It macro - list item
+.\" NS iD local register
+.\" NS aA save pA font string for section FILES (no underline if nroff)
+.de It
+.if "\\*(L\\n(lC"" \{\
+. tm Usage .Bl -list-type [-width [string] | -compact | -offset [string]] (#\\n(.c)
+. tm .It \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
+.\}
+.\" .tm Here is L[\\n(lC]==\\*(L\\n(lC
+.ne 3v
+.ie \\n(.$>0 \{\
+. ds mN It
+. ds b1
+. nr iD 0
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. if "\\*(L\\n(lC"mL" \{\
+. nr iD 1
+. nr aP 0
+. aX
+. \\*(L\\n(lC
+. \}
+. if "\\*(L\\n(lC"cL" \{\
+. ds b1
+. nr aP 0
+. nr iD 1
+. \\*(L\\n(lC
+. \}
+. if "\\*(L\\n(lC"iT" \{\
+. nr aP 0
+. nr iD 1
+. \\*(L\\n(lC
+. \}
+. if \\n(iD==0 \{\
+. fV
+.\" tm ------------------------------------------------------------------------
+.\" tm It list-type==\\*(L\\n(lC, aP==\\n(aP
+.\" tm It beg arg(A[1])==\\*(A1; oM==\\n(oM; dZ==\\n(dZ; Xt==\\n(Xt; aC==\\n(aC
+. nr oM \\n(oM+1
+. nr tP 1
+. nr aP \\n(aP+1
+. nr tX \\n(C\\n(aP
+. ds tX \\*(A\\n(aP
+. if \\n(nF==1 \{\
+. ds aA \\*(pA
+. if n .ds pA \\*(nO
+. \}
+. ie \\n(C\\n(aP==1 \{\
+. \\*(A\\n(aP
+. \}
+. el \{\
+. nr aP \\n(aP-1
+. No
+. \}
+.\" tm in It here is b1==\\*(b1
+.\" tm It mid arg(A[1])==\\*(A1; oM==\\n(oM; dZ==\\n(dZ; Xt==\\n(Xt; aC==\\n(aC
+. ie \\n(Xt==1 .ds xB \&\\*(L\\n(lC
+. el .\\*(L\\n(lC
+. \}
+. nr iD 0
+.\}
+.el .\\*(L\\n(lC
+..
+.\" NS lL macro - .It item of list-type inset
+.de lL
+.lY
+.br
+\&\\*(b1
+.nr oM \\n(oM-1
+.nr tP 0
+.ds b1
+.aY
+'fi
+..
+.\" NS hL macro - .It item of list-type hanging label (as opposed to tagged)
+.de hL
+.lX
+.nr bb \\n(w\\n(lCu+\\n(lSu
+.ti -\\n(bbu
+.ie \w\\*(b1u>=(\\n(w\\n(lCu) \&\\*(b1
+.el \&\\*(b1\h'|\\n(bbu'\c
+.nr oM \\n(oM-1
+.ds b1
+.nr tP 0
+.aY
+'fi
+..
+.\" NS oL macro - .It item of list-type overhanging label
+.de oL
+.lY
+\&\\*(b1
+.br
+.nr oM \\n(oM-1
+.ds b1
+.nr tP 0
+.aY
+'fi
+..
+.\" NS iT macro - .It item of list-type [empty label]
+.de iT
+.lY
+.br
+.\" .ds b1
+.aY
+'fi
+..
+.\" NS nU macro - Enumerated list
+.\" NS nU register count
+.\" NS hU macro - Hyphen paragraph list (sub bullet list)
+.\" NS bU macro - Bullet paragraph list
+.de nU
+.nr oM \\n(oM+1
+.nr nU \\n(nU+1
+.ds b1 \&\\n(nU.
+.uL
+..
+.de bU
+.nr oM \\n(oM+1
+.nr bU \\n(bU+1
+.ds b1 \&\\*(sY\&\(bu\fP
+.uL
+..
+.de hU
+.nr oM \\n(oM+1
+.nr bU \\n(bU+1
+.ds b1 \&\\*(sY\&\-\fP
+.uL
+..
+.\" NS uL macro - .It item of list-type enum/bullet/hyphen
+.de uL
+.lX
+.nr bb \\n(w\\n(lCu+\\n(lSu
+.ti -\\n(bbu
+.ie \w\\*(b1u>=(\\n(w\\n(lCu) \&\\*(b1
+.el \&\\*(b1\h'|\\n(bbu'\c
+.nr oM \\n(oM-1
+.\" .nr dZ \\n(dZ+1
+.ds b1
+.nr tP 0
+.aY
+'fi
+..
+.\" NS mL macro - .It item of list-type diagnostic-message
+.de mL
+.nr cF \\n(.f
+.nr cZ \\n(.s
+.ie \\n(mL==1 \{\
+. nr zB \\n(.c
+. ie (\\n(zB-\\n(zA)>1 .Pp
+. el .br
+. nr zA \\n(zB
+. nr zB 0
+.\}
+.el \{\
+. nr zA \\n(.c
+. br
+.\}
+\&\\*(sY\\*(b1\f\\n(cF\s\\n(cZ\\*(lS\c
+.aY
+.ds b1
+'fi
+..
+.\" NS tL macro - .It item of list-type "tag"
+.de tL
+.\" tm in tL here is b1==\\*(b1
+.if \\n(tW==0 .lW
+.lX
+.nr bb \\n(w\\n(lCu+\\n(lSu
+.ti -\\n(bbu
+.ie (\w\\*(b1u)>(\\n(w\\n(lCu) \{\&\\*(b1
+. br
+.\}
+.el \&\\*(b1\h'|\\n(bbu'\c
+.if \\n(nF==1 \{\
+. if n .ds pA \\*(aA
+.\}
+.nr oM \\n(oM-1
+.nr tP 0
+.\" .nr dZ \\n(dZ+1
+.ds b1
+.aY
+'fi
+..
+.\" NS lW macro - resolve unknown label/tag width (if .Bl [inset | tag] only)
+.de lW
+.if !"TagwidtH"\\*(t\\n(lC" \{\
+. ie \\n(tX==1 \{\
+. ds t\\n(lN \\*(tX
+. nr w\\n(lN \\n(\\*(tX
+. \}
+. el \{\
+. ds t\\n(lN No
+. nr w\\n(lN \\n(No
+. \}
+. if !"\\*(t\\n(lC"\\*(t\\n(lN" .nr tC 1
+.\}
+..
+.\" NS lX macro - set up vertical spacing (if compact) and offset+indent (all)
+.de lX
+.ie \\n(tC \{\
+. nr tC 0
+. nr tW 0
+. if \\n(v\\n(lC==0 .sp \\n(dVu
+. in \\n(.iu+\\n(w\\n(lCu+\\n(o\\n(lCu+\\n(lSu
+.\}
+.el \{\
+. ie \\n(v\\n(lC==1 \{\
+. nr aa 0
+. \}
+. el \{\
+. sp \\n(dVu
+. \}
+.\}
+.if !\\n(cR .ne 2v
+..
+.\" NS lY macro - set up vertical spacing (if compact) and offset+indent (all)
+.de lY
+.ie \\n(tC \{\
+. nr tC 0
+. nr tW 0
+. if \\n(v\\n(lC==0 .sp \\n(dVu
+. in \\n(.iu+\\n(o\\n(lCu
+.\}
+.el \{\
+. ie \\n(v\\n(lC==1 \{\
+. nr aa 0
+. \}
+. el \{\
+. sp \\n(dVu
+. \}
+.\}
+.if !\\n(cR .ne 2v
+..
+.\" NS tS temporary string
+.\" NS hL macro - hanging list function
+.\" NS tS temporary string
+.\" NS hL macro - hanging list function
+.\" NS lT macro - tagged list function
+.\" NS lE macro - list end function
+.\" NS tX string (initial string)
+.\" NS tX register (initial class)
+.\" NS tC parameter change flag
+.\" NS Xt save current list-type flag
+.\" NS lC register - list type stack counter
+.\" NS tP register tag flag (for diversions)
+.\" NS w[0-9] register tag stack (nested tags)
+.\" NS t[0-9] register tag string stack (nested tags)
+.\" NS o[0-9] register offset stack (nested tags)
+.\" NS v[0-9] register vertical tag break stack
+.\" NS h[0-9] register horizontal tag stack (continuous if 1, break if 0)
+.nr lC 0
+.nr wV 0
+.nr w1 0
+.nr o1 0
+.nr v1 0
+.nr h1 0
+.ds t\n(lC
+.de lE
+.\" IN lC o[\\n(lC]==\\n(o\\n(lC, w[\\n(lC]==\\n(w\\n(lC,
+.ie \\n(o\\n(lC>0 \{\
+' in \\n(.iu-(\\n(w\\n(lCu)-(\\n(o\\n(lCu)-\\n(lSu
+. rr o\\n(lC
+.\}
+.el 'in \\n(.iu-\\n(w\\n(lCu-\\n(lSu
+.if \\n(lC<=0 .tm Extraneous .El call (#\\n(.c)
+.tZ
+.nr lC \\n(lC-1
+.tY
+..
+.\" NS tY macro - set up next block for list
+.\" NS tZ macro - decrement stack
+.\" NS tY register (next possible lC value)
+.de tY
+.nr tY (\\n(lC+1)
+.nr w\\n(tY 0
+.nr h\\n(tY 0
+.nr o\\n(tY 0
+.ds t\\n(tY \\*(t\\n(lC
+.ds L\\n(tY
+.nr v\\n(tY 0
+..
+.de tZ
+.rm L\\n(tY
+.rr w\\n(tY
+.rr h\\n(tY
+.rr o\\n(tY
+.rm t\\n(tY
+.rr v\\n(tY
+.nr tY \\n(tY-1
+..
+.\" initial values
+.nr w1 0
+.nr o1 0
+.nr h1 0
+.ds t1
+.nr v1 0
+.nr tY 1
+.\" NS Xr macro - cross reference (man page only)
+.de Xr
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .Xr manpage_name [section#] \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN Xr
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. ie \\n(C\\n(aP==1 .tm Usage: .Xr manpage_name [section#] \\*(Pu (#\\n(.c)
+. el \{\
+. ie \\n(C\\n(aP>2 .y\\n(C\\n(aP
+. el \{\
+. as b1 \&\\*(xR\\*(A\\n(aP\fP\s0
+. if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. if \\n(C\\n(aP==2 \{\
+. as b1 \&(\\*(A\\n(aP)
+. nr aP \\n(aP+1
+. \}
+. if \\n(aC>=\\n(aP \{\
+. c\\n(C\\n(aP
+. \}
+. \}
+. \}
+. aZ
+. \}
+.\}
+..
+.\" NS Sx macro - cross section reference
+.de Sx
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Sx Usage: .Sx Section Header \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN Sx
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. as b1 \\*(sX
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+.\}
+..
+.\" NS cC macro - column-list end-list
+.\" NS eW macro - column indent width
+.\" NS cI register - column indent width
+.\" NS W[1-5] macro - establish tabs for list-type column
+.de cC
+'in \\n(.iu-\\n(o\\n(lCu-\\n(w\\n(lCu
+.ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 6i 6.5i
+.fi
+.tZ
+.nr lC \\n(lC-1
+.tY
+..
+.de W1
+.ta \w\\*(A1 u
+.nr eW \w\\*(A1 u
+'in \\n(.iu+\\n(eWu+\\n(o\\n(lCu
+..
+.de W2
+.ta \w\\*(A1 u +\w\\*(A2 u
+.nr eW \w\\*(A1 u+\w\\*(A2 u
+'in \\n(.iu+\\n(eWu+\\n(o\\n(lCu
+..
+.de W3
+.ta \w\\*(A1 u +\w\\*(A2 u +\w\\*(A3 u
+.nr eW \w\\*(A1 u+\w\\*(A2 u+\w\\*(A3 u
+'in \\n(.iu+\\n(eWu+\\n(o\\n(lCu
+..
+.de W4
+.ta \w\\*(A1 u +\w\\*(A2 u +\w\\*(A3 u +\w\\*(A4 u
+.nr eW \w\\*(A1 u+\w\\*(A2 u +\w\\*(A3 u +\w\\*(A4 u
+'in \\n(.iu+\\n(eWu+\\n(o\\n(lCu
+..
+.de W5
+.ta \w\\*(A1 u +\w\\*(A2 u +\w\\*(A3 u +\w\\*(A4 u +\w\\*(A5 u
+.nr eW \w\\*(A1 u +\w\\*(A2 u +\w\\*(A3 u +\w\\*(A4 u +\w\\*(A5 u
+' in \\n(.iu+\\n(eWu+\\n(o\\n(lCu
+..
+.\" This is packed abnormally close, intercol width should be an option
+.de W6
+.ta \w\\*(A1 u +\w\\*(A2 u +\w\\*(A3 u +\w\\*(A4 u +\w\\*(A5 u +\w\\*(A6
+.nr eW \w\\*(A1 u +\w\\*(A2 u +\w\\*(A3 u +\w\\*(A4 u +\w\\*(A5 u +\w\\*(A6
+' in \\n(.iu+\\n(eWu+\\n(o\\n(lCu
+..
+.\" NS cL macro - column items
+.de cL
+.if \\n(w\\n(lC==0 .nr w\\n(lC \\n(eWu
+.if \\n(.u==0 \{\
+. fi
+' in \\n(.iu+\\n(eWu
+.\}
+.ti -\\n(eWu
+.fV
+.nr aP \\n(aP+1
+.ie \\n(aC>=\\n(aP \{\
+. if "\\*(A\\n(aP"Ta" \{\
+. nr jJ \\n(aP-1
+. rm S\\n(jJ
+. rr jJ
+. \}
+. c\\n(C\\n(aP
+.\}
+.el .tm Usage: .It column_string [Ta [column_string ...] ] (#\\n(.c)
+..
+.\" NS Ta macro - append tab (\t)
+.de Ta
+.ie \\n(aC>0 \{\
+. nr aP \\n(aP+1
+. ie \\n(aC>=\\n(aP \{\
+. if "\\*(A\\n(aP"Ta" \{\
+. nr jJ \\n(aP-1
+. rm S\\n(jJ
+. rr jJ
+. \}
+. as b1 \\t
+. c\\n(C\\n(aP
+. \}
+. el \{\
+. as b1 \\t\\c
+. rm S\\n(aP
+. pB
+. aY
+.\" . ds b1
+. \}
+.\}
+.el \{\
+. tm Usage: Ta must follow column entry: e.g. (#\\n(.c)
+. tm .It column_string [Ta [column_string ...] ]
+.\}
+..
+.\"
+.\" NS Dl macro - display (one line) literal
+.de Dl
+'ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 6i 6.5i
+.in \\n(.iu+\\n(Dsu
+.ie \\n(aC==0 \{\
+. ie \\n(.$==0 \{\
+. tm Usage: .Dl argument ... (#\\n(.c)
+. \}
+. el \{\
+. ds mN Dl
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. Li
+. \}
+.\}
+.el \{\
+. tm Usage: .Dl not callable by other macros (#\\n(.c)
+.\}
+.in \\n(.iu-\\n(Dsu
+..
+.\"
+.\" NS D1 macro - display (one line)
+.de D1
+'ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 6i 6.5i
+.in \\n(.iu+\\n(Dsu
+.ie \\n(aC==0 \{\
+. ie \\n(.$==0 \{\
+. tm Usage: .D1 argument ... (#\\n(.c)
+. \}
+. el \{\
+. ds mN D1
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. nr aP \\n(aP+1
+. ie \\n(C\\n(aP==1 .\\*(A\\n(aP
+. el .No
+. \}
+.\}
+.el \{\
+. tm Usage: .D1 not callable by other macros (#\\n(.c)
+.\}
+.in \\n(.iu-\\n(Dsu
+..
+.\" NS Ex macro - DEFUNCT
+.de Ex
+.tm Ex defunct, Use .D1: \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\"
+.\" NS Ex macro - DEFUNCT
+.de Ex
+.tm Ex defunct, Use .D1: \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\"
+.\" NS Vt macro - Variable type (for forcing old style variable declarations)
+.\" this is not done in the same manner as .Ot for fortrash - clean up later
+.de Vt
+.\" if a function declaration was the last thing given, want vertical space
+.if \\n(fD>0 \{\
+. Pp
+. nr fD 0
+.\}
+.\" if a subroutine was the last thing given, want vertical space
+.if \\n(fZ>0 \{\
+. ie \\n(fX==0 \{\
+. Pp
+. rs
+. \}
+. el .br
+.\}
+.nr fX \\n(fX+1
+.nr cF \\n(.f
+.nr cZ \\n(.s
+\\*(fT\&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.ie \\n(oT==0 .br
+.el \&\ \&
+.ft \\n(cF
+.fs \\n(cZ
+..
+.\"
+.\" NS Ft macro - Function type
+.nr fZ 0
+.de Ft
+.if \\n(nS>0 \{\
+. if \\n(fZ>0 \{\
+. Pp
+. nr fD 0
+. nr fX 0
+. \}
+. if \\n(fD>0 \{\
+. Pp
+. nr fD 0
+. nr fX 0
+. \}
+. if \\n(fX>0 \{\
+. Pp
+. nr fX 0
+. \}
+. nr fY 1
+.\}
+.nr cF \\n(.f
+.nr cZ \\n(.s
+\&\\*(fT\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.ft \\n(cF
+.fs \\n(cZ
+.\" .br
+..
+.\"
+.\" NS Ot macro - Old Function type (fortran - no newline)
+.\" Ns oT register
+.nr oT 0
+.de Ot
+.nr oT 1
+.if \\n(nS>0 \{\
+. if \\n(fZ>0 \{\
+. Pp
+. nr fD 0
+. nr fX 0
+. \}
+. if \\n(fD>0 \{\
+. Pp
+. nr fD 0
+. nr fX 0
+. \}
+. if \\n(fX>0 \{\
+. Pp
+. nr fX 0
+. \}
+. nr fY 1
+.\}
+.if \\n(.$==4 .as b1 \&\\*(fT\&\\$1 \\$2 \\$3 \\$4
+.if \\n(.$==3 .as b1 \&\\*(fT\&\\$1 \\$2 \\$3
+.if \\n(.$==2 .as b1 \&\\*(fT\&\\$1 \\$2
+.if \\n(.$==1 .as b1 \&\\*(fT\&\\$1
+.as b1 \&\ \fP
+..
+.\"
+.\" NS Fa macro - Function arguments
+.de Fa
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .Fa Function Arguments ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN Fa
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.ie \\n(fC>0 \{\
+. fC
+.\}
+.el \{\
+. if \\n(aC>\\n(aP \{\
+. as b1 \\*(fA
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+. if \\n(nS>0 \{\
+. if \\n(fZ>0 .br
+. \}
+. \}
+.\}
+..
+.\" NS fC macro - interal .Fa for .FO and .Fc
+.de fC
+.ie \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+.\" . nr aa \\n(aP
+.\" . if \\n(nS>0 \{\
+. ds Fb
+. nr fB 0
+. nr Fb 0
+. fB \\*(A\\n(aP
+. if \\n(fB>1 \{\
+. rm A\\n(aP
+. rn Fb A\\n(aP
+. \}
+.\" . \}
+. if \\n(fC>1 \{\
+. as b1 \&\f\\n(cF\s\\n(cZ,\\*(S\\n(aP\\*(fA\\*(A\\n(aP\fP\s0
+.\" . as b1 \&\\,\\*(S\\n(aP\fP\s0\\*(fA\\*(A\\n(aP\fP\s0
+. \}
+. if \\n(fC==1 \{\
+. as b1 \&\|\\*(fA\\*(A\\n(aP\fP\s0
+. \}
+. nr fC \\n(fC+1
+. fC
+.\}
+.el \{\
+. aY
+.\}
+..
+.\" NS Fn macro - functions
+.\" NS fY register - dick with old style function declarations (fortran)
+.\" NS fZ register - break a line when more than one function in a synopsis
+.\"
+.de Fn
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .Fn function_name function_arg(s) ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN Fn
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.if \\n(nS>0 \{\
+.\" if there is/has been more than one subroutine declaration
+. if \\n(fY==0 \{\
+. if \\n(fZ>0 \{\
+. Pp
+. nr fX 0
+. nr fD 0
+. \}
+. \}
+. if \\n(fY==1 \{\
+. br
+. nr fX 0
+. nr fD 0
+. nr fY 0
+. \}
+. if \\n(fD>0 \{\
+. Pp
+. nr fX 0
+. \}
+. if \\n(fX>0 \{\
+. Pp
+. nr fD 0
+. \}
+. nr fZ \\n(fZ+1
+. nr fY 0
+. rs
+. ie \\n(nS>1 .br
+. el \{\
+. if \\n(iS==0 \{\
+. nr iS ((8)*\\n(fW)u
+. \}
+. \}
+. in +\\n(iSu
+. ti -\\n(iSu
+. nr nS \\n(nS+1
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. as b1 \\*(fN\\*(A\\n(aP\fP\s0\\*(lp
+. ie \\n(aC>\\n(aP \{\
+. as b1 \\*(fA
+. nr aP \\n(aP+1
+. f\\n(C\\n(aP
+. \}
+. el \{\
+. as b1 \|\\*(rp
+. aZ
+. \}
+. if \\n(nS>0 \{\
+. in -\\n(iSu
+. \}
+.\}
+..
+.\"
+.\" NS f1 macro - class switch
+.\" NS f2 macro - handle function arguments
+.\" NS f3 macro - punctuation
+.\" NS f4 macro - write out function
+.de f1
+.as b1 \\*(rp\f\\n(cF\s\\n(cZ
+.\\*(A\\n(aP
+..
+.de f2
+.if \\n(nS>0 \{\
+. ds Fb
+. nr fB 0
+. nr Fb 0
+. fB \\*(A\\n(aP
+. if \\n(fB>1 \{\
+. rm A\\n(aP
+. rn Fb A\\n(aP
+. \}
+.\}
+.as b1 \\*(A\\n(aP
+.ie \\n(aC>\\n(aP \{\
+. nr aa \\n(aP
+. nr aP \\n(aP+1
+. if \\n(C\\n(aP==2 \{\
+. as b1 \&\|\f\\n(cF\s\\n(cZ,\\*(S\\n(aa\fP\s0\|
+. \}
+. f\\n(C\\n(aP
+.\}
+.el \{\
+. as b1 \\*(rp\f\\n(cF\s\\n(cZ
+. aZ
+.\}
+..
+.de f3
+.as b1 \\*(rp\f\\n(cF\s\\n(cZ\\*(A\\n(aP
+.ie \\n(aC>\\n(aP \{\
+. No
+.\}
+.el .aZ
+..
+.de f4
+.as b1 \\*(rp\f\\n(cF\s\\n(cZ\\*(S\\n(aP\\*(A\\n(aP
+.ie \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. No
+.\}
+.el .aZ
+..
+.de Fo
+.hy 0
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .Fo function_name
+. el \{\
+. ds mN Fo
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.if \\n(nS>0 \{\
+.\" if there is/has been more than one subroutine declaration
+. if \\n(fY==0 \{\
+. if \\n(fZ>0 \{\
+. Pp
+. nr fX 0
+. nr fD 0
+. \}
+. \}
+. if \\n(fY==1 \{\
+. br
+. nr fX 0
+. nr fD 0
+. nr fY 0
+. \}
+. if \\n(fD>0 \{\
+. Pp
+. nr fX 0
+. \}
+. if \\n(fX>0 \{\
+. Pp
+. nr fD 0
+. \}
+. nr fZ \\n(fZ+1
+. nr fY 0
+. rs
+. ie \\n(nS>1 .br
+. el \{\
+. if \\n(iS==0 \{\
+. nr iS ((8)*\\n(fW)u
+. \}
+. \}
+. in +\\n(iSu
+. ti -\\n(iSu
+. nr nS \\n(nS+1
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr oM \\n(oM+1
+. nr fC 1
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. as b1 \\*(fN\\*(A\\n(aP\fP\s0\\*(lp
+. aY
+.\}
+..
+.de Fc
+.if \\n(aC==0 \{\
+. if \\n(.$>0 \{\
+. ds mN Fo
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.nr fC 0
+.nr oM \\n(oM-1
+.as b1 \|\\*(rp
+.ie \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. \\*(A\\n(aP
+.\}
+.el \{\
+. aZ
+.\}
+.if \\n(nS>0 \{\
+. in -\\n(iSu
+.\}
+.hy
+..
+.\" NS fb macro - if SYNOPSIS, set hard space inbetween function args
+.\" NS fb register - count of words in a function argument
+.\" NS Fb register - counter
+.\" NS Fb string - temporary string
+.de fB
+.\" .tm fB==\\n(fB, Fb==\\n(Fb, 1==\\$1 2==\\$2 3==\\$3 4==\\$4 5==\\$5 6==\\$6
+.if \\n(fB==0 \{\
+. nr fB \\n(.$
+. nr Fb 0
+. ds Fb
+.\}
+.nr Fb \\n(Fb+1
+.as Fb \&\\$1
+.if \\n(Fb<\\n(fB \{\
+. as Fb \&\\*(hV
+. fB \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.\}
+..
+.\" NS Fc - Function close - not implemented yet
+.\" NS Fo - Function open - not implemented yet
+.\"
+.\" Very crude references, stash all reference info into strings (usual
+.\" use of b1 buffer, then b1 contents copied to string of retrievable
+.\" naming convention), print out reference on .Re request and clean up.
+.\" Ordering very limited, no fancy citations, but can do articles, journals
+.\" and books - need to add several missing options (like city etc).
+.\" should be able to grab a refer entry, massage it a wee bit (prefix
+.\" a `.' to the %[A-Z]) and not worry (ha!)
+.\"
+.\" NS Rs macro - Reference Start
+.\" NS rS register - Reference Start flag
+.\" NS rS string - Reference Start buffer name for next save (of b1 buffer)
+.de Rs
+.nr rS 1
+.rC
+.if \\n(nA==1 .Pp
+.nr Kl 0
+..
+.\" NS Re macro - Reference End
+.de Re
+.rZ
+.rC
+.nr rS 0
+..
+.\" NS rC macro - reference cleanup
+.de rC
+.nr uK 0
+.nr jK 0
+.nr nK 0
+.nr oK 0
+.nr qK 0
+.nr rK 0
+.nr tK 0
+.nr vK 0
+.nr dK 0
+.nr pK 0
+.nr bK 0
+.ds rS
+.rm U1 U2 U3 U4 U5 U6 U7 U8
+.rm uK jK nK oK rK qK tK vK dK pK bK
+..
+.\" NS rZ macro - reference print
+.de rZ
+.if \\n(uK \{\&\\*(U1,
+. nr aK 1
+. if (\\n(uK>1 \{\
+. aK
+. \}
+. nr Kl -\\n(uK
+.\}
+.if \\n(tK \{\
+. nr Kl \\n(Kl-1
+. if \\n(Kl==0 \{\
+. ie (\\n(jK==1):(\\n(bK==1) \{\&\\*q\\*(tK\\*q.
+. \}
+. el \{\&\\*(eM\\*(tK\\*(nO.
+. \}
+. \}
+. if \\n(Kl>0 \{\
+. ie (\\n(jK==1):(\\n(bK==1) \{\&\\*q\\*(tK\\*q,
+. \}
+. el \{\&\\*(eM\\*(tK\\*(nO,
+. \}
+. \}
+.\}
+.if \\n(bK \{\
+. nr Kl \\n(Kl-1
+. if \\n(Kl==0 \&\\*(eM\\*(bK\\*(nO.
+. if \\n(Kl>0 \&\\*(eM\\*(bK\\*(nO,
+.\}
+.if \\n(jK \{\
+. nr Kl \\n(Kl-1
+. if \\n(Kl==0 \&\\*(eM\\*(jK\\*(nO.
+. if \\n(Kl>0 \&\\*(eM\\*(jK\\*(nO,
+.\}
+.if \\n(rK \{\
+. nr Kl \\n(Kl-1
+. if \\n(Kl==0 \&\\*(rK.
+. if \\n(Kl>0 \&\\*(rK,
+.\}
+.if \\n(nK \{\
+. nr Kl \\n(Kl-1
+. if \\n(Kl==0 \&\\*(nK.
+. if \\n(Kl>0 \&\\*(nK,
+.\}
+.if \\n(vK \{\
+. nr Kl \\n(Kl-1
+. if \\n(Kl==0 \&\\*(vK.
+. if \\n(Kl>0 \&\\*(vK,
+.\}
+.if \\n(pK \{\
+. nr Kl \\n(Kl-1
+. if \\n(Kl==0 \&\\*(pK.
+. if \\n(Kl>0 \&\\*(pK,
+.\}
+.if \\n(qK \{\
+. nr Kl \\n(Kl-1
+. if \\n(Kl==0 \&\\*(qK.
+. if \\n(Kl>0 \&\\*(qK,
+.\}
+.if \\n(dK \{\
+. nr Kl \\n(Kl-1
+. if \\n(Kl==0 \&\\*(dK.
+. if \\n(Kl>0 \&\\*(dK,
+.\}
+.if \\n(oK \{\
+. nr Kl \\n(Kl-1
+. if \\n(Kl==0 \&\\*(oK.
+. if \\n(Kl>0 \&\\*(oK,
+.\}
+.if \\n(Kl>0 .tm unresolved reference problem
+..
+.\" NS aK macro - print out reference authors
+.de aK
+.nr aK \\n(aK+1
+.ie (\\n(uK-\\n(aK)==0 \{\&and \\*(U\\n(aK,
+.\}
+.el \{\&\\*(U\\n(aK,
+. aK
+.\}
+..
+.\" NS %A macro - reference author(s)
+.\" NS uK register - reference author(s) counter
+.\" NS U[1-9] strings - reference author(s) names
+.de %A
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .%A Author_name (#\\n(.c)
+. el \{\
+. nr uK \\n(uK+1
+. nr Kl \\n(Kl+1
+. ds rS U\\n(uK
+. ds mN %A
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. rR
+.\}
+..
+.\" NS %B macro - [reference] Book Name
+.\" NS bK string - Book Name
+.\" NS bK register - Book Name flag
+.de %B
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .%B Book Name (#\\n(.c)
+. el \{\
+. ds mN %B
+. if \\n(rS>0 \{\
+. nr bK \\n(bK+1
+. nr Kl \\n(Kl+1
+. ds rS bK
+. \}
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. ie \\n(rS==0 \{\
+. as b1 \&\\*(eM
+. nR
+. \}
+. el .rR
+.\}
+..
+.\" NS %D macro - [reference] Date
+.\" NS dK string - Date String
+.\" NS dK register - Date flag
+.de %D
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .%D Date (#\\n(.c)
+. el \{\
+. ds mN %D
+. nr dK \\n(dK+1
+. nr Kl \\n(Kl+1
+. ds rS dK
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. rR
+.\}
+..
+.\" NS %J macro - [reference] Journal Name
+.\" NS jK register - [reference] Journal Name flag
+.\" NS jK string - [reference] Journal Name
+.de %J
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .%J Journal Name (#\\n(.c)
+. el \{\
+. ds mN %J
+. nr jK \\n(jK+1
+. ds rS jK
+. nr Kl \\n(Kl+1
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. rR
+.\}
+..
+.\" NS %N macro - [reference] issue number
+.\" NS nK register - [reference] issue number flag
+.\" NS nK string - [reference] issue number
+.de %N
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .%N issue number (#\\n(.c)
+. el \{\
+. nr nK \\n(nK+1
+. nr Kl \\n(Kl+1
+. ds rS nK
+. ds mN %N
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. rR
+.\}
+..
+.\" NS %O macro - [reference] optional information
+.\" NS oK register - [reference] optional information flag
+.\" NS oK string - [reference] optional information
+.de %O
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .%O optional information ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN %O
+. nr oK \\n(oK+1
+. nr Kl \\n(Kl+1
+. ds rS oK
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. rR
+.\}
+..
+.\" NS %P macro - [reference] page numbers
+.\" NS pK register - [reference] page number flag
+.\" NS pK string - [reference] page number
+.de %P
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .%P page numbers ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN %P
+. nr pK \\n(pK+1
+. nr Kl \\n(Kl+1
+. ds rS pK
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. rR
+.\}
+..
+.\" NS %Q macro - Corporate or Foreign Author
+.\" NS qK string - Corporate or Foreign Author
+.\" NS qK register - Corporate or Foreign Author flag
+.de %Q
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .%Q Corporate or Foreign Author (#\\n(.c)
+. el \{\
+. ds mN %Q
+. nr qK \\n(qK+1
+. nr Kl \\n(Kl+1
+. ds rS qK
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. rR
+.\}
+..
+.\" NS %R macro - [reference] report name
+.\" NS rK string - [reference] report name
+.\" NS rK register - [reference] report flag
+.de %R
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .%R reference report (#\\n(.c)
+. el \{\
+. ds mN %R
+. nr rK \\n(rK+1
+. nr Kl \\n(Kl+1
+. ds rS rK
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. rR
+.\}
+..
+.\" NS %T macro - reference title
+.\" NS tK string - reference title
+.\" NS tK register - reference title flag
+.de %T
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .%T (#\\n(.c)
+. el \{\
+. ds mN %T
+. if \\n(rS>0 \{\
+. nr tK \\n(tK+1
+. nr Kl \\n(Kl+1
+. ds rS tK
+. \}
+. ds A1 \\$1
+. ds A2 \\$2
+. ds A3 \\$3
+. ds A4 \\$4
+. ds A5 \\$5
+. ds A6 \\$6
+. ds A7 \\$7
+. ds A8 \\$8
+. ds A9 \\$9
+. nr fV \\n(.$
+. fV
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+.\" . ie \\n(jS==1 \{\
+.\" . nr cF \\n(.f
+.\" . nr cZ \\n(.s
+.\" . ds qL \&\\*(Lq\\*(rA
+.\" . ds qR \&\\*(Rq\f\\n(cF\s\\n(cZ
+.\" . En \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.\" . \}
+.\" . el \{\
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. ie \\n(rS==0 \{\
+. as b1 \&\\*(eM
+. nR
+. \}
+. el .rR
+.\" . \}
+.\}
+..
+.\" NS %V macro - reference volume
+.\" NS vK string - reference volume
+.\" NS vK register - reference volume flag
+.de %V
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .%V Volume , ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN %V
+. nr vK \\n(vK+1
+. nr Kl \\n(Kl+1
+. ds rS vK
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. rR
+.\}
+..
+.\" NS rR macro - reference recursion routine
+.\" NS jM local register
+.\" NS jN local register
+.de rR
+.hy 0
+.nr jM \\n(C\\n(aP
+.ie \\n(jM==1 \{\
+.\" . as b1 \&\f\\n(cF\s\\n(cZ
+. ie "\\*(A\\n(aP"Tn" \{\
+. nN
+. \}
+. el \{\
+. if \\n(aC>8 .tm Usage: \\*(mN - maximum 8 arguments (#\\n(.c)
+. aI rR 1
+. \\*(A\\n(aP
+. \}
+.\}
+.el \{\
+. nr jN \\n(aP
+. ie \\n(jM==2 .as b1 \&\\*(A\\n(aP
+. el .as b1 \&\\*(A\\n(aP
+.\" . el .as b1 \&\f\\n(cF\s\\n(cZ\\*(A\\n(aP\fP\s0
+. ie \\n(aC==\\n(aP \{\
+.\" . as b1 \&\f\\n(cF\s\\n(cZ
+. rD
+. \}
+. el \{\
+. nr aP \\n(aP+1
+. as b1 \&\\*(S\\n(jN
+. rR
+. \}
+.\}
+.rr jM jN
+..
+.\" NS rD macro - save b1 buffer in to appropriate name
+.de rD
+.as \\*(rS \\*(b1
+.ds b1
+.ds rS
+.aY
+..
+.\" NS Hf macro - source include header files.
+.de Hf
+.Pp
+File:
+.Pa \\$1
+.Pp
+.nr cF \\n(.f
+.nr cZ \\n(.s
+.ie t \{\
+\&\\*(lI
+.br
+.ta +9n 18n 27n 36n 45n 54n 63n 72n
+.\}
+.el \{\
+.ta +8n 16n 24n 32n 40n 48n 56n 64n 72n
+.\}
+.nf
+.so \\$1
+.fi
+.ft \\n(cF
+.fz \\n(cZ
+.Pp
+..
+.\" NS An macro - author name
+.\" NS aN register
+.nr aN 0
+.de An
+.if \\n(nY==1 \{\
+. ie \\n(aN==1 \{\
+. br
+. \}
+. el \{\
+. nr aN 1
+. \}
+.\}
+.if \\n(aC==0 \{\
+. ie \\n(.$==0 .tm Usage: .An author_name ... \\*(Pu (#\\n(.c)
+. el \{\
+. ds mN An
+. aV \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+.if \\n(aC>\\n(aP \{\
+. nr aP \\n(aP+1
+. nr cF \\n(.f
+. nr cZ \\n(.s
+. nR
+.\}
+..
+.\" NS Sf macro -defunct
+.de Sf
+.tm .Sf defunct, use prefix or Ns
+..
+.ds rV "function returns the value 0 if successful; otherwise the value -1 is returned and the global variable \\*(vAerrno\fP is set to indicate the error.
+.\" Ns Rv macro - return values
+.\" Ns rV string - standard return message
+.de Rv
+.ie \\n(.$==0 \{\
+.tm Usage: .Rv [-std] (#\\n(.c)
+.\}
+.el \{\
+. ds mN Rv
+.\" . nr aP 0
+.\" . nr lR \\n(lR+1
+.\" . ds A1 \\$2
+.\" . ds A2 \\$3
+.\" . ds A3 \\$4
+.\" . ds A4 \\$5
+.\" . ds A5 \\$6
+.\" . ds A6 \\$7
+.\" . ds A7 \\$8
+.\" . ds A8 \\$9
+.\" . nr fV \\n(.$-1
+. if "\\$1"-std" \{\
+. nr cH \\*(cH
+. if (\\n(cH<2):(\\n(cH>3) .tm Usage: .Rv -std sections 2 and 3 only
+. br
+\&The
+.Fn \\$2
+\&\\*(rV
+. \}
+.\}
+..
diff --git a/tmac/tmac.dvi b/tmac/tmac.dvi
new file mode 100755
index 00000000..59c6df50
--- /dev/null
+++ b/tmac/tmac.dvi
@@ -0,0 +1,135 @@
+.nr _C \n(.C
+.cp 0
+.ftr CR CW
+.ftr C CW
+.ftr TT CW
+.ftr HR H
+.\" This uses the dvi-char_1 string in font CW, dvi-char_0 otherwise.
+.char _ \R'dvi-char_ \\n(.f=\f(CW\\n(.f\fP'\\*[dvi-char_\\n[dvi-char_]]
+.char \[ul] \R'dvi-char_ \w'M'=\w'i''\\*[dvi-char_\\n[dvi-char_]]
+.\" Normally use a rule.
+.\" This is designed so that \(ul, \(rn and \(br form corners.
+.ds dvi-char_0 \Z'\v'.23m'\D'R .54m .04m''\h'.5m'
+.\" In font CW use a real _ character.
+.ds dvi-char_1 _
+.if !c\[radicalex] .char \[radicalex] \D'R .5m -.04m'\v'.04m'
+.if !c\[br] .char \[br] \Z'\v'.25m'\D'R .04m -1m''
+.if !c\[ru] .char \[ru] \Z'\v'-.02m'\D'R .54m .04m''\h'.5m'
+.if !c\[rn] .char \[rn] \Z'\v'-.77m'\D'R .54m .04m''\h'.5m'
+.if !c\[co] .char \[co] \z\(ci\h'\w'\(ci'u-\w'c'u/2u'c\h'\w'\(ci'u-\w'c'u/2u'
+.if !c\[rg] .char \[rg] \z\(ci\h'\w'\(ci'u-\w'r'u/2u'r\h'\w'\(ci'u-\w'r'u/2u'
+.if !c\[fm] .char \[fm] \v'-.35m'\s[\\n(.s*7u/10u]\[prime]\s0\v'.35m'
+.if !c\[de] .char \[de] \h'.05m'\v'-.54m'\D'c .3m'\v'.54m'\h'.05m'
+.if !c\[ct] .char \[ct] \o'c/'
+.if !c\[sq] .char \[sq] \Z'\h'.05m'\D'R .4m -.04m'\v'.04m'\h'-.04m'\
+\D'R .04m -.4m'\v'.04m'\D'R -.4m -.04m'\D'R .04m .4m''\h'.5m'
+.\"char \[sq] \h'.05m'\D'l .4m 0'\D'l 0 -.4m'\D'l -.4m 0'\D'l 0 .4m'\h'.45m'
+.if !c\[!=] .char \[!=] \[slashnot]\(eq
+.if !c\[tm] .char \[tm] \v'-.3m'\s[\\n(.s/2u]TM\s0\v'.3m'
+.if !c\[aq] .char \[aq] '
+.if !c\[bq] .char \[bq] ,
+.if !c\[Bq] .char \[Bq] ,\h'\w'\(rq'u-(2u*\w"'"u)',
+.if !c\[ho] .char \[ho] \s[\En[.s]/2u]\v'.4m'c\v'-.4m'\s0
+.if !c\[-D] .char \[-D] \Z'\v'-.1m'\h'.05m'-'D
+.if !c\[Sd] .char \[Sd] \Z'\v'-.3m'\h'.35m'-'\(pd
+.if !c\[TP] .char \[TP] I\h'-.25m'\v'-.33m'\s[\En[.s]*6u/10u]\v'.33m'D\
+\v'-.33m'\s0\v'.33m'
+.if !c\[Tp] .char \[Tp] \zlp
+.if !c\[nb] .char \[nb] \[slashnot]\(sb
+.cflags 8 \(an
+.if !c\[an] .char \[an] \h'-.167m'\(mi\h'-.167m'
+.\" Define some fractions.
+.de dvi-frac
+.if !c\[\\$1\\$2] .char \[\\$1\\$2] \
+\v'-.25m'\s[\\\\n(.s*7u/10u]\\$1\s0\v'.25m'\h'-.2m'\
+/\h'-.2m'\v'.25m'\s[\\\\n(.s*7u/10u]\\$2\s0\v'-.25m'
+..
+.dvi-frac 1 2
+.dvi-frac 3 4
+.dvi-frac 1 4
+.dvi-frac 1 8
+.dvi-frac 3 8
+.dvi-frac 5 8
+.dvi-frac 7 8
+.\" support for ISO Latin-1
+.if !c\[S1] .char \[S1] \v'-.2m'\s-31\s+3\v'+.2m'
+.if !c\[S2] .char \[S2] \v'-.2m'\s-32\s+3\v'+.2m'
+.if !c\[S3] .char \[S3] \v'-.2m'\s-33\s+3\v'+.2m'
+.if !c\[Of] .char \[Of] \v'-.2m'\s'\En(.s*6u/10u'\o'_a'\s0\v'.2m'
+.if !c\[Om] .char \[Om] \v'-.2m'\s'\En(.s*6u/10u'\o'_o'\s0\v'.2m'
+.if !c\[Fo] .char \[Fo] <<
+.if !c\[Fc] .char \[Fc] >>
+.if !c\[bb] .char \[bb] |
+.if !c\[Ye] .char \[Ye] \o'-Y'
+.if !c\[Cs] .char \[Cs] \o'\[mu]o'
+.de dvi-achar
+.\" Note that character definitions are always interpreted with
+.\" compatibility mode off.
+.if !c\\$1 \{\
+.char \\$1 \\$3\
+\k[acc]\
+\h'(u;-\w'\\$2'-\w'\\$3'/2+\\\\n[skw]+(\w'x'*0)-\\\\n[skw])'\
+\v'(u;\w'x'*0+\\\\n[rst]+(\w'\\$3'*0)-\\\\n[rst])'\
+\\$2\
+\v'(u;\w'x'*0-\\\\n[rst]+(\w'\\$3'*0)+\\\\n[rst])'\
+\h'|\\\\n[acc]u'
+.\}
+.hcode \\$1\\$4
+..
+.dvi-achar \(`A \` A a
+.dvi-achar \('A \' A a
+.dvi-achar \(^A ^ A a
+.dvi-achar \(~A ~ A a
+.dvi-achar \(:A \(ad A a
+.dvi-achar \(oA \(ao A a
+.dvi-achar \(`E \` E e
+.dvi-achar \('E \' E e
+.dvi-achar \(^E ^ E e
+.dvi-achar \(:E \(ad E e
+.dvi-achar \(`I \` I i
+.dvi-achar \('I \' I i
+.dvi-achar \(^I ^ I i
+.dvi-achar \(:I \(ad I i
+.dvi-achar \(~N ~ N n
+.dvi-achar \(`O \` O o
+.dvi-achar \('O \' O o
+.dvi-achar \(^O ^ O o
+.dvi-achar \(~O ~ O o
+.dvi-achar \(:O \(ad O o
+.dvi-achar \(`U \` U u
+.dvi-achar \('U \' U u
+.dvi-achar \(^U ^ U u
+.dvi-achar \(:U \(ad U u
+.dvi-achar \('Y \' Y y
+.dvi-achar \(`a \` a a
+.dvi-achar \('a \' a a
+.dvi-achar \(^a ^ a a
+.dvi-achar \(~a ~ a a
+.dvi-achar \(:a \(ad a a
+.dvi-achar \(oa \(ao a a
+.dvi-achar \(`e \` e e
+.dvi-achar \('e \' e e
+.dvi-achar \(^e ^ e e
+.dvi-achar \(:e \(ad e e
+.dvi-achar \(`i \` \(.i i
+.dvi-achar \('i \' \(.i i
+.dvi-achar \(^i ^ \(.i i
+.dvi-achar \(:i \(ad \(.i i
+.dvi-achar \(~n ~ n n
+.dvi-achar \(`o \` o o
+.dvi-achar \('o \' o o
+.dvi-achar \(^o ^ o o
+.dvi-achar \(~o ~ o o
+.dvi-achar \(:o \(ad o o
+.dvi-achar \(`u \` u u
+.dvi-achar \('u \' u u
+.dvi-achar \(^u ^ u u
+.dvi-achar \(:u \(ad u u
+.dvi-achar \('y \' y y
+.dvi-achar \(:y \(ad y y
+.if !c\(,C .char \(,C \o'\(acC'
+.hcode \(,Cc
+.if !c\(,c .char \(,c \o'\(acc'
+.hcode \(,cc
+.cp \n(_C
+.do mso tmac.latin1
diff --git a/tmac/tmac.e b/tmac/tmac.e
new file mode 100755
index 00000000..3a4eb86a
--- /dev/null
+++ b/tmac/tmac.e
@@ -0,0 +1,1661 @@
+.\" @(#)tmac.e 2.31 (Berkeley) 5/21/88
+.\" Modified by James Clark for use with groff.
+.\"
+.\" Copyright (c) 1988 Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms are permitted
+.\" provided that this notice is preserved and that due credit is given
+.\" to the University of California at Berkeley. The name of the University
+.\" may not be used to endorse or promote products derived from this
+.\" software without specific prior written permission. This software
+.\" is provided ``as is'' without express or implied warranty.
+.\" %beginstrip%
+.\"
+.\"**********************************************************************
+.\"* *
+.\"* ****** - M E N R O F F / T R O F F M A C R O S ****** *
+.\"* *
+.\"* Produced for your edification and enjoyment by: *
+.\"* Eric Allman *
+.\"* Electronics Research Laboratory *
+.\"* U.C. Berkeley. *
+.\"* current address: *
+.\"* Britton-Lee, Inc. *
+.\"* 1919 Addison Street Suite 105 *
+.\"* Berkeley, California 94704 *
+.\"* *
+.\"* VERSION 2.31 First Release: 11 Sept 1978 *
+.\"* *
+.\"* Documentation is available. *
+.\"* *
+.\"**********************************************************************
+.\"
+.\" Code on .de commands:
+.\" *** a user interface macro.
+.\" &&& a user interface macro which is redefined
+.\" when used to be the real thing.
+.\" $$$ a macro which may be redefined by the user
+.\" to provide variant functions.
+.\" --- an internal macro.
+.\"
+.if !\n(.g .ig
+.de @R \" --- initialize number register to 0, if undefined
+.if !r\\$1 .nr \\$1 0
+..
+.@R pf
+.if \n(pf .nx
+.if !\n(.g .ig
+.de @S \" --- initialize string/macro to empty, if undefined
+.if !d\\$1 .ds \\$1 \" empty
+..
+.@R @\" \" debugging level
+.\" *** INTERNAL GP MACROS ***
+.de @C \" --- change ev's, taking info with us
+.nr _S \\n(.s
+.nr _V \\n(.v
+.nr _F \\n(.f
+.do ds _A \\n[.fam]
+.nr _I \\n(.i
+.ev \\$1
+.ps \\n(_S
+.vs \\n(_Vu
+.ft \\n(_F
+.do @fam \\*(_A
+'in \\n(_Iu
+.xl \\n($lu
+.lt \\n($lu
+.rr _S
+.rr _V
+.rr _F
+.rr _I
+.ls 1
+'ce 0
+..
+.de @D \" --- determine display type (Indent, Left, Center)
+.ds |p "\\$3
+.nr _d 0
+.if "\\$2"C" \
+. nr _d 1
+.if "\\$2"L" \
+. nr _d 2
+.if "\\$2"I" \
+. nr _d 3
+.if "\\$2"M" \
+. nr _d 4
+.if !\\n(_d \{\
+. nr _d \\$1
+. ds |p "\\$2
+.\}
+..
+.de @z \" --- end macro
+.if \n@>1 .tm >> @z, .z=\\n(.z ?a=\\n(?a
+.if !"\\n(.z"" \
+\{\
+. tm Line \\n(c. -- Unclosed block, footnote, or other diversion (\\n(.z)
+. di
+. ex
+.\}
+.if \\n(?a \
+. bp \" force out final table
+.ds bp
+.ds @b\" \" don't start another page
+.br
+.if \n@>1 .tm << @z
+..
+.\" *** STANDARD HEADERS AND FOOTERS ***
+.ie \n(.g .ds $* \\\\$*
+.el .ds $* \\\\$1 \\\\$2 \\\\$3 \\\\$4 \\\\$5 \\\\$6 \\\\$7 \\\\$8 \\\\$9
+.de he \" *** define header
+.ie !\\n(.$ \
+\{\
+. rm |4
+. rm |5
+.\}
+.el \
+\{\
+. ds |4 "\*($*
+. ds |5 "\*($*
+.\}
+..
+.de eh \" *** define even header
+.ie !\\n(.$ \
+. rm |4
+.el \
+. ds |4 "\*($*
+..
+.de oh \" *** define odd header
+.ie !\\n(.$ \
+. rm |5
+.el \
+. ds |5 "\*($*
+..
+.de fo \" *** define footer
+.ie !\\n(.$ \
+\{\
+. rm |6
+. rm |7
+.\}
+.el \
+\{\
+. ds |6 "\*($*
+. ds |7 "\*($*
+.\}
+..
+.de ef \" *** define even foot
+.ie !\\n(.$ \
+. rm |6
+.el \
+. ds |6 "\*($*
+..
+.de of \" *** define odd footer
+.ie !\\n(.$ \
+. rm |7
+.el \
+. ds |7 "\*($*
+..
+.de ep \" *** end page (must always be followed by a .bp)
+.if \\n(nl>0 \
+\{\
+. wh 0
+. rs
+. @b
+.\}
+..
+.\" *** INTERNAL HEADER AND FOOTER MACROS ***
+.de @h \" --- header
+.if \n@>1 .tm >> @h %=\\n% ?a=\\n(?a ?b=\\n(?b ?w=\\n(?w
+.if (\\n(.i+\\n(.o)>=\\n(.l \
+. tm Line \\n(c. -- Offset + indent exceeds line length
+.\" initialize a pile of junk
+.nr ?h \\n(?H \" transfer "next page" to "this page"
+.nr ?H 0
+.nr ?c \\n(?C
+.nr ?C 0
+.rn |4 |0
+.rn |5 |1
+.rn |6 |2
+.rn |7 |3
+.nr _w 0 \" reset max footnote width
+.nr ?W 0 \" no wide floats this page (yet)
+.nr ?I 1
+.\" begin actual header stuff
+.ev 2
+.rs
+.if \\n(hm>0 \
+. sp |\\n(hmu \" move to header position
+.@t $h \" output header title
+.if \\n(tm<=0 \
+. nr tm \n(.Vu
+.sp |\\n(tmu \" move to top of text
+.ev
+.mk _k \" for columned output
+.if \\n(?n .nm 1 \" restore line numbering if n1 mode
+.nr $c 1 \" set first column
+.if \n@>4 .tm -- @h >> .ns nl=\\n(nl %=\\n% _k=\\n(_k tm=\\n(tm
+.ie \\n(?s \
+\{\
+. nr ?s 0
+. rs
+' @b
+.\}
+.el \
+. @n \" begin the column
+.if \n@>2 .tm << @h
+..
+.de @n \" --- new column or page
+.if \n@>3 .tm >> @n nl=\\n(nl %=\\n% ?f=\\n(?f ?o=\\n(?o
+.if \\n(bm<=0 \
+. nr bm \\n(.Vu
+.if (\\n(_w<=\\n($l)&(\\n(?W=0) \
+\{\
+. nr _b (\\n(ppp*\\n($vu)/200u \" compute fudge factor (must be < 1P)
+. if \\n(_bu>((\\n(bmu-\\n(fmu-((\\n(tpp*\\n($vu)/100u))/2u) \
+. nr _b (\\n(ppp*\\n($vu)/100u-\n(.Vu
+. nr _b +\\n(bmu
+.\}
+.nr _B \\n(_bu
+.ch @f
+.wh -\\n(_bu @f
+.nr _b +(\\n(ppp*\\n($vu)/100u \" add 1 paragraph v in case of sweep past
+.if \n@>2 .tm @n .p=\\n(.p bm=\\n(bm _b=\\n(_b _B=\\n(_B
+.nr ?f 0 \" reset footnote flag
+.if \\n(?o \
+\{\
+. (f _ \" reprocess footnotes which run off page
+. nf
+. |o
+. fi
+. )f
+. rm |o
+.\}
+.nr ?o 0
+.if \\n(?T \
+\{\
+. nr _i \\n(.i
+. in 0
+. |h \" output the table header
+. in \\n(_iu
+. rr _i
+. mk #T \" for tbl commands
+. ns
+.\}
+.if (\\n(?a)&((\\n($c<2):(\\n(?w=0)) \
+\{\
+. nr ?a 0 \" output floating keep
+. @k |t
+. if \\n(?w \
+. mk _k \" don't overstrike wide keeps
+. nr ?w 0
+.\}
+.os
+.$H \" special column header macro
+.ns
+..
+.de @f \" --- footer
+.if \n@>1 .tm >> @f %=\\n% nl=\\n(nl ?a=\\n(?a ?b=\\n(?b ?f=\\n(?f
+.if \n@>2 .nr VL \\n(.pu-\\n(nlu
+.if \n@>2 .tm @f bm=\\n(bm _B=\\n(_B _b=\\n(_b .p-nl=\\n(VL
+.ec
+.if \\n(?T \
+\{\
+. nr T. 1 \" for tbl commands (to output bottom line)
+. T# 1 \" output the sides and bottom lines
+. br
+.\}
+.ev 2
+.ce 0
+.if \\n(?b \
+\{\
+. nr ?b 0
+. @k |b\" \" output bottom of page tables
+.\}
+.if \\n(?f \
+. @o \" output footnote if present
+.ie \\n($c<\\n($m \
+. @c \" handle new column
+.el \
+. @e \" new page
+.ev
+.if \n@>2 .tm << @f
+..
+.de @o \" --- output footnote
+.nf
+.ls 1
+.in 0
+.if \n@>2 .tm @o last printed text = \\n(nl placing @r trap at -\\n(_B
+.wh -\\n(_Bu @r
+.|f
+.fi
+.if \n@>2 .tm @o triggered @r (?o) = \\n(?o
+.if \\n(?o \
+\{\
+. di \" just in case triggered @r
+. if \\n(dn=0 \
+\{\
+. rm |o
+. nr ?o 0
+. \}
+. nr dn \\n(_D
+. rr _D
+.\}
+.rm |f
+.ch @r
+..
+.de @c \" --- new column
+.if \n@>2 .tm >> @c %=\\n%
+.rs
+.sp |\\n(_ku
+.@O +\\n($lu+\\n($su
+.nr $c +1
+.@n
+..
+.de @e \" --- end page
+.if \n@>2 .tm >> @e
+.@O \\n(_ou
+.rs
+.sp |\\n(.pu-\\n(fmu-((\\n(tpp*\\n($vu)/100u) \" move to footer position
+.@t $f \" output footer title
+.nr ?h 0
+.bp
+..
+.de @t \" --- output header or footer title
+.if !\\n(?h \
+\{\
+. sz \\n(tp \" set header/footer type fonts, etc.
+. @F \\n(tf
+. lt \\n(_Lu \" make title span entire page
+. nf
+. \\$1
+. br
+.\}
+..
+.de $h \" $$$ print header
+.ds |z
+.if !\\n(?c \
+\{\
+. if e .ds |z "\\*(|0
+. if o .ds |z "\\*(|1
+.\}
+.if !\(ts\\*(|z\(ts\(ts \
+' tl \\*(|z
+.rm |z
+..
+.de $f \" $$$ print footer
+.ds |z
+.if \\n(?c \
+\{\
+. if e .ds |z "\\*(|0
+. if o .ds |z "\\*(|1
+.\}
+.if \(ts\\*(|z\(ts\(ts \
+\{\
+. if e .ds |z "\\*(|2
+. if o .ds |z "\\*(|3
+.\}
+.if !\(ts\\*(|z\(ts\(ts \
+' tl \\*(|z
+.rm |z
+..
+.de @r \" --- reprocess overflow footnotes
+.if \n@>3 .tm >> @r .z=\\n(.z ?f=\\n(?f ?a=\\n(?a ?b=\\n(?b _b=\\n(_b
+.di |o \" save overflow footnote
+.nr ?o 1
+.nr _D \\n(dn
+.ns
+..
+.\" *** COMMANDS WITH VARIANT DEFINITIONS ***
+.rn bp @b \" --- begin page
+.de bp \" *** begin new page (overrides columns)
+.nr $c \\n($m \" force new page, not new column
+.ie \\n(nl>0 \
+. @b \\$1
+.el \
+\{\
+. if \\n(.$>0 \
+. pn \\$1
+. if \\n(?I \
+. @h \" 'spring' the header trap
+.\}
+.br
+.wh 0 @h \" reset header
+..
+.rn ll xl \" *** special line length (local)
+.de ll \" *** line length (global to environments)
+.xl \\$1
+.lt \\$1
+.nr $l \\n(.l
+.if (\\n($m<=1):(\\n($l>\\n(_L) \
+. nr _L \\n(.l
+..
+.rn po @O \" --- local page offset
+.de po \" *** page offset
+.@O \\$1
+.nr _o \\n(.o
+..
+.\" Redefine the fam request to set the family in
+.\" environment 2 as well as the current environment.
+.if !\n(.g .ig
+.do rn fam @fam \" --- set family in current environment
+.do de fam \" *** set font family in ev 2 and current ev
+.do @fam \\$1
+.ev 2
+.do @fam \\$1
+.ev
+..
+.\" *** MISCELLANEOUS ROFF COMMANDS ***
+.de hx \" *** suppress headers and footers next page
+.nr ?H 1
+..
+.de ix \" *** indent, no break
+'in \\$1
+..
+.de bl \" *** contiguous blank lines
+.br
+.ne \\$1
+.rs
+.sp \\$1
+..
+.de n1 \" *** line numbering 1
+.nm 1
+.xl -\w'0000'u
+.nr ?n 1
+..
+.de n2 \" *** line numbering 2
+.nm \\$1
+.ie \\n(.$ \
+. xl -\w'0000'u
+.el \
+. xl \\n($lu
+..
+.de pa \" *** new page
+.bp \\$1
+..
+.de ro \" *** roman page numbers
+.af % i
+..
+.de ar \" *** arabic page numbers
+.af % 1
+..
+.de m1 \" *** position one space
+.nr _0 \\n(hmu
+.nr hm \\$1v
+.nr tm +\\n(hmu-\\n(_0u
+.rr _0
+..
+.de m2 \" *** position two space
+.nr tm \\n(hmu+\\n(tpp+\\$1v
+..
+.de m3 \" *** position three space
+.nr bm \\n(fmu+\\n(tpp+\\$1v
+..
+.de m4 \" *** position four space
+.nr _0 \\n(fmu
+.nr fm \\$1v
+.nr bm +\\n(fmu-\\n(_0u
+..
+.de sk \" *** leave a blank page (next page)
+.if \\n(.$>0 \
+. tm Line \\n(c. -- I cannot skip multiple pages
+.nr ?s 1
+..
+.\" *** MISCELLANEOUS USER SUPPORT COMMANDS ***
+.if !\n(.g .ig
+.de re \" *** reset tabs (TROFF defines 15 stops default)
+.ta T 0.5i
+..
+.if \n(.g .ig
+.de re
+.ta 0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i
+..
+.de ba \" *** set base indent
+.ie \\n(.$ \
+. nr $i \\$1n
+.el \
+. nr $i \\n(siu*\\n($0u
+..
+.de hl \" *** draw horizontal line
+.br
+.ie \n(.g .do nr _I \\n[.in]
+.el .nr _I \\n(.i
+\l'\\n(.lu-\\n(_Iu'
+.sp
+..
+.\" *** PARAGRAPHING ***
+.de pp \" *** paragraph
+.lp \\n(piu
+..
+.de lp \" *** left aligned paragraph
+.@p
+.if \\n(.$ \
+. ti +\\$1
+.nr $p 0 1
+..
+.de ip \" *** indented paragraph w/ optional tag
+.if (\\n(ii>0)&(\\n(ii<1n) \
+. nr ii \\n(iin
+.nr _0 \\n(ii
+.if \\n(.$>1 \
+. nr _0 \\$2n
+.@p \\n(_0u
+.nr _I \\n(.iu
+.in 0
+.di |i
+\&\\$1
+.br
+.di
+.in \\n(_Iu
+.ds |j \\*(|i\\
+.if \\w"\\*(|j" \
+\{\
+. ti -\\n(_0u
+. ie \\w"\\*(|j">=\\n(_0 \
+\{\
+\\*(|j
+. br
+. \}
+. el \\*(|j\h'|\\n(_0u'\c
+.\}
+.rr _0
+.rm |i |j
+..
+.de np \" *** numbered paragraph
+.\" use string comparison in case user has changed format of $p
+.if '\\n($p'-1' \
+. nr $p 0 \" reset number after .bu
+.nr $p +1 \" increment paragraph number
+.@p \w'\0(000)\0'u
+.ti -\w'\0(000)\0'u
+\0(\\n($p)\h'|\w'\0(000)\0'u'\c
+..
+.de bu \" *** bulleted paragraph
+.br
+.\" use string comparison in case user has changed format of $p
+.if '\\n($p'-1' \
+. ns \" don't space between .bu paragraphs
+.nr $p 0-1 \" mark "bulleted paragraph" mode
+.@p \w'\0\(bu\0'u
+.ti -\w'\0\(bu\0'u
+\0\(bu\0\c
+..
+.de @p \" --- initialize for paragraph
+.if "\\n(.z"|e" .tm Line \\n(c. -- Unmatched continued equation
+.in \\n($iu+\\n(pou
+.if \\n(.$ \
+. in +\\$1n
+.ce 0
+.fi
+.@F \\n(pf
+.sz \\n(pp
+.sp \\n(psu
+.ne \\n(.Lv+\\n(.Vu
+.ns
+..
+.\" *** SECTION HEADINGS ***
+.de sh \" *** section heading
+.fi
+.if (\\n(si>0)&(\\n(si<1n) \
+. nr si \\n(sin
+.ce 0
+.@d "\\$1" +1 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
+.if !"\\$2"_" \
+\{\
+. ds |n \&\\$2
+. $p "\\*(|n" "\\*($n" \\n($0
+. $0 "\\*(|n" "\\*($n" \\n($0
+. rm |n
+.\}
+.nr $p 0 1 \" reset .np count
+..
+.de @d \" --- change section depth
+.if !""\\$1" \
+. nr $0 \\$1
+.if \\n($0&(\\n(.$>1) \
+. nr $\\n($0 \\$2
+.ds $n \&\"
+.ie \\n($0>=1 \
+\{\
+. if '\\n($1'0' \
+. nr $1 1
+. if (\\n(.$>=3) .if !"\\$3"-" \
+. nr $1 \\$3
+. as $n \\n($1
+.\}
+.el \
+. nr $1 0
+.ie \\n($0>=2 \
+\{\
+. if '\\n($2'0' \
+. nr $2 1
+. if (\\n(.$>=4) .if !"\\$4"-" \
+. nr $2 \\$4
+. as $n .\\n($2
+.\}
+.el \
+. nr $2 0
+.ie \\n($0>=3 \
+\{\
+. if '\\n($3'0' \
+. nr $3 1
+. if (\\n(.$>=5) .if !"\\$5"-" \
+. nr $3 \\$5
+. as $n .\\n($3
+.\}
+.el \
+. nr $3 0
+.ie \\n($0>=4 \
+\{\
+. if '\\n($4'0' \
+. nr $4 1
+. if (\\n(.$>=6) .if !"\\$6"-" \
+. nr $4 \\$6
+. as $n .\\n($4
+.\}
+.el \
+. nr $4 0
+.ie \\n($0>=5 \
+\{\
+. if '\\n($5'0' \
+. nr $5 1
+. if (\\n(.$>=7) .if !"\\$7"-" \
+. nr $5 \\$7
+. as $n .\\n($5
+.\}
+.el \
+. nr $5 0
+.ie \\n($0>=6 \
+\{\
+. if '\\n($6'0' \
+. nr $6 1
+. if (\\n(.$>=8) .if !"\\$8"-" \
+. nr $6 \\$8
+. as $n .\\n($6
+.\}
+.el \
+. nr $6 0
+..
+.de sx \" *** heading up, no increment (2.1.1 -> 2.1)
+.ce 0
+.ul 0
+.nr _0 \\n($0-1
+.if \\n(.$ .nr _0 +1
+.if \\n(.$ .nr _0 \\$1
+.@d \\n(_0
+.rr _0
+.$p "" "" \\n($0
+.nr $p 0 1 \" reset .np count
+..
+.de uh \" *** unnumbered section heading
+.$p "\\$1"
+.$0 "\\$1"
+..
+.de $p \" $$$ print section heading
+.if (\\n(si>0)&(\\n(.$>2) \
+. nr $i \\$3*\\n(si
+.in \\n($iu
+.ie !"\\$1\\$2"" \
+\{\
+. sp \\n(ssu \" one of them is non-null
+. ne \\n(.Lv+\\n(.Vu+\\n(psu+((\\n(spp*\\n($vu*\\n(.Lu)/100u)
+. \" exdent if \\$3 > 0
+. ie 0\\$3 \
+. ti -(\\n(siu-\\n(sou)
+. el \
+. ti +\\n(sou
+. @F \\n(sf
+. sz \\n(sp
+. if 0\\$3 \
+. $\\$3
+. if \w"\\$2">0 \\$2.
+. if \w"\\$1">0 \\$1\f1\ \ \&
+.\}
+.el \
+. sp \\n(psu
+.@F \\n(pf
+.sz \\n(pp
+..
+.\" *** COLUMNNED OUTPUT ***
+.de 2c \" *** double columned output
+.br
+.if \\n($m>1 \
+. 1c \" revert to 1c if already 2c
+.nr $c 1
+.nr $m 2
+.if \\n(.$>1 \
+. nr $m \\$2
+.if \\n(.$>0 \
+. nr $s \\$1n \" param 1: column seperation
+.nr $l (\\n(.l-((\\n($m-1)*\\n($s))/\\n($m
+.xl \\n($lu
+.mk _k
+.ns
+..
+.de 1c \" *** single columned output
+.br
+.nr $c 1
+.nr $m 1
+.ll \\n(_Lu \" return to normal output
+.sp |\\n(.hu
+.@O \\n(_ou
+..
+.de bc \" *** begin column
+.sp 24i
+..
+.\" *** FLOATING TABLES AND NONFLOATING BLOCKS ***
+.de (z \" *** begin floating keep
+.if \n@>4 .tm >> (z, .z=\n(.z
+.@D 4 \\$1 \\$2
+.@(
+..
+.de )z \" *** end floating keep
+.if \n@>4 .tm >> )z, .z=\n(.z
+.sp \\n(zsu
+.@)
+.if \n@>4 .tm -- )z << @), .z=\n(.z
+.rr _0
+.if !\\n(?b \
+. nr dn +(\\n(ppp*\\n($vu)/200u+\\n(zsu
+.nr dl -\n(.H \" fudge factor necessary to make it work
+.ie ((\\n(dn+\n(.V)>=\\n(.t):(\\n(?a):((\\n(dl>\\n($l)&(\\n($c>1)) \
+\{\
+. nr ?a 1
+. if (\\n(dl>\\n($l)&(\\n($m>1) \
+. nr ?w 1 \" mark wider than one column (top)
+. ds |x |t
+.\}
+.el \
+\{\
+. nr ?b 1
+. if (\\n(dl>\\n($l)&(\\n($m>1) \
+. nr ?W 1 \" mark wider than one column (bottom)
+. nr _b +\\n(dnu
+. \" avoid moving @f back past the current position
+. if \\n(.p-\\n(nl-\n(.V<\\n(_b \
+. nr _b \\n(.p-\\n(nl-\n(.V
+. ch @f -\\n(_bu
+. ds |x |b
+.\}
+.da \\*(|x \" copy to save macro
+.nf
+.ls 1
+.nr ?k 1
+.if \n@>4 .tm -- )z >> \\*(|x
+\!.if \\\\n(nl>(\\\\n(tm+2v) .ne \\n(dnu-\\n(zsu
+.|k\" \" and the body
+.ec
+.if \n@>4 .tm -- )z << \\*(|x, .z=\\n(.z
+.nr ?k 0
+.rm |k\" \" remove the temp macro
+.da
+.in 0
+.ls 1
+.xl \\n($lu
+.ev
+.if \n@>4 .tm << )z, .z=\\n(.z
+..
+.de @k \" --- output floating keep
+.if \n@>4 .tm >> @k, $1=\\$1, .z=\\n(.z
+.ev 1
+.nf
+.ls 1
+.in 0
+.sp \\n(zsu
+.\\$1
+.ec
+.br
+.rm \\$1
+.ev
+..
+.de (t \" XXX temp ref to (z
+.(z \\$1 \\$2
+..
+.de )t \" XXX temp ref to )t
+.)z \\$1 \\$2
+..
+.de (b \" *** begin block
+.br
+.@D 3 \\$1 \\$2
+.sp \\n(bsu
+.@(
+..
+.de )b \" *** end block
+.br
+.@)
+.if (\\n(bt=0):(\\n(.t<\\n(bt) \
+. ne \\n(dnu \" make it all on one page
+.ls 1
+.nf
+.|k
+.ec
+.fi
+.in 0
+.xl \\n($lu
+.ev
+.rm |k
+.sp \\n(bsu+\\n(.Lv-1v
+..
+.de @( \" --- begin keep
+.if !"\\n(.z"" .tm Line \\n(c. -- Illegal nested keep \\n(.z
+.@M
+.di |k
+\!'rs
+..
+.de @M \" --- set modes for display
+.nr ?k 1
+.@C 1
+.@F \\n(df
+.if \\n($R .@V
+.vs \\n(.sp*\\n($Vu/100u
+.nf
+.if "\\*(|p"F" \
+. fi \" set fill mode if "F" parameter
+.if \\n(_d=4 \
+. in 0
+.if \\n(_d=3 \
+\{\
+. in +\\n(biu
+. xl -\\n(biu
+.\}
+.if \\n(_d=1 \
+. ce 10000
+..
+.de @) \" --- end keep
+.br
+.if !"\\n(.z"|k" .tm Line \\n(c. -- Close of a keep which has never been opened
+.nr ?k 0
+.di
+.in 0
+.ce 0
+..
+.de (c \" *** begin block centered text
+.if "\\n(.z"|c" .tm Line \\n(c. -- Nested .(c requests
+.di |c
+..
+.de )c \" *** end block centered text
+.if !"\\n(.z"|c" .tm Line \\n(c. -- Unmatched .)c
+.br \" force out final line
+.di
+.if \n@>4 .tm >> .)c .l=\\n(.l .i=\\n(.i $i=\\n($i dl=\\n(dl
+.ev 1
+.ls 1
+.in (\\n(.lu-\\n(.iu-\\n(dlu)/2u
+.if \n@>4 .tm -- .)c << .in .l=\\n(.l .i=\\n(.i dl=\\n(dl
+.nf
+.|c
+.ec
+.in
+.ls
+.ev
+.rm |c
+..
+.\" *** BLOCK QUOTES (OR WHATEVER) AND LISTS ***
+.de (q \" *** begin block quote
+.br
+.@C 1
+.fi
+.sp \\n(qsu
+.in +\\n(qiu
+.xl -\\n(qiu
+.sz \\n(qp
+..
+.de )q \" *** end block quote
+.br
+.ev
+.sp \\n(qsu+\\n(.Lv-1v
+.nr ?k 0
+..
+.de (l \" *** begin list
+.br
+.sp \\n(bsu
+.@D 3 \\$1 \\$2
+.@M
+..
+.de )l \" *** end list
+.br
+.ev
+.sp \\n(bsu+\\n(.Lv-1v
+.nr ?k 0
+..
+.\" *** PREPROCESSOR SUPPORT ***
+.\"
+.\" EQN
+.\"
+.de EQ \" *** equation start
+.ec
+.if !\\n(?e \
+\{\
+. if "\\n(.z"|e" .tm Line \\n(c. -- Nested .EQ request
+. @D 1 "\\$1" "\\$2"
+. @C 2
+. di |e
+.\}
+.ls 1
+.in 0
+.nf
+..
+.de EN \" *** equation end
+.br
+.ie "\\$1"C" \
+\{\
+. nr ?e 1
+. sp \\n(esu
+.\}
+.el \
+\{\
+. nr ?e 0
+. di
+. if \\n(dn \
+. @q \" actual equation output
+. rm |e
+. ev
+.\}
+..
+.de @q \" --- equation output
+.nr _Q \\n(dnu
+.ev
+.sp \\n(esu \" output rest of preceeding text
+.if !"\\n(.z"" \!.ne \\n(_Qu
+.ne \\n(_Qu+\n(.Vu \" keep it on one page
+.@C 2 \" .ev 2 may be jumbled from header
+.if \\n(_d=1 \
+. in (\\n(.lu+\\n($iu-\\n(dlu)/2u
+.if \\n(_d=2 \
+. in \\n($iu
+.if \\n(_d=3 \
+. in \\n(biu+\\n($iu
+.if \\n(_d=4 \
+. in 0
+.mk _q
+.if \n@>1 .tm --@e: _Q=\\n(_Q _q=\\n(_q nl=\\n(nl |p=\\*(|p
+.if !"\\*(|p"" \
+\{\
+. rs
+. sp (\\n(_Qu-\\n(.vu)/2u
+. tl """\\*(|p"
+. rt \\n(_qu
+.\}
+.|e
+.sp |\\n(_qu+\\n(_Qu
+.sp \\n(esu+\\n(.Lv-1v
+.rr _q
+.rr _Q
+..
+.\"
+.\" TBL
+.\"
+.de TS \" *** table start
+.sp \\n(bsu
+.@C 1
+.fi \" drop into fill mode for text boxes
+.if "\\$1"H" \
+\{\
+. di |h \" save header part
+. nr ?T 1
+.\}
+.ls 1
+.ch @f -(\\n(_bu+1v) \" set pseudo-trap for bottom line
+.if \\n(.p-\\n(_b-1v<=\\n(nl \
+. ch @f \\n(nlu+\n(.Vu
+..
+.de TH \" *** end header part of table
+.nr T. 0
+.T# 0
+.di
+.nr _T \\n(?T
+.nr ?T 0
+.ne \\n(dnu+1v
+.nr ?T \\n(_T
+.nr _i \\n(.i
+.in 0
+.|h \" put in the initial header
+.in \\n(_iu
+.rr _i
+.mk #T
+..
+.de TE \" *** table end
+.nr ?T 0
+.ch @f -\\n(_bu \" reset pseudo-trap
+.if \\n(.p-\\n(_b<=\\n(nl \
+. ch @f \\n(nlu+\n(.Vu
+.ev
+.sp \\n(bsu+\\n(.Lv-1v
+.re
+..
+.\"
+.\" REFER
+.\"
+.de ][ \" *** refer output
+.if \\$1>5 .tm Bad arg to []
+.[\\$1
+..
+.de [0 \" --- other
+.(f
+.ip "\\*([F.\0"
+.if !"\\*([A"" \\*([A,
+.if !"\\*([T"" \\f2\\*([T\\f1\c
+.if !"\\*([T"" .if !"\\*([O"" ,\
+.ie !"\\*([O"" \\*([O
+.el .if !"\\*([T"" \&.
+.if !"\\*([D"" \\*([D.
+.@p
+.)f
+..
+.de [1 \" --- journal article
+.(f
+.ip "\\*([F.\0"
+\\*([A,
+.if !"\\*([T"" \\*(lq\\*([T,\\*(rq
+.if "\\*([V"" \\f2\\*([J\\f1,
+.if !"\\*([V"" \\f2\\*([J\\f1
+.if !"\\*([V"" \\f3\\*([V\\f1\c
+.if !"\\*([N"" (\\*([N)\c
+.if !"\\*([P"" \
+\{\
+. ie \\n([P>0 \ pp.\&
+. el \ p.\&
+\\*([P
+.\}
+.if !"\\*([I"" .if "\\*([R"" \\*([I,
+(\\*([D).
+.if !"\\*([O"" \\*([O
+.)f
+..
+.de [2 \" --- book
+.(f
+.ip "\\*([F.\0"
+\\*([A, \\f2\\*([T,\\f1
+\\*([I\c
+.if !"\\*([C"" , \\*([C\c
+ (\\*([D).
+.if !"\\*([G"" Gov't. ordering no. \\*([G
+.if !"\\*([O"" \\*([O
+.)f
+..
+.de [3 \" --- article in book
+.(f
+.ip "\\*([F.\0"
+\\*([A, \\*(lq\\*([T,\\*(rq
+.if !"\\*([P"" pp. \\*([P
+in \\f2\\*([B\\f1, \c
+.if !"\\*([E"" ed. \\*([E, \c
+.if !"\\*([I"" \\*([I\c
+.if !"\\*([C"" , \\*([C\c
+ (\\*([D).
+.if !"\\*([O"" \\*([O
+.)f
+..
+.de [4 \" --- report
+.(f
+.ip "\\*([F.\0"
+\\*([A, \\*(lq\\*([T,\\*(rq
+\\*([R\c
+.if !"\\*([G"" \& (\\*([G)\c
+.if !"\\*([I"" , \\*([I\c
+.if !"\\*([C"" , \\*([C\c
+ (\\*([D).
+.if !"\\*([O"" \\*([O
+.)f
+..
+.de [5 \" --- tm style
+.(f
+.ip "\\*([F.\0"
+\\*([A, \\f2\\*([T\\f1,
+.ie \\n(TN \\*([M.
+.el Bell Laboratories internal memorandum (\\*([D).
+.)f
+..
+.de ]<
+.$p References
+.lp
+.rm (f )f
+..
+.de ]>
+.sp
+..
+.de ]-
+.rm [V [P [A [T [N [C [B [O [R [I [E [D
+..
+.ie \n(.V<1v \
+\{\
+. ds [. \s-2\v'-.4m'\f1
+. ds .] \v'.4m'\s+2\fP
+.\}
+.el \
+\{\
+. ds [. " [
+. ds .] ]
+.\}
+.\"
+.\" IDEAL
+.\"
+.de IS \" *** start ideal picture
+.nr g7 \\n(.u
+.ls 1
+..
+.de IF
+.if \\n(g7 .fi
+.ls
+..
+.de IE \" *** end ideal picture
+.if \\n(g7 .fi
+.ls
+..
+.\"
+.\" PIC
+.\"
+.de PS \" *** start picture: $1=height, $2=width in units or inches
+.sp 0.3
+.nr g7 \\$2
+.in (\\n(.lu-\\n(g7u)/2u
+.ne \\$1u
+.nr g7 \\n(.u
+.ls 1
+..
+.de PE \" *** end picture
+.ls
+.in
+.if \\n(g7 .fi
+.sp .6
+..
+.\"
+.\" GREMLIN
+.\"
+.de GS \" *** start gremlin picture
+.nr g7 (\\n(.lu-\\n(g1u)/2u
+.if "\\$1"L" .nr g7 \\n(.iu
+.if "\\$1"R" .nr g7 \\n(.lu-\\n(g1u
+.in \\n(g7u
+.nr g7 \\n(.u
+.ls 1
+.nf
+.ne \\n(g2u
+..
+.de GE \" *** end gremlin picture
+.GF
+.sp .6
+..
+.de GF \" *** finish gremlin picture; stay at top
+.ls
+.in
+.if \\n(g7 .fi
+..
+.\" *** FONT AIDS ***
+.de sz \" *** set point size and vertical spacing
+.ps \\$1
+.if \\n($r .@v
+.vs \\n(.sp*\\n($vu/100u \" default vs at pointsize + 20%
+..
+.de @v \" --- possibly set $v from $r
+.if (1i>=240u)&(1p<=\\n($r)&(\\n($r<=4p) .nr $v \\n($r00/1p
+..
+.de @V \" --- possibly set $V from $R
+.if (1i>=240u)&(1p<=\\n($R)&(\\n($R<=4p) .nr $V \\n($R00/1p
+..
+.de @E \" --- store in _F argument to \f for restoring font
+.ie \\n(.f<10 \
+. ds _F \\n(.f
+.el \
+\{\
+. ie \\n(.f<100&\n(.g \
+. ds _F (\\n(.f
+. el \
+. ds _F P
+.\}
+..
+.de r \" *** enter roman font
+.@E
+.ft 1
+.if \\n(.$ \&\\$1\f\\*(_F\\$2
+..
+.de i \" *** enter italic
+.@E
+.ft 2
+.if \\n(.$ \&\\$1\f\\*(_F\\$2
+..
+.de b \" *** enter boldface
+.@E
+.ft 3
+.if \\n(.$ \&\\$1\f\\*(_F\\$2
+..
+.de rb \" *** enter real boldface
+.@E
+.ft 3
+.if \\n(.$ \&\\$1\f\\*(_F\\$2
+..
+.de bi \" *** enter bold italic
+.@E
+.ft 4
+.if \\n(.$ \&\\$1\f\\*(_F\\$2
+..
+.de u \" *** enter underlined word
+\&\\$1\l'|0\(ul'\\$2
+..
+.\" a better version of u
+.if !\n(.g .ig
+.de u
+\Z'\\$1'\v'.25m'\D'l \w'\\$1'u 0'\v'-.25m'\\$2
+..
+.de q \" *** enter quoted word
+\&\\*(lq\\$1\\*(rq\\$2
+..
+.de bx \" *** enter boxed word
+\k~\(br\|\\$1\|\(br\l'|\\n~u\(rn'\l'|\\n~u\(ul'\^\\$2
+..
+.de sm \" *** print in smaller font
+\s-1\\$1\\s0\\$2
+..
+.de @F \" --- change font (0 -> no change)
+.nr ~ \\$1
+.if \\n~>0 \
+. ft \\n~
+.rr ~
+..
+.\" *** FOOTNOTING ***
+.de (f \" *** begin footnote
+.ec
+.if "\\n(.z"|f" .tm Line \\n(c. -- Illegal footnote nesting
+.ie "\\n(.z"" \
+\{\
+. nr _D \\n(dn
+. nr _0 1v+\\n(nlu
+. ev 2
+. da |f
+. in 0
+. xl \\n($lu-\\n(fuu
+. @F \\n(ff
+. sz \\n(fp
+. vs \\n(.sp*\\n($Vu/100u
+. if !\\n(?f \
+\{\
+. nr _b +1v \" allow space for $s
+. $s
+. \}
+. br
+. if \\n(.p-\\n(_b-\\n(_0-\\n(.h-1v-\\n(fs<0 \
+\{\
+. da\" \" won't fit on page at all
+. bc
+. if !\\n(?f \
+. rm |f
+. da |f
+.\" next five lines could be dropped if headers had their own environment
+. in 0 \" reset everything from .bc
+. xl \\n($lu-\\n(fuu
+. @F \\n(ff
+. sz \\n(fp
+. vs \\n(.sp*\\n($Vu/100u
+. if !\\n(?f \
+. $s
+. br
+. \}
+. rr _0
+. sp \\n(fsu
+. nr ?f 1
+. fi
+. if !"\\$1"_" \
+. ti \\n(fiu
+. if \n@>2 .tm << (f $f=\\n($f
+.\}
+.el \
+\{\
+. ev 2
+. in 0
+. xl \\n($lu-\\n(fuu
+. @F \\n(ff
+. sz \\n(fp
+. vs \\n(.sp*\\n($Vu/100u
+. fi
+\!.(f \\$1
+\!.@N
+.\}
+..
+.de @N \" --- set no fill mode in the top-level diversion
+.ie "\\n(.z"" .nf
+.el \!.@N
+..
+.de )f \" *** end footnote
+.ie "\\n(.z"|f" \
+\{\
+. if \\n* \
+. nr $f +1
+. ds * \\*{\\n($f\\*}\k*
+. nr * 0
+. in 0
+. da
+. ev
+. if \\n(_w<\\n(dl \
+. nr _w \\n(dl \" compute maximum fn width
+. nr _b +\\n(dn
+. ch @f -\\n(_bu
+. if \\n(.p-\\n(_b<=\\n(nl \
+. ch @f \\n(nlu+\n(.Vu
+. nr dn \\n(_D
+. rr _D
+.\}
+.el \
+\{\
+. br
+\!.)f
+. ev
+.\}
+..
+.@R ff
+.if \n(ff<=0 \
+. nr ff 1 \" footnote font: Times Roman
+.@R fp
+.if \n(fp<=0 \
+. nr fp 8 \" footnote pointsize
+.de $s \" $$$ footnote separator
+\l'2i'
+..
+.\" *** DELAYED TEXT ***
+.de (d \" *** begin delayed text
+.am |d )d
+.sp \\n(bsu
+..
+.de )d \" *** end delayed text
+.if \\n# \
+. nr $d +1
+.ds # [\\n($d]\k#
+.rr #
+..
+.de pd \" *** print delayed text
+.|d
+.rm |d
+.nr $d 1 1
+.ds # [1]\k#
+..
+.\" *** INDEXES (TABLE OF CONTENTS) ***
+.nr _x 0 1
+.af _x a
+.de (x \" *** begin index entry
+.if \n@>4 .tm >> (x, .z=\\n(.z
+.ds |X x
+.if \\n(.$>0 \
+. ds |X \\$1
+.ie "\\n(.z"" \
+. nr _z 0
+.el \
+. nr _z 1
+.@\\n(_z
+..
+.de @0 \" --- finish (x if no current diversion
+.am %\\*(|X )x
+.sp \\n(xsu
+.ti -\\n(piu
+..
+.de @1 \" --- finish (x if current diversion
+.if "\\n(_x"z" .nr _x 0
+.de =\\n+(_x )x
+..
+.de )x \" *** end index entry
+.if \n@>4 .tm >> )x, .z=\\n(.z
+.ie "\\n(.z"" \
+\{\
+. ds |x \\n%
+. if \\n(.$>0 \
+. ds |x \\$1
+. if "\\*(|x"_" \
+. ig ..
+. am %\\*(|X ..
+. if \w"\\$2">(\\n(.l-\\n(.i-\\n(.k) \
+. ti +\\n(xuu
+\\\\a\\\\t\\$2\\*(|x
+...
+. rm |x
+. rm |X
+.\}
+.el \
+\{\
+\!.(x \\*(|X
+\!\\\\*(=\\n(_x\\\\
+\!.)x \\$1 \\$2
+\!.rm =\\n(_x
+.\}
+..
+.de xp \" *** print the index
+.br
+.@C 2
+.ls 1
+.vs \\n(.sp*\\n($Vu/100u
+.fi
+.in +\\n(piu
+.ds |X x
+.if \\n(.$>0 \
+. ds |X \\$1
+.xl -(\\n(xuu+\w'...'u)
+.di |x
+.%\\*(|X
+.br
+.di
+.rm %\\*(|X
+.xl \\n($lu
+.rm |X
+.ev
+.nf
+.in 0
+.ta \\n(.lu-\\n(xuuR \\n(.luR
+.|x
+.fi
+.in
+.rm |x
+..
+.de +c \" *** begin chapter
+.ep \" force out footnotes
+.if \\n(?o:\\n(?a \
+\{\
+. bp \" force out a table or more footnote
+. rs
+. ep
+.\}
+.nr ?C 1
+.nr $f 1 1
+.ds * \\*{1\\*}\k*
+.if \\n(?R \
+. pn 1
+.bp
+.in \\n($iu \" reset the indent
+.rs
+.ie \\n(.$ \
+. $c "\\$1"
+.el \
+. sp 3
+..
+.de ++ \" *** declare chapter type
+.nr _0 0
+.if "\\$1"C" \
+. nr _0 1 \" chapter
+.if "\\$1"RC" \
+. nr _0 11 \" renumbered chapter
+.if "\\$1"A" \
+. nr _0 2 \" appendix
+.if "\\$1"RA" \
+. nr _0 12 \" renumbered appendix
+.if "\\$1"P" \
+. nr _0 3 \" preliminary material
+.if "\\$1"B" \
+. nr _0 4 \" bibliographic material
+.if "\\$1"AB" \
+. nr _0 5 \" abstract
+.if \\n(_0=0 \
+. tm Line \\n(c. -- Bad mode to .++
+.nr ?R 0
+.if \\n(_0>10 \
+.\{
+. nr ?R 1
+. nr _0 -10
+.\}
+.nr ch 0 1
+.if (\\n(_0=3):(\\n(_0=5) \
+. pn 1 \" must do before .ep
+.if !\\n(_0=\\n(_M .if \\n(_M=3 \
+. pn 1 \" must do before .ep
+.ep \" end page for correct page number types
+.if \\n(_0=1 \
+\{\
+. af ch 1
+. af % 1
+.\}
+.if \\n(_0=2 \
+\{\
+. af ch A
+. af % 1
+.\}
+.if \\n(_0=3 \
+. af % i
+.if \\n(_0=4 \
+. af % 1
+.if \\n(_0=5 \
+. af % 1
+.if \\n(.$>1 \
+. he \\$2
+.nr _M \\n(_0
+.rr _0
+..
+.de $c \" $$$ print chapter title
+.sz 12
+.ft 3
+.ce 1000
+.if \\n(_M<3 \
+. nr ch +1
+.ie \\n(_M=1 CHAPTER\ \ \\n(ch
+.el .if \\n(_M=2 APPENDIX\ \ \\n(ch
+.if \w"\\$1" .sp 3-\\n(.L
+.if \w"\\$1" \\$1
+.if (\\n(_M<3):(\w"\\$1") \
+. sp 4-\\n(.L
+.ce 0
+.ft
+.sz
+.ie \\n(_M=1 \
+. $C Chapter \\n(ch "\\$1"
+.el .if \\n(_M=2 \
+. $C Appendix \\n(ch "\\$1"
+..
+.de tp \" *** title page
+.hx
+.bp
+.br
+.rs
+.pn \\n%
+..
+.\" *** DATES ***
+.if \n(mo=1 .ds mo January
+.if \n(mo=2 .ds mo February
+.if \n(mo=3 .ds mo March
+.if \n(mo=4 .ds mo April
+.if \n(mo=5 .ds mo May
+.if \n(mo=6 .ds mo June
+.if \n(mo=7 .ds mo July
+.if \n(mo=8 .ds mo August
+.if \n(mo=9 .ds mo September
+.if \n(mo=10 .ds mo October
+.if \n(mo=11 .ds mo November
+.if \n(mo=12 .ds mo December
+.if \n(dw=1 .ds dw Sunday
+.if \n(dw=2 .ds dw Monday
+.if \n(dw=3 .ds dw Tuesday
+.if \n(dw=4 .ds dw Wednesday
+.if \n(dw=5 .ds dw Thursday
+.if \n(dw=6 .ds dw Friday
+.if \n(dw=7 .ds dw Saturday
+.nr y2 \n(yr%100
+.af y2 00
+.nr y4 \n(yr+1900
+.ds td \*(mo \n(dy, \n(y4
+.\" *** PARAMETRIC INITIALIZATIONS ***
+.rr x
+.nr $v \n(.v00+\n(.sp-1/\n(.sp \" vs as percentage of ps for .sz request
+.nr $V \n($v \" same for displays & footnotes
+.nr hm 4v \" header margin
+.nr tm 7v \" top margin
+.nr bm 6v \" bottom margin
+.nr fm 3v \" footer margin
+.nr tf 3 \" title font: (real) Times Bold
+.nr tp 10 \" title point size
+.hy 14
+.nr bi 4m \" indent for blocks
+.nr pi 5n \" indent for paragraphs
+.nr pf 1 \" normal text font
+.nr pp 10 \" normal text point size
+.nr qi 4n \" indent for quotes
+.nr qp -1 \" down one point
+.nr ii 5n \" indent for .ip's and .np's
+.nr $m 1 \" max number of columns
+.nr $s 4n \" column separation
+.nr sf 3 \" section font -- Times Bold
+.nr sp 10 \" section title pointsize
+.nr ss 12p \" section prespacing
+.nr si 0 \" section indent
+.\" *** OTHER INITIALIZATION ***
+.\" GNU pic sets this register to 1, to indicate that \x should not be used.
+.@R 0x
+.ds { \v'-0.4m'\x'\\n(0x=0*-0.2m'\s-3
+.ds } \s0\v'0.4m'
+.\" for compatibility with traditional -me
+.\" (the first will work only in compatibility mode)
+.ds [ \*{
+.ds ] \*}
+.ds < \v'0.4m'\x'\\n(0x=0*0.2m'\s-3
+.ds > \s0\v'-0.4m'
+.ds - \(em
+.\" Avoid warnings from groff -ww.
+.@S |0
+.@S |1
+.@S |2
+.@S |3
+.@S $H
+.@S $0
+.@S $1
+.@S $2
+.@S $3
+.@S $4
+.@S $5
+.@S $6
+.@S $7
+.@S $8
+.@S $9
+.@S ..
+.@R po\" \" simulated page offset
+.@R $0\" \" section depth
+.@R $i\" \" paragraph base indent
+.@R $p\" \" numbered paragraph number
+.@R $r\" \" ratio of vs to ps (may override $v)
+.@R $R\" \" same for displays (may override $V)
+.@R df\" \" display font: same as surrounding text
+.@R so\" \" additional section title offset
+.@R fu\" \" footnote undent
+.@R bt\" \" block keep threshold
+.@R *\" \" has \** been referenced?
+.@R ?a\" \" pending floating keep at page top?
+.@R ?b\" \" pending floating keep at page bottom?
+.@R ?C\" \" at chapter header?
+.@R ?e\" \" in equation?
+.@R ?H\" \" suppress headers and footers next page?
+.@R ?I\" \" has the header trap been sprung?
+.@R ?n\" \" n1 mode?
+.@R ?o\" \" footnote overflow?
+.@R ?R\" \" renumbered chapter?
+.@R ?s\" \" skip next page?
+.@R ?T\" \" inside .TS H?
+.@R ?W\" \" wide floating keep at page bottom?
+.@R ?w\" \" wide floating keep at page top?
+.nr fi 0.3i
+.nr _o \n(.o
+.nr $b 3 \" bold
+.nr ps 0.35v
+.if \n(ps<\n(.V .nr ps \n(.V
+.nr bs \n(ps \" block pre/post spacing
+.nr qs \n(ps \" quote pre/post spacing
+.nr zs 1v \" float-block pre/postspacing
+.nr xs 0.2v \" index prespacing
+.nr xu 0.5i \" index undent
+.nr fs 0.2v \" footnote prespacing
+.nr es 0.5v \" equation pre/postspacing
+.if \n(es<\n(.V .nr es \n(.V
+.wh 0 @h \" set header
+.nr $l \n(.lu \" line length
+.nr _L \n(.lu \" line length of page
+.nr $c 1 \" current column number
+.nr $f 1 1 \" footnote number
+.ds * \*{1\*}\k*\" \" footnote "name"
+.nr $d 1 1 \" delayed text number
+.ds # [1]\k#\" \" delayed text "name"
+.nr _M 1 \" chapter mode is chapter
+.ds lq \(lq\" \" left quote
+.ds rq \(rq\" \" right quote
+.em @z
+.\" *** FOREIGN LETTERS AND SPECIAL CHARACTERS ***
+.ds #h ((1u-(\\\\n(.fu%2u))*0.13m)
+.ds #v 0.6m
+.\" \" accents
+.ds ' \k_\h'-(\\n(.wu*8/10-\*(#h)'\(aa\h'|\\n_u'
+.ds ` \k_\h'-(\\n(.wu*7/10-\*(#h)'\(ga\h'|\\n_u'
+.\" \" umlaut
+.ds : \k_\h'-(\\n(.wu*8/10-\*(#h+0.1m)'\v'-\*(#v'\z.\h'0.2m'.\h'|\\n_u'\v'\*(#v'
+.\" \" circumflex and tilde
+.ds ^ \k_\h'-(\\n(.wu-\*(#h-0.05m)'^\h'|\\n_u'
+.ds ~ \k_\h'-(\\n(.wu-\*(#h-0.05m)'~\h'|\\n_u'
+.\" \" cedilla and czech
+.ds , \k_\h'-(\\n(.wu)',\h'|\\n_u'
+.ds v \k_\h'-(\\n(.wu*9/10-\*(#h)'\v'-\*(#v'\s-4v\s0\v'\*(#v'\h'|\\n_u'
+.\" \" Norwegian A or angstrom
+.ds o \k_\h'-(\\n(.wu+\w'\(de'u-\*(#h)/2u'\v'-0.4n'\z\(de\v'0.4n'\h'|\\n_u'
+.\" \" there exists, for all
+.ds qe \s-2\v'0.45m'\z\(em\v'-0.625m'\z\(em\v'-0.625m'\(em\v'0.8m'\s0\h'-0.1m'\v'-0.05m'\(br\v'0.05m'\h'0.1m'
+.ds qa \z\e\h'0.35m'\z\(sl\h'-0.33m'\v'-0.3m'\s-4\(em\s0\v'0.3m'\h'0.15m'
+.rm #h #v
+.ll 6.0i
+.lt 6.0i
+.de @U
+.tm The \\$1 macro has been removed from this version of the -me macros.
+..
+.de lo
+.@U lo
+..
+.de th
+.@U th
+..
+.de ac
+.@U ac
+..
diff --git a/tmac/tmac.html b/tmac/tmac.html
new file mode 100755
index 00000000..991ced36
--- /dev/null
+++ b/tmac/tmac.html
@@ -0,0 +1,60 @@
+.nr _C \n(.C
+.cp 0
+.ftr CW CR
+.ftr C CR
+.ftr CO CI
+.ftr CX CBI
+.ftr H HR
+.ftr HO HI
+.ftr HX HBI
+.ftr NX NBI
+.char \(ru \D'l .5m 0'
+.char \(ul \v'.25m'\D'l .5m 0'\v'-.25m'
+.char \(br \v'.25m'\D'l 0 -1m'\v'.75m'
+.char \(rn \v'-.75m'\D'l .5m 0'\v'.75m'
+.\" .char ~ \v'-.55m'\\s[\\n(.s/2u]\v'.2m'\(ti\v'-.2m'\s0\v'.55m'
+.\" .char ^ \v'-.55m'\\s[\\n(.s/2u]\v'.3m'\(ha\v'-.3m'\s0\v'.55m'
+.if !c\(va .char \(va \o'\(ua\(da'
+.if !c\(em .char \(em --
+.if !c\(en .char \(en \-
+.if !c\(fi .char \(fi fi
+.if !c\(fl .char \(fl fl
+.if !c\(ff .char \(ff ff
+.if !c\(Fi .char \(Fi ffi
+.if !c\(Fl .char \(Fl ffl
+.if !c\(ci .char \(ci \v'-.25m'\h'.05m'\D'c .5m'\h'.05m'\v'.25m'
+.if !c\(sq .char \(sq \h'.05m'\D'l .5m 0'\D'l 0 -.5m'\D'l -.5m 0'\D'l 0 .5m'\h'.55m'
+.if !c\(ga .char \(ga \Z'\v'-.7m'\D'l .22m .18m''\h'.33m'
+.if !c\(dg .char \(dg \Z'\h'.25m'\v'.15m'\D'l 0 -.8m'\v'.2m'\h'-.195m'\
+\D'l .39m 0''\h'.5m'
+.if !c\(dd .char \(dd \Z'\h'.25m'\v'.15m'\D'l 0 -.8m'\v'.2m'\h'-.195m'\
+\D'l .39m 0'\v'.4m'\D'l -.39m 0''\h'.5m'
+.if !c\(lq .char \(lq ``
+.if !c\(rq .char \(rq ''
+.if !c\(Bq .char \(bq ,,
+.if !c\(OE .char \(OE O\h'-.25m'E
+.if !c\(oe .char \(oe o\h'-.14m'e
+.if !c\(ah .char \(ah \v'-.55m'\s[\En[.s]/2u]v\s0\v'.55m'
+.if !c\(ao .char \(ao \v'-.55m'\s[\En[.s]*6u/10u]\D'c .25m'\s0\v'.55m'
+.if !c\(ho .char \(ho \s[\En[.s]/2u]\v'.4m'c\v'-.4m'\s0
+.if !c\(lh .char \(lh <-
+.if !c\(rh .char \(rh ->
+.if !c\(bq .tr \(bq,
+.if !c\(aq .tr \(aq'
+.if '\*(.T'html' .char \[radicalex] \h'-\w'\(sr'u'\[radicalex]\h'\w'\(sr'u'
+.if !\n(_C .mso tmac.pspic
+.cp \n(_C
+.\" now turn off all headers and footers for ms, me and mm macro sets
+.if d EF .EF '''
+.if d EH .EH '''
+.if d OF .OF '''
+.if d OH .OH '''
+.if d ef .ef '''
+.if d of .of '''
+.if d oh .oh '''
+.if d eh .eh '''
+.\" it doesn't make sense to use hyphenation with html, so we turn it off.
+.hy 0
+.nr HY 0
+.\" avoid line breaks after hyphen-like characters.
+.cflags 0 -\(hy\(em\(en
diff --git a/tmac/tmac.latin1 b/tmac/tmac.latin1
new file mode 100755
index 00000000..f33ea216
--- /dev/null
+++ b/tmac/tmac.latin1
@@ -0,0 +1,101 @@
+.nr _C \n(.C
+.cp 0
+.de latin1-tr
+.if c\\$2 .if !c\\$1 .tr \\$1\\$2
+..
+.latin1-tr \[char161] \(r!
+.latin1-tr \[char162] \(ct
+.latin1-tr \[char163] \(Po
+.latin1-tr \[char164] \(Cs
+.latin1-tr \[char165] \(Ye
+.latin1-tr \[char166] \(bb
+.latin1-tr \[char167] \(sc
+.latin1-tr \[char168] \(ad
+.latin1-tr \[char169] \(co
+.latin1-tr \[char170] \(Of
+.latin1-tr \[char171] \(Fo
+.latin1-tr \[char172] \(no
+.latin1-tr \[char173] \(hy
+.latin1-tr \[char174] \(rg
+.latin1-tr \[char175] \(a-
+.latin1-tr \[char176] \(de
+.latin1-tr \[char177] \(+-
+.latin1-tr \[char178] \(S2
+.latin1-tr \[char179] \(S3
+.latin1-tr \[char180] \(aa
+.latin1-tr \[char181] \(*m
+.latin1-tr \[char182] \(ps
+.latin1-tr \[char183] \(md
+.latin1-tr \[char184] \(ac
+.latin1-tr \[char185] \(S1
+.latin1-tr \[char186] \(Om
+.latin1-tr \[char187] \(Fc
+.latin1-tr \[char188] \(14
+.latin1-tr \[char189] \(12
+.latin1-tr \[char190] \(34
+.latin1-tr \[char191] \(r?
+.latin1-tr \[char192] \(`A
+.latin1-tr \[char193] \('A
+.latin1-tr \[char194] \(^A
+.latin1-tr \[char195] \(~A
+.latin1-tr \[char196] \(:A
+.latin1-tr \[char197] \(oA
+.latin1-tr \[char198] \(AE
+.latin1-tr \[char199] \(,C
+.latin1-tr \[char200] \(`E
+.latin1-tr \[char201] \('E
+.latin1-tr \[char202] \(^E
+.latin1-tr \[char203] \(:E
+.latin1-tr \[char204] \(`I
+.latin1-tr \[char205] \('I
+.latin1-tr \[char206] \(^I
+.latin1-tr \[char207] \(:I
+.latin1-tr \[char208] \(-D
+.latin1-tr \[char209] \(~N
+.latin1-tr \[char210] \(`O
+.latin1-tr \[char211] \('O
+.latin1-tr \[char212] \(^O
+.latin1-tr \[char213] \(~O
+.latin1-tr \[char214] \(:O
+.latin1-tr \[char215] \(mu
+.latin1-tr \[char216] \(/O
+.latin1-tr \[char217] \(`U
+.latin1-tr \[char218] \('U
+.latin1-tr \[char219] \(^U
+.latin1-tr \[char220] \(:U
+.latin1-tr \[char221] \('Y
+.latin1-tr \[char222] \(TP
+.latin1-tr \[char223] \(ss
+.latin1-tr \[char224] \(`a
+.latin1-tr \[char225] \('a
+.latin1-tr \[char226] \(^a
+.latin1-tr \[char227] \(~a
+.latin1-tr \[char228] \(:a
+.latin1-tr \[char229] \(oa
+.latin1-tr \[char230] \(ae
+.latin1-tr \[char231] \(,c
+.latin1-tr \[char232] \(`e
+.latin1-tr \[char233] \('e
+.latin1-tr \[char234] \(^e
+.latin1-tr \[char235] \(:e
+.latin1-tr \[char236] \(`i
+.latin1-tr \[char237] \('i
+.latin1-tr \[char238] \(^i
+.latin1-tr \[char239] \(:i
+.latin1-tr \[char240] \(Sd
+.latin1-tr \[char241] \(~n
+.latin1-tr \[char242] \(`o
+.latin1-tr \[char243] \('o
+.latin1-tr \[char244] \(^o
+.latin1-tr \[char245] \(~o
+.latin1-tr \[char246] \(:o
+.latin1-tr \[char247] \(di
+.latin1-tr \[char248] \(/o
+.latin1-tr \[char249] \(`u
+.latin1-tr \[char250] \('u
+.latin1-tr \[char251] \(^u
+.latin1-tr \[char252] \(:u
+.latin1-tr \[char253] \('y
+.latin1-tr \[char254] \(Tp
+.latin1-tr \[char255] \(:y
+.cp \n(_C
diff --git a/tmac/tmac.lj4 b/tmac/tmac.lj4
new file mode 100755
index 00000000..658b9a7a
--- /dev/null
+++ b/tmac/tmac.lj4
@@ -0,0 +1,18 @@
+.nr _C \n(.C
+.cp 0
+.ftr CW CR
+.ftr C CR
+.ftr CX CBI
+.ftr H UR
+.ftr HR UR
+.ftr HB UB
+.ftr HBI UBI
+.ftr HI UI
+.ftr HO UI
+.ftr HX UBI
+.\" This is designed so that \(ul, \(rn and \(br form corners.
+.if !c\[br] .char \[br] \Z'\v'.25m'\D'R .04m -1m''
+.if !c\[ru] .char \[ru] \Z'\v'-.02m'\D'R .54m .04m''\h'.5m'
+.if !c\[rn] .char \[rn] \Z'\v'-.77m'\D'R .54m .04m''\h'.5m'
+.if !c\[ul] .char \[ul] \Z'\v'.23m'\D'R .54m .04m''\h'.5m'
+.cp \n(_C
diff --git a/tmac/tmac.pic b/tmac/tmac.pic
new file mode 100755
index 00000000..1177fc09
--- /dev/null
+++ b/tmac/tmac.pic
@@ -0,0 +1,10 @@
+.de PS
+.br
+.sp .3v
+.ne 0\\$1+1v+\n(.Vu
+.in \\n(.lu-\\n(.iu-0\\$2/2u>?0
+..
+.de PE
+.in
+.sp .3v+.5m
+..
diff --git a/tmac/tmac.ps b/tmac/tmac.ps
new file mode 100755
index 00000000..4d954f4a
--- /dev/null
+++ b/tmac/tmac.ps
@@ -0,0 +1,53 @@
+.nr _C \n(.C
+.cp 0
+.ftr AX ABI
+.ftr KR BMR
+.ftr KI BMI
+.ftr KB BMB
+.ftr KX BMBI
+.ftr CW CR
+.ftr CO CI
+.ftr CX CBI
+.ftr H HR
+.ftr HO HI
+.ftr HX HBI
+.ftr Hr HNR
+.ftr Hi HNI
+.ftr Hb HNB
+.ftr Hx HNBI
+.ftr NX NBI
+.ftr PA PR
+.ftr PX PBI
+.ftr ZI ZCMI
+.ftr C CR
+.cflags 8 \(an
+.char \[radicalex] \h'-\w'\(sr'u'\[radicalex]\h'\w'\(sr'u'
+.char \(mo \h'.08m'\(mo\h'-.08m'
+.char \(nm \h'.08m'\(nm\h'-.08m'
+.char \[parenlefttp] \[parenlefttp]\h'.016m'
+.char \[parenleftbt] \[parenleftbt]\h'.016m'
+.char \[parenleftex] \[parenleftex]\h'.016m'
+.char \[parenrighttp] \[parenrighttp]\h'.016m'
+.char \[parenrightbt] \[parenrightbt]\h'.016m'
+.char \[parenrightex] \[parenrightex]\h'.016m'
+.if !c\[va] .char \[va] \o'\[ua]\[da]'
+.if !c\[ci] \
+.char \[ci] \v'-.25m'\h'.05m'\D'c .5m'\h'.05m'\v'.25m'
+.if !c\[sq] \
+.char \[sq] \h'.05m'\D'l .5m 0'\D'l 0 -.5m'\D'l -.5m 0'\D'l 0 .5m'\h'.55m'
+.if !c\[ru] .char \[ru] \D'l .5m 0'
+.if !c\[ul] .char \[ul] \v'.25m'\D'l .5m 0'\v'-.25m'
+.if !c\[br] .char \[br] \Z'\v'.25m'\D'l 0 -1m''
+.if !c\[rn] .char \[rn] \v'-.75m'\D'l .5m 0'\v'.75m'
+.if !c\[or] .char \[or] \h'.1m'\Z'\D'l 0 -.675m''\h'.1m'
+.if !c\[Fi] .char \[Fi] ffi
+.if !c\[Fl] .char \[Fl] ffl
+.if !c\[ff] .char \[ff] ff
+.if !c\[ij] .char \[ij] ij
+.if !c\[IJ] .char \[IJ] IJ
+.if !c\[tm] .char \[tm] \s-3\v'-.3m'TM\v'+.3m'\s+3
+.\" pic tests this register to see whether it should use \X'ps:...'
+.nr 0p 1
+.cp \n(_C
+.if !\n(.C .mso tmac.pspic
+.do mso tmac.psold
diff --git a/tmac/tmac.psatk b/tmac/tmac.psatk
new file mode 100755
index 00000000..b59d23a2
--- /dev/null
+++ b/tmac/tmac.psatk
@@ -0,0 +1,61 @@
+.\" Implementation of the ATK PB and PE macros for use with groff and grops.
+.\" Load this after tmac.atk.
+.nr zT 0
+.if '\*(.T'ps' .nr zT 1
+.nr psatk-unit 1p
+.de psatk-defs
+ps: mdef 5
+/PB {
+ /saved save def
+ currentpoint translate
+ \n[psatk-unit] u -\n[psatk-unit] u scale
+ userdict begin
+ /showpage {} def
+} bind def
+/PE {
+ end
+ saved restore
+} bind def
+/troffadjust {
+ pop 0
+} bind def
+..
+.de PB
+.ne \\$1p
+.nr zT \\n(zT>0
+\\*[PB\\n(zT]\\
+..
+.de PE
+\\*[PE\\n(zT]\\
+..
+.ds PB0
+.\" The last line before the "'PE" is "\}" rather than ".\}". This
+.\" would cause a spurious space to be introduced before any picture
+.\" that was the first thing on a line. So we have to catch that and
+.\" remove it.
+.de PB1
+.ev psatk
+.fi
+.di psatk-mac
+\!ps: exec PB
+..
+.de PE0
+\v'-.75m'\
+\D'l \\$1p 0'\D'l 0 \\$2p'\D'l -\\$1p 0'\D'l 0 -\\$2p'\
+\h'\\$1p'\v'.75m'\x'\\$2p-1m>?0'\c
+..
+.ds psatk-init \Y[psatk-defs]
+.de PE1
+\!PE
+.di
+.di null
+.br
+.di
+.rm null
+.ev
+\v'-.75m'\
+\\*[psatk-init]\Y[psatk-mac]\
+\h'\\$1p'\v'.75m'\x'\\$2p-1m>?0'\c
+.rm psatk-mac
+.if \\n(.P .ds psatk-init
+..
diff --git a/tmac/tmac.psfig b/tmac/tmac.psfig
new file mode 100755
index 00000000..5f4111ce
--- /dev/null
+++ b/tmac/tmac.psfig
@@ -0,0 +1,87 @@
+.\" These are macros to make psfig work with groff.
+.\" They require that psfig be patched as described in ../grops/psfig.diff.
+.de psfig-defs
+ps: mdef 100
+
+% wid ht llx lly urx ury psfigstart -
+
+/psfigstart {
+ /level1 save def
+ /ury exch def
+ /urx exch def
+ /lly exch def
+ /llx exch def
+ /ht exch u def
+ /wid exch u def
+ currentpoint ht add translate
+ wid urx llx sub div ht ury lly sub div neg scale
+ llx neg lly neg translate
+
+ % set the graphics state to default values
+ 0 setgray
+ 0 setlinecap
+ 1 setlinewidth
+ 0 setlinejoin
+ 10 setmiterlimit
+ [] 0 setdash
+ newpath
+ /showpage {} def
+} bind def
+
+% psfigclip -
+
+/psfigclip {
+ currentpoint newpath
+ llx lly moveto
+ urx lly lineto
+ urx ury lineto
+ llx ury lineto
+ closepath clip
+ newpath moveto
+} bind def
+
+% psfigend -
+
+/psfigend {
+ level1 restore
+} bind def
+
+% globalstart -
+
+/globalstart {
+ % save the current space code on the stack
+ SC
+ level0 restore
+} bind def
+
+% globalend -
+
+/globalend {
+ end
+ BP
+ /SC exch def
+ DEFS begin
+} bind def
+..
+.de psfig-init
+.if \\n[.P] \{\
+\Y[psfig-defs]
+. br
+. sp -1
+. ds psfig-init\" empty
+. rm psfig-defs
+.\}
+..
+.de F+
+.br
+.psfig-init
+.nr psfig-fill \\n[.u]
+.nf
+.sp -.5
+.if !\\n[.$] .ce 9999
+..
+.de F-
+.br
+.ce 0
+.if \\n[psfig-fill] .fi
+..
diff --git a/tmac/tmac.psnew b/tmac/tmac.psnew
new file mode 100755
index 00000000..e13bdb88
--- /dev/null
+++ b/tmac/tmac.psnew
@@ -0,0 +1,26 @@
+.\" Undo the effect of tmac.psold. This gives access to the additional
+.\" characters that are present in the text fonts of newer PostScript
+.\" printers. It is a bad idea to use this if you are going to
+.\" distribute the resulting PostScript output to others.
+.nr _C \n(.C
+.cp 0
+.rchar \('y\('Y\(12\(14\(34\(S1\(S2\(S3\(bb\(de\(Tp\(TP\(-D\(Sd
+.tr \[char166]\[char166]
+.tr \[char176]\[char176]
+.tr \[char177]\[char177]
+.tr \[char178]\[char178]
+.tr \[char179]\[char179]
+.tr \[char181]\[char181]
+.tr \[char185]\[char185]
+.tr \[char188]\[char188]
+.tr \[char189]\[char189]
+.tr \[char190]\[char190]
+.tr \[char208]\[char208]
+.tr \[char215]\[char215]
+.tr \[char221]\[char221]
+.tr \[char222]\[char222]
+.tr \[char240]\[char240]
+.tr \[char247]\[char247]
+.tr \[char253]\[char253]
+.tr \[char254]\[char254]
+.cp \n(_C
diff --git a/tmac/tmac.psold b/tmac/tmac.psold
new file mode 100755
index 00000000..04a5f6df
--- /dev/null
+++ b/tmac/tmac.psold
@@ -0,0 +1,60 @@
+.\" In the newer PostScript printers, the text fonts contain all ISO Latin-1
+.\" characters. The font description files that comes with groff match
+.\" these fonts. The text fonts in older PostScript printers are missing
+.\" some of these characters. This file prevents those characters from
+.\" being used. This will allow the PostScript output to be printed on both
+.\" old and new printers. The effect of this file can be undone by
+.\" tmac.psnew.
+.nr _C \n(.C
+.cp 0
+.\" Define an accented character.
+.de ps-achar
+.\" Note that character definitions are always interpreted with
+.\" compatibility mode off.
+.char \\$1 \\$3\
+\k[acc]\
+\h'(u;-\w'\\$2'-\w'\\$3'/2+\\\\n[skw]+(\w'x'*0)-\\\\n[skw])'\
+\v'(u;\w'x'*0+\\\\n[rst]+(\w'\\$3'*0)-\\\\n[rst])'\
+\\$2\
+\v'(u;\w'x'*0-\\\\n[rst]+(\w'\\$3'*0)+\\\\n[rst])'\
+\h'|\\\\n[acc]u'
+.ie '\\$3'\(.i' .hcode \\$1i
+.el .hcode \\$1\\$3
+..
+.ps-achar \['y] \(aa y
+.ps-achar \['Y] \(aa Y
+.char \[12] \v'-.7m\s[\\n(.s*6u/10u]+.7m'1\v'-.7m\s0+.7m'\
+\(f/\s[\\n(.s*6u/10u]2\s0
+.char \[14] \v'-.7m\s[\\n(.s*6u/10u]+.7m'1\v'-.7m\s0+.7m'\
+\(f/\s[\\n(.s*6u/10u]4\s0
+.char \[34] \v'-.7m\s[\\n(.s*6u/10u]+.7m'3\v'-.7m\s0+.7m'\
+\(f/\s[\\n(.s*6u/10u]4\s0
+.char \[S1] \v'-.2m'\s-31\s+3\v'+.2m'
+.char \[S2] \v'-.2m'\s-32\s+3\v'+.2m'
+.char \[S3] \v'-.2m'\s-33\s+3\v'+.2m'
+.char \[bb] |
+.char \[de] \fS\(de
+.char \[-D] \Z'\v'-.1m'-'D
+.char \[TP] \
+I\h'-.25m'\v'-.33m'\s'\En(.s*6u/10u'\v'.33m'D\v'-.33m'\s0\v'.33m'
+.char \[Sd] \Z'\v'-.3m'\h'.2m'-'\(pd
+.char \[Tp] \zlp
+.tr \[char166]\[bb]
+.tr \[char176]\[de]
+.tr \[char177]\[+-]
+.tr \[char178]\[S2]
+.tr \[char179]\[S3]
+.tr \[char181]\[*m]
+.tr \[char185]\[S1]
+.tr \[char188]\[14]
+.tr \[char189]\[12]
+.tr \[char190]\[34]
+.tr \[char208]\[-D]
+.tr \[char215]\[mu]
+.tr \[char221]\['Y]
+.tr \[char222]\[TP]
+.tr \[char240]\[Sd]
+.tr \[char247]\[di]
+.tr \[char253]\['y]
+.tr \[char254]\[Tp]
+.cp \n(_C
diff --git a/tmac/tmac.pspic b/tmac/tmac.pspic
new file mode 100755
index 00000000..ef4186f6
--- /dev/null
+++ b/tmac/tmac.pspic
@@ -0,0 +1,50 @@
+.\" Define the PSPIC macro.
+.\" When used other than with -Tps, it will draw a box around where
+.\" the picture would go.
+.de PSPIC
+.nr ps-offset-mode 0
+.if '\\$1'-L' \{\
+. nr ps-offset-mode 1
+. shift
+.\}
+.if '\\$1'-R' \{\
+. nr ps-offset-mode 2
+. shift
+.\}
+.if '\\$1'-I' \{\
+. nr ps-offset-mode 3
+. nr ps-offset (m;\\$2)
+. shift 2
+.\}
+.br
+.psbb \\$1
+.if (\\n[llx] & \\n[lly] & \\n[urx] & \\n[ury]) \{\
+. nr ps-wid (\\n[urx]-\\n[llx])
+. nr ps-ht (\\n[ury]-\\n[lly])
+. if \\n[ps-wid]<0 .nr ps-wid 0-\\n[ps-wid]
+. if \\n[ps-ht]<0 .nr ps-ht 0-\\n[ps-ht]
+. ie \\n[.$]>=2 .nr ps-deswid (i;\\$2)
+. el .nr ps-deswid \\n[.l]-\\n[.i]<?\\n[ps-wid]p
+. nr ps-desht \\n[ps-deswid]*1000+(\\n[ps-wid]/2)/\\n[ps-wid]\
+*\\n[ps-ht]+500/1000
+. if \\n[.$]>=3&(\\n[ps-desht]>(i;0\\$3)) \{\
+. nr ps-desht (i;\\$3)
+. nr ps-deswid \\n[ps-desht]*1000+(\\n[ps-ht]/2)/\\n[ps-ht]\
+*\\n[ps-wid]+500/1000
+. \}
+. ne \\n[ps-desht]u+1v
+. if \\n[ps-offset-mode]=0 .nr ps-offset \\n[.l]-\\n[.i]-\\n[ps-deswid]/2
+. if \\n[ps-offset-mode]=1 .nr ps-offset 0
+. if \\n[ps-offset-mode]=2 .nr ps-offset \\n[.l]-\\n[.i]-\\n[ps-deswid]
+. ie \\n[.$]>=3 .ds ps-desht \\n[ps-desht]
+. el .ds ps-desht \" empty
+\h'\\n[ps-offset]u'\
+\X'ps: invis'\
+\Z'\D'p 0 \\n[ps-desht]u \\n[ps-deswid]u 0 0 -\\n[ps-desht]u''\
+\X'ps: endinvis'\
+\v'\\n[ps-desht]u'\X'ps: import \\$1 \
+\\n[llx] \\n[lly] \\n[urx] \\n[ury] \\n[ps-deswid] \\*[ps-desht]'
+. br
+. sp \\n[ps-desht]u
+.\}
+..
diff --git a/tmac/tmac.s b/tmac/tmac.s
new file mode 100755
index 00000000..6770b0df
--- /dev/null
+++ b/tmac/tmac.s
@@ -0,0 +1,1869 @@
+.\" -*- nroff -*-
+.ig
+Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+..
+.if !\n(.g .ab These ms macros require groff.
+.if \n(.C \
+. ab The groff ms macros do not work in compatibility mode.
+.\" Enable warnings. You can delete this if you want.
+.warn
+.\" See if already loaded.
+.if r GS .nx
+.nr GS 1
+.de @error
+.tm \\n(.F:\\n(.c: macro error: \\$*
+..
+.de @warning
+.tm \\n(.F:\\n(.c: macro warning: \\$*
+..
+.de @fatal
+.ab \\n(.F:\\n(.c: fatal macro error: \\$*
+..
+.de @not-implemented
+.@error sorry, \\$0 not implemented
+.als \\$0 @nop
+..
+.als TM @not-implemented
+.als CT @not-implemented
+.de @nop
+..
+.de @init
+.nr PO \\n(.o
+.\" a non-empty environment
+.ev ne
+\c
+.ev
+.ev nf
+'nf
+.ev
+..
+.ds REFERENCES References
+.ds ABSTRACT ABSTRACT
+.ds TOC Table of Contents
+.ds MONTH1 January
+.ds MONTH2 February
+.ds MONTH3 March
+.ds MONTH4 April
+.ds MONTH5 May
+.ds MONTH6 June
+.ds MONTH7 July
+.ds MONTH8 August
+.ds MONTH9 September
+.ds MONTH10 October
+.ds MONTH11 November
+.ds MONTH12 December
+.ds MO \\*[MONTH\n[mo]]
+.ds DY \n[dy] \*[MO] \n[year]
+.de ND
+.if \\n[.$] .ds DY "\\$*
+..
+.de DA
+.if \\n[.$] .ds DY "\\$*
+.ds CF \\*[DY]
+..
+.\" indexing
+.de IX
+.tm \\$1\t\\$2\t\\$3\t\\$4 ... \\n[PN]
+..
+.\" print an error message and then try to recover
+.de @error-recover
+.@error \\$@ (recovering)
+.nr *pop-count 0
+.while !'\\n(.z'' \{\
+. \"@warning automatically terminating diversion \\n(.z
+. ie d @div-end!\\n(.z .@div-end!\\n(.z
+. el .*div-end-default
+. nr *pop-count +1
+. \" ensure that we don't loop forever
+. if \\n[*pop-count]>20 .@fatal recovery failed
+.\}
+.while !'\\n[.ev]'0' .ev
+.par@reset-env
+.par@reset
+..
+.de *div-end-default
+.ds *last-div \\n(.z
+.br
+.di
+.ev nf
+.\\*[*last-div]
+.ev
+..
+.\" ****************************
+.\" ******** module cov ********
+.\" ****************************
+.\" Cover sheet and first page.
+.de cov*err-not-after-first-page
+.@error \\$0 is not allowed after the first page has started
+..
+.de cov*err-not-before-tl
+.@error \\$0 is not allowed before TL
+..
+.de cov*err-not-again
+.@error \\$0 is not allowed more than once
+..
+.de cov*err-not-after-ab
+.@error \\$0 is not allowed after first AB, LP, PP, IP, SH or NH
+..
+.als AU cov*err-not-before-tl
+.als AI cov*err-not-before-tl
+.als AB cov*err-not-before-tl
+.de cov*first-page-init
+.rm cov*first-page-init
+.par@init
+.als RP cov*err-not-after-first-page
+.@init
+.ie \\n[cov*rp-format] \{\
+. pg@cs-top
+. als FS cov*FS
+. als FE cov*FE
+.\}
+.el \{\
+. pg@top
+. als FS @FS
+. als FE @FE
+.\}
+.wh 0 pg@top
+..
+.wh 0 cov*first-page-init
+.\" This handles the case where FS occurs before TL or LP.
+.de FS
+.br
+\\*[FS]\\
+..
+.nr cov*rp-format 0
+.nr cov*rp-no 0
+.\" released paper format
+.de RP
+.nr cov*rp-format 1
+.if \\n[.$] .if '\\$1'no' .nr cov*rp-no 1
+.pn 0
+..
+.de TL
+.br
+.als TL cov*err-not-again
+.rn @AB AB
+.rn @AU AU
+.rn @AI AI
+.di cov*tl-div
+.par@reset
+.ft B
+.ps +2
+.vs +3p
+.ll (u;\\n[LL]*5/6)
+.nr cov*n-au 0
+..
+.de @AU
+.par@reset
+.if !'\\n(.z'' \{\
+. br
+. di
+.\}
+.nr cov*n-au +1
+.di cov*au-div!\\n[cov*n-au]
+.nf
+.ft I
+.ps \\n[PS]
+..
+.de @AI
+.par@reset
+.if !'\\n(.z'' \{\
+. br
+. di
+.\}
+.ie !\\n[cov*n-au] .@error AI before AU
+.el \{\
+. di cov*ai-div!\\n[cov*n-au]
+. nf
+. ft R
+. ps \\n[PS]
+.\}
+..
+.de LP
+.if !'\\n[.z]'' \{\
+. br
+. di
+.\}
+.br
+.cov*ab-init
+.cov*print
+\\*[\\$0]\\
+..
+.als IP LP
+.als PP LP
+.als XP LP
+.als QP LP
+.als RS LP
+.als NH LP
+.als SH LP
+.als MC LP
+.als RT LP
+.als XS LP
+.de cov*ab-init
+.als cov*ab-init @nop
+.als LP @LP
+.als IP @IP
+.als PP @PP
+.als XP @XP
+.als RT @RT
+.als XS @XS
+.als SH @SH
+.als NH @NH
+.als QP @QP
+.als RS @RS
+.als RE @RE
+.als QS @QS
+.als QE @QE
+.als MC @MC
+.als EQ @EQ
+.als EN @EN
+.als TS @TS
+.als AB cov*err-not-after-ab
+.als AU par@AU
+.als AI par@AI
+.als TL par@TL
+..
+.de @AB
+.if !'\\n(.z'' \{\
+. br
+. di
+.\}
+.cov*ab-init
+.di cov*ab-div
+.par@ab-indent
+.par@reset
+.if !'\\$1'no' \{\
+. ft I
+. ce 1
+\\*[ABSTRACT]
+. sp
+. ft R
+.\}
+.ns
+.@PP
+..
+.de AE
+.ie '\\n(.z'cov*ab-div' \{\
+. als AE cov*err-not-again
+. br
+. di
+.\" nr cov*ab-height \\n[dn]
+. par@reset-env
+. par@reset
+. cov*print
+.\}
+.el .@error AE without AB
+..
+.de @div-end!cov*ab-div
+.AE
+..
+.de cov*print
+.als cov*print @nop
+.ie d cov*tl-div \{\
+. ie \\n[cov*rp-format] .cov*rp-print
+. el .cov*draft-print
+.\}
+.el \{\
+. if \\n[cov*rp-format] \{\
+. @warning RP format but no TL
+. bp 1
+. als FS @FS
+. als FE @FE
+. \}
+. br
+.\}
+..
+.de cov*rp-print
+.nr cov*page-length \\n[.p]
+.pl 1000i
+.cov*tl-au-print
+.sp 3
+.if d cov*ab-div \{\
+. nf
+. cov*ab-div
+.\}
+.sp 3
+.par@reset
+\\*[DY]
+.br
+.if \\n[cov*fn-height] \{\
+. sp |(u;\\n[cov*page-length]-\\n[FM]\
+-\\n[cov*fn-height]-\\n[fn@sep-dist]>?\\n[nl])
+. fn@print-sep
+. ev nf
+. cov*fn-div
+. ev
+. ie \\n[cov*rp-no] .rm cov*fn-div
+. el \{\
+. rn cov*fn-div fn@overflow-div
+. nr fn@have-overflow 1
+. \}
+.\}
+.als FS @FS
+.als FE @FE
+.\" If anything was printed below where the footer line is normally printed,
+.\" then that's an overflow.
+.if -\\n[FM]/2+1v+\\n[cov*page-length]<\\n[nl] .@error cover sheet overflow
+.pl \\n[cov*page-length]u
+.bp 1
+.if !\\n[cov*rp-no] .cov*tl-au-print
+.rs
+.sp 1
+..
+.de cov*draft-print
+.cov*tl-au-print
+.if d cov*ab-div \{\
+. nf
+. sp 2
+. cov*ab-div
+.\}
+.sp 1
+..
+.de cov*tl-au-print
+.par@reset
+.nf
+.rs
+.sp 3
+.ce 9999
+.cov*tl-div
+.nr cov*i 1
+.nr cov*sp 1v
+.while \\n[cov*i]<=\\n[cov*n-au] \{\
+. sp \\n[cov*sp]u
+. cov*au-div!\\n[cov*i]
+. ie d cov*ai-div!\\n[cov*i] \{\
+. sp .5v
+. cov*ai-div!\\n[cov*i]
+. nr cov*sp 1v
+. \}
+. el .nr cov*sp .5v
+. nr cov*i +1
+.\}
+.ce 0
+..
+.nr cov*fn-height 0
+.nr cov*in-fn 0
+.\" start of footnote on cover
+.de cov*FS
+.if \\n[cov*in-fn] \{\
+. @error nested FS
+. FE
+.\}
+.nr cov*in-fn 1
+.ev fn
+.par@reset-env
+.da cov*fn-div
+.if !\\n[cov*fn-height] .ns
+.ie \\n[.$] .FP "\\$1" no
+.el .@LP
+..
+.de @div-end!cov*fn-div
+.cov*FE
+..
+.\" end of footnote on cover
+.de cov*FE
+.ie '\\n(.z'cov*fn-div' \{\
+. br
+. ev
+. di
+. nr cov*in-fn 0
+. nr cov*fn-height +\\n[dn]
+.\}
+.el .@error FE without matching FS
+..
+.\" ***************************
+.\" ******** module pg ********
+.\" ***************************
+.\" Page-level formatting.
+.\" > 0 if we have a footnote on the current page
+.nr pg@fn-flag 0
+.nr pg@colw 0
+.nr pg@fn-colw 0
+.nr HM 1i
+.nr FM 1i
+.ds LF
+.ds CF
+.ds RF
+.ds LH
+.ds CH -\\n[PN]-
+.ds RH
+.ds pg*OH '\\*[LH]'\\*[CH]'\\*[RH]'
+.ds pg*EH '\\*[LH]'\\*[CH]'\\*[RH]'
+.ds pg*OF '\\*[LF]'\\*[CF]'\\*[RF]'
+.ds pg*EF '\\*[LF]'\\*[CF]'\\*[RF]'
+.de OH
+.ds pg*\\$0 "\\$*
+..
+.als EH OH
+.als OF OH
+.als EF OH
+.de PT
+.ie \\n%=1 .if \\n[pg*P1] .tl \\*[pg*OH]
+.el \{\
+. ie o .tl \\*[pg*OH]
+. el .tl \\*[pg*EH]
+.\}
+..
+.de BT
+.ie o .tl \\*[pg*OF]
+.el .tl \\*[pg*EF]
+..
+.nr pg*P1 0
+.de P1
+.nr pg*P1 1
+..
+.wh -\n[FM]u pg@bottom
+.wh -\n[FM]u/2u pg*footer
+.nr MINGW 2n
+.nr pg@ncols 1
+.de @MC
+.if !'\\n(.z'' .error-recover MC while diversion open
+.br
+.ie \\n[pg@ncols]>1 .pg@super-eject
+.el \{\
+. \" flush out any floating keeps
+. while \\n[kp@tail]>\\n[kp@head] \{\
+. rs
+. bp
+. \}
+.\}
+.ie !\\n(.$ \{\
+. nr pg@colw \\n[LL]*7/15
+. nr pg*gutw \\n[LL]-(2*\\n[pg@colw])
+. nr pg@ncols 2
+.\}
+.el \{\
+. nr pg@colw (n;\\$1)<?\\n[LL]
+. ie \\n[.$]<2 .nr pg*gutw \\n[MINGW]
+. el .nr pg*gutw (n;\\$2)
+. nr pg@ncols \\n[LL]-\\n[pg@colw]/(\\n[pg@colw]+\\n[pg*gutw])+1
+. ie \\n[pg@ncols]>1 \
+. nr pg*gutw \\n[LL]-(\\n[pg@ncols]*\\n[pg@colw])/(\\n[pg@ncols]-1)
+. el .nr pg*gutw 0
+.\}
+.mk pg*col-top
+.ns
+.nr pg*col-num 0
+.nr pg@fn-colw \\n[pg@colw]*5/6
+.par@reset
+..
+.de 2C
+.MC
+..
+.de 1C
+.MC \\n[LL]u
+..
+.\" top of page macro
+.de pg@top
+.ch pg*footer -\\n[FM]u/2u
+.nr PN \\n%
+.nr pg*col-num 0
+.nr pg@fn-bottom-margin 0
+.nr pg*saved-po \\n[PO]
+.po \\n[PO]u
+.ev h
+.par@reset
+.sp (u;\\n[HM]/2)
+.PT
+.sp |\\n[HM]u
+.if d HD .HD
+.mk pg@header-bottom
+.ev
+.mk pg*col-top
+.pg*start-col
+..
+.de pg*start-col
+.\" Handle footnote overflow before floating keeps, because the keep
+.\" might contain an embedded footnote.
+.fn@top-hook
+.kp@top-hook
+.tbl@top-hook
+.ns
+..
+.de pg@cs-top
+.sp \\n[HM]u
+.\" move pg@bottom and pg*footer out of the way
+.ch pg@bottom \\n[.p]u*2u
+.ch pg*footer \\n[.p]u*2u
+.ns
+..
+.de pg@bottom
+.tbl@bottom-hook
+.if \\n[pg@fn-flag] .fn@bottom-hook
+.nr pg*col-num +1
+.ie \\n[pg*col-num]<\\n[pg@ncols] .pg*end-col
+.el .pg*end-page
+..
+.de pg*end-col
+'sp |\\n[pg*col-top]u
+.po (u;\\n[pg*saved-po]+(\\n[pg@colw]+\\n[pg*gutw]*\\n[pg*col-num]))
+.\"po +(u;\\n[pg@colw]+\\n[pg*gutw])
+.pg*start-col
+..
+.de pg*end-page
+.po \\n[pg*saved-po]u
+.\" Make sure we don't exit if there are still floats or footnotes left-over.
+.ie \\n[kp@head]<\\n[kp@tail]:\\n[fn@have-overflow] \{\
+. \" Switching environments ensures that we don't get an unnecessary
+. \" blank line at the top of the page.
+. ev ne
+' bp
+. ev
+.\}
+.el \{\
+. \" If the text has ended and there are no more footnotes or keeps, exit.
+. if \\n[pg@text-ended] .ex
+. if r pg*next-number \{\
+. pn \\n[pg*next-number]
+. rr pg*next-number
+. if d pg*next-format \{\
+. af PN \\*[pg*next-format]
+. rm pg*next-format
+. \}
+. \}
+' bp
+.\}
+..
+.\" pg@begin number format
+.de pg@begin
+.ie \\n[.$]>0 \{\
+. nr pg*next-number (;\\$1)
+. ie \\n[.$]>1 .ds pg*next-format \\$2
+. el .rm pg*next-format
+.\}
+.el .rr pg*next-number
+.pg@super-eject
+..
+.\" print the footer line
+.de pg*footer
+.ev h
+.par@reset
+.BT
+.ev
+..
+.\" flush out any keeps or footnotes
+.de pg@super-eject
+.br
+.if !'\\n(.z'' .@error-recover diversion open while ejecting page
+.\" Make sure we stay in the end macro while there is still footnote overflow
+.\" left, or floating keeps.
+.while \\n[kp@tail]>\\n[kp@head]:\\n[pg@fn-flag] \{\
+. rs
+. bp
+.\}
+.bp
+..
+.nr pg@text-ended 0
+.de pg@end-text
+.br
+.nr pg@text-ended 1
+.pg@super-eject
+..
+.em pg@end-text
+.\" ***************************
+.\" ******** module fn ********
+.\" ***************************
+.\" Footnotes.
+.nr fn@sep-dist 8p
+.ev fn
+.\" Round it vertically
+.vs \n[fn@sep-dist]u
+.nr fn@sep-dist \n[.v]
+.ev
+.nr fn*text-num 0 1
+.nr fn*note-num 0 1
+.ds * \\*[par@sup-start]\En+[fn*text-num]\\*[par@sup-end]
+.nr fn*open 0
+.\" normal FS
+.de @FS
+.ie \\n[.$] .fn*do-FS "\\$1" no
+.el \{\
+. ie \\n[fn*text-num]>\\n[fn*note-num] .fn*do-FS \\n+[fn*note-num]
+. el .fn*do-FS
+.\}
+..
+.\" Second argument of `no' means don't embellish the first argument.
+.de fn*do-FS
+.if \\n[fn*open] .@error-recover nested FS
+.nr fn*open 1
+.if \\n[.u] \{\
+. \" Ensure that the first line of the footnote is on the same page
+. \" as the reference. I think this is minimal.
+. ev fn
+. nr fn*need 1v
+. ev
+. ie \\n[pg@fn-flag] .nr fn*need +\\n[fn:PD]
+. el .nr fn*need +\\n[fn@sep-dist]
+. ne \\n[fn*need]u+\\n[.V]u>?0
+.\}
+.ev fn
+.par@reset-env
+.fn*start-div
+.par@reset
+.ie \\n[.$] .FP \\$@
+.el .@LP
+..
+.de @FE
+.ie !\\n[fn*open] .@error FE without FS
+.el \{\
+. nr fn*open 0
+. br
+. ev
+. fn*end-div
+.\}
+..
+.nr fn@have-overflow 0
+.\" called at the top of each column
+.de fn@top-hook
+.nr fn*max-width 0
+.nr fn*page-bottom-pos 0-\\n[FM]-\\n[pg@fn-bottom-margin]
+.ch pg@bottom \\n[fn*page-bottom-pos]u
+.if \\n[fn@have-overflow] \{\
+. nr fn@have-overflow 0
+. fn*start-div
+. ev nf
+. fn@overflow-div
+. ev
+. fn*end-div
+.\}
+..
+.\" This is called at the bottom of the column if pg@fn-flag is set.
+.de fn@bottom-hook
+.nr pg@fn-flag 0
+.nr fn@have-overflow 0
+.nr fn@bottom-pos \\n[.p]-\\n[FM]-\\n[pg@fn-bottom-margin]+\\n[.v]
+.ev fn
+.nr fn@bottom-pos -\\n[.v]
+.ev
+.ie \\n[nl]+\\n[fn@sep-dist]+\n[.V]>\\n[fn@bottom-pos] \{\
+. rn fn@div fn@overflow-div
+. nr fn@have-overflow 1
+.\}
+.el \{\
+. if \\n[pg@ncols]>1 \
+. if \\n[fn*max-width]>\\n[pg@fn-colw] \
+. nr pg@fn-bottom-margin \\n[.p]-\\n[FM]-\\n[nl]+1v
+. wh \\n[fn@bottom-pos]u fn*catch-overflow
+. fn@print-sep
+. ev nf
+. fn@div
+. rm fn@div
+. ev
+. if '\\n(.z'fn@overflow-div' \{\
+. di
+. nr fn@have-overflow \\n[dn]>0
+. \}
+. ch fn*catch-overflow
+.\}
+..
+.de fn*catch-overflow
+.di fn@overflow-div
+..
+.nr fn*embed-count 0
+.de @div-end!fn@div
+.br
+.if '\\n[.ev]'fn' .ev
+.fn*end-div
+.nr fn*open 0
+..
+.als @div-end!fn*embed-div @div-end!fn@div
+.de fn*start-div
+.ie '\\n(.z'' \{\
+. da fn@div
+. if !\\n[pg@fn-flag] .ns
+.\}
+.el .di fn*embed-div
+..
+.de fn*end-div
+.ie '\\n(.z'fn@div' \{\
+. di
+. nr fn*page-bottom-pos -\\n[dn]
+. nr fn*max-width \\n[fn*max-width]>?\\n[dl]
+. if !\\n[pg@fn-flag] .nr fn*page-bottom-pos -\\n[fn@sep-dist]
+. nr pg@fn-flag 1
+. nr fn*page-bottom-pos \\n[nl]-\\n[.p]+\n[.V]>?\\n[fn*page-bottom-pos]
+. ch pg@bottom \\n[fn*page-bottom-pos]u
+.\}
+.el \{\
+. ie '\\n(.z'fn*embed-div' \{\
+. di
+. rn fn*embed-div fn*embed-div!\\n[fn*embed-count]
+\!. fn*embed-start \\n[fn*embed-count]
+. rs
+' sp (u;\\n[dn]+\\n[fn@sep-dist]+\\n[.V])
+\!. fn*embed-end
+. nr fn*embed-count +1
+. \}
+. el \{\
+. ev fn
+. @error-recover unclosed diversion within footnote
+. \}
+.\}
+..
+.de fn*embed-start
+.ie '\\n(.z'' \{\
+. fn*start-div
+. ev nf
+. fn*embed-div!\\$1
+. rm fn*embed-div!\\$1
+. ev
+. fn*end-div
+. di fn*null
+.\}
+.el \{\
+\!. fn*embed-start \\$1
+. rs
+.\}
+..
+.de fn*embed-end
+.ie '\\n(.z'fn*null' \{\
+. di
+. rm fn*null
+.\}
+.el \!.fn*embed-end
+..
+.\" It's important that fn@print-sep use up exactly fn@sep-dist vertical space.
+.de fn@print-sep
+.ev fn
+.in 0
+.vs \\n[fn@sep-dist]u
+\D'l 1i 0'
+.br
+.ev
+..
+.\" ***************************
+.\" ******** module kp ********
+.\" ***************************
+.\" Keeps.
+.de KS
+.br
+.di kp*div
+..
+.de KF
+.if !'\\n(.z'' .@error-recover KF while open diversion
+.di kp*fdiv
+.ev k
+.par@reset-env
+.par@reset
+..
+.de KE
+.ie '\\n(.z'kp*div' .kp*end
+.el \{\
+. ie '\\n(.z'kp*fdiv' .kp*fend
+. el .@error KE without KS or KF
+.\}
+..
+.de @div-end!kp*div
+.kp*end
+..
+.de @div-end!kp*fdiv
+.kp*fend
+..
+.de kp*need
+.ie '\\n(.z'' .ds@need \\$1
+.el \!.kp*need \\$1
+..
+.\" end non-floating keep
+.de kp*end
+.br
+.di
+.kp*need \\n[dn]
+.ev nf
+.kp*div
+.ev
+.rm kp*div
+..
+.\" Floating keeps.
+.nr kp@head 0
+.nr kp@tail 0
+.\" end floating keep
+.de kp*fend
+.br
+.ev
+.di
+.ie \\n[.t]-(\\n[.k]>0*1v)>\\n[dn] \{\
+. br
+. ev nf
+. kp*fdiv
+. rm kp*fdiv
+. ev
+.\}
+.el \{\
+. rn kp*fdiv kp*div!\\n[kp@tail]
+. nr kp*ht!\\n[kp@tail] 0\\n[dn]
+. nr kp@tail +1
+.\}
+..
+.\" top of page processing for KF
+.nr kp*doing-top 0
+.de kp@top-hook
+.if !\\n[kp*doing-top] \{\
+. nr kp*doing-top 1
+. kp*do-top
+. nr kp*doing-top 0
+.\}
+..
+.de kp*do-top
+.\" If the first keep won't fit, only force it out if we haven't had a footnote
+.\" and we're at the top of the page.
+.nr kp*force \\n[pg@fn-flag]=0&(\\n[nl]<=\\n[pg@header-bottom])
+.nr kp*fits 1
+.while \\n[kp@tail]>\\n[kp@head]&\\n[kp*fits] \{\
+. ie \\n[.t]>\\n[kp*ht!\\n[kp@head]]:\\n[kp*force] \{\
+. nr kp*force 0
+. \" It's important to advance kp@head before bringing
+. \" back the keep, so that if the last line of the
+. \" last keep springs the bottom of page trap, a new
+. \" page will not be started unnecessarily.
+. rn kp*div!\\n[kp@head] kp*temp
+. nr kp@head +1
+. ev nf
+. kp*temp
+. ev
+. rm kp*temp
+. \}
+. el .nr kp*fits 0
+.\}
+..
+.\" ***************************
+.\" ******** module ds ********
+.\" ***************************
+.\" Displays and non-floating keeps.
+.de DE
+.ds*end!\\n[\\n[.ev]:ds-type]
+.nr \\n[.ev]:ds-type 0
+..
+.de ds@auto-end
+.if \\n[\\n[.ev]:ds-type] \{\
+. @error automatically terminating display
+. DE
+.\}
+..
+.de @div-end!ds*div
+.ie \\n[\\n[.ev]:ds-type] .DE
+.el .ds*end!2
+..
+.de ds*end!0
+.@error DE without DS, ID, CD, LD or BD
+..
+.de LD
+.br
+.nr \\n[.ev]:ds-type 1
+.par@reset
+.nf
+.sp \\n[DD]u
+..
+.de ID
+.LD
+.ie \\n[.$] .in +(n;\\$1)
+.el .in +\\n[DI]u
+..
+.de CD
+.LD
+.ce 9999
+..
+.de RD
+.LD
+.rj 9999
+..
+.de ds*common-end
+.par@reset
+.sp \\n[DD]u
+..
+.als ds*end!1 ds*common-end
+.de BD
+.LD
+.nr \\n[.ev]:ds-type 2
+.di ds*div
+..
+.de ds*end!2
+.br
+.ie '\\n(.z'ds*div' \{\
+. di
+. nf
+. in (u;\\n[.l]-\\n[dl]/2)
+. ds*div
+. rm ds*div
+. ds*common-end
+.\}
+.el .@error-recover mismatched DE
+..
+.de DS
+.br
+.di ds*div
+.ie '\\$1'B' \{\
+. LD
+. nr \\n[.ev]:ds-type 4
+.\}
+.el \{\
+. ie '\\$1'L' .LD
+. el \{\
+. ie '\\$1'C' .CD
+. el \{\
+. ie '\\$1'R' .RD
+. el \{\
+. ie '\\$1'I' .ID \\$2
+. el .ID \\$1
+. \}
+. \}
+. \}
+. nr \\n[.ev]:ds-type 3
+.\}
+..
+.de ds@need
+.if '\\n(.z'' \{\
+. while \\n[.t]<=(\\$1)&(\\n[nl]>\\n[pg@header-bottom]) \{\
+. rs
+' sp \\n[.t]u
+. \}
+.\}
+..
+.de ds*end!3
+.br
+.ie '\\n(.z'ds*div' \{\
+. di
+. ds@need \\n[dn]
+. ev nf
+. ds*div
+. ev
+. rm ds*div
+. ds*common-end
+.\}
+.el .@error-recover mismatched DE
+..
+.de ds*end!4
+.ie '\\n(.z'ds*div' \{\
+. br
+. di
+. nf
+. in (u;\\n[.l]-\\n[dl]/2)
+. ds@need \\n[dn]
+. ds*div
+. rm ds*div
+. ds*common-end
+.\}
+.el .@error-recover mismatched DE
+..
+.\" ****************************
+.\" ******** module par ********
+.\" ****************************
+.\" Paragraph-level formatting.
+.\" Load time initialization.
+.de par@load-init
+.\" PS and VS might have been set on the command-line
+.if !rPS .nr PS 10
+.if !rLL .nr LL 6i
+.ll \\n[LL]u
+.\" don't set LT so that it can be defaulted from LL
+.ie rLT .lt \\n[LT]u
+.el .lt \\n[LL]u
+.ps \\n[PS]
+.\" don't set VS so that it can be defaulted from PS
+.ie rVS .par*vs \\n[VS]
+.el .par*vs \\n[PS]+2
+.if dFAM .fam \\*[FAM]
+.if !rHY .nr HY 14
+.hy \\n[HY]
+.TA
+..
+.de par*vs
+.\" If it's too big to be in points, treat it as units.
+.ie (p;\\$1)>=40p .vs (u;\\$1)
+.el .vs (p;\\$1)
+..
+.de par@ab-indent
+.nr 0:li (u;\\n[LL]/12)
+.nr 0:ri \\n[0:li]
+..
+.de par*env-init
+.aln \\n[.ev]:PS PS
+.aln \\n[.ev]:VS VS
+.aln \\n[.ev]:LL LL
+.aln \\n[.ev]:MCLL LL
+.aln \\n[.ev]:LT LT
+.aln \\n[.ev]:MCLT LT
+.aln \\n[.ev]:PI PI
+.aln \\n[.ev]:PD PD
+.ad \\n[par*adj]
+.par@reset-env
+..
+.\" happens when the first page begins
+.de par@init
+.if !rLT .nr LT \\n[LL]
+.if !rFL .nr FL \\n[LL]*5/6
+.if !rVS .nr VS \\n[PS]+2
+.if !rDI .nr DI .5i
+.if !rFPS .nr FPS \\n[PS]-2
+.if !rFVS .nr FVS \\n[FPS]+2
+.\" don't change environment 0
+.ev h
+.ps \\n[PS]
+.if !rQI .nr QI 5n
+.if !rPI .nr PI 5n
+.par*vs \\n[VS]
+.if !rPD .nr PD .3v>?\n(.V
+.if !rDD .nr DD .5v>?\n(.V
+.if !rFI .nr FI 2n
+.if !rFPD .nr FPD \\n[PD]/2
+.ev
+.if !dFAM .ds FAM \\n[.fam]
+.nr par*adj \\n[.j]
+.par*env-init
+.ev h
+.par*env-init
+.ev
+.ev fn
+.par*env-init
+.ev
+.ev k
+.par*env-init
+.ev
+.aln 0:MCLL pg@colw
+.aln 0:MCLT pg@colw
+.aln k:MCLL pg@colw
+.aln k:MCLT pg@colw
+.aln fn:PS FPS
+.aln fn:VS FVS
+.aln fn:LL FL
+.aln fn:LT FL
+.aln fn:PI FI
+.aln fn:PD FPD
+.aln fn:MCLL pg@fn-colw
+.aln fn:MCLT pg@fn-colw
+..
+.de par@reset-env
+.nr \\n[.ev]:il 0
+.nr \\n[.ev]:li 0
+.nr \\n[.ev]:ri 0
+.nr \\n[.ev]:ai \\n[\\n[.ev]:PI]
+.nr \\n[.ev]:pli 0
+.nr \\n[.ev]:pri 0
+.nr \\n[.ev]:ds-type 0
+..
+.\" par@reset
+.de par@reset
+.br
+.ce 0
+.rj 0
+.ul 0
+.fi
+.ie \\n[pg@ncols]>1 \{\
+. ll (u;\\n[\\n[.ev]:MCLL]-\\n[\\n[.ev]:ri]-\\n[\\n[.ev]:pri])
+. lt \\n[\\n[.ev]:MCLT]u
+.\}
+.el \{\
+. ll (u;\\n[\\n[.ev]:LL]-\\n[\\n[.ev]:ri]-\\n[\\n[.ev]:pri])
+. lt \\n[\\n[.ev]:LT]u
+.\}
+.in (u;\\n[\\n[.ev]:li]+\\n[\\n[.ev]:pli])
+.ft 1
+.fam \\*[FAM]
+.ps \\n[\\n[.ev]:PS]
+.par*vs \\n[\\n[.ev]:VS]
+.ls 1
+.TA
+.hy \\n[HY]
+..
+.de @RT
+.nr \\n[.ev]:pli 0
+.nr \\n[.ev]:pri 0
+.par@reset
+..
+.\" This can be redefined by the user.
+.de TA
+.ta T 5n
+..
+.de par*start
+.ds@auto-end
+.nr \\n[.ev]:pli \\$1
+.nr \\n[.ev]:pri \\$2
+.par@reset
+.sp \\n[\\n[.ev]:PD]u
+.ne 1v+\\n(.Vu
+..
+.de par@finish
+.nr \\n[.ev]:pli 0
+.nr \\n[.ev]:pri 0
+.par@reset
+..
+.\" normal LP
+.de @LP
+.par*start 0 0
+.nr \\n[.ev]:ai \\n[\\n[.ev]:PI]
+..
+.de @PP
+.par*start 0 0
+.nr \\n[.ev]:ai \\n[\\n[.ev]:PI]
+.ti +\\n[\\n[.ev]:ai]u
+..
+.de @QP
+.nr \\n[.ev]:ai \\n[\\n[.ev]:PI]
+.par*start \\n[QI] \\n[QI]
+..
+.de @XP
+.par*start \\n[\\n[.ev]:PI] 0
+.ti -\\n[\\n[.ev]:PI]u
+..
+.de @IP
+.if \\n[.$]>1 .nr \\n[.ev]:ai (n;\\$2)
+.par*start \\n[\\n[.ev]:ai] 0
+.if !'\\$1'' \{\
+. \" Divert the label so as to freeze any spaces.
+. di par*label
+. par*push-tag-env
+\&\\$1
+. par*pop-tag-env
+. di
+. chop par*label
+. ti -\\n[\\n[.ev]:ai]u
+. ie \\n[dl]+1n<=\\n[\\n[.ev]:ai] \\*[par*label]\h'|\\n[\\n[.ev]:ai]u'\c
+. el \{\
+\\*[par*label]
+. br
+. \}
+. rm par*label
+.\}
+..
+.\" We don't want margin characters to be attached when we divert
+.\" the tag. Since there's no way to save and restore the current
+.\" margin character, we have to switch to a new environment, taking
+.\" what we need of the old environment with us.
+.de par*push-tag-env
+.nr par*saved-font \\n[.f]
+.nr par*saved-size \\n[.s]z
+.nr par*saved-ss \\n[.ss]
+.ds par*saved-fam \\n[.fam]
+.ev par
+.nf
+.TA
+.ft \\n[par*saved-font]
+.ps \\n[par*saved-size]u
+.ss \\n[par*saved-ss]
+.fam \\*[par*saved-fam]
+..
+.de par*pop-tag-env
+.ev
+..
+.de @RS
+.br
+.nr \\n[.ev]:li!\\n[\\n[.ev]:il] \\n[\\n[.ev]:li]
+.nr \\n[.ev]:ri!\\n[\\n[.ev]:il] \\n[\\n[.ev]:ri]
+.nr \\n[.ev]:ai!\\n[\\n[.ev]:il] \\n[\\n[.ev]:ai]
+.nr \\n[.ev]:pli!\\n[\\n[.ev]:il] \\n[\\n[.ev]:pli]
+.nr \\n[.ev]:pri!\\n[\\n[.ev]:il] \\n[\\n[.ev]:pri]
+.nr \\n[.ev]:il +1
+.nr \\n[.ev]:li +\\n[\\n[.ev]:ai]
+.nr \\n[.ev]:ai \\n[\\n[.ev]:PI]
+.par@reset
+..
+.de @RE
+.br
+.ie \\n[\\n[.ev]:il] \{\
+. nr \\n[.ev]:il -1
+. nr \\n[.ev]:ai \\n[\\n[.ev]:ai!\\n[\\n[.ev]:il]]
+. nr \\n[.ev]:li \\n[\\n[.ev]:li!\\n[\\n[.ev]:il]]
+. nr \\n[.ev]:ri \\n[\\n[.ev]:ri!\\n[\\n[.ev]:il]]
+. nr \\n[.ev]:pli \\n[\\n[.ev]:pli!\\n[\\n[.ev]:il]]
+. nr \\n[.ev]:pri \\n[\\n[.ev]:pri!\\n[\\n[.ev]:il]]
+.\}
+.el .@error unbalanced \\$0
+.par@reset
+..
+.de @QS
+.br
+.nr \\n[.ev]:li!\\n[\\n[.ev]:il] \\n[\\n[.ev]:li]
+.nr \\n[.ev]:ri!\\n[\\n[.ev]:il] \\n[\\n[.ev]:ri]
+.nr \\n[.ev]:ai!\\n[\\n[.ev]:il] \\n[\\n[.ev]:ai]
+.nr \\n[.ev]:pli!\\n[\\n[.ev]:il] \\n[\\n[.ev]:pli]
+.nr \\n[.ev]:pri!\\n[\\n[.ev]:il] \\n[\\n[.ev]:pri]
+.nr \\n[.ev]:il +1
+.nr \\n[.ev]:li +\\n[QI]
+.nr \\n[.ev]:ri +\\n[QI]
+.nr \\n[.ev]:ai \\n[\\n[.ev]:PI]
+.par@reset
+..
+.als @QE @RE
+.\" start boxed text
+.de B1
+.br
+.di par*box-div
+.nr \\n[.ev]:li +1n
+.nr \\n[.ev]:ri +1n
+.nr par*box-in \\n[.in]
+.\" remember what 1n is, just in case the point size changes
+.nr par*box-n 1n
+.in +1n
+.ll -1n
+.lt -1n
+.ti \\n[par*box-in]u+1n
+..
+.de @div-end!par*box-div
+.B2
+..
+.\" end boxed text
+.\" Postpone the drawing of the box until we're in the top-level diversion,
+.\" in case there's a footnote inside the box.
+.de B2
+.ie '\\n(.z'par*box-div' \{\
+. br
+. if \n[.V]>.25m .sp
+. di
+. if \n[.V]>.25m .sp
+. ds@need \\n[dn]
+. par*box-mark-top
+. ev nf
+. par*box-div
+. ev
+. nr \\n[.ev]:ri -\\n[par*box-n]
+. nr \\n[.ev]:li -\\n[par*box-n]
+. in -\\n[par*box-n]u
+. ll +\\n[par*box-n]u
+. lt +\\n[par*box-n]u
+. par*box-draw \\n[.i]u \\n[.l]u-(\\n[.H]u==1n*1n)
+.\}
+.el .@error B2 without B1
+..
+.de par*box-mark-top
+.ie '\\n[.z]'' \{\
+. rs
+. mk par*box-top
+.\}
+.el \!.par*box-mark-top
+..
+.de par*box-draw
+.ie '\\n[.z]'' \{\
+. nr par*box-in \\n[.i]
+. nr par*box-ll \\n[.l]
+. nr par*box-vpt \\n[.vpt]
+. nr par*box-ad \\n[.j]
+. ad l
+. vpt 0
+. in \\$1
+. ll \\$2
+\v'-1v+.25m'\
+\D'l (u;\\n[.l]-\\n[.i]) 0'\
+\D'l 0 |\\n[par*box-top]u'\
+\D'l -(u;\\n[.l]-\\n[.i]) 0'\
+\D'l 0 -|\\n[par*box-top]u'
+. br
+. sp -1
+. in \\n[par*box-in]u
+. ll \\n[par*box-ll]u
+. vpt \\n[par*box-vpt]
+. ad \\n[par*box-ad]
+.\}
+.el \!.par*box-draw \\$1 \\$2
+..
+.de @SH
+.par@finish
+.\" Keep together the heading and the first two lines of the next paragraph.
+.ne 3v+\\n[\\n[.ev]:PD]u+\\n(.Vu
+.sp 1
+.ft B
+..
+.\" TL, AU, and AI are aliased to these in cov*ab-init.
+.de par@TL
+.par@finish
+.sp 1
+.ft B
+.ps +2
+.vs +3p
+.ce 9999
+..
+.de par@AU
+.par@finish
+.sp 1
+.ft I
+.ce 9999
+..
+.de par@AI
+.par@finish
+.sp .5
+.ce 9999
+..
+.\" In paragraph macros.
+.de NL
+.ps \\n[\\n[.ev]:PS]
+..
+.de SM
+.ps -2
+..
+.de LG
+.ps +2
+..
+.de R
+.ft R
+..
+.\" par*define-font-macro macro font
+.de par*define-font-macro
+.de \\$1
+.ie \\\\n[.$] \{\
+. nr par*prev-font \\\\n[.f]
+\&\\\\$3\f[\\$2]\\\\$1\f[\\\\n[par*prev-font]]\\\\$2
+.\}
+.el .ft \\$2
+\\..
+..
+.par*define-font-macro B B
+.par*define-font-macro I I
+.par*define-font-macro BI BI
+.par*define-font-macro CW CR
+.\" underline a word
+.de UL
+\Z'\\$1'\v'.25m'\D'l \w'\\$1'u 0'\v'-.25m'\\$2
+..
+.\" box a word
+.de BX
+.nr par*bxw \w'\\$1'+.4m
+\Z'\v'.25m'\D'l 0 -1m'\D'l \\n[par*bxw]u 0'\D'l 0 1m'\D'l -\\n[par*bxw]u 0''\
+\Z'\h'.2m'\\$1'\
+\h'\\n[par*bxw]u'
+..
+.\" The first time UX is used, put a registered mark after it.
+.ds par*ux-rg \(rg
+.de UX
+\s[\\n[.s]*8u/10u]UNIX\s0\\$1\\*[par*ux-rg]
+.ds par*ux-rg
+..
+.ds par@sup-start \v'-.9m\s'\En[.s]*7u/10u'+.7m'
+.als { par@sup-start
+.ds par@sup-end \v'-.7m\s0+.9m'
+.als } par@sup-end
+.\" footnote paragraphs
+.\" FF is the footnote format
+.nr FF 0
+.\" This can be redefined. It gets a second argument of `no' if the first
+.\" argument was supplied by the user, rather than automatically.
+.de FP
+.br
+.if !d par*fp!\\n[FF] \{\
+. @error unknown footnote format `\\n[FF]'
+. nr FF 0
+.\}
+.ie '\\$2'no' .par*fp!\\n[FF]-no "\\$1"
+.el .par*fp!\\n[FF] "\\$1"
+..
+.de par*fp!0
+.@PP
+\&\\*[par@sup-start]\\$1\\*[par@sup-end]\ \c
+..
+.de par*fp!0-no
+.@PP
+\&\\$1\ \c
+..
+.de par*fp!1
+.@PP
+\&\\$1.\ \c
+..
+.de par*fp!1-no
+.@PP
+\&\\$1\ \c
+..
+.de par*fp!2
+.@LP
+\&\\$1.\ \c
+..
+.de par*fp!2-no
+.@LP
+\&\\$1\ \c
+..
+.de par*fp!3
+.@IP "\\$1." (u;\\n[\\n[.ev]:PI]*2)
+..
+.de par*fp!3-no
+.@IP "\\$1" (u;\\n[\\n[.ev]:PI]*2)
+..
+.\" ***************************
+.\" ******** module nh ********
+.\" ***************************
+.\" Numbered headings.
+.\" nh*hl is the level of the last heading
+.nr nh*hl 0
+.\" numbered heading
+.de @NH
+.ie '\\$1'S' \{\
+. shift
+. nr nh*hl 0
+. while \\n[.$] \{\
+. nr nh*hl +1
+. nr H\\n[nh*hl] 0\\$1
+. shift
+. \}
+. if !\\n[nh*hl] \{\
+. nr H1 1
+. nr nh*hl 1
+. @error missing arguments to .NH S
+. \}
+.\}
+.el \{\
+. nr nh*ohl \\n[nh*hl]
+. ie \\n[.$] \{\
+. nr nh*hl 0\\$1
+. ie \\n[nh*hl]<=0 \{\
+. nr nh*ohl 0
+. nr nh*hl 1
+. \}
+. el \{\
+. if \\n[nh*hl]-\\n[nh*ohl]>1 \
+. @warning .NH \\n[nh*ohl] followed by .NH \\n[nh*hl]
+. \}
+. \}
+. el .nr nh*hl 1
+. while \\n[nh*hl]>\\n[nh*ohl] \{\
+. nr nh*ohl +1
+. nr H\\n[nh*ohl] 0
+. \}
+. nr H\\n[nh*hl] +1
+.\}
+.ds SN
+.nr nh*i 0
+.while \\n[nh*i]<\\n[nh*hl] \{\
+. nr nh*i +1
+. as SN \\n[H\\n[nh*i]].
+.\}
+.SH
+\\*[SN]
+..
+.\" ****************************
+.\" ******** module toc ********
+.\" ****************************
+.\" Table of contents generation.
+.de @XS
+.da toc*div
+.ev h
+.ie \\n[.$] .XA "\\$1"
+.el .XA
+..
+.de @div-end!toc*div
+.XE
+..
+.de XA
+.ie '\\n(.z'toc*div' \{\
+. if d toc*num .toc*end-entry
+. ie \\n[.$] \{\
+. ie '\\$1'no' .ds toc*num
+. el .ds toc*num "\\$1
+. \}
+. el .ds toc*num \\n[PN]
+. br
+. par@reset
+. na
+. ll -8n
+. in (n;0\\$2)
+.\}
+.el .@error XA without XS
+..
+.de XE
+.ie '\\n(.z'toc*div' \{\
+. if d toc*num .toc*end-entry
+. ev
+. di
+.\}
+.el .@error XS without XE
+..
+.de toc*end-entry
+\\a\\t\\*[toc*num]
+.br
+.rm toc*num
+..
+.de PX
+.1C
+.if !'\\$1'no' \{\
+. ce 1
+. ps \\n[PS]+2
+. ft B
+\\*[TOC]
+. ft
+. ps
+.\}
+.nf
+.char \[toc*leader-char] .\h'1m'
+.lc \[toc*leader-char]
+.ta (u;\\n[.l]-\\n[.i]-\w'000') (u;\\n[.l]-\\n[.i])R
+.sp 2
+.toc*div
+.par@reset
+..
+.\" print the table of contents on page i
+.de TC
+.P1
+.pg@begin 1 i
+.PX \\$1
+..
+.\" ****************************
+.\" ******** module eqn ********
+.\" ****************************
+.\" Eqn support.
+.de EQ
+..
+.de EN
+..
+.de @EQ
+.br
+.ds eqn*num "\\$2
+.ie '\\$1'L' .nr eqn*type 0
+.el \{\
+. ie '\\$1'I' .nr eqn*type 1
+. el \{\
+. nr eqn*type 2
+. if !'\\$1'C' .ds eqn*num "\\$1
+. \}
+.\}
+.di eqn*div
+.in 0
+.nf
+..
+.de @div-end!eqn*div
+.@EN
+..
+.\" Note that geqn mark and lineup work correctly in centered equations.
+.de @EN
+.ie !'\\n(.z'eqn*div' .@error-recover mismatched EN
+.el \{\
+. br
+. di
+. nr eqn*have-num 0
+. if !'\\*[eqn*num]'' .nr eqn*have-num 1
+. if \\n[dl]:\\n[eqn*have-num] \{\
+. sp \\n[DD]u
+. par@reset
+. ds eqn*tabs \\n[.tabs]
+. nf
+. ie \\n[dl] \{\
+. ds@need \\n[dn]u-1v+\n[.V]u
+. chop eqn*div
+. ie \\n[eqn*type]=0 \{\
+. ta (u;\\n[.l]-\\n[.i])R
+\\*[eqn*div]\t\\*[eqn*num]
+. \}
+. el \{\
+. ie \\n[eqn*type]=1 .ta \\n[DI]u \
+(u;\\n[.l]-\\n[.i])R
+. el .ta (u;\\n[.l]-\\n[.i]/2)C \
+(u;\\n[.l]-\\n[.i])R
+\t\\*[eqn*div]\t\\*[eqn*num]
+. \}
+. \}
+. el \{\
+. ta (u;\\n[.l]-\\n[.i])R
+\t\\*[eqn*num]
+. \}
+. sp \\n[DD]u
+. ta \\*[eqn*tabs]
+. \}
+. fi
+.\}
+..
+.\" ****************************
+.\" ******** module tbl ********
+.\" ****************************
+.\" Tbl support.
+.nr tbl*have-header 0
+.\" This gets called if TS occurs before the first paragraph.
+.de TS
+.LP
+.\" cov*ab-init aliases TS to @TS
+\\*[TS]\\
+..
+.de @TS
+.sp \\n[DD]u
+.if '\\$1'H' .di tbl*header-div
+..
+.de tbl@top-hook
+.if \\n[tbl*have-header] \{\
+. ie \\n[.t]-\\n[tbl*header-ht]-1v .tbl*print-header
+. el .sp \\n[.t]u
+.\}
+..
+.de tbl*print-header
+.ev nf
+.tbl*header-div
+.ev
+.mk #T
+..
+.de TH
+.ie '\\n[.z]'tbl*header-div' \{\
+. nr T. 0
+. T#
+. br
+. di
+. ie \\n[dn]+\\n[FM]+\\n[HM]+2v>=\\n[.p] \{\
+. @error ridiculously long table header
+. ds@need \\n[dn]
+. tbl*print-header
+. \}
+. el \{\
+. nr tbl*header-ht \\n[dn]
+. ds@need \\n[dn]u+1v
+. tbl*print-header
+. nr tbl*have-header 1
+. \}
+.\}
+.el .@error-recover .TH without .TS H
+..
+.de @div-end!tbl*header-div
+.TH
+.TE
+..
+.de TE
+.ie '\\n(.z'tbl*header-div' .@error-recover .TS H but no .TH before .TE
+.el \{\
+. nr tbl*have-header 0
+. sp \\n[DD]u
+.\}
+.\" reset tabs
+.TA
+..
+.de tbl@bottom-hook
+.if \\n[tbl*have-header] \{\
+. nr T. 1
+. T#
+.\}
+..
+.de T&
+..
+.\" ****************************
+.\" ******** module pic ********
+.\" ****************************
+.\" Pic support.
+.\" PS height width
+.de PS
+.br
+.sp \\n[DD]u
+.ie \\n[.$]<2 .@error bad arguments to PS (not preprocessed with pic?)
+.el \{\
+. ds@need (u;\\$1)+1v
+. in +(u;\\n[.l]-\\n[.i]-\\$2/2>?0)
+.\}
+..
+.de PE
+.par@reset
+.sp \\n[DD]u+.5m
+..
+.\" ****************************
+.\" ******** module ref ********
+.\" ****************************
+.\" Refer support.
+.de ]-
+.rm [A [B [C [D [E [G [I [J [N [O [P [Q [R [S [T [V
+.rm ref*string
+..
+.\" Other
+.ds ref*spec!0 Q A T1 S V N P I C D O
+.\" Journal article
+.ds ref*spec!1 Q A T2 J S V N P I C D O
+.\" Book
+.ds ref*spec!2 Q A T1 S V P I C D O
+.\" Article within book
+.ds ref*spec!3 Q A T2 B E S V P I C D O
+.\" Tech report
+.ds ref*spec!4 Q A T2 R G P I C D O
+.\" ][ type
+.de ][
+.if r [T \{\
+. als [T1 [T
+. als [T2 [T
+.\}
+.ie d ref*spec!\\$1 .ref*build \\*[ref*spec!\\$1]
+.el \{\
+. @error unknown reference type `\\$1'
+. ref*build \\*[ref*spec!0]
+.\}
+.ref*print
+.rm ref*string
+.rm [F [T1 [T2
+..
+.\" start of reference number
+.ds [. \\*[par@sup-start]
+.\" end of reference number
+.ds .] \\*[par@sup-end]
+.\" period before reference
+.ds <. .
+.\" period after reference
+.ds >. \" empty
+.\" comma before reference
+.ds <, ,
+.\" comma after reference
+.ds >, \" empty
+.\" start collected references
+.de ]<
+.als ref*print ref*end-print
+.SH
+\&\\*[REFERENCES]
+.par@reset
+..
+.\" end collected references
+.de ]>
+.par@finish
+.als ref*print ref*normal-print
+..
+.de ref*normal-print
+.ie d [F .FS "\\*([.\\*([F\\*(.]"
+.el .FS \&
+\\*[ref*string]
+.FE
+..
+.de ref*end-print
+.ie d [F .IP "\\*([F."
+.el .XP
+\\*[ref*string]
+..
+.als ref*print ref*normal-print
+.de ref*build
+.rm ref*string ref*post-punct
+.nr ref*suppress-period 1
+.while \\n[.$] \{\
+. if d [\\$1 \{\
+. ie d ref*add-\\$1 .ref*add-\\$1
+. el .ref*add-dflt \\$1
+. \}
+. shift
+.\}
+.\" now add a final period
+.ie d ref*string \{\
+. if !\\n[ref*suppress-period] .as ref*string .
+. if d ref*post-punct \{\
+. as ref*string "\\*[ref*post-punct]
+. rm ref*post-punct
+. \}
+.\}
+.el .ds ref*string
+..
+.de ref*add-T1
+.ref*field T , "\fI" "" "\fP"
+.if r [T .nr ref*suppress-period \\n([T
+..
+.de ref*add-T2
+.ref*field T , "\\*Q" "" "\\*U"
+.if r [T .nr ref*suppress-period \\n([T
+..
+.de ref*add-P
+.ie \\n([P>0 .ref*field P , "pp. "
+.el .ref*field P , "p. "
+..
+.de ref*add-J
+.ref*field J , \fI "" \fP
+..
+.de ref*add-D
+.ref*field D "" ( )
+..
+.de ref*add-E
+.ref*field E , "ed. "
+..
+.de ref*add-G
+.ref*field G "" ( )
+..
+.de ref*add-B
+.ref*field B "" "in \fI" "" \fP
+..
+.de ref*add-O
+.ref*field O .
+.ie r [O .nr ref*suppress-period \\n([O
+.el .nr ref*suppress-period 1
+..
+.de ref*add-A
+.ref*field A ,
+.if r [A .nr ref*suppress-period \\n([A
+..
+.de ref*add-dflt
+.ref*field \\$1 ,
+..
+.\" First argument is the field letter.
+.\" Second argument is the punctuation character to use to separate this field
+.\" from the previous field.
+.\" Third argument is a string with which to prefix this field.
+.\" Fourth argument is a string with which to postfix this field.
+.\" Fifth argument is a string to add after the punctuation character supplied
+.\" by the next field.
+.de ref*field
+.if d ref*string \{\
+. ie d ref*post-punct \{\
+. as ref*string "\\$2\\*[ref*post-punct] \"
+. rm ref*post-punct
+. \}
+. el .as ref*string "\\$2 \"
+.\}
+.as ref*string "\\$3\\*([\\$1\\$4
+.if \\n[.$]>4 .ds ref*post-punct "\\$5
+.nr ref*suppress-period 0
+..
+.\" ****************************
+.\" ******** module acc ********
+.\" ****************************
+.\" Accents and special characters.
+.ds Q \(lq
+.ds U \(rq
+.ds - \(em
+.\" Characters
+.\" The idea of this definition is for the top of the 3 to be at the x-height.
+.if !c\[yogh] .char \[yogh] \Z'\v'\w'x'*0-\En[rst]u'\s[\En[.s]*8u/10u]\
+\v'\w'3'*0+\En[rst]u'3\s0'\h'\w'\s[\En[.s]*8u/10u]3'u'
+.\" Accents
+.de acc*over-def
+.ds \\$1 \Z'\v'(u;\w'x'*0+\En[rst]-\En[.cht])'\
+\h'(u;-\En[skw]+(-\En[.w]-\w'\\$2'/2)+\En[.csk])'\\$2'
+..
+.de acc*under-def
+.ds \\$1 \Z'\v'\En[.cdp]u'\h'(u;-\En[.w]-\w'\\$2'/2)'\\$2'
+..
+.de acc*slash-def
+.ds \\$1 \Z'\h'(u;-\En[.w]-\w'\\$2'/2)'\
+\v'(u;\En[.cdp]-\En[.cht]+\En[rst]+\En[rsb]/2)'\\$2'
+..
+.de acc*prefix-def
+.ds \\$1 \Z'\h'(u;\w'x'-\w'\\$2'/2)'\\$2'
+..
+.acc*prefix-def ' \'
+.acc*prefix-def ` \`
+.acc*prefix-def ^ ^
+.acc*prefix-def , \(ac
+.acc*prefix-def : \(ad
+.acc*prefix-def ~ ~
+.\" improved accent marks
+.de AM
+.acc*over-def ' \'
+.acc*over-def ` \`
+.acc*over-def ^ ^
+.acc*over-def ~ ~
+.acc*over-def : \(ad
+.acc*over-def v \(ah
+.acc*over-def _ \(a-
+.acc*over-def o \(ao
+.acc*under-def , \(ac
+.acc*under-def . \s[\En[.s]*8u/10u]\v'.2m'.\v'-.2m'\s0
+.acc*under-def hook \(ho
+.acc*slash-def / /
+.char \[hooko] o\\\\*[hook]
+.ds q \[hooko]
+.ds 3 \[yogh]
+.ds D- \(-D\" Icelandic uppercase eth
+.ds d- \(Sd\" Icelandic lowercase eth
+.ds Th \(TP\" Icelandic uppercase thorn
+.ds th \(Tp\" Icelandic lowercase thorn
+.ds 8 \(ss\" German double s
+.ds Ae \(AE\" AE ligature
+.ds ae \(ae\" ae ligature
+.ds Oe \(OE\" OE ligature
+.ds oe \(oe\" oe ligature
+.ds ? \(r?\" upside down ?
+.ds ! \(r!\" upside down !
+..
+.par@load-init
+.\" Make sure that no blank lines creep in at the end of this file.
diff --git a/tmac/tmac.safer b/tmac/tmac.safer
new file mode 100755
index 00000000..be348d5f
--- /dev/null
+++ b/tmac/tmac.safer
@@ -0,0 +1,10 @@
+.\" remove unsafe requests
+.rm open opena pso sy pi
+.de unsafe
+.tm \\n(.F:\\n(.c: unsafe to execute request `\\$1'
+..
+.als open unsafe
+.als opena unsafe
+.als pso unsafe
+.als sy unsafe
+.als pi unsafe
diff --git a/tmac/tmac.trace b/tmac/tmac.trace
new file mode 100755
index 00000000..2691c46e
--- /dev/null
+++ b/tmac/tmac.trace
@@ -0,0 +1,10 @@
+.\" Load this before a macro package that you want to trace.
+.rn de !!de
+.!!de de
+.!!de \\$1
+.tm *** trace enter \\$1: \\\\$0 \\\\$@
+\\\\*[!!\\$1]\\\\
+.tm *** trace exit \\$1: \\\\$0 \\\\$@
+\\..
+.!!de !!\\$1 \\$2
+..
diff --git a/tmac/tmac.tty b/tmac/tmac.tty
new file mode 100755
index 00000000..419a6853
--- /dev/null
+++ b/tmac/tmac.tty
@@ -0,0 +1,47 @@
+.nr _C \n(.C
+.cp 0
+.nroff
+.\" Don't warn about non-existent fonts.
+.warn \n[.warn]-(\n[.warn]/131072%2*131072)
+.po 0
+.if c\[char173] .shc \[char173]
+.de tty-char
+.if !c\\$1 .char \\$1 "\\$2
+..
+.if c\(md .tr \(bu\(md
+.tty-char \(bu \z+o
+.tty-char \(14 1/4
+.tty-char \(12 1/2
+.tty-char \(34 3/4
+.tty-char \(ff ff
+.tty-char \(fi fi
+.tty-char \(fl fl
+.tty-char \(Fi ffi
+.tty-char \(Fl ffl
+.tty-char \(<- <-
+.tty-char \(-> ->
+.tty-char \(<> <->
+.tty-char \(em --
+.tty-char \(+- +-
+.tty-char \(co (C)
+.tty-char \(<= <=
+.tty-char \(>= >=
+.tty-char \(!= !=
+.tty-char \(== ==
+.tty-char \(~= ~=
+.tty-char \(sq []
+.tty-char \(lh <=
+.tty-char \(rh =>
+.tty-char \(lA <=
+.tty-char \(rA =>
+.tty-char \(hA <=>
+.tty-char \(rg (R)
+.tty-char \(OE OE
+.tty-char \(oe oe
+.tty-char \(AE AE
+.tty-char \(ae ae
+.tty-char \(an -
+.cp \n(_C
+.\" If you want the character definitions in tmac.tty-char to be loaded
+.\" automatically, remove the `\"' from the next line.
+.\"do mso tmac.tty-char
diff --git a/tmac/tmac.tty-char b/tmac/tmac.tty-char
new file mode 100755
index 00000000..8dc1aee7
--- /dev/null
+++ b/tmac/tmac.tty-char
@@ -0,0 +1,198 @@
+.\" This file defines standard troff characters and some groff characters for
+.\" use with -Tascii, -Tlatin1 and -Tutf8.
+.\"
+.\" These definitions are chosen so that, as far as possible, they:
+.\" - work with all of -Tascii, -Tlatin1 and -Tutf8.
+.\" - work on devices that display only the last overstruck character
+.\" as well as on devices that support overstriking
+.\" - represent the character's graphical shape (not its meaning)
+.\"
+.nr _C \n(.C
+.cp 0
+.de tty-char
+.if !c\\$1 .char \\$1 "\\$2
+..
+.ie c\(a- .ds tty-rn \(a-
+.el .ds tty-rn \v'-1m'_\v'+1m'
+.tty-char \(tm tm
+.tty-char \(rn \*[tty-rn]
+.tty-char \(ua \z|^
+.tty-char \(da \z|v
+.tty-char \(sc S
+.tty-char \(ct \z/c
+.tty-char \(dg \z|-
+.tty-char \(dd \z|=
+.tty-char \(ib (\z=_
+.tty-char \(ip \z=_)
+.tty-char \(sb (=
+.tty-char \(sp =)
+.tty-char \(if oo
+.tty-char \(pt oc
+.tty-char \(es {}
+.tty-char \(ca (^)
+.tty-char \(cu U
+.tty-char \(de o
+.tty-char \(di -:-
+.tty-char \(no ~
+.tty-char \(gr \Z'\*[tty-rn]'V
+.tty-char \(is \z'\z,I
+.tty-char \(mo E
+.tty-char \(pd a
+.tty-char \(sr \e/
+.tty-char \(*C \z_H
+.tty-char \(*D \z_/\z_\e
+.tty-char \(*F \zIO
+.tty-char \(*G |\*[tty-rn]
+.tty-char \(*H \z-O
+.tty-char \(*L /\e
+.tty-char \(*P TT
+.tty-char \(*Q \zIY
+.tty-char \(*S \z_\Z'\*[tty-rn]'>
+.tty-char \(*W \z_O
+.if c\(ss .tty-char \(*b \(ss
+.tty-char \(*b B
+.tty-char \(*a a
+.tty-char \(*c \z,E
+.tty-char \(*d d
+.tty-char \(*e e
+.tty-char \(*f \z|o
+.tty-char \(+f \z|o
+.tty-char \(*g y
+.tty-char \(*h \z-0
+.tty-char \(+h \z-0
+.tty-char \(*i i
+.tty-char \(*k k
+.tty-char \(*l \z>\e
+.tty-char \(*m \z,u
+.tty-char \(*n v
+.tty-char \(*p \z-n
+.tty-char \(+p \z-w
+.tty-char \(*q \z|u
+.tty-char \(*r p
+.tty-char \(*s \z-o
+.tty-char \(*t \z~t
+.tty-char \(*u u
+.tty-char \(*w w
+.tty-char \(*x x
+.tty-char \(*y n
+.tty-char \(*z \z,C
+.tty-char \(ts s
+.\" Definition of \(ss should follow that of \(*b.
+.tty-char \(ss B
+.tty-char \(c* \zO\(mu
+.tty-char \(c+ \zO+
+.tty-char \(AN ^
+.tty-char \(OR v
+.tty-char \(uA \z=^
+.tty-char \(dA \z=v
+.if c\(md .tty-char \(a. \(md
+.tty-char \(Im I
+.tty-char \(Re R
+.tty-char \(/L \z/L
+.tty-char \(/l \z/l
+.tty-char \(%0 %o
+.tty-char \(ao o
+.tty-char \(a" """"
+.tty-char \(ab \z'`
+.tty-char \(ah v
+.tty-char \(ho \(ac
+.tty-char \(/_ \z_/
+.tty-char \(=~ =~
+.tty-char \(Ah N
+.tty-char \(CR _|
+.tty-char \(fa \z-V
+.tty-char \(nm \z/E
+.tty-char \(pp \z_|
+.tty-char \(sd ''
+.tty-char \(st -)
+.tty-char \(te 3
+.if c\(md .tty-char \(tf .\(md.
+.tty-char \(tf .:.
+.tty-char \(wp p
+.tty-char \(~~ ~~
+.tty-char \(Fn \z,f
+.tty-char \(Bq ,,
+.tty-char \(bq ,
+.tty-char \(lz <>
+.\" Latin-1 characters
+.tty-char \(r! \z,i
+.tty-char \(Po \z-L
+.tty-char \(Cs \zox
+.tty-char \(Ye \z=Y
+.tty-char \(bb |
+.tty-char \(ad """"
+.tty-char \(Of \z_a
+.tty-char \(Fo <<
+.tty-char \(a- \*[tty-rn]
+.tty-char \(S2 2
+.tty-char \(S3 3
+.tty-char \(ps 9|
+.tty-char \(md .
+.tty-char \(ac ,
+.tty-char \(S1 1
+.tty-char \(Om \z_o
+.tty-char \(Fc >>
+.tty-char \(r? \z'c
+.tty-char \(`A \z`A
+.tty-char \('A \z'A
+.tty-char \(^A \z^A
+.tty-char \(~A \z~A
+.tty-char \(:A \z"A
+.tty-char \(oA \zoA
+.tty-char \(,C \z,C
+.tty-char \(`E \z`E
+.tty-char \('E \z'E
+.tty-char \(^E \z^E
+.tty-char \(:E \z"E
+.tty-char \(`I \z`I
+.tty-char \('I \z'I
+.tty-char \(^I \z^I
+.tty-char \(:I \z"I
+.tty-char \(-D \z-D
+.tty-char \(~N \z~N
+.tty-char \(`O \z`O
+.tty-char \('O \z'O
+.tty-char \(^O \z^O
+.tty-char \(~O \z~O
+.tty-char \(:O \z"O
+.tty-char \(/O \z/O
+.tty-char \(`U \z`U
+.tty-char \('U \z'U
+.tty-char \(^U \z^U
+.tty-char \(:U \z"U
+.tty-char \('Y \z'Y
+.tty-char \(TP \zIb
+.tty-char \(`a \z`a
+.tty-char \('a \z'a
+.tty-char \(^a \z^a
+.tty-char \(~a \z~a
+.tty-char \(:a \z"a
+.tty-char \(oa \zoa
+.tty-char \(,c \z,c
+.tty-char \(`e \z`e
+.tty-char \('e \z'e
+.tty-char \(^e \z^e
+.tty-char \(:e \z"e
+.tty-char \(`i \z`i
+.tty-char \('i \z'i
+.tty-char \(^i \z^i
+.tty-char \(:i \z"i
+.tty-char \(Sd \z`\z'o
+.tty-char \(~n \z~n
+.tty-char \(`o \z`o
+.tty-char \('o \z'o
+.tty-char \(^o \z^o
+.tty-char \(~o \z~o
+.tty-char \(:o \z"o
+.tty-char \(/o \z/o
+.tty-char \(`u \z`u
+.tty-char \('u \z'u
+.tty-char \(^u \z^u
+.tty-char \(:u \z"u
+.tty-char \('y \z'y
+.tty-char \(Tp \zpb
+.tty-char \(:y \z"y
+.\"tty-char \(:y \ij
+.tty-char \[arrowvertex] |
+.cp \n(_C
+.do mso tmac.latin1
diff --git a/tmac/troffrc b/tmac/troffrc
new file mode 100644
index 00000000..952c78f7
--- /dev/null
+++ b/tmac/troffrc
@@ -0,0 +1,27 @@
+.\" Startup file for troff.
+.\" This is tested by pic.
+.nr 0p 0
+.\" Use .do here, so that it works with -C.
+.\" The groff command defines the .X string if the -X option was given.
+.ie r.X .do ds troffrc!ps tmac.Xps
+.el .do ds troffrc!ps tmac.ps
+.do ds troffrc!dvi tmac.dvi
+.do ds troffrc!X75 tmac.X
+.do ds troffrc!X75-12 tmac.X
+.do ds troffrc!X100 tmac.X
+.do ds troffrc!X100-12 tmac.X
+.do ds troffrc!ascii tmac.tty
+.do ds troffrc!latin1 tmac.tty
+.do ds troffrc!utf8 tmac.tty
+.do ds troffrc!lj4 tmac.lj4
+.do ds troffrc!html tmac.arkup
+.do if d troffrc!\*[.T] \
+. do mso \*[troffrc!\*[.T]]
+.do rm troffrc!ps troffrc!Xps troffrc!dvi troffrc!X75 troffrc!X75-12 \
+troffrc!X100 troffrc!X100-12 troffrc!lj4 troffrc!html
+.do tr \[char160]
+.\" Set the hyphenation language to `us'.
+.do hla us
+.\" Load hyphenation patterns from `hyphen.us' (in the tmac directory).
+.do hpf hyphen.us
+.\" Don't let blank lines creep in here.
diff --git a/tmac/troffrc-end b/tmac/troffrc-end
new file mode 100644
index 00000000..edd23e4f
--- /dev/null
+++ b/tmac/troffrc-end
@@ -0,0 +1,6 @@
+.\"
+.\" final startup file for troff
+.\" this file is parsed after all macro sets have been read
+.\"
+.if '\*(.T'html' .mso tmac.html
+.\" Don't let blank lines creep in here. \ No newline at end of file